共享单车预测

通过历史数据预测某一地区接下来一段时间内的共享单车的数量。首先对数据进行预处理,然后在训练集上训练,并在测试集上验证模型。设计神经网络数据进行拟合,利用训练后的模型对数据拟合并进行预测, 记录误差,并绘制出拟合效果。

导包

1
2
3
4
5
import torch
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch.optim as optim

文件形式:

离散数据处理

通过 pd.get_dummies 函数,对指定的几个列进行了独热编码。独热编码是一种将分类变量转换为二进制向量的方法,以便更好地在机器学习模型中使用。循环中的每个列都进行了独热编码,并将结果与原始数据框进行连接(pd.concat)。

1
2
3
4
5
6
7
8
data = pd.read_csv('bikes.csv')
col_titles = ['season', 'weathersit', 'mnth', 'hr', 'weekday']
for i in col_titles:
dummies = pd.get_dummies(data[i], prefix=i)
data = pd.concat([data, dummies], axis=1)
col_titles_to_drop = ['instant', 'dteday', 'season', 'weathersit', 'weekday', 'mnth', 'workingday', 'hr']
data = data.drop(col_titles_to_drop, axis=1)
print(data.head())

离散数据处理后的 data:

   holiday  temp   hum  windspeed  cnt  season_1  season_2  season_3  \
0        0  0.24  0.81        0.0   16      True     False     False   
1        0  0.22  0.80        0.0   40      True     False     False   
2        0  0.22  0.80        0.0   32      True     False     False   
3        0  0.24  0.75        0.0   13      True     False     False   
4        0  0.24  0.75        0.0    1      True     False     False   

   season_4  weathersit_1  ...  hr_21  hr_22  hr_23  weekday_0  weekday_1  \
0     False          True  ...  False  False  False      False      False   
1     False          True  ...  False  False  False      False      False   
2     False          True  ...  False  False  False      False      False   
3     False          True  ...  False  False  False      False      False   
4     False          True  ...  False  False  False      False      False   

   weekday_2  weekday_3  weekday_4  weekday_5  weekday_6  
0      False      False      False      False       True  
1      False      False      False      False       True  
2      False      False      False      False       True  
3      False      False      False      False       True  
4      False      False      False      False       True  

[5 rows x 56 columns]

连续数据标准化处理

标准化

  • 对于每个列,使用循环进行以下操作:
    • mean, std = data[i].mean(), data[i].std() 计算当前列的均值(mean)和标准差(std)。
    • data[i] = (data[i] - mean) / std 对当前列进行标准化处理,即将每个元素减去均值并除以标准差。通过标准化,将每个特征的值调整为均值为0,标准差为1的分布,从而使得它们的数值范围相对一致。有助于训练某些机器学习模型。
1
2
3
4
5
6
7
col_titles = ['cnt', 'temp', 'hum', 'windspeed']
for i in col_titles:
mean, std = data[i].mean(), data[i].std()
if i == 'cnt':
mean_cnt, std_cnt = mean, std
data[i] = (data[i]-mean)/std
print(data[col_titles])

连续数据处理后:

            cnt      temp       hum  windspeed
0     -0.956312 -1.334609  0.947345  -1.553844
1     -0.823998 -1.438475  0.895513  -1.553844
2     -0.868103 -1.438475  0.895513  -1.553844
3     -0.972851 -1.334609  0.636351  -1.553844
4     -1.039008 -1.334609  0.636351  -1.553844
...         ...       ...       ...        ...
17374 -0.388467 -1.230743 -0.141133  -0.211685
17375 -0.553859 -1.230743 -0.141133  -0.211685
17376 -0.548346 -1.230743 -0.141133  -0.211685
17377 -0.708224 -1.230743 -0.348463  -0.456086
17378 -0.774381 -1.230743  0.118028  -0.456086

[17379 rows x 4 columns]

数据集处理

按11:1划分

1
2
3
4
5
6
7
test_data = data[-30*24:]
train_data = data[:-30*24]
X = train_data.drop(['cnt'], axis=1)
X = X.values.astype(float)
Y = train_data['cnt']
Y = Y.values.astype(float)
Y = np.reshape(Y, [len(Y), 1])

搭建神经网络

1
2
3
4
5
6
7
8
9
10
11
input_size = X.shape[1]
hidden_size = 10
output_size = 1
batch_size = 128
neu = torch.nn.Sequential(
torch.nn.Linear(input_size, hidden_size),
torch.nn.Sigmoid(),
torch.nn.Linear(hidden_size, output_size)
)
loss_fn = torch.nn.MSELoss()
opt = torch.optim.SGD(neu.parameters(), lr=0.01)

训练

batch:小批量梯度下降

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
losses = []
for i in range(1000):
batch_loss = []
for start in range(0, len(X), batch_size):
if start+batch_size < len(X):
end = start+batch_size
else:
end = len(X)
x = torch.FloatTensor(X[start:end])
y = torch.FloatTensor(Y[start:end])
pred = neu(x)
loss = loss_fn(pred, y)
opt.zero_grad()
loss.backward()
opt.step()
batch_loss.append(loss.data.numpy())
if i % 100 == 0:
losses.append(np.mean(batch_loss))
print(i, np.mean(batch_loss))

plt.plot(np.arange(len(losses))*100, losses)
plt.xlabel('batch')
plt.ylabel('MSE')
plt.show()

训练时损失:

0 0.9076614
100 0.3113705
200 0.28764674
300 0.24460928
400 0.18675153
500 0.14928792
600 0.13117069
700 0.12224861
800 0.117569864
900 0.114756

png

测试

  • Y = Y.values.reshape([len(Y), 1])
    • Y.values 将 pandas 数据框中的目标变量 Y 转换为 NumPy 数组。
    • reshape([len(Y), 1]) 将目标变量 Y 从一维数组调整为二维数组,其中列数为 1。这是因为 PyTorch 中的目标变量通常被期望是一个二维张量,其中每行代表一个样本,每列代表一个目标值。这有助于与模型的输出格式匹配。
  • X = torch.FloatTensor(X.values)
    • X.values 将 pandas 数据框中的特征变量 X 转换为 NumPy 数组。
    • torch.FloatTensor() 将 NumPy 数组转换为 PyTorch 的浮点张量。神经网络的输入通常需要是浮点数类型,因此这一步确保了输入数据的类型正确。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
X = test_data.drop(['cnt'], axis=1)
X = X.astype(float)
Y = test_data['cnt']
Y = Y.values.reshape([len(Y), 1])
X = torch.FloatTensor(X.values)
Y = torch.FloatTensor(Y)
pred = neu(X)

Y = Y.data.numpy()*std_cnt+mean_cnt
pred = pred.data.numpy()*std_cnt+mean_cnt

plt.figure(figsize=(10, 7))
xplot, = plt.plot(np.arange(X.size(0)), Y)
yplot, = plt.plot(np.arange(X.size(0)), pred, ':')
plt.show()

预测对比:

png