用pytorch实现循环神经网络LSTM。

学习过程中用到LSTM(简单版),记录下对这个网络的理解。

首先是数据的问题。如果数据是按照时间顺序获取的,那就按顺序输入就行。

 每一行是一个时刻采集到的6个数据。一共168个时刻。168*6

当我们只输入一条数据时,整个网络的结构,此时可以看作是一个普通的网络后面再接一个全连接层(如下图)

 这里有几点需要明确一下。输入数据需要转化为三维(涉及到一个步数的问题),LSTM层输出的也是三维,lstm层输出的三维需要转化为二维接入全连接层,再把输出的二维转化为三维。  

 下面是代码

class LstmRNN(nn.Module):
    """
        Parameters:
        - input_size:   特征大小
        - hidden_size:  隐藏神经元数
        - output_size:      输出的神经元数
        - num_layers:   隐藏层数,一般为1
    """

    def __init__(self, input_size, hidden_size, output_size, num_layers=1):
        super().__init__()

        self.lstm = nn.LSTM(input_size, hidden_size, num_layers)
       ### input_size输入特征维度 hidden_size 隐藏层维度 num_layers lstm的隐藏层数
        self.linear1 = nn.Linear(hidden_size, output_size)  # 全连接层

    def forward(self, _x):
        x, _ = self.lstm(_x)  #_x是输入的数据,需要转化为三维。 _x is input, size (seq_len, batch, input_size)即 总的时间长度,每个批次大小,输入特征大小

        s, b, h = x.shape  # x是lstm的输出结果,转化为二维。
#    x is output, size (seq_len, batch, hidden_size)即 总的时间长度,批次大小  隐藏层神经元个数
        x = x.view(s * b, h)  ## 把x转换为二维(s*b,h) 这里是为后面连接一个全连接层做准备
        x = self.linear1(x)   ##  把lstm的输出结果输入进最后的全连接层得到结果
        x = x.view(s, b, -1)  ## 把最后全连接层输出的结果转化为三维
        return x

接下来是读入数据,我用的pandas

if __name__ == '__main__':

    # checking if GPU is available
    device = torch.device("cpu")

    if (torch.cuda.is_available()):
        device = torch.device("cuda:0")
        print('Training on GPU.')
    else:
        print('No GPU available, training on CPU.')

     ##  读入数据集和标签集并进行归一化。
    # data_x = np.array(pd.read_csv('特征集/特征-6.csv', header=None,skiprows=1)).astype('float32')
    data_x = pd.read_csv('特征集/特征-6.csv')
    data_x=np.array((data_x)).astype(('float32')) # 转化数据类型
    data_x = (data_x- data_x.min()) / (data_x.max() - data_x.min()) ## 归一化
data_y = pd.read_csv('特征集/soh-6.csv')  # 这里是标签集的操作 和数据集一样
data_y = np.array((data_y)).astype(('float32'))
data_y = (data_y - data_y.min()) / (data_y.max() - data_y.min())

data_len = len(data_x)  ## 获取总的时间维度,即数据集的条数 168
t = np.linspace(0, data_len-1, data_len)  ## 生成一个序列号

train_data_ratio = 0.6  # 为了把数据集拆分,这里设置一个数字
train_data_len = int(data_len * train_data_ratio)  

train_x = data_x[:train_data_len]   ##切分数据集,这里取前134个作为训练集
train_y = data_y[:train_data_len]   ##  训练集的标签
t_for_training = t[:train_data_len]  ## 训练集的序列号

test_x = data_x[train_data_len:]  ## 这里是 测试集
test_y = data_y[train_data_len:]
t_for_testing = t[train_data_len:]

接下来是数据的转化

INPUT_FEATURES_NUM = 6   ## 特征个数是6
OUTPUT_FEATURES_NUM = 1

## 把训练集和训练的标签转化为3维
train_x_tensor = train_x.reshape(-1, 1, INPUT_FEATURES_NUM)  # set batch size to 1
train_y_tensor = train_y.reshape(-1, 1, OUTPUT_FEATURES_NUM)  # set batch size to 1

# transfer data to pytorch tensor
train_x_tensor = torch.from_numpy(train_x_tensor)  ## 把数组改为张量
train_y_tensor = torch.from_numpy(train_y_tensor)

lstm_model = LstmRNN(INPUT_FEATURES_NUM, 20, output_size=OUTPUT_FEATURES_NUM, num_layers=1)   ## 调用我们的lstm类 并传入参数
criterion = nn.L1Loss()  ## 损失函数
optimizer = torch.optim.Adam(lstm_model.parameters(), lr=1e-2)  ## 梯度下降法


max_epochs = 3000    ## 训练次数

接下来是训练

train_x_tensor = train_x_tensor.to(device)  ## 训练数据加载到CPU上
for epoch in range(max_epochs):
    output = lstm_model(train_x_tensor).to(device)  ## 把我们的模型也加载到CPU
    loss = criterion(output, train_y_tensor)  ## 计算损失

    optimizer.zero_grad()  ## 梯度下降
    loss.backward()  
    optimizer.step() 
pred_y_for_train = lstm_model(train_x_tensor).to(device)  ## 训练数据的预测值 即从lstm网络中输出的是三维
pred_y_for_train = pred_y_for_train.view(-1, OUTPUT_FEATURES_NUM).data.numpy()## 把预测的值从三维转化为二维
lstm_model = lstm_model.eval()  ## 我们的训练已经完毕,权重W B都已得到,接下来进行预测,不需要梯度的计算
test_x_tensor = test_x.reshape(-1, 1,INPUT_FEATURES_NUM)  ##测试集转化为三维,并转化为张量,加载到cpu上
test_x_tensor = torch.from_numpy(test_x_tensor)
test_x_tensor = test_x_tensor.to(device)
pred_y_for_test = lstm_model(test_x_tensor).to(device)  ## 测试集的预测值,转化为二维
pred_y_for_test = pred_y_for_test.view(-1, OUTPUT_FEATURES_NUM).data.numpy()
loss = criterion(torch.from_numpy(pred_y_for_test), torch.from_numpy(test_y))
## 计算损失
print("test loss:", loss.item())  #输出损失 

如果想画图可以自己添加画图的程序。

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值