这个作业是关于线性回归的作业,其要求如下:
给定训练集train.csv,要求根据前9个小时的空气监测情况预测第10个小时的PM2.5含量。
训练集介绍:
(1)、CSV文件,包含台湾丰原地区240天的气象观测资料(取每个月前20天的数据做训练集,12月X20天=240天,每月后10天数据用于测试,对学生不可见);
(2)、每天的监测时间点为0时,1时......到23时,共24个时间节点;
(3)、每天的检测指标包括CO、NO、PM2.5、PM10等气体浓度,是否降雨、刮风等气象信息,共计18项;
首先,需要对数据进行预处理,由于在excel表格中,RAINFALL项目会有NR值,这不是一个整数,因此需要把它转化成0,此外excel表格的格式为big5,这一点需要注意以下
线性回归步骤如下:
1.选择一个模型,我选择的模型是线性模型
excel表格中每小时有18个特征项,每天有24个小时进行记录,因此每天的记录值为18*24项,但是题目是根据前9个小时预测第10个小时的PM2.5含量,因此我们只需要前10个小时的值。并且前9个小时的值被用作Xi
所以该模型具有18*9个特征项,也就具有18*9个Wi
2.设置损失函数
为什么要在前面乘以0.5呢?因为L具有平方项,如果进行求导数则会由2出现,2*0.5=1这样子就可以消去常数。
L分别对b和Wi求偏导
这个图是我盗别人的,哈哈哈哈。。。所以需要自己改下,把8改成18*9
接下来的任务就是更新W和b的值,更新方法如下(这个图也是盗用的......)
3.最后使用自适应的梯度下降算法
这样子就完成了整个训练流程,只需要完成最后一步:得到训练后的模型后对该模型进行测试
训练代码如下:
import numpy as np
import pandas as pd
# 数据处理
def DealData(filePath):
inputList = []
outputList = []
# 读取数据
trainData = pd.read_csv(filePath, encoding="big5")
# 删除测站列
trainData = trainData.drop(columns=['測站'])
trainData = trainData.replace(["NR"], '0')
days = sorted(set(trainData["日期"]))
for day in days:
dayData = trainData[trainData["日期"] == day]
inputData = sum(dayData.iloc[:, 2:11].astype(float).values.tolist(), [])
outputData = float(dayData.iloc[9, 11])
inputList.append(inputData)
outputList.append(outputData)
return inputList, outputList
# 对数据进行训练
def Train(inputList, outputList, trainCount):
# 设置偏差值和参数的权重 Y=W1X1....WnXn+bias
bias = 0
weights = np.ones(9*18)
# 设置学习率
learningRate = 1
# 设置正则项系数
regRate = 0.001
# 设置偏差值和权重的平方
biasPow = 0
weightsPow = np.zeros(9*18)
# 训练trainCount次
for i in range(trainCount):
# 损失函数对偏差值bias的偏导
b_g = 0
# 损失函数对权重的偏导
w_g = np.zeros(9*18)
for k in range(len(inputList)):
outputSuppose = float(weights.dot(inputList[k])+bias)
b_g += (-1)*(outputList[k] - outputSuppose)
for m in range(9*18):
w_g[m] += (outputList[k] - outputSuppose)*(-inputList[k][m])
b_g /= trainCount
w_g /= trainCount
for n in range(9*18):
w_g[n] += regRate * weights[n]
# adagrad
biasPow += b_g**2
weightsPow += w_g**2
# 更新权重和偏置
bias -= learningRate/biasPow**0.5 * b_g
weights -= learningRate/weightsPow**0.5 * w_g
if i % 200 == 0:
loss = 0
for j in range(len(inputList)):
loss += pow(outputList[j]-weights.dot(inputList[j])-bias, 2)
print("当前训练轮次:{0},损失函数:{1}".format(i, loss/len(inputList)))
return bias, weights
# 测试模型
def TestModel(bias, weights, testInputList, testOutput):
loss = 0
for i in range(len(testInputList)):
realOutput = testOutput[i]
outputSuppose = bias+weights.dot(testInputList[i])
var = pow((outputSuppose-realOutput), 2)
print("第{0}项预测值为{1},实际值为{2},方差为{3}".format(i, outputSuppose, realOutput, var))
loss += var
loss = loss/len(testInputList)
print("损失函数为{0}".format(loss))
pass
# 主程序函数
def main():
trainPath = "G:/机器学习/数据/hw1/train.csv"
inputList, outputList = DealData(trainPath)
trainInputList = inputList[0:200]
trainOutputList = outputList[0:200]
testInputList = inputList[200:]
testOutputList = outputList[200:]
trainCount = 4000
bias, weights = Train(trainInputList, trainOutputList, trainCount)
TestModel(bias, weights, testInputList, testOutputList)
pass
# 程序执行
if __name__ == '__main__':
main()
测试后得到的结果如下:
当前训练轮次:0,损失函数:684.3899999999957
当前训练轮次:200,损失函数:56.473359934458045
当前训练轮次:400,损失函数:45.33881919382273
当前训练轮次:600,损失函数:39.488325781453476
当前训练轮次:800,损失函数:35.72138372192509
当前训练轮次:1000,损失函数:33.0441540501544
当前训练轮次:1200,损失函数:31.022581763943364
当前训练轮次:1400,损失函数:29.430439131643695
当前训练轮次:1600,损失函数:28.1364394643143
当前训练轮次:1800,损失函数:27.05860648592519
当前训练轮次:2000,损失函数:26.142945874331875
当前训练轮次:2200,损失函数:25.352417398212104
当前训练轮次:2400,损失函数:24.660778290122344
当前训练轮次:2600,损失函数:24.04893173674829
当前训练轮次:2800,损失函数:23.502655271751813
当前训练轮次:3000,损失函数:23.011133804188486
当前训练轮次:3200,损失函数:22.565984138367618
当前训练轮次:3400,损失函数:22.160591049327444
当前训练轮次:3600,损失函数:21.789646709579955
当前训练轮次:3800,损失函数:21.44882593553877
第0项预测值为11.909631516110835,实际值为20.0,方差为65.45406220510706
第1项预测值为4.602955352355311,实际值为3.0,方差为2.569465861644539
第2项预测值为5.4557501727339766,实际值为8.0,方差为6.47320718354319
第3项预测值为5.387123641570756,实际值为1.0,方差为19.246853846429055
第4项预测值为-1.540062191641304,实际值为1.0,方差为6.451915937405625
第5项预测值为3.9624436659645657,实际值为7.0,方差为9.226748482438786
第6项预测值为9.9467200412393,实际值为6.0,方差为15.576599083919948
第7项预测值为8.939173678979122,实际值为15.0,方差为36.73361569357947
第8项预测值为12.38817785190848,实际值为22.0,方差为92.38712500654268
第9项预测值为11.92536843089255,实际值为18.0,方差为36.90114870039683
第10项预测值为6.021903193501299,实际值为5.0,方差为1.0442861368881542
第11项预测值为12.466206403583957,实际值为18.0,方差为30.622871567735203
第12项预测值为2.0375630369547473,实际值为14.0,方差为143.09989809483133
第13项预测值为20.390103560269754,实际值为24.0,方差为13.031352305577105
第14项预测值为7.512445048571662,实际值为12.0,方差为20.138149442088995
第15项预测值为7.5324707672260605,实际值为6.0,方差为2.3484666524024305
第16项预测值为13.710002579791938,实际值为11.0,方差为7.3441139824789605
第17项预测值为22.103521040370428,实际值为33.0,方差为118.73325371764997
第18项预测值为7.436302234120388,实际值为3.0,方差为19.68077751246155
第19项预测值为7.229633674162784,实际值为13.0,方差为33.29712753435609
第20项预测值为15.636336560302368,实际值为10.0,方差为31.76828982100113
第21项预测值为13.142288922885504,实际值为4.0,方差为83.58144674951498
第22项预测值为16.490073912721158,实际值为15.0,方差为2.220320265372141
第23项预测值为24.119061908180925,实际值为19.0,方差为26.20479481978893
第24项预测值为5.290761020144716,实际值为9.0,方差为13.758453809677869
第25项预测值为9.114654378861811,实际值为15.0,方差为34.63729308025046
第26项预测值为26.516070168463376,实际值为28.0,方差为2.202047744924314
第27项预测值为22.947627904320363,实际值为20.0,方差为8.688510262328057
第28项预测值为24.89476170611225,实际值为25.0,方差为0.011075098500404735
第29项预测值为26.542123395012194,实际值为19.0,方差为56.88362530559026
第30项预测值为30.05447374152368,实际值为37.0,方差为48.24033500718407
第31项预测值为22.83571732140236,实际值为27.0,方差为17.34125022726834
第32项预测值为47.312246813541506,实际值为39.0,方差为69.09344708923092
第33项预测值为23.527986474140697,实际值为21.0,方差为6.390715613438312
第34项预测值为14.273157336046825,实际值为18.0,方差为13.889356241861595
第35项预测值为15.891649151200326,实际值为15.0,方差为0.7950382088362621
第36项预测值为25.588011635858344,实际值为28.0,方差为5.817687868754744
第37项预测值为14.02102790455091,实际值为22.0,方差为63.66399569995523
第38项预测值为22.124489392589677,实际值为34.0,方差为141.0277521867151
第39项预测值为9.102401266080344,实际值为6.0,方差为9.624893615776921
损失函数为32.90503419158618
可以看到在训练集中的损失函数为21.4,在测试集中的损失函数为33。也就是说预测的值和实际的值相差5到6之间。比我借鉴的人好了1秒左右......但是损失函数依然很大。
目前我的想法为:
1.模型过于简单,只有一次项,可能多几项会好一些。
2.可能和季节有关系,比如说冬天的PM2.5可能会比夏天的高
写了一上午和一下午了,终于把这个项目大概搞完了,对于梯度下降算法还有很多不懂,还需要继续学习。
线性回归预测PM2.5----台大李宏毅机器学习作业1(HW1) - 秋沐霖 - 博客园 (cnblogs.com) 这个是我借鉴的博客,大家可以去看下