其他分享
首页 > 其他分享> > 李宏毅机器学习作业1_PM2.5预测

李宏毅机器学习作业1_PM2.5预测

作者:互联网

data及代码链接:
链接:https://pan.baidu.com/s/1BZvtDkuf3Mctzxs-NRA-VQ
提取码:0uje
复制这段内容后打开百度网盘手机App,操作更方便哦

课程链接:https://aistudio.baidu.com/aistudio/course/introduce/1978
项目描述:
本次作业的资料是从行政院环境环保署空气品质监测网所下载的观测资料。
希望大家能在本作业实现 linear regression 预测出 PM2.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。
项目要求:
请手动实现 linear regression,方法限使用 gradient descent。
禁止使用 numpy.linalg.lstsq

import pandas as pd
import numpy as np
import math

data = pd.read_csv('./train.csv', encoding='gb18030')
#print(data.head())#打印前5行

data = data.iloc[:, 3:]#iloc用来取行列数据,现取所有行和第4列开始取
data[data == 'NR'] = 0#数据为NR的值全变为0

#拼接数据
raw_data = data.to_numpy()#转成numpy数组进行拼接
month_data = {}
for month in range(12):#按月进行拼接,20天的每一天数据可以连起来,但每个月的首末时间连不起来
    sample = np.empty([18, 480])#相当于创建空数组装值,每天18种因素,一个月20天,一天24小时,每个月20*24=480
    for day in range(20):
        sample[:, day * 24: (day + 1) * 24] = raw_data[(day + month * 20) * 18:(day + 1 + month * 20) * 18, :]#填充数值
    month_data[month] = sample#因为sample存的是每个月的数据

#滑动窗口采样
x = np.empty([471 * 12, 18 * 9], dtype=float)#480-9=471,一天18个因素,用9天数据预测1天
y = np.empty([471 * 12, 1], dtype=float)
for month in range(12):
    for day in range(20):
        for hour in range(24):#此时的操作按小时进行,因为拼接后的数据连在一起了,昨天和今天的小时是连一起的
            if day == 19 and hour > 14:#24-9=15,超过20天进入下一个月
                continue
            x[month * 471 + day * 24 + hour, :] = month_data[month][:, day * 24 + hour: day * 24 + hour + 9].reshape(1, -1)#reshape(1, -1)可将【m,n】的矩阵拉成【1,m*n]的矩阵
            y[month * 471 + day * 24 + hour, 0] = month_data[month][9, day * 24 + hour + 9]#第10行才是PM2.5的值,第10天的值为预测值

#标准化,因为所有数据中有些值77,有些才0.04,不在一个量纲里,差得太大
#标准化就是用本身的值减去它的均值再除于它的标准差
mean_x = np.mean(x, axis=0)
std_x = np.std(x, axis=0)
for i in range(len(x)):
    for j in range(len(x[0])):
        if std_x[j] != 0:
            x[i][j] = (x[i][j] - mean_x[j]) / std_x[j]

#梯度下降法不同于线性回归,这种逼近的方法可能出现求得的结果不太好,所以需要一个验证集
#划分出验证集,前80%的数据作为训练集,后20%的数据作为验证集
x_train_set = x[:math.floor(len(x) * 0.8), :]#math.floor()为向下取整,45.95则为45,-45.95则为-46
y_train_set = y[:math.floor(len(x) * 0.8), :]#训练样本
x_validation_set = x[math.floor(len(x) * 0.8):, :]#验证样本
y_validation_set = y[math.floor(len(x) * 0.8):, :]

#定义参数
dim = 18 * 9 + 1 #定义维度,18个因素,9个小时,1是偏置b
w = np.zeros([dim, 1])#定义各因素权重
x_train_set = np.concatenate((np.ones([len(x_train_set), 1]), x_train_set), axis=1).astype(float)#为给偏置一个x,将所有数据最前面1列拼接一个1;由于ones跟x_train_set数据类型不同,故需将其都转成float类型
learning_rate = 10#定义学习率
iter_time = 30000#定义循环次数
#将分母中累加梯度值做平滑处理
#使用AdaGrad优化算法,可使每一次更新力度不会太大,且保证每个样本更新力度不同。即在参数空间更为平缓的方向,会取得更大的进步(因为平缓,所以历史梯度平方和较小,对应学习下降的幅度较小),并且能够使得陡峭的方向变得平缓,从而加快训练速度。
adagrad = np.zeros([dim, 1])#定义用于平滑的那个参数即梯度,其shape和w的shape一样
eps = 0.0001#定义平滑时的偏置系数

#开始训练
for t in range(iter_time):
    loss = np.sqrt(sum(np.power(np.dot(x_train_set, w) - y_train_set, 2)) / len(x_train_set))#sqrt是开平方,dot是矩阵乘法
    if(t % 100 == 0):
        print("迭代次数:%i  损失值:%f"%(t, loss))
    gradient = (np.dot(x_train_set.T, np.dot(x_train_set, w) - y_train_set)) / (loss * len(x_train_set))#梯度
    adagrad += (gradient ** 2)#准备平滑处理,平方
    w = w - learning_rate * gradient / np.sqrt(adagrad + eps)#梯度下降且做平滑

#保存数组
np.save('weights.npy', w)#保存成npy格式
#训练完毕

#开始测试
#用同样的操作处理测试集数据,处理成和训练集一样的18*9等等的格式
test_data = pd.read_csv('./test.csv', header=None, encoding='gb18030')#注意一定加header=None,否则读取的矩阵维度不正确
test_data = test_data.iloc[:, 2:]#iloc用来取行列数据,现取所有行和第3列开始取
test_data[test_data == 'NR'] = 0
test_data = test_data.to_numpy()
test_x = np.empty([240, 18 * 9], dtype=float)

for day in range(240):
    test_x[day, :] = test_data[day * 18:(day + 1) * 18, :].reshape(1, -1)#将【240*18,9】的测试集拉成【240,18*9】的矩阵
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([len(test_x), 1]), test_x), axis=1).astype(float)

w = np.load('./weights.npy')#加载参数w
ans_y = np.dot(test_x, w)#加了各因素权重之后的预测值
print(ans_y)#打印预测值

标签:set,李宏毅,train,作业,np,PM2.5,test,data,day
来源: https://blog.csdn.net/qq_15821487/article/details/117607500