本文首要内容是在上一篇文章的基础上,持续完成LSTM神经网络实现我国人口猜测项目,上一节介绍了项目的数据处理部分,本节将首要对数据预处理,模型建立,模型练习,模型猜测部分进行开发与演示。

1. 项目回顾

本项目运用PaddlePaddle结构进行机器学习实战,依据指定数据集(我国人口数据集等)运用Paddle结构建立LSTM神经网络,包括数据预处理、模型构建、模型练习、模型猜测、猜测成果可视化等。

  • 咱们将依据我国人口数据会集的多个特征(features),例如:出世人口(万)、我国人均GPA(美元计)、我国性别份额(按照女生=100)、自然增长率(%)等8个特征字段,猜测我国未来总人口(万人)这1个标签字段。属于多输入,单输出LSTM神经网路猜测范畴。
  • LSTM算法是一种重要的现在运用最多的时刻序列算法,是一种特别的RNN(Recurrent Neural Network,循环神经网络),能够学习长期的依赖关系。

2. 数据预处理

2.1 结构窗口

  • 因为LSTM网络是由一个个窗口进行滑动去猜测的,因而,需要界说窗口函数
  • 对于LSTM网络,此数据会集,“总人口(万人)”为目标值
  • 在每个窗口后的“总人口(万人)”数据为此窗口的目标值
  • 目标值为表中的第3列数据data[ , 2]
# 窗口区分
def split_windows(data, size):
    X = []
    Y = []
    # X作为数据,Y作为标签
    # 滑动窗口,步长为1,结构窗口化数据,每一个窗口的数据标签是窗口结尾的“总人口(万人)”
    for i in range(len(data) - size):
        X.append(data[i:i+size, :])
        Y.append(data[i+size, 2])
    return np.array(X), np.array(Y)

2.2 区分数据集

  • 在练习之前咱们还需要区分练习集与测验集样本
  • 区分练习集与测验集样本
  • 切分份额为:0.6 :0.4
  • 对区分后的数据集进行可视化
all_data = population.values
split_fraction = 0.6
train_split = int(split_fraction * int(population.shape[0])) # 计算切分的练习集巨细
train_data = all_data[:train_split, :]
test_data = all_data[train_split:, :]
plt.figure(figsize=(10, 5))
# 数据可视化
plt.plot(np.arange(train_data.shape[0]), train_data[:, 2], label='train data')
plt.plot(np.arange(train_data.shape[0], train_data.shape[0] + test_data.shape[0]), test_data[:, 2], label='test data')
plt.legend()

运转成果如下图所示:

  • 数据集共有50条样本
  • 通过区分,有30条练习数据,20条测验数据

【机器学习】LSTM神经网络实现中国人口预测(2)

2.3 归一化并区分窗口

  • 运用sklearn库中的最大最小归一化对练习数据与测验数据进行归一化
  • 运用之前界说的窗口区分函数对练习集和测验集的特征与目标值进行区分
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaled_train_data = scaler.fit_transform(train_data)
# 运用练习集的最值对测验集归一化,保证练习集和测验集的散布一致性
scaled_test_data = scaler.transform(test_data)
# 练习集测验集区分
window_size = 5
train_X, train_Y = split_windows(scaled_train_data, size=window_size)
test_X, test_Y = split_windows(scaled_test_data, size=window_size)
print('train shape', train_X.shape, train_Y.shape)
print('test shape', test_X.shape, test_Y.shape)

运转成果如下图所示:

【机器学习】LSTM神经网络实现中国人口预测(2)

3. 模型建立

3.1 建立LSTM模型

下面将进行LSTM神经网络模型进行建立。网络结构大体如下:

  • Reshape层:用于将输入数据转换为指定的输入方式。
  • 2D Conv层:进行卷积操作,滤波器个数为64,padding设置为same用于获取相同巨细的feature map,激活函数为relu。
  • Maxpooling层:进行下采样,然后接一个Dropout用于防止过拟合。
  • LSTM层:界说了一层LSTM层
  • Linear:最终设置一层全衔接层进行输出下一时刻的猜测值
  • 窗口巨细:window_size = 5
  • 特征数:fea_num = 10
  • 批处理巨细:batch_size = 5
# 输入的目标维度
window_size = 5
fea_num = 10
batch_size = 5
class CNN_LSTM(paddle.nn.Layer):
    def __init__(self, window_size, fea_num):
        super().__init__()
        self.window_size = window_size
        self.fea_num = fea_num
        self.conv1 = paddle.nn.Conv2D(in_channels=1, out_channels=64, stride=1, kernel_size=3, padding='same')
        self.relu1 = paddle.nn.ReLU()
        self.pool = paddle.nn.MaxPool2D(kernel_size=2, stride=1, padding='same')
        self.dropout = paddle.nn.Dropout2D(0.3)
        self.lstm1 = paddle.nn.LSTM(input_size=64*fea_num, hidden_size=128, num_layers=1, time_major=False)
        # self.lstm2 = paddle.nn.LSTM(input_size=128, hidden_size=64, num_layers=1, time_major=False)
        self.fc = paddle.nn.Linear(in_features=128, out_features=64)
        self.relu2 = paddle.nn.ReLU()
        self.head = paddle.nn.Linear(in_features=64, out_features=1)
    def forward(self, x):
        x = x.reshape([x.shape[0], 1, self.window_size, self.fea_num])
        x = self.conv1(x)
        x = self.relu1(x)
        x = self.pool(x)
        x = self.dropout(x)
        x = x.reshape([x.shape[0], self.window_size, -1])
        x, (h, c) = self.lstm1(x)
        # x, (h,c) = self.lstm2(x)
        x = x[:,-1,:] # 最终一个LSTM只要窗口中最终一个特征的输出
        x = self.fc(x)
        x = self.relu2(x)
        x = self.head(x)
        return x

3.2 检查建立的网络参数

在建立完神经网络往后,咱们可以运用一下代码对网络结构进行检查:

# 打印网络结构
model = CNN_LSTM(window_size, fea_num)
paddle.summary(model, (5, 5, 10)) # batchsize样本数,窗口巨细,特征数量

运转成果如下图所示:

【机器学习】LSTM神经网络实现中国人口预测(2)

3.3 界说超参数与优化器

下面将界说练习轮数,batchsize,学习率等超参数,然后界说丢失函数以及优化器。

# 界说超参数
base_lr = 0.005
BATCH_SIZE = 5
EPOCH = 50
lr_schedual = paddle.optimizer.lr.CosineAnnealingDecay(learning_rate=base_lr, T_max=EPOCH, verbose=True)
loss_fn = nn.MSELoss()
metric = paddle.metric.Accuracy()
opt = paddle.optimizer.Adam(parameters=model.parameters(), learning_rate=lr_schedual, beta1=0.9, beta2=0.999)
def process(data, bs):
    l = len(data)
    tmp = []
    for i in range(0, l, bs):
        if i + bs > l:
            tmp.append(data[i:].tolist())
        else:
            tmp.append(data[i:i+bs].tolist())
    tmp = np.array(tmp)
    return tmp
# 处理练习数据
train_X = process(train_X, 5)
train_Y = process(train_Y, 5)
print(train_X.shape, train_Y.shape)

4. 模型练习

  • 在练习过程中打印练习轮数、练习丢失

  • 保存模型参数到途径work/cnn_lstm_ep50_lr0.005

  • 练习超参数已在前面指定:

    • base_lr = 0.005
    • BATCH_SIZE = 5
    • EPOCH = 50
# 模型练习
for epoch in range(EPOCH):
    model.train()
    loss_train = 0
    for batch_id, data in enumerate(train_X):
        label = train_Y[batch_id]
        data = paddle.to_tensor(data, dtype='float32')
        label = paddle.to_tensor(label, dtype='float32')
        label = label.reshape([label.shape[0],1])
        y = model(data)
        loss = loss_fn(y, label)
        opt.clear_grad()
        loss.backward()
        opt.step()
        loss_train += loss.item()
    print("[TRAIN]epoch: {},  loss: {:.4f}".format(epoch+1, loss_train))
    lr_schedual.step()
# 保存模型参数
paddle.save(model.state_dict(), 'work/cnn_lstm_ep50_lr0.005.params')
paddle.save(lr_schedual.state_dict(), 'work/cnn_lstm_ep50_lr0.005.pdopts')

部分运转成果如下图所示:

  • 通过上述敞开练习代码,模型就可以练习起来了。

【机器学习】LSTM神经网络实现中国人口预测(2)

5. 模型猜测

通过模型练习,就可以开始模型猜测步骤了。

  • 运用练习好的模型对测验集数据进行猜测
  • 因为之前测验集数据通过了归一化,因而咱们还需要对猜测成果以及测验集实在数据进行反归一化
  • 可视化展示测验集的猜测标签数据与实在标签数据
# 加载模型
model = CNN_LSTM(window_size, fea_num)
model_dict = paddle.load('work/cnn_lstm_ep150_lr0.005.params')
model.load_dict(model_dict)
test_X = paddle.to_tensor(test_X, dtype='float32')
prediction = model(test_X)
prediction = prediction.cpu().numpy()
prediction = prediction.reshape(prediction.shape[0], )
# 反归一化
scaled_prediction = prediction * (scaler.data_max_[2] - scaler.data_min_[2]) + scaler.data_min_[2]
scaled_true = test_Y * (scaler.data_max_[2] - scaler.data_min_[2]) + scaler.data_min_[2]
# 画图
plt.plot(range(len(scaled_true)), scaled_true, label='true')
plt.plot(range(len(scaled_prediction)), scaled_prediction, label='prediction', marker='*')
plt.legend()

运转成果如下图所示:

  • 通过猜测,发现模型学到了数据的大体变化趋势
  • 因为本数据集样本量太小,模型练习后的作用有限,还需要进一步优化
    【机器学习】LSTM神经网络实现中国人口预测(2)

6. 总结

本文完成了LSTM人口猜测项目的数据预处理、模型建立、模型练习与模型猜测阶段。若想进一步提高模型准确率,在往后可以对模型进一步改进,大体方向如下:

  • 因为本数据集样本量有限,往后可以挑选在样本更充沛的数据集进行试验。
  • 别的,在往后可以考虑改进网络结构与参数来进一步优化模型。
  • 运用不同的归一化手法(标准化)

本文正在参与「金石方案 . 分割6万现金大奖」