李宏毅机器学习作业1:预测PM2.5(含训练数据)
1.要求
給定訓(xùn)練集train.csv,要求根據(jù)前9個(gè)小時(shí)的空氣監(jiān)測情況預(yù)測第10個(gè)小時(shí)的PM2.5含量。
訓(xùn)練集介紹:
- CSV文件,包含臺(tái)灣豐原地區(qū)240天的氣象觀測資料(取每個(gè)月前20天的數(shù)據(jù)做訓(xùn)練集,12月X20天=240天,每月后10天數(shù)據(jù)用于測試)
- 每天的監(jiān)測時(shí)間點(diǎn)為0時(shí),1時(shí)…到23時(shí),共24個(gè)時(shí)間節(jié)點(diǎn);
- 每天的檢測指標(biāo)包括CO、NO、PM2.5、PM10等氣體濃度,是否降雨、刮風(fēng)等氣象信息,共計(jì)18項(xiàng);
- 數(shù)據(jù)集地址:https://pan.baidu.com/s/1o2Yx42dZBJZFZqCa5y3WzQ,提取碼:qgtm。
2. 思路分析
前注:下文中提到的“數(shù)據(jù)幀”并非指pandas庫中的數(shù)據(jù)結(jié)構(gòu)DataFrame,而是指一個(gè)二維的數(shù)據(jù)包。
2.1 數(shù)據(jù)預(yù)處理
訓(xùn)練集中數(shù)據(jù)排列形式符合人類觀察數(shù)據(jù)的習(xí)慣,但并不能直接拿來喂給模型進(jìn)行訓(xùn)練,因此需要對數(shù)據(jù)進(jìn)行預(yù)處理。
瀏覽數(shù)據(jù)可知,數(shù)據(jù)中存在一定量的空數(shù)據(jù)NR,且多存在于RAINFALL一項(xiàng)。對于空數(shù)據(jù),常規(guī)的處理方法無非就是刪除法和補(bǔ)全法兩種。查閱資料后發(fā)現(xiàn),RAINFALL表示當(dāng)天對應(yīng)時(shí)間點(diǎn)是否降雨,有降雨值為1,無降雨值為NR,類似于布爾變量。因此可以采用補(bǔ)全法處理空數(shù)據(jù):將空數(shù)據(jù)NR全部補(bǔ)為0即可。
根據(jù)作業(yè)要求可知,需要用到連續(xù)9個(gè)時(shí)間點(diǎn)的氣象觀測數(shù)據(jù),來預(yù)測第10個(gè)時(shí)間點(diǎn)的PM2.5含量。針對每一天來說,其包含的信息維度為(18,24)(18項(xiàng)指標(biāo),24個(gè)時(shí)間節(jié)點(diǎn))。可以將0到8時(shí)的數(shù)據(jù)截取出來,形成一個(gè)維度為(18,9)的數(shù)據(jù)幀,作為訓(xùn)練數(shù)據(jù),將9時(shí)的PM2.5含量取出來,作為該訓(xùn)練數(shù)據(jù)對應(yīng)的label;同理可取1到9時(shí)的數(shù)據(jù)作為訓(xùn)練用的數(shù)據(jù)幀,10時(shí)的PM2.5含量作為label…以此分割,可將每天的信息分割為15個(gè)shape為(18,9)的數(shù)據(jù)幀和與之對應(yīng)的15個(gè)label。
訓(xùn)練集中共包含240天的數(shù)據(jù),因此共可獲得240X15=3600個(gè)數(shù)據(jù)幀和與之對應(yīng)的3600個(gè)label
# 數(shù)據(jù)預(yù)處理 def dataProcess(df):x_list, y_list = [], []# df替換指定元素,將空數(shù)據(jù)填充為0df = df.replace(['NR'], [0.0])array = np.array(df).astype(float)#astype就是轉(zhuǎn)換numpy數(shù)組的數(shù)據(jù)類型為float型# 將數(shù)據(jù)集拆分為多個(gè)數(shù)據(jù)幀for i in range(0, 4320, 18):for j in range(24 - 9):mat = array[i:i + 18, j:j + 9]label = array[i + 9, j + 9] # 第10行是PM2.5x_list.append(mat)y_list.append(label)x = np.array(x_list)y = np.array(y_list)return x, y, array x.shape:(3600,18,9) y.shape:(3600,)2.2 模型建立
2.2.1 回歸模型
采用最普通的線性回歸模型,并沒有用上訓(xùn)練集中所有的數(shù)據(jù),只用到了每個(gè)數(shù)據(jù)幀樣本中的9個(gè)PM2.5含量值:
y=∑i=08wixi+by=\sum_{i=0}^{8} w_{i} x_{i}+b y=i=0∑8?wi?xi?+b
xix_{i}xi?為對應(yīng)數(shù)據(jù)幀中第i個(gè)PM2.5含量,wiw_{i}wi?為其對應(yīng)的權(quán)重值,bbb為偏置項(xiàng),yyy為該數(shù)據(jù)幀樣本的預(yù)測結(jié)果。
2.2.2 損失函數(shù)
用預(yù)測值與label之間的平均歐式距離來衡量預(yù)測的準(zhǔn)確程度,并充當(dāng)損失函數(shù)(這里的損失指的是平均損失;乘1/2是為了在后續(xù)求梯度過程中保證梯度項(xiàng)系數(shù)為1,方便計(jì)算):
Loss?hocl?=12num?∑n=0num?1(y^n?yn)2\operatorname{Loss}_{\text {hocl }}=\frac{1}{2 \text { num }} \sum_{n=0}^{ { num }-1}\left(\hat{y}^{n}-y^{n}\right)^{2} Losshocl??=2?num?1?n=0∑num?1?(y^?n?yn)2
y^n\hat{y}^{n}y^?n為第n個(gè)label,yny^{n}yn為第n個(gè)數(shù)據(jù)幀的預(yù)測結(jié)果,numnumnum為參加訓(xùn)練的數(shù)據(jù)幀樣本個(gè)數(shù)。
為了防止過擬合,加入正則項(xiàng):
Loss?regularization=12∑i=08wi2\operatorname{Loss}_{\text {regularization}}=\frac{1}{2} \sum_{i=0}^{8} w_{i}^{2} Lossregularization?=21?i=0∑8?wi2?
Loss?=Losslabel?+β?Lossregularization?=12[1mum?∑n=0num?1(y^n?yn)2+β∑i=08wi2]\text {Loss }=L o s s_{\text {label }}+\beta \cdot L o s s_{\text {regularization }}=\frac{1}{2}\left[\frac{1}{\operatorname{mum}} \sum_{n=0}^{n u m-1}\left(\hat{y}^{n}-y^{n}\right)^{2}+\beta \sum_{i=0}^{8} w_{i}^{2}\right] Loss?=Losslabel??+β?Lossregularization??=21?[mum1?n=0∑num?1?(y^?n?yn)2+βi=0∑8?wi2?]
β\betaβ為正則項(xiàng)系數(shù)。
2.2.3 梯度更新
梯度計(jì)算:需明確此時(shí)的目標(biāo)是使Loss最小,而可優(yōu)化的參數(shù)為權(quán)重w和偏置值b,因此需要求Loss在w上的偏微分和Loss在b上的偏微分。
?Loss?wi=?Losslabel??y?y?wi+?Lossregularization?wi=1mum∑n=0num?1(y^n?∑i=08wixi?b)?(?xi)+β?∑i=08wi?Loss?b=?Losslabel??y?y?b+?Lossregularization?b=1mum∑n=0num?1(y^n?∑i=08wixi?b)?(?1)\begin{array}{l}{\frac{\partial L o s s}{\partial w_{i}}=\frac{\partial L o s s_{\text {label }}}{\partial y} \frac{\partial y}{\partial w_{i}}+\frac{\partial L o ss_{\text {regularization}}}{\partial w_{i}}=\frac{1}{{mum}} \sum_{n=0}^{num-1}\left(\hat{y}^{n}-\sum_{i=0}^{8} w_{i} x_{i}-b\right) \cdot\left(-x_{i}\right)+\beta \cdot \sum_{i=0}^{8} w_{i}} \\ {\frac{\partial L o s s}{\partial b}=\frac{\partial L o s s_{\text {label }}}{\partial y} \frac{\partial y}{\partial b}+\frac{\partial L o ss_{\text {regularization}}}{\partial b}=\frac{1}{m u m} \sum_{n=0}^{num-1}\left(\hat{y}^{n}-\sum_{i=0}^{8} w_{i} x_{i}-b\right) \cdot(-1)}\end{array} ?wi??Loss?=?y?Losslabel????wi??y?+?wi??Lossregularization??=mum1?∑n=0num?1?(y^?n?∑i=08?wi?xi??b)?(?xi?)+β?∑i=08?wi??b?Loss?=?y?Losslabel????b?y?+?b?Lossregularization??=mum1?∑n=0num?1?(y^?n?∑i=08?wi?xi??b)?(?1)?
計(jì)算出梯度后,通過梯度下降法實(shí)現(xiàn)參數(shù)更新。
wnewi=wi?ηw?Loss?wi,bnew=b?ηb?Loss?bw_{n e w i}=w_{i}-\eta_{w} \frac{\partial L o ss}{\partial w_{i}}, b_{n e w}=b-\eta_{b} \frac{\partial L o s s}{\partial b} wnewi?=wi??ηw??wi??Loss?,bnew?=b?ηb??b?Loss?
ηw\eta_{w}ηw?為權(quán)重w更新時(shí)的學(xué)習(xí)率,ηb\eta_{b}ηb?為偏置b更新時(shí)的學(xué)習(xí)率。
2.2.3 學(xué)習(xí)率更新
為了在不影響模型效果的前提下提高學(xué)習(xí)速度,可以對學(xué)習(xí)率進(jìn)行實(shí)時(shí)更新:即讓學(xué)習(xí)率的值在學(xué)習(xí)初期較大,之后逐漸減小。這里采用比較經(jīng)典的adagrad算法來更新學(xué)習(xí)率。
ηn=ηn?1∑i=1n?1gradi2\eta_{n}=\frac{\eta_{n-1}}{\sqrt{\sum_{i=1}^{n-1} g r a d_{i}^{2}}} ηn?=∑i=1n?1?gradi2??ηn?1??
ηn\eta_{n}ηn?為更新后的學(xué)習(xí)率,ηn?1\eta_{n-1}ηn?1?為更新前的學(xué)習(xí)率。∑i=1n?1gradi2\sqrt{\sum_{i=1}^{n-1} g r a d_{i}^{2}}∑i=1n?1?gradi2??為在此之前所有梯度平方和的二次根。
3.完整代碼與結(jié)果分析
3.1 testPM2.5.py
import pandas as pd import numpy as np# 數(shù)據(jù)預(yù)處理 def dataProcess(df):x_list, y_list = [], []# df替換指定元素,將空數(shù)據(jù)填充為0df = df.replace(['NR'], [0.0])array = np.array(df).astype(float)#astype就是轉(zhuǎn)換numpy數(shù)組的數(shù)據(jù)類型為float型# 將數(shù)據(jù)集拆分為多個(gè)數(shù)據(jù)幀for i in range(0, 4320, 18):for j in range(24 - 9):mat = array[i:i + 18, j:j + 9]label = array[i + 9, j + 9] # 第10行是PM2.5x_list.append(mat)y_list.append(label)x = np.array(x_list)y = np.array(y_list)return x, y, array# 更新參數(shù),訓(xùn)練模型 def train(x_train, y_train, epoch):bias = 0 # 偏置值初始化weights = np.ones(9) # 權(quán)重初始化learning_rate = 1 # 初始學(xué)習(xí)率reg_rate = 0.001 # 正則項(xiàng)系數(shù)bg2_sum = 0 # 用于存放偏置值的梯度平方和wg2_sum = np.zeros(9) # 用于存放權(quán)重的梯度平方和for i in range(epoch):b_g = 0w_g = np.zeros(9)# 在所有數(shù)據(jù)上計(jì)算Loss_label的梯度#Loss在w上的偏微分和Loss在b上的偏微分#參加訓(xùn)練的數(shù)據(jù)幀樣本個(gè)數(shù)num采用了3200,0~3200是訓(xùn)練集,3200~3600是驗(yàn)證集for j in range(3200):b_g += (y_train[j] - weights.dot(x_train[j, 9, :]) - bias) * (-1)for k in range(9):w_g[k] += (y_train[j] - weights.dot(x_train[j, 9, :]) - bias) * (-x_train[j, 9, k])# 求平均,除以numb_g /= 3200w_g /= 3200# 加上Loss_regularization在w上的梯度for m in range(9):w_g[m] += reg_rate * weights[m]# adagrad,相當(dāng)于grad**2的加權(quán)和,adagrad算法來更新學(xué)習(xí)率bg2_sum += b_g ** 2wg2_sum += w_g ** 2# 更新權(quán)重和偏置bias -= learning_rate / bg2_sum ** 0.5 * b_gweights -= learning_rate / wg2_sum ** 0.5 * w_g# 每訓(xùn)練200輪,輸出一次在訓(xùn)練集上的損失if i % 200 == 0:loss = 0for j in range(3200):loss += (y_train[j] - weights.dot(x_train[j, 9, :]) - bias) ** 2print('after {} epochs, the loss on train data is:'.format(i), loss / 3200)return weights, bias# 驗(yàn)證模型效果 #驗(yàn)證集3400~3600 def validate(x_val, y_val, weights, bias):loss = 0for i in range(400):loss += (y_val[i] - weights.dot(x_val[i, 9, :]) - bias) ** 2return loss / 400def main():# 從csv中讀取有用的信息# 由于大家獲取數(shù)據(jù)集的渠道不同,所以數(shù)可據(jù)集的編碼格式能不同# 若讀取失敗,可在參數(shù)欄中加入encoding = 'gb18030'df = pd.read_csv('train.csv', usecols=range(3, 27))x, y, _ = dataProcess(df)# 劃分訓(xùn)練集與驗(yàn)證集x_train, y_train = x[0:3200], y[0:3200]x_val, y_val = x[3200:3600], y[3200:3600]epoch = 2000 # 訓(xùn)練輪數(shù)# 開始訓(xùn)練w, b = train(x_train, y_train, epoch)# 在驗(yàn)證集上看效果loss = validate(x_val, y_val, w, b)print('The loss on val data is:', loss)if __name__ == '__main__':main()3.2 結(jié)果顯示
after 0 epochs, the loss on train data is: 955.3009375 after 200 epochs, the loss on train data is: 49.86823677027294 after 400 epochs, the loss on train data is: 46.20101423801224 after 600 epochs, the loss on train data is: 44.88913061600439 after 800 epochs, the loss on train data is: 44.26903588227097 after 1000 epochs, the loss on train data is: 43.950109190566856 after 1200 epochs, the loss on train data is: 43.78092633274224 after 1400 epochs, the loss on train data is: 43.68982565130423 after 1600 epochs, the loss on train data is: 43.640314303297686 after 1800 epochs, the loss on train data is: 43.61322589236443 The loss on val data is: 40.35422383809947可以看出,模型在驗(yàn)證集上的損失為40左右,即預(yù)測值與label之間的平均差異在6到7之間,由此可見,模型的整體效果還是比較差的。
總結(jié)
以上是生活随笔為你收集整理的李宏毅机器学习作业1:预测PM2.5(含训练数据)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【ML】 李宏毅机器学习一:Regres
- 下一篇: 【ML】 李宏毅机器学习一:error