作业笔记被我手贱删了, 只能凭回忆重新总结个简洁版本的
我用的是kaggle提供的在线notebook, 代码与部分思路公开在:
https://www.kaggle.com/laugoon/homework1( 第一行注释中注明报告题目的cell, 在预测时无需运行 )
不方便用kaggle也可以在CSDN下载源码:
https://download.csdn.net/download/lagoon_lala/16721800
其他好用的在线notebook还有:
deepnote( 比colab多一些协作编程等功能 ):
http://deepnote.com
colab(需要能上谷歌), 这是台大给出的作业范例:
https://colab.research.google.com/drive/131sSqmrmWXfjFZ3jWSELl8cm0Ox5ah3C
目录
数据说明
PM2.5预测
本次作業使用豐原站的觀測記錄
train.csv: 每個月前 20 天的完整資料。
test.csv : 從剩下的資料當中取樣出連續的 10 小時為一筆,前九小時的所有觀測數據當作 feature,第十小時的 PM2.5 當作 answer。一共取出 240 筆不重複的 test data,請根據 feature 預測這 240 筆的 PM2.5。
Data 含有 18 項觀測數據 AMB_TEMP, CH4, CO, NHMC, NO, NO2, NOx, O3, PM10, PM2.5, RAINFALL, RH, SO2, THC, WD_HR, WIND_DIREC, WIND_SPEED, WS_HR。
kaggle要求
Link: https://www.kaggle.com/c/ml2020spring-hw1
預測 240 筆 testing data 中的 PM2.5 值,並將預測結果上傳至 Kaggle
Upload format : csv file( kaggle上会有提交样例 )
第一行必須是 id,value
第二行開始,每行分別為 id 值及預測 PM2.5 數值,以逗號隔開。
作 linear regression,方法限使用 gradient descent。
禁止使用 numpy.linalg.lstsq
预测思路
我的代码https://www.kaggle.com/laugoon/homework1
其中初次预测部分主要参考作业范例:
https://colab.research.google.com/drive/131sSqmrmWXfjFZ3jWSELl8cm0Ox5ah3C
补充一些作业范例中的思路图片:
特征提取:
原数据每18行为1个月, 放到横向
每10h为一笔资料( 其中前9h为输入, 第10h为输出 ), 把输入输出分别保存
线性回归实现, 梯度下降算法
对测试集的输入预处理
相關 reference 可以參考:
Adagrad:
https://youtu.be/yKKNr-QKz2Q?list=PLJV_el3uVTsPy9oCRY30oBPNLCo89yu49&t=705
对应李宏毅该系列视频的梯度下降
RMSprop :
https://www.youtube.com/watch?v=5Yt-obwvMHI
对应B站吴恩达:
https://www.bilibili.com/video/BV1V441127zE?p=21&t=1
Adam:
https://www.youtube.com/watch?v=JXQT_vxqwIs
对应B站吴恩达:
https://www.bilibili.com/video/BV1V441127zE?p=22
可以藉由調整 learning rate、iter_time (iteration 次數)、取用 features 的多寡(取幾個小時,取哪些特徵欄位),甚至是不同的 model 來超越 baseline。
Report 的問題模板請參照 :
https://docs.google.com/document/d/1s84RXs2AEgZr54WCK9IgZrfTF-6B1td-AlKR9oqYa4g/edit
报告题
備註 :
a. 1~3題的回答中,NR 請皆設為 0,其他的數值不要做任何更動。
b. 可以使用所有 advanced 的 gradient descent 技術(如 Adam、Adagrad)。
c. 1~3題請用linear regression的方法進行討論作答。
1. 不同学习率收敛情况
1. (2%) 使用四種不同的 learning rate 進行 training (其他參數需一致),作圖並討論其收斂過程(橫軸為 iteration 次數,縱軸為 loss 的大小,四種 learning rate 的收斂線請以不同顏色呈現在一張圖裡做比較)。
关于matplotlib, 太久没用, 重点补了一下这次用到的, 可以看博客旁边一篇"作图笔记"
全部数据直接生成出来, 第一次长这样
观察数据之后, 发现是前几个点太大了, 导致后面看起来像长尾, 考虑缩小y轴显示范围. 最终显示结果:
在其他参数不变的情况下, 学习率为2左右收敛情况最好, 学习率小于1后 收敛速度反而显著变慢
2. 减少feature (只取后5h)
2. (1%) 比較取前 5 hrs 和前 9 hrs 的資料(5*18 + 1 v.s 9*18 + 1)在 validation set 上預測的結果,並說明造成的可能原因(1. 因為 testing set 預測結果要上傳 Kaggle 後才能得知,所以在報告中並不要求同學們呈現 testing set 的結果,至於什麼是 validation set 請參考:https://youtu.be/D_S6y0Jm6dQ?t=1949 2. 9hr:取前9小時預測第10小時的PM2.5;5hr:在前面的那些features中,以5~9hr預測第10小時的PM2.5。這樣兩者在相同的validation set比例下,會有一樣筆數的資料)。
预测时原本用的是全部训练集, 本题要求使用划分训练/验证集后的数据.
划分后训练时, 拼接常数项参数的矩阵形状, 标准差计算时的总个数都要改变.
此外, 还要提取后5小时的属性作为训练, 测试集的输入. 要进行提取, 首先要明白处理后的x形状.
x [12 * 471, 18 * 9], y [12 * 471, 1]
行数的含义为一年12mon*每月471笔数据
列数的含义为每笔数据含10h, 其中9h在x, 1h在y.
np多维数组分片时不用加iloc, dataframe需要.
在训练出验证集的y后需要考虑如何衡量预测结果, 看到老师在上课时用的是平均误差, 所以决定用这个. ( 也看过一些同学用loss )
最后平均误差结果: 9h的3.5+ 5h的3.4+
可能的原因为. 前4h对第10h的PM2.5影响不大,甚至有点过拟合.
3. 减少feature (只取PM2.5)
3. (1%) 比較只取前 9 hrs 的 PM2.5 和取所有前 9 hrs 的 features(9*1 + 1 vs. 9*18 + 1)在 validation set上預測的結果,並說明造成的可能原因。
9*18 + 1的部分仍可用上题预测出的结果
9*1 + 1
需要找到PM2.5的那部分
开始看原始数据读入时每把表头算入, 而且从0开始计, 所以是第9行.
只取第9行会报错
all the input arrays must have same number of dimensions, but the array at index 0 has 2 dimension(s) and the array at index 1 has 1 dimension(s) |
单独一行, 外面没套那一层, 所以退化成一维数组了
然后想起来训练数据集是处理过的, 已经不是这个形状了
x [12 * 471, 18 * 9], y [12 * 471, 1]
每笔数据的PM2.5应该在第9列, 18+9列…以此类推
循环提取, 整列赋值参考:
https://blog.csdn.net/PJCKR/article/details/95453642
赋值是没问题的, 最后找到问题在于定义数组形状的时候没*0.8(这是划分训练集, 验证集后的大小)
碰到这样的报错:
shapes (4521,11) and (10,1) not aligned: 11 (dim 1) != 10 (dim 0) |
那一般是加常数参数项的单元格被多次执行了, 9*1+1变成了9*1+2
最后得到平均误差结果:
所有属性: 4.63735404055456
只看PM2.5: 12.194386766277699
可能原因: 其他属性中有些对PM2.5的起关键作用.
4. 调整改进
4. (2%) 請說明你超越 baseline 的 model(最後選擇在Kaggle上提交的) 是如何實作的(例如:怎麼進行 feature selection, 有沒有做 pre-processing、learning rate 的調整、advanced gradient descent 技術、不同的 model 等等)。
根据验证集预测的结果, learning rate=2, 取后5h的效果比较好, 其他属性中有重要的, 但是要去除不重要属性还是需要分析. 属性太多画图是不方便了, 一会看看哪个w比较大.
w依次对应x的一行(一笔数据), x[12 * 471, 18 * 5]
x的每一行是h5的18个属性, … h9的18个属性
5h训练得到的w:
AMB_TEMP | -1.61E-01 | 2.81E-02 | -5.09E-01 | -3.30E-02 | -2.09E-01 |
CH4 | 2.09E-01 | -8.12E-03 | 4.11E-01 | 3.04E-01 | -1.52E-01 |
CO | 9.15E-02 | -1.23E-01 | -5.95E-02 | -4.90E-02 | 2.51E-01 |
NMHC | 1.07E-01 | 1.56E-03 | -1.74E-01 | 2.48E-01 | 9.93E-02 |
NO | -4.19E-01 | -8.53E-02 | 3.30E-02 | 7.38E-02 | -1.68E-01 |
NO2 | 8.84E-02 | 1.16E-01 | 1.31E-01 | 1.48E-01 | -1.62E-01 |
NOx | 1.32E-01 | 7.35E-02 | -3.92E-01 | -2.42E-01 | -5.54E-02 |
O3 | -4.32E-01 | -1.05E-02 | 1.53E-01 | 1.33E-01 | -1.02E-01 |
PM10 | 1.82E+00 | -1.27E-01 | 7.70E-01 | 4.35E-02 | -1.21E-02 |
PM2.5 | -2.68E-01 | 1.73E-02 | -2.25E-04 | -1.95E-01 | -6.87E-02 |
RAINFALL | 4.22E-01 | 3.12E-01 | -1.59E-01 | -1.16E-01 | 2.97E-01 |
RH | 1.41E+00 | 1.29E-01 | 2.94E-02 | 2.69E-02 | -1.51E-01 |
SO2 | -2.19E+00 | -9.66E-02 | -2.72E-01 | -2.54E-01 | -3.07E-01 |
THC | 4.15E-01 | -1.69E-01 | 1.62E-01 | 4.98E-02 | -5.67E-02 |
WD_HR | 5.29E+00 | 6.34E-01 | 6.48E-02 | 2.88E-02 | 3.79E-01 |
WIND_DIREC | -7.38E+00 | -8.56E-01 | -3.10E-02 | -2.59E-03 | -1.94E-02 |
WIND_SPEED | 7.51E-01 | 4.28E-02 | -6.34E-02 | -1.90E-01 | -2.53E-01 |
WS_HR | 1.52E+01 | -5.54E-01 | 7.75E-01 | 1.03E-01 | 9.33E-02 |
常数 | 2.14E+01 |
取绝对值, 每h分别排序, w最小的feature分别为
第一次 | 第二次 | 第三次 | 第四次 | 第五次 |
NMHC(2) | O3 | WIND_DIREC(3) | WD_HR | NOx |
CO | CH4 | RH(2) | RH | WIND_DIREC |
NO2 | NMHC | PM2.5 | WIND_DIREC | PM10 |
有点奇怪. w由时间前到后越来越小, 但最后一笔数据最靠近预测日期, 应该影响更大啊.
而且没有固定的某个属性对PM2.5影响很小, 决定不对属性动手了
用后5h的数据训练, 虽然验证集误差稍小, 但测试集得分很低
比较下loss, 是5.861416265758481, 相差不大, 比原来好些, 原来loss收敛到貌似7+
loss没有问题, 但输出就是很离谱, 可能测试集的输入处理有问题
#测试集输入数据标准化结果有问题 for i in range(len(test_x_5h)): for j in range(len(test_x_5h[0])): if std_x[j] != 0: test_x_5h[i][j] = (test_x_5h[i][j] - mean_x[j]) / std_x[j] test_x_5h = np.concatenate((np.ones([240, 1]), test_x_5h), axis = 1).astype(float) |
此处输出不太对, 考虑是std, mean不合适. 训练集是先标准化再取后5h
训练集标准化时用的是:
mean_x = np.mean(x, axis = 0) #18 * 9 std_x = np.std(x, axis = 0) #18 * 9 标准差 |
重新标准化后得分好很多, 没那么离谱了: 9.24833
说明重新标准化是有必要的, 但很奇怪之前作业范例中, 测试集的标准差和均值用的是训练集生成的.
试了试完整数据集预测时重新标准化, 效果不如5h( 和5h相似, 9.5 ), 也不如第一次.
担心是其他环节影响了数据, 控制变量, 只把std, mean换回来. 还真的没问题.
说明使用完整训练集预测时, 在测试集中, 输入数据的标准化时, 使用训练集的期望标准差, 结果好很多. 使用9h而非5h的训练集结果好很多.
就只剩下修改学习率了, 学习率根据第一问的最佳结果改成了1, 居然分数迅速变好, 5.57977
真是哭笑不得, 太菜了用了那么多馊主意改模型, 最后还不如调参数.