机器学习-回归
前言
此次学习的课程为李宏毅机器学习,之前学过一遍吴恩达的课程,只可惜当时没记笔记,且近些时候没有写代码,逐渐疏忽了,故选择李宏毅再进行新一遍的学习,所谓温故而知新。
回归是我们通常会使用的机器学习中的一类,比如日常中的我们的身高预测,股票预测等等,这些都可以看作为粗略的回归。
举一个例子
小时候我们会玩一个叫赛尔号的游戏,游戏里有各种各样的精力,就好比我们捕捉到了一只雷伊,然后我们可以向雷伊投经验值,让他升级,这只雷伊会有一个攻击力,我们想要预测雷伊的各种各样的属性与其攻击力之间的关系。
于是我们设其血量为\(X_{hp}\),其体重为\(x_{w}\),其身高为\(x_{h}\),其物种为\(x_s\),其战斗力为\(x_{cp}\),然后预测他进化之后的战斗力值。那么便有\(y=b+\sum w_ix_i\),其中\(w_i:weight,b:bias\)。如果单一个\(x_{cp}\)作预测的话便是\(y=b+w\cdot x_{cp}\)。
收集到了数据之后,便是可以进行预测,在此我们使用一个名为Loss函数进行Loss计算
\[ L(f) = \sum^{10}_{n=1}(\hat y^n-f(x^n_{cp}))^2\\ L(f) = \sum^{10}_{n=1}(\hat y^n-(b+w\cdot x^n_{cp}))^2 \]
我们想要的结果是需要 loss 函数尽可能的小,我们需要选择一个最好的函数,在此我们通过梯度下降来进行函数优化,进行如此迭代。
\[ w^1 = w^0-\alpha\frac{dL}{dw}|_{w=w^0}\\ w^2 = w^1-\alpha\frac{dL}{dw}|_{w=w^1} \]
对于我们有两个参数的函数来说,也是一样可以进行迭代
\[ w^1 = w^0-\alpha\frac{\partial L}{\partial w}|_{w=w^0,b=b^0},b^1 = b^0-\alpha\frac{\partial L}{\partial b}|_{w=w^0,b=b^0} \]
沿着梯度方向逐渐减小,直到让 loss 函数最小,偏微分公式如下
\[ \frac{\partial L}{\partial w}=\sum^{10}_{n=1}2(\hat y^n-(b+w\cdot x^n_{cp}))(-x^n_{cp}) \]
那么经过迭代之后便可以求得一个较为合适的\(w和b\),便是得到了方程。
实践
此次的实践为一项 PM.2.5 预测任务
- 数据使用丰原站的观测记录,分成 train set 跟 test set,train set 是丰原站每个月的前 20 天所有资料。test set 则是从丰原站剩下的资料中取样出来。
- 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。
1 | import sys |
1 | data = pd.read_csv('work/hw1_data/train.csv',encoding='big5') |
日期 | 測站 | 測項 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | ... | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2014/1/1 | 豐原 | AMB_TEMP | 14 | 14 | 14 | 13 | 12 | 12 | 12 | ... | 22 | 22 | 21 | 19 | 17 | 16 | 15 | 15 | 15 | 15 |
1 | 2014/1/1 | 豐原 | CH4 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | ... | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 |
2 | 2014/1/1 | 豐原 | CO | 0.51 | 0.41 | 0.39 | 0.37 | 0.35 | 0.3 | 0.37 | ... | 0.37 | 0.37 | 0.47 | 0.69 | 0.56 | 0.45 | 0.38 | 0.35 | 0.36 | 0.32 |
3 | 2014/1/1 | 豐原 | NMHC | 0.2 | 0.15 | 0.13 | 0.12 | 0.11 | 0.06 | 0.1 | ... | 0.1 | 0.13 | 0.14 | 0.23 | 0.18 | 0.12 | 0.1 | 0.09 | 0.1 | 0.08 |
4 | 2014/1/1 | 豐原 | NO | 0.9 | 0.6 | 0.5 | 1.7 | 1.8 | 1.5 | 1.9 | ... | 2.5 | 2.2 | 2.5 | 2.3 | 2.1 | 1.9 | 1.5 | 1.6 | 1.8 | 1.5 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
4315 | 2014/12/20 | 豐原 | THC | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.7 | 1.7 | ... | 1.8 | 1.8 | 2 | 2.1 | 2 | 1.9 | 1.9 | 1.9 | 2 | 2 |
4316 | 2014/12/20 | 豐原 | WD_HR | 46 | 13 | 61 | 44 | 55 | 68 | 66 | ... | 59 | 308 | 327 | 21 | 100 | 109 | 108 | 114 | 108 | 109 |
4317 | 2014/12/20 | 豐原 | WIND_DIREC | 36 | 55 | 72 | 327 | 74 | 52 | 59 | ... | 18 | 311 | 52 | 54 | 121 | 97 | 107 | 118 | 100 | 105 |
4318 | 2014/12/20 | 豐原 | WIND_SPEED | 1.9 | 2.4 | 1.9 | 2.8 | 2.3 | 1.9 | 2.1 | ... | 2.3 | 2.6 | 1.3 | 1 | 1.5 | 1 | 1.7 | 1.5 | 2 | 2 |
4319 | 2014/12/20 | 豐原 | WS_HR | 0.7 | 0.8 | 1.8 | 1 | 1.9 | 1.7 | 2.1 | ... | 1.3 | 1.7 | 0.7 | 0.4 | 1.1 | 1.4 | 1.3 | 1.6 | 1.8 | 2 |
4320 rows × 27 columns
1 | raw_data = data.iloc[:,3:] |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 14 | 14 | 14 | 13 | 12 | 12 | 12 | 12 | 15 | 17 | ... | 22 | 22 | 21 | 19 | 17 | 16 | 15 | 15 | 15 | 15 |
1 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | ... | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 |
2 | 0.51 | 0.41 | 0.39 | 0.37 | 0.35 | 0.3 | 0.37 | 0.47 | 0.78 | 0.74 | ... | 0.37 | 0.37 | 0.47 | 0.69 | 0.56 | 0.45 | 0.38 | 0.35 | 0.36 | 0.32 |
3 | 0.2 | 0.15 | 0.13 | 0.12 | 0.11 | 0.06 | 0.1 | 0.13 | 0.26 | 0.23 | ... | 0.1 | 0.13 | 0.14 | 0.23 | 0.18 | 0.12 | 0.1 | 0.09 | 0.1 | 0.08 |
4 | 0.9 | 0.6 | 0.5 | 1.7 | 1.8 | 1.5 | 1.9 | 2.2 | 6.6 | 7.9 | ... | 2.5 | 2.2 | 2.5 | 2.3 | 2.1 | 1.9 | 1.5 | 1.6 | 1.8 | 1.5 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
4315 | 1.8 | 1.8 | 1.8 | 1.8 | 1.8 | 1.7 | 1.7 | 1.8 | 1.8 | 1.8 | ... | 1.8 | 1.8 | 2 | 2.1 | 2 | 1.9 | 1.9 | 1.9 | 2 | 2 |
4316 | 46 | 13 | 61 | 44 | 55 | 68 | 66 | 70 | 66 | 85 | ... | 59 | 308 | 327 | 21 | 100 | 109 | 108 | 114 | 108 | 109 |
4317 | 36 | 55 | 72 | 327 | 74 | 52 | 59 | 83 | 106 | 105 | ... | 18 | 311 | 52 | 54 | 121 | 97 | 107 | 118 | 100 | 105 |
4318 | 1.9 | 2.4 | 1.9 | 2.8 | 2.3 | 1.9 | 2.1 | 3.7 | 2.8 | 3.8 | ... | 2.3 | 2.6 | 1.3 | 1 | 1.5 | 1 | 1.7 | 1.5 | 2 | 2 |
4319 | 0.7 | 0.8 | 1.8 | 1 | 1.9 | 1.7 | 2.1 | 2 | 2 | 1.7 | ... | 1.3 | 1.7 | 0.7 | 0.4 | 1.1 | 1.4 | 1.3 | 1.6 | 1.8 | 2 |
4320 rows × 24 columns
1 | mouth_data = {} |
根据题目描述,我们要根据前九个小时的数据去预测第十个小时的数据,所以我们需要将数据再次进行切分,每个前九个小时都是x,每个第十个小时都是y,每个月一共有480个小时,所以每个月 y 的数量为 480-9 =471 个,每个 y 对应 18*9 个特征
1 | x = np.empty([12*471,18*9],dtype=float) |
目前 x 为12 * 471 行, 18*9 列
目前 y 为12 * 471 行, 1 列
将 x 进行归一化
1 | mean_x = np.mean(x,axis=0) # 每一列的均值 |
1 | # 将数据集进行划分,训练集:测试集 = 4:1 |
4521 4521 1131 1131
使用梯度下降进行训练
1 | dim = 18 * 9 + 1 |
0:23.067503022281024
100:16.01469450959162
200:15.785217268902825
300:15.667044002058859
400:15.59344540214558
500:15.54253683834305
600:15.504902944004627
700:15.475801107300377
800:15.452554803514973
900:15.433523145338306
读取测试数据
1 | testdata = pd.read_csv('work/hw1_data/test.csv',header=None, encoding='big5') |
进行预测
1 | w = np.load('work/weight.npy') |
保存到 CSV 文件
1 | import csv |
如此便是完成了预测,并未找到对比的真实数据,等找到真实数据再去测试正确率