前言
这里主要是用Pytorch重新写一下李宏毅机器学习的作业一,那里主要是用pandas和numpy来实现的数据操作,这里将用Pytorch工具来写线性回归,实现多因素作用下的PM2.5预测。本笔记主要是为了熟悉一下Pytorch张量与张量的创建与Pytorch张量操作,两篇笔记中涉及的张量创建函数与张量操作函数的使用。
原理分析见:台大李宏毅 机器学习 2020学习笔记(二):回归与过拟合
数据分析见:台大李宏毅机器学习 2020作业(一):手写线性回归,实现多因素作用下的PM2.5预测
代码及资料:lhy_PM2.5_pytorch.zip或者本笔记末尾网盘链接
任务
- 处理数据
从我的另一篇笔记中,我们可以知道训练数据是一个(18x20x12)*24
的二维表格。24指一天24小时,18指18个特征,如温度值、降雨值、PM2.5等,20指一个月有20天的数据,然后12指一年12个月。训练数据部分截图如图1所示,可以发现数据的存放方式是很奇怪的,没有办法直接作为训练集使用,所以我们需要改变它。我们希望每一组输入数据都展成一行,以便于与w做点乘,这就是转换的目标。
需要预测的数据是一个(18x240)* 9的二维表格,如图2。240个id
,每个id给了前9
个小时的数据,每个数据18
个特征。要求我们通过每个id前9
个小时的数据,来预测其第10
个小时PM2.5
值。我们当然可以只用前9
个小时的PM2.5值作为特征,然后预测第10
个小时的PM2.5的值,但是这样不准确。所以,最后用数据前9
个小时的所有数据作为特征,共(18 *9)个特征,来预测第10
个小时的PM2.5值。
- 训练模型
模型:多元线性函数
损失:MSE loss
优化:梯度下降
- 预测
输出测试数据中每个id
第10
个小时的PM2.5
值。
处理数据
- 载入数据并转换成张量
同样的,用pandas
来读入big5
编码的csv
文件。然后将读入的数据先转换成numpy
,然后用from_numpy
函数将数据再转换成tensor
。
import pandas as pd
import matplotlib.pyplot as plt
import torch
data = pd.read_csv('./data/train.csv', encoding='big5')
data = data.iloc[:, 3:] # 去掉前三列,即非数据列
data[data == 'NR'] = 0 # 将rainfall里的NR换成0,即不下雨为0
raw_data = data.to_numpy().astype(float) # 将pandas转换成numpy,再转换成tensor
data_tensor = torch.from_numpy(raw_data)
print(data_tensor.shape, '\n', data_tensor[0:2])
输出前两行结果,与原数据比对,相同,说明没有问题。
2014/1/1 AMB_TEMP 14 14 14 13 12 12 12 12 15 17 20 22 22 22 22 22 21 19 17 16 15 15 15 15
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 1.8 1.8 1.8 1.8 1.8 1.8 1.8
torch.Size([4320, 24])
tensor([[14.0000, 14.0000, 14.0000, 13.0000, 12.0000, 12.0000, 12.0000, 12.0000,
15.0000, 17.0000, 20.0000, 22.0000, 22.0000, 22.0000, 22.0000, 22.0000,
21.0000, 19.0000, 17.0000, 16.0000, 15.0000, 15.0000, 15.0000, 15.0000],
[ 1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000,
1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000,
1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000]],
dtype=torch.float64)
- 数据形状变换
将原先训练数据每天的24小时,18个特征,纵向排列的方式,转变成横向排列的方式,即将每天的数据依次横向首尾相接,最后构成一个形状(24* 12* 240)*18
的二维张量。张量操作上是先切,再合,要用到split和cat两个方法,用法见此
tensor_split = torch.split(data_tensor, 18, dim=0) # 由于是18个特征,所以切分尺寸是18
print(tensor_split[0].shape, len(tensor_split))
# tensor_cat = torch.cat([tensor_split[0], tensor_split[1]], dim=1)
tensor_cat = tensor_split[0]
for i in range(len(tensor_split)-1):
tensor_cat = torch.cat([tensor_cat, tensor_split[i+1]], dim=1)
print(tensor_cat.shape, len(tensor_cat[0]))
print(tensor_cat[0][0:48])
输出第一行前48个数据,与原数据比对,相同,说明没有问题。
2014/1/1 AMB_TEMP 14 14 14 13 12 12 12 12 15 17 20 22 22 22 22 22 21 19 17 16 15 15 15 15
2014/1/2 AMB_TEMP 16 15 15 14 14 15 16 16 17 20 22 23 24 24 24 24 23 21 20 19 18 18 18 18
torch.Size([18, 5760]) 5760
tensor([14., 14., 14., 13., 12., 12., 12., 12., 15., 17., 20., 22., 22., 22.,
22., 22., 21<