各类神经网络学习:(四)RNN 循环神经网络(下集),pytorch 版的 RNN 代码编写

news/2025/3/29 18:50:41/
上一篇下一篇
RNN(中集)待编写

代码详解

pytorch 官网主要有两个可调用的模块,分别是 nn.RNNCellnn.RNN ,下面会进行详细讲解。

RNN 的同步多对多、多对一、一对多等等结构都是由这两个模块实现的,只需要将对输入和输出进行调整就行。

nn.RNN 为例,它有两个输出,一个是 output ,一个是 hidden ,使用前者就是同步多对多结构,使用后者就是多对一结构(这种情形下 hidden 其实就是 output 的最后一个元素)(先说,后面慢慢看)。

1)pytorch版模块调用

①nn.RNNCell(单步RNN)

官网链接:RNNCell — PyTorch 2.6 documentation

使用此函数,需要再手动实现时间循环

  • 对应公式:
    h ′ = t a n h ( W i h ⋅ x + b i h + W h h ⋅ h + b h h ) h^{'} = tanh(W_{ih}·x+b_{ih}+W_{hh}·h+b_{hh}) h=tanh(Wihx+bih+Whhh+bhh)
    这里和之前提到的 s t = g 1 ( U ⋅ x t + W ⋅ s t − 1 + b s ) s_t=g1(U·x_t+W·s_{t-1}+b_s) st=g1(Uxt+Wst1+bs) 是一个意思, s s s 就是 h h h ,只不过更细化了,稍微转换一下即可。

  • 公式图解:

    在这里插入图片描述

  • 模块解析:

    class torch.nn.RNNCell(input_size, hidden_size, bias=True, nonlinearity='tanh', device=None, dtype=None)
    # 实例化为:rnncell = torch.nn.RNNCell(10,20)
    
    • 类的参数解释:
      • input_size (int):输入 x x x 的特征数------------------------------------------ 其实就是 x x x 的维度,即向量 x x x 中的元素个数。
      • hidden_size (int):隐藏状态 h h h 的特征数---------------------------------- 其实就是 h h h 的维度,即向量 h h h 中的元素个数。
      • bias (bool):偏置设置项,默认为 True ---------------------------------- 如果为 F a l s e False False 则不使用偏置 b i h 、 b h h b_{ih}、b_{hh} bihbhh
      • nonlinearity (str):激活函数设置项,默认为 'tanh' ---------------- 可设置为 nonlinearity='relu'
    • 输入,的类型及形状:
      • input :类型:tensor,形状: ( N , H i n ) (N,H_{in}) (N,Hin) ( H i n ) (H_{in}) (Hin) ------------------ 其中 N N N 就是 batch_size (批量), H i n H_{in} Hin = input_size
      • hidden :类型:tensor,形状: ( N , H o u t ) (N,H_{out}) (N,Hout) ( H o u t ) (H_{out}) (Hout) -------------- 其中 H o u t H_{out} Hout = hidden_size ,如果不提供就默认为 0 张量。
    • 输出,的类型及形状:
      • hidden :类型:tensor,形状: ( N , H o u t ) (N,H_{out}) (N,Hout) ( H o u t ) (H_{out}) (Hout) -------------- 其中 H o u t H_{out} Hout = hidden_size ,此输出代表了下 一时刻的隐藏层状态。
    • 其中的权重 W 、 b W、b Wb 都是自动初始化、可自学习的。
  • 调用展示:

    import torchcell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size)
    hidden = Cell(input, hidden)
    # hidden = Cell(input, hidden) 其实就是在调用 cell 中的 forword 函数,因为 cell 本身是个 class 类嘛
    
  • 完整样例展示(构造数据集时会引入 seqlen ):

    有关 seqlen 的讲解请看下面点②,其含义就是时间步。

    seqlen 是在使用 RNN 之前,构造数据集时需要设置的参数, nn.RNNCell 没有调用此参数,但是在写代码时需要设置(其实可以不设置,因为毕竟也用不到这个参数,只是说后面的 nn.RNN 里用到了这个参数,索性就一起用了),模型会自动获取 batch_sizeinput_size

    事实上,下方代码中的循环次数就是 seqlen

    import torchbatch_size = 2
    seq_len = 3
    input_size = 4
    hidden_size = 2cell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size)  # 实例化dataset = torch.randn(seq_len, batch_size, input_size)  # 构造固定格式的数据集, (seq, batch, features)
    hidden = torch.zeros(batch_size, hidden_size)  # 初始化隐层状态输入for idx, input in enumerate(dataset):print('=' * 20, idx, '=' * 20)print('input size:', input.shape)hidden = cell(input, hidden)print('outputs size:', hidden.shape)print(hidden)-----------------------------------------------------------------------------------------------------------------------
    # 输出结果为:
    ==================== 0 ====================
    input size: torch.Size([2, 4])
    outputs size: torch.Size([2, 2])
    tensor([[-0.9041, -0.9441],[ 0.7673, -0.7628]], grad_fn=<TanhBackward0>)
    ==================== 1 ====================
    input size: torch.Size([2, 4])
    outputs size: torch.Size([2, 2])
    tensor([[ 0.5290, -0.6024],[ 0.1011, -0.9541]], grad_fn=<TanhBackward0>)
    ==================== 2 ====================
    input size: torch.Size([2, 4])
    outputs size: torch.Size([2, 2])
    tensor([[ 0.5451,  0.4806],[-0.9263,  0.2988]], grad_fn=<TanhBackward0>)
    

    对于输出结果的解析:

    因为随机构造的数据集正好是只有 2 个样本,且 batch_size = 2, seq_len=3 ,所以循环执行了 3 次。

②构造数据集的规范

如果对上面的 nn.RNNCell 样例中参数尺寸不理解的,可以看这一节

1:

在这里插入图片描述

2:

在这里插入图片描述

记住: 循环次数 ≠ ≠ = batch_size * seq_len 。而且使用 nn.RNNCell 时编写的循环次数不是之前 CNN 一样的 epoch ,使用 nn.RNN 时才是。

对于语言建模而言: batchsize 相当于几句话, seqlen 相当于每句话里有几个字, inputsize 就是每个字的向量形式维度(one-hot编码)。

③nn.RNN(重点)

官网链接:RNN — PyTorch 2.6 documentation

使用此函数,无需手动实现时间循环

可以理解为由多个 nn.RNNCell 组成的集成网络。

  • 每一层的公式:
    h t = t a n h ( W i h T ⋅ x + b i h + W h h T ⋅ h t − 1 + b h h ) h_t = tanh(W_{ih}^{T}·x+b_{ih}+W_{hh}^{T}·h_{t-1}+b_{hh}) ht=tanh(WihTx+bih+WhhTht1+bhh)
    这里也和之前提到的 s t = g 1 ( U ⋅ x t + W ⋅ s t − 1 + b s ) s_t=g1(U·x_t+W·s_{t-1}+b_s) st=g1(Uxt+Wst1+bs) 是一个意思, s s s 就是 h h h ,只不过更细化了,稍微转换一下即可。

    公式里的转置不用在意,权重都是内部自动初始化、更新的。公示图解和 nn.RNNCCell 的差不多,就是多个转置。

  • 模块解析:

    class torch.nn.RNN(input_size, hidden_size, num_layers=1, nonlinearity='tanh', bias=True, batch_first=False, dropout=0.0, 		  bidirectional=False, device=None, dtype=None)
    
    • 类的参数解释:

      • input_size (int):输入 x x x 的特征数------------------------------------------ 其实就是 x x x 的维度,即向量 x x x 中的元素个数。

      • hidden_size (int):隐藏状态 h h h 的特征数---------------------------------- 其实就是 h h h 的维度,即向量 h h h 中的元素个数。

      • num_layers (int):循环层数,默认为 1 ----------------------------------- 意味着将 num_layersRNN 堆叠在一起,后
                                      一个 RNN 接收第一个 RNN 的隐层状态输出作
                                      为输入,并且计算最终结果。

      • nonlinearity (str):激活函数设置项,默认为 'tanh' -------------- 可设置为 nonlinearity='relu'

      • bias (bool):偏置设置项,默认为 True ---------------------------------- 如果为 False 则不使用偏置 b i h 、 b h h b_{ih}、b_{hh} bihbhh

      • batch_first (bool):输入输出格式设置项,默认为 False -------- 如果为 True 则用户需要按照
                                      (batch_size, seq_len, input_size) 来构造数据格式,
                                     默认是 (seq_len, batch_size, input_size)

      • dropout :神经元随机丢弃概率( 0 ∼ 1 0\sim1 01),默认值:0 ------------- 如果非零,则在除最后一层之外的每个 RNN
                                      的输出上引入一个 Dropout 层,会在训练过程
                                      中随机丢弃一部分神经元(即将其输出置为零),
                                      dropout 的概率等于 dropout 参数指定的值。

      • bidirectional (bool):双向 RNN 设置项,默认为 False --------- 如果为 True ,则变成双向 RNN

    • 输入,的类型及形状( D D D 一般都为 1 1 1 ):

      • input :类型:tensor,形状: ( L , N , H i n ) (L,N,H_{in}) (L,N,Hin) ( L , H i n ) (L,H_{in}) (L,Hin) ----------- 其中 L L Lseq_len N N Nbatch_size (批量), H i n H_{in} Hin = input_size 。当 batch_first=True 时为 ( N , L , H i n ) (N,L,H_{in}) (N,L,Hin)

      • hidden :类型:tensor,形状: ( D ∗ n u m _ l a y e r s , N , H o u t ) (D*num\_layers,N,H_{out}) (Dnum_layers,N,Hout) ( D ∗ n u m _ l a y e r s , H o u t ) (D*num\_layers,H_{out}) (Dnum_layers,Hout) ---------------其中 H o u t H_{out} Hout = hidden_size D = 2 i f b i d i r e c t i o n a l = T r u e o t h e r w i s e 1 D=2~~~if~bidirectional=True~~~otherwise~1 D=2   if bidirectional=True   otherwise 1 ,如果不提供就默认为 0 张量。

    • 输出,的类型及形状( D D D 一般都为 1 1 1 ):

      • output:类型:tensor,形状: ( L , N , D ∗ H o u t ) (L,N,D*H_{out}) (L,N,DHout) ( L , D ∗ H o u t ) (L,D*H_{out}) (L,DHout) ------------------------当 batch_first=True 时为 ( N , L , D ∗ H o u t ) (N,L,D∗H_{out}) (N,L,DHout)
      • hidden :类型:tensor,形状: ( D ∗ n u m _ l a y e r s , N , H o u t ) (D*num\_layers,N,H_{out}) (Dnum_layers,N,Hout) ( D ∗ n u m _ l a y e r s , H o u t ) (D*num\_layers,H_{out}) (Dnum_layers,Hout) --------------- 此输出代表了最后一个时刻的隐藏层状态输出。
    • 其中的权重 W 、 b W、b Wb 都是自动初始化、可自学习的。

    其实输出 output 就是所有的隐层输出状态, hidden 就是最后一刻的隐层输出状态( num_layers >1 的稍有不同)。

  • 模块使用图解:

    • num_layers 默认为 1 时:

      调用展示:

      import torchcell= torch.nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=1)
      out, hidden = cell(inputs, hidden)
      

      在这里插入图片描述

      上图中,就单个 RNN Cell 而言, x i x_i xi 是输入,左边箭头是隐层状态输入,右边箭头和上边箭头都是隐层状态输出。

      注意: 这里 RNN Cell 的个数就是 seq_len 的值。

    • num_layers > 1 时(令其=3):

      调用展示:

      import torchcell= torch.nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=3)
      out, hidden = cell(inputs, hidden)
      

    在这里插入图片描述

    上图中,就最下面一排的单个 RNN Cell 而言, x i x_i xi 是输入,左边箭头是隐层状态输入,右边箭头和上边箭头都是隐层状态输出。

    就上面两排的单个 RNN Cell 而言,下面一排 RNN Cell 的隐层状态输出是其输入,左边箭头是隐层状态输入,右边箭头和上边箭头都是隐层状态输出。

  • 完整样例展示:

    这里 nn.RNN 内部前向传播的时间步数就是 seq_len 的值。

    import torchbatch_size = 2
    seq_len = 3
    input_size = 4
    hidden_size = 2
    num_layers = 1single_rnn = torch.nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers)#(seqLen, batchSize, inputSize) 
    inputs = torch.randn(seq_len, batch_size, input_size)
    hidden = torch.zeros(num_layers, batch_size, hidden_size)
    out, hidden = single_rnn(inputs, hidden)
    print('output size:', out.shape)
    print('output:', out)
    print('Hidden size:', hidden.shape)
    print('Hidden:', hidden)-----------------------------------------------------------------------------------------------------------------------
    # 输出结果为:
    output size: torch.Size([3, 2, 2])
    output: tensor([[[ 0.5540, -0.3186],[ 0.1407, -0.9272]],[[ 0.8301,  0.5667],[ 0.9692, -0.4985]],[[ 0.7678,  0.6239],[-0.4899, -0.9761]]], grad_fn=<StackBackward0>)
    Hidden size: torch.Size([1, 2, 2])
    Hidden: tensor([[[ 0.7678,  0.6239],[-0.4899, -0.9761]]], grad_fn=<StackBackward0>)
    

2)单值序列预测实例

在训练之前制作数据集时,通常是用前 m 个数据预测第 m+1 个数据,第 m+1 个数据作为真实值,前 m 个数据作为输入得出的一个结果作为预测值(这 m+1 个数据就作为一个样本)。如果 batch_size 不为 1 ,则 batch_size 个样本就作为一次 epoch 的输入。

数据集:某国际航班每月乘客量变化表,international-airline-passengers.csv,CSDN 都有提供下载的,下载之后不要改动。

目标:拿 12 个月的数据来预测下一个月的客流量。

完整代码:

import torch
import torch.nn as nn
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from torch.utils.data import TensorDataset, DataLoader
from torch.utils.tensorboard import SummaryWriterwriter = SummaryWriter(log_dir='runs/airline_model')# 1. 数据预处理
data = pd.read_csv('international-airline-passengers.csv', usecols=['Month', 'Passengers'])
data['Month'] = pd.to_datetime(data['Month'])
data.set_index('Month', inplace=True)# 2. 数据集划分
train_size = int(len(data) * 0.8)
train_data = data[:train_size]
test_data = data[train_size:]# 3. 归一化处理
scaler = MinMaxScaler(feature_range=(0, 1))
train_scaled = scaler.fit_transform(train_data)
test_scaled = scaler.transform(test_data)# 4. 创建滑动窗口数据集
def create_sliding_windows(data, window_size):X, Y = [], []for i in range(len(data) - window_size):X.append(data[i:i + window_size])Y.append(data[i + window_size])return np.array(X), np.array(Y)window_size = 12
X_train, y_train = create_sliding_windows(train_scaled, window_size)
X_test, y_test = create_sliding_windows(test_scaled, window_size)# 转换为PyTorch张量 (batch_size, seq_len, features)
X_train = torch.FloatTensor(X_train).unsqueeze(-1)  # [samples, seq_len, 1]
X_train = X_train.squeeze(2) if X_train.dim() == 4 else X_train  # 消除多余维度
y_train = torch.FloatTensor(y_train)
X_test = torch.FloatTensor(X_test).unsqueeze(-1)
X_test = X_test.squeeze(2) if X_test.dim() == 4 else X_test
y_test = torch.FloatTensor(y_test)# 5. 构建RNN模型(使用tanh激活)
class AirlinePassengerModel(nn.Module):def __init__(self, input_size=1, hidden_size=50, output_size=1):super().__init__()self.rnn = nn.RNN(input_size=input_size,hidden_size=hidden_size,nonlinearity='tanh',batch_first=True,num_layers=1  # 显式指定层数)self.fc = nn.Linear(hidden_size, output_size)def forward(self, x):out, _ = self.rnn(x)  # RNN层使用内置tanh激活out = self.fc(out[:, -1, :])  # 取最后一个时间步输出return outmodel = AirlinePassengerModel()
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)dummy_input = torch.randn(1, window_size, 1)
writer.add_graph(model,dummy_input)# 6. 训练模型
train_loader = DataLoader(TensorDataset(X_train, y_train), batch_size=32, shuffle=True)epochs = 100
train_loss, val_loss = [], []for epoch in range(epochs):model.train()batch_loss = 0for X_batch, y_batch in train_loader:optimizer.zero_grad()y_pred = model(X_batch)loss = criterion(y_pred, y_batch)loss.backward()optimizer.step()batch_loss += loss.item()train_loss.append(batch_loss / len(train_loader))# 验证步骤model.eval()with torch.no_grad():y_val_pred = model(X_test)loss = criterion(y_val_pred, y_test)val_loss.append(loss.item())print(f'Epoch {epoch + 1}/{epochs} | Train Loss: {train_loss[-1]:.4f} | Val Loss: {val_loss[-1]:.4f}')# 7. 预测与逆归一化
model.eval()
with torch.no_grad():train_pred = model(X_train).numpy()test_pred = model(X_test).numpy()# 逆归一化处理
train_pred = scaler.inverse_transform(train_pred)
y_train = scaler.inverse_transform(y_train.numpy().reshape(-1, 1))
test_pred = scaler.inverse_transform(test_pred)
y_test = scaler.inverse_transform(y_test.numpy().reshape(-1, 1))# 8. 可视化
# 训练损失曲线可视化
plt.figure(figsize=(12, 5))
plt.plot(range(1, len(train_loss)+1), train_loss, 'b-', label='Train Loss')
plt.plot(range(1, len(val_loss)+1), val_loss, 'r--', label='Validation Loss')
plt.title('Training Process Monitoring\n(2025-03-11)', fontsize=14)
plt.xlabel('Epochs', fontsize=12)
plt.ylabel('Loss', fontsize=12)
plt.xticks(np.arange(0, len(train_loss)+1, 10))
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
plt.show()# 综合预测结果可视化
plt.figure(figsize=(14, 6))# 原始数据曲线
plt.plot(data.index, data['Passengers'],label='Original Data',color='gray',alpha=0.4)# 训练集预测曲线(需注意时间对齐)
train_pred_dates = train_data.index[window_size:train_size]
plt.plot(train_pred_dates, train_pred,label='Train Predictions',color='blue',linestyle='--')# 测试集预测曲线
test_pred_dates = test_data.index[window_size:]
plt.plot(test_pred_dates, test_pred,label='Test Predictions',color='red',linewidth=2)# 格式设置
plt.title('Time Series Prediction Results', fontsize=14)
plt.xlabel('Date', fontsize=12)
plt.ylabel('Passengers', fontsize=12)
plt.legend(loc='upper left')
plt.grid(True, linestyle=':', alpha=0.5)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()writer.close()

输出训练结果:

Epoch 1/100 | Train Loss: 0.0893 | Val Loss: 0.3493
Epoch 2/100 | Train Loss: 0.0473 | Val Loss: 0.1947
Epoch 3/100 | Train Loss: 0.0469 | Val Loss: 0.2113
Epoch 4/100 | Train Loss: 0.0387 | Val Loss: 0.2346
...
...
Epoch 95/100 | Train Loss: 0.0064 | Val Loss: 0.0304
Epoch 96/100 | Train Loss: 0.0052 | Val Loss: 0.0384
Epoch 97/100 | Train Loss: 0.0047 | Val Loss: 0.0434
Epoch 98/100 | Train Loss: 0.0048 | Val Loss: 0.0332
Epoch 99/100 | Train Loss: 0.0051 | Val Loss: 0.0285
Epoch 100/100 | Train Loss: 0.0051 | Val Loss: 0.0283

训练及预测可视化:

在这里插入图片描述

3)同步多对多序列预测实例

目标:给出输入 'hello' ,给出其标签 'ohlol' ,通过训练使得输入 'hello' ,模型能输出 'ohlol'

  • nn.RNNCell

    import torch# ==================================================准备数据==================================================
    input_size = 4
    hidden_size = 4
    batch_size = 1
    # seq_len 在这里不用显示定义, 模型会自动识别输入的尺寸idx2char = ['e', 'h', 'l', 'o']  # 字母字典
    x_data = [1, 0, 2, 2, 3]  # x_data 表示的单词是 hello, 在这里表示的是输入 inputs
    y_data = [3, 1, 2, 3, 2]  # y_data 表示的单词是 ohlol, 在这里表示的输出标签
    one_hot_lookup = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]  # 独热字典x_one_hot = [one_hot_lookup[x] for x in x_data]  # x_data 的独热编码向量组, 形状为:(seq_len, input_size)
    # 更改 x_one_hot 的形状, 在中间加一个 batch_size 维度, 其中 -1 参数表示获取列表中的元素个数(5个子列表, 那么个数就是5)
    inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
    labels = torch.LongTensor(y_data).view(-1, 1)  # 形状为(seq_len, batch_size)print(x_one_hot)
    print(labels)# ==================================================定义模型==================================================
    class MyModel(torch.nn.Module):def __init__(self, input_size, hidden_size, batch_size):super(MyModel, self).__init__()self.batch_size = batch_sizeself.input_size = input_sizeself.hidden_size = hidden_sizeself.rnncell = torch.nn.RNNCell(input_size=self.input_size, hidden_size=self.hidden_size)def forward(self, input, hidden):hidden = self.rnncell(input, hidden)return hiddendef init_hidden(self):return torch.zeros(self.batch_size, self.hidden_size)net = MyModel(input_size, hidden_size, batch_size)# ==================================================准备训练==================================================
    criterion = torch.nn.CrossEntropyLoss()  # 交叉熵损失
    optimizer = torch.optim.Adam(net.parameters(), lr=0.1)  # Adam 优化器for epoch in range(15):loss = 0optimizer.zero_grad()hidden = net.init_hidden()print('Predicted string: ', end='')for input, label in zip(inputs, labels):hidden = net(input, hidden)# seq_len 个单元的损失要加起来得到总损失,并且还要添加 view 操作适配形状# 这里的 -1 就是在自动填充 batch_size 的值loss += criterion(hidden.view(-1, hidden_size), label.view(-1))_, idx = hidden.max(dim=1)print(idx2char[idx.item()], end='')loss.backward()optimizer.step()print(', Epoch [%d/ 15] loss=%.4f' % (epoch+1, loss.item()))
    

    输出结果:

    Predicted string: llllh, Epoch [1/15] loss=6.5481
    Predicted string: ollll, Epoch [2/15] loss=5.6356
    Predicted string: oolll, Epoch [3/15] loss=5.1777
    Predicted string: oolol, Epoch [4/15] loss=4.7279
    Predicted string: oolol, Epoch [5/15] loss=4.2586
    Predicted string: ohlol, Epoch [6/15] loss=3.8693
    Predicted string: ohlol, Epoch [7/15] loss=3.6075
    Predicted string: ohlol, Epoch [8/15] loss=3.3900
    Predicted string: ohlol, Epoch [9/15] loss=3.1333
    Predicted string: ohlol, Epoch [10/15] loss=2.8496
    Predicted string: ohlol, Epoch [11/15] loss=2.5996
    Predicted string: ohlol, Epoch [12/15] loss=2.4079
    Predicted string: ohlol, Epoch [13/15] loss=2.2640
    Predicted string: ohlol, Epoch [14/15] loss=2.1526
    Predicted string: ohlol, Epoch [15/15] loss=2.0646
    
  • 训练过程图解(尤其是尺寸的要求和变化):

    其中交叉熵损失的输入输出尺寸可以参考此篇博客:损失函数。

    在这里插入图片描述

    在这里插入图片描述

  • nn.RNN

    import torch# ==================================================准备数据==================================================
    input_size = 4
    hidden_size = 4
    batch_size = 1
    num_layers = 1
    # seq_len = 5 在这里不用显示定义, 模型会自动识别输入的尺寸idx2char = ['e', 'h', 'l', 'o']  # 字母字典, 复杂情形可以是单词字典
    x_data = [1, 0, 2, 2, 3]  # x_data 表示的单词是 hello, 在这里表示的是输入 input
    y_data = [3, 1, 2, 3, 2]  # y_data 表示的单词是 ohlol, 在这里表示的输出标签
    one_hot_lookup = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]  # 独热字典x_one_hot = [one_hot_lookup[x] for x in x_data]  # x_data 的独热编码向量组, 形状为:(seq_len, input_size)
    # 更改 x_one_hot 的形状, 在中间加一个 batch_size 维度, 其中 -1 参数表示获取 seq_len, 就是列表中的元素个数(5个子列表, 那么个数就是5)
    inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
    labels = torch.LongTensor(y_data)print(x_one_hot)
    print(inputs)
    print(labels)# ==================================================定义模型==================================================
    class Single_RNN(torch.nn.Module):def __init__(self, input_size, hidden_size, batch_size, num_layers=1):super(Single_RNN, self).__init__()self.num_layers = num_layersself.batch_size = batch_sizeself.input_size = input_sizeself.hidden_size = hidden_sizeself.rnn = torch.nn.RNN(input_size=self.input_size, hidden_size=self.hidden_size, num_layers=self.num_layers)def forward(self, input, hidden):output, hidden = self.rnn(input, hidden)# 输出设置成 2 维张量,return output.view(-1, self.hidden_size)def init_hidden(self):return torch.zeros(self.num_layers, self.batch_size, self.hidden_size)net = Single_RNN(input_size, hidden_size, batch_size, num_layers)# ==================================================准备训练==================================================
    criterion = torch.nn.CrossEntropyLoss()  # 交叉熵损失
    optimizer = torch.optim.Adam(net.parameters(), lr=0.05)  # Adam 优化器for epoch in range(15):optimizer.zero_grad()hidden = net.init_hidden()  # 初始化 h0outputs = net(inputs, hidden)loss = criterion(outputs, labels)loss.backward()optimizer.step()_, idx = outputs.max(dim=1)idx = idx.data.numpy()  # 将 idx 变成numpy数组, 元素和尺寸不变print('Predicted: ', ''.join([idx2char[x] for x in idx]), end='')print(', Epoch [%d/ 15] loss=%.4f' % (epoch + 1, loss.item()))

    输出结果:

    Predicted:  ohooe, Epoch [1/ 15] loss=1.2800
    Predicted:  ohooo, Epoch [2/ 15] loss=1.1455
    Predicted:  ohooo, Epoch [3/ 15] loss=1.0370
    Predicted:  ohloo, Epoch [4/ 15] loss=0.9497
    Predicted:  ohlol, Epoch [5/ 15] loss=0.8746
    Predicted:  ohlol, Epoch [6/ 15] loss=0.8034
    Predicted:  ohlol, Epoch [7/ 15] loss=0.7356
    Predicted:  ohlol, Epoch [8/ 15] loss=0.6763
    Predicted:  ohlol, Epoch [9/ 15] loss=0.6283
    Predicted:  ohlol, Epoch [10/ 15] loss=0.5905
    Predicted:  ohlol, Epoch [11/ 15] loss=0.5614
    Predicted:  ohlol, Epoch [12/ 15] loss=0.5392
    Predicted:  ohlol, Epoch [13/ 15] loss=0.5220
    Predicted:  ohlol, Epoch [14/ 15] loss=0.5073
    Predicted:  ohlol, Epoch [15/ 15] loss=0.4934
    


http://www.ppmy.cn/news/1583235.html

相关文章

单片机 - RAM 与内存、ROM 与硬盘 之间的详细对比总结

RAM 与 内存 RAM&#xff08;Random Access Memory&#xff0c;随机存取存储器&#xff09; 和 内存 这两个术语通常是 同义词&#xff0c;即 内存 常常指的就是 RAM。 1. RAM&#xff08;内存&#xff09; 定义&#xff1a;RAM 是计算机中的 主存储器&#xff0c;用于临时存…

微服务中的服务发现与注册中心

在微服务架构中&#xff0c;服务实例的数量可能随着流量负载自动扩展或缩减&#xff0c;因此服务之间如何高效地进行通信成为一个重要问题。本篇博客将介绍服务发现的概念&#xff0c;并结合 Consul 和 自定义注册中心 进行实践&#xff0c;帮助开发者在微服务架构下高效管理服…

结构型——代理模式

结构型——代理模式 代理模式指的是通过创建一个代理来控制对原始对象的访问。代理在客户端与实际对象之间充当“中介” 特点 访问控制&#xff1a;代理对象可以控制对实际对象的访问&#xff0c;从而实现对访问权限的控制。延迟加载&#xff1a;代理对象可以在实际对象被调…

【C语言】多进程/多线程

【C语言】多进程/多线程 参考链接多进程/多线程服务器1. 多进程服务器2. 多线程服务器 结语参考链接 参考链接 c 中文网 菜鸟 c 多进程/多线程服务器 多进程和多线程是常用的并发编程技术。它们都允许程序同时执行多个任务&#xff0c;提高了系统的资源利用率和程序的运行效率…

git-lfs: command not found

遇到 git-lfs: command not found 错误&#xff0c;表示你的系统中未安装 Git Large File Storage (LFS) 扩展工具。以下是针对不同操作系统的解决方案&#xff1a; 1. 安装 Git LFS 根据你的操作系统选择安装方式&#xff1a; macOS 使用 Homebrew&#xff08;推荐&#xff…

MATLAB 中,并行池(Parallel Pool)自动关闭的情况

在 MATLAB 中&#xff0c;并行池&#xff08;Parallel Pool&#xff09;的行为可以通过设置进行控制&#xff0c;但默认情况下&#xff0c;并行池不会自动关闭&#xff0c;除非满足某些条件或显式调用关闭命令。以下是关于并行池自动关闭机制的详细说明&#xff1a; 自动关闭的…

19926 分球

19926 分球 ⭐️考点&#xff1a;数学、排列组合 &#x1f31f;难度&#xff1a;简单 &#x1f4d6; &#x1f4da; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static long[][] dp ne…

盛铂科技SPP5006/18/40G峰值脉冲功率计探头 国产功率计

功率计简述 SPP5000系列是盛铂科技自主开发的自带USB 接口的多功能便携式数字脉冲峰值功率计&#xff0c;可快速执行50MHz至40GHz频率范围和-20dBm至20dBm动态范围的设置和测量&#xff0c;SPP5000系列具备脉冲信号测量与连续波信号测量能力。系统内置等效24Bit 高速采样ADC 并…