機(jī)器學(xué)習(xí)(李宏毅)作業(yè)1-利用regression預(yù)測豐原站pm2.5值

最近開始學(xué)習(xí)機(jī)器學(xué)習(xí),聽同學(xué)介紹,選擇了臺大李宏毅老師的視頻,https://www.bilibili.com/video/BV1JE411g7XF
老師布置了很多作業(yè),這里記錄下自己寫作業(yè)的過程和一些參考資料
本篇是作業(yè)一缓呛,根據(jù)豐源站歷史的空氣數(shù)據(jù),預(yù)測下一小時(shí)的pm2.5的值杭隙。
本次作業(yè)說明視頻參見 https://www.bilibili.com/video/BV1gE411F7td

import numpy as np
import pandas as pd

本次作業(yè)要求只用numpy,pandas手寫線性回歸哟绊,所以只導(dǎo)入pandas和numpy兩個(gè)包,
學(xué)習(xí)這兩個(gè)包推薦一個(gè)gitbook痰憎, 利用python進(jìn)行數(shù)據(jù)分析
另外這本書有本實(shí)體版的票髓,是另外一個(gè)人翻譯的,翻譯的非常差铣耘,非常不建議購買洽沟,看這個(gè)gitbook版的就好。
本次作業(yè)代碼參考 https://zhuanlan.zhihu.com/p/115335196
上面知乎專欄的大佬寫的比較簡單蜗细,我添加了更多的細(xì)節(jié)裆操,便于新人理解。

data = pd.read_csv('data/train.csv', encoding='big5')

首先使用pandas讀取訓(xùn)練文件鳄乏,并做一些預(yù)處理跷车,李宏毅老師是灣灣人棘利,
用的是繁體橱野,所以要指定下編碼為big5,否則里面的中文為亂碼善玫。
看一下文件的結(jié)構(gòu)水援,有27列,第一列為日期茅郎,第三列為檢測項(xiàng)蜗元,后面的是0-23點(diǎn)每一點(diǎn)的數(shù)值。
然后每天有18行系冗,即18個(gè)檢測項(xiàng)奕扣,其中第10行是pm2.5。
一共12月*20天*18項(xiàng)=4320行

data.head(20)


然后前三項(xiàng)是沒用的掌敬,我們用切片去掉惯豆。shape就變?yōu)榱?320*24
數(shù)據(jù)中還有很多是NR,我們替換為0奔害。
接下來就是numpy的處理范圍了楷兽,使用to_numpy轉(zhuǎn)換為矩陣。

data = data.iloc[:,3:]
data.replace('NR',0,inplace=True)
row_data = data.to_numpy()
row_data



參考上圖华临,我們需要把數(shù)據(jù)shape做一個(gè)轉(zhuǎn)換芯杀,把240天內(nèi)相同的測量項(xiàng)放在同一行。
也就是從(12月*20天*18項(xiàng)),24小時(shí)變?yōu)?18項(xiàng),(24小時(shí)*20天),12月
下面的兩個(gè)循環(huán)就是在做轉(zhuǎn)換,每個(gè)月的數(shù)據(jù)寫在以月份為鍵名的字典里的揭厚。

month_data={}
for month in range(12):
    sample = np.empty([18, 480])
    for day in range(20):
        sample[:,day*24:(day+1)*24] = row_data[18*(month*20+day):18*(month*20+(day+1)),:]
    month_data[month] = sample

然后我們以10小時(shí)為一個(gè)data却特,把前9個(gè)小時(shí)的data作訓(xùn)練,第10個(gè)小時(shí)的值為target筛圆。
即0-9點(diǎn)的data來預(yù)測10點(diǎn)的pm2.5核偿,第1-10點(diǎn)的和data來預(yù)測11點(diǎn)的pm2.5
最后一筆是471-479來預(yù)測480的pm2.5,所以一共有471筆data
shape從\color{red}{(18*5760)}變?yōu)?img class="math-inline" src="https://math.jianshu.com/math?formula=%5Ccolor%7Bred%7D%7B(12%E6%9C%88*471%E7%AC%94)%2C(18%E9%A1%B9*9%E5%B0%8F%E6%97%B6)%7D" alt="\color{red}{(12月*471筆),(18項(xiàng)*9小時(shí))}" mathimg="1">
y就是第10個(gè)小時(shí)的pm2.5的值顽染,shape為\color{red}{12*471,1}

x = np.empty([12 * 471, 18 * 9], dtype = float)
y = np.empty([12 * 471, 1], dtype = float)
for month in range(12):
    for day in range(20):
        for hour in range(24):
            if day == 19 and hour > 14:
                continue
            x[month * 471 + day * 24 + hour, :] = \
                month_data[month][:,day * 24 + hour : day * 24 + hour + 9].reshape(1, -1)
            y[month * 471 + day * 24 + hour, 0] = month_data[month][9, day * 24 + hour + 9]
x



接下來做Normalize漾岳,教學(xué)視頻里說明了為什么要做Normalize,不知道的請復(fù)習(xí)視頻
按照上面的公式粉寞,需要求平均值和標(biāo)準(zhǔn)差尼荆,然后x處理對應(yīng)位置的值

mean_x = np.mean(x, axis = 0)
std_x = np.std(x, axis = 0) #18 * 9 
for i in range(len(x)): #12 * 471
    for j in range(len(x[0])): #18 * 9 
        if std_x[j] != 0:
            x[i][j] = (x[i][j] - mean_x[j]) / std_x[j]
x




接下來就是最重要的部分了,我們開始做梯度下降
我們有9小時(shí)*18項(xiàng)的變量唧垦,所以需要9*18個(gè)w值捅儒,還有一個(gè)bias:b
注意下面代碼的第三行,這里是整個(gè)矩陣前拼接了一列1值振亮,這一列在點(diǎn)乘后就是b
所以這就是為什么dim有18*9+1項(xiàng)

dim = 18 * 9 + 1
w = np.zeros([dim, 1])
x = np.concatenate((np.ones([12 * 471, 1]), x), axis = 1).astype(float)
learning_rate = 100
iter_time = 1000
adagrad = np.zeros([dim, 1])
eps = 0.0000000001

然后定義loss函數(shù)巧还,這里知乎作者用的是均方根誤差來做loss函數(shù)
貼一段百度百科的解釋:
均方根誤差是預(yù)測值與真實(shí)值偏差的平方與觀測次數(shù)n比值的平方根,
在實(shí)際測量中坊秸,觀測次數(shù)n總是有限的麸祷,真值只能用最可信賴(最佳)值來代替。
標(biāo)準(zhǔn)誤差對一組測量中的特大或特小誤差反映非常敏感褒搔,
所以阶牍,標(biāo)準(zhǔn)誤差能夠很好地反映出測量的精密度。
這正是標(biāo)準(zhǔn)誤差在工程測量中廣泛被采用的原因星瘾。
因此走孽,標(biāo)準(zhǔn)差是用來衡量一組數(shù)自身的離散程度,
而均方根誤差是用來衡量觀測值同真值之間的偏差琳状,
它們的研究對象和研究目的不同磕瓷,但是計(jì)算過程類似。
因?yàn)槌?shù)項(xiàng)的存在念逞,所以 dimension (dim) 需要多加一欄困食;
eps 項(xiàng)是避免 adagrad 的分母為 0 而加的極小數(shù)值。
rmse公式:


然后adagrid的公式:


這里對gt的計(jì)算我沒有看懂肮柜,根據(jù)公式應(yīng)該是loss對w的偏導(dǎo)陷舅,以后搞懂了再來補(bǔ)說明吧
adagrid這一行就是上面的累計(jì)求和
然后對w做更新,這樣就可以實(shí)現(xiàn)梯度下降了
最后保存計(jì)算出的w矩陣

for t in range(iter_time):
    loss = np.sqrt(np.sum(np.power(np.dot(x, w) - y, 2))/471/12) #rmse
    if(t%100==0):
        print(str(t) + ":" + str(loss))
    gradient = 2 * np.dot(x.transpose(), np.dot(x, w) - y) #dim*1
    adagrad += gradient ** 2
    w = w - learning_rate * gradient / np.sqrt(adagrad + eps)
np.save('weight.npy', w)


這樣我們的w和b就計(jì)算完了审洞,接下來拿測試集做測試
還是和train.csv一樣先做預(yù)處理和Normalize莱睁,然后用w和測試集做點(diǎn)乘就可以得到預(yù)測值了
記得在拼接1列1作為b

testdata = pd.read_csv('./data/test.csv', header = None, encoding = 'big5')
test_data = testdata.iloc[:, 2:].copy()
test_data.replace('NR', 0, inplace=True)
test_data = test_data.to_numpy()
test_x = np.empty([240, 18*9], dtype = float)
for i in range(240):
    test_x[i, :] = test_data[18 * i: 18* (i + 1), :].reshape(1, -1)
for i in range(len(test_x)):
    for j in range(len(test_x[0])):
        if std_x[j] != 0:
            test_x[i][j] = (test_x[i][j] - mean_x[j]) / std_x[j]
test_x = np.concatenate((np.ones([240, 1]), test_x), axis = 1).astype(float)
w = np.load('weight.npy')
ans_y = np.dot(test_x, w)
ans_y[:10]


ans_y就是預(yù)測值了待讳,然后按照作業(yè)要求寫成csv文件。
這里轉(zhuǎn)回pandas處理仰剿,因?yàn)閜andas的to_csv方法很好用

res = pd.DataFrame(ans_y)
res['id'] = ['id_' + str(x) for x in res.index]
res.rename(columns={0:'value'}, inplace=True)
res=res[['id', 'value']]  # 調(diào)換順序
res.to_csv('submit.csv', index=False)

最后创淡,可以調(diào)整 learning rate、iter_time (iteration 次數(shù))南吮、
取用 features 的多少(取幾個(gè)小時(shí)琳彩,取哪些特征)
甚至是不同的 model 來超越 baseline。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末部凑,一起剝皮案震驚了整個(gè)濱河市露乏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涂邀,老刑警劉巖瘟仿,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異比勉,居然都是意外死亡劳较,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門浩聋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來观蜗,“玉大人,你說我怎么就攤上這事衣洁∧鼓恚” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵闸与,是天一觀的道長毙替。 經(jīng)常有香客問我岸售,道長践樱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任凸丸,我火速辦了婚禮拷邢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屎慢。我一直安慰自己瞭稼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布腻惠。 她就那樣靜靜地躺著环肘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪集灌。 梳的紋絲不亂的頭發(fā)上悔雹,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼腌零。 笑死梯找,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的益涧。 我是一名探鬼主播锈锤,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闲询!你這毒婦竟也來了久免?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤扭弧,失蹤者是張志新(化名)和其女友劉穎妄壶,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寄狼,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丁寄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泊愧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伊磺。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖删咱,靈堂內(nèi)的尸體忽然破棺而出屑埋,到底是詐尸還是另有隱情,我是刑警寧澤痰滋,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布摘能,位于F島的核電站,受9級特大地震影響敲街,放射性物質(zhì)發(fā)生泄漏团搞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一多艇、第九天 我趴在偏房一處隱蔽的房頂上張望逻恐。 院中可真熱鬧,春花似錦峻黍、人聲如沸复隆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至人灼,卻和暖如春骨饿,著一層夾襖步出監(jiān)牢的瞬間亏栈,已是汗流浹背洪鸭。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仑扑,地道東北人览爵。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像镇饮,于是被迫代替她去往敵國和親蜓竹。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容