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

news2025/4/21 9:52:05
上一篇下一篇
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 torch
    
    cell = 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 torch
    
    batch_size = 2
    seq_len = 3
    input_size = 4
    hidden_size = 2
    
    cell = 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 torch
      
      cell= 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 torch
      
      cell= 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 torch
    
    batch_size = 2
    seq_len = 3
    input_size = 4
    hidden_size = 2
    num_layers = 1
    
    single_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 SummaryWriter

writer = 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 out


model = 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 = 0
    for 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_size
            self.input_size = input_size
            self.hidden_size = hidden_size
            self.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 hidden
    
        def 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 = 0
        optimizer.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_layers
            self.batch_size = batch_size
            self.input_size = input_size
            self.hidden_size = hidden_size
            self.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()  # 初始化 h0
    
        outputs = 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.coloradmin.cn/o/2322014.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DeepSeek 发布DeepSeek-V3-0324 版本 前端与网页开发能力、推理与多任务能力提升

DeepSeek 发布 DeepSeek-V3-0324 版本 DeepSeek 发布 DeepSeek-V3-0324 版本&#xff0c;在其前代模型 DeepSeek-V3 的基础上进行了显著升级。 该模型专注于中文和多语言文本生成、推理、代码编写等综合能力的提升&#xff0c;支持 Function Calling&#xff08;函数调用&…

传输层安全协议 SSL/TLS 详细介绍

传输层安全性协议TLS及其前身安全套接层SSL是一种安全传输协议&#xff0c;目前TLS协议已成为互联网上保密通信的工业标准&#xff0c;在浏览器、邮箱、即时通信、VoIP等应用程序中得到广泛的应用。本文对SSL和TLS协议进行一个详细的介绍&#xff0c;以便于大家更直观的理解和认…

CentOS8 安装 Docker-CE

如果之前安装过docker,请先卸载旧版本: yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 安装所需的软件包: yum install -y yum-utils 添加软件源信息(设置存储库)…

【Docker系列八】使用 Docker run 命令部署 Nginx

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

基于 PHP 内置类及函数的免杀 WebShell

前言 PHP 作为广泛使用的服务端语言&#xff0c;其灵活的内置类&#xff08;如 DOMDocument&#xff09;和文件操作机制&#xff08;.ini、.inc 的自动加载&#xff09;&#xff0c;为攻击者提供了天然的隐蔽通道。通过 动态函数拼接、反射调用、加密混淆 和 伪命名空间 等手法…

鸿蒙移动应用开发--UI组件布局

实验要求&#xff1a; 制作一个B站视频卡片界面&#xff0c;大致如下图所示&#xff0c;要求应用到线性布局、层叠布局等相关课堂知识。背景图、logo及文本内容不限。 实验环境 &#xff1a;DevEco Studio 实验过程&#xff1a; 步骤1&#xff1a;创建项目 1. 在您的开发环境…

C++(16)—类和对象(下) ①再探构造函数

文章目录 一、构造函数初始化方式回顾二、初始化列表详解1. 初始化列表语法与特点2. 必须使用初始化列表的成员变量 三、初始化列表的底层机制四、最佳实践五、总结 一、构造函数初始化方式回顾 在C中&#xff0c;构造函数用于初始化对象的成员变量。传统的初始化方式是在构造…

投sci论文自己查重方法

首先进入查重网站科研者之家-Home of Reasearchers 会看到里面有很多小工具&#xff08;比较高级的是要付费的&#xff09; 我们找到论文查重的小工具&#xff1a;论文查重——>英文论文自助查重系统 把论文上传

宝塔docker flarum默认登录账号密码,crazymax/flarum镜像默认登录账号密码

docker flarum默认账号密码 刚创建完毕时的登录账号和密码都是flarum 来源说明 宝塔安装的这个1.8.5版本的docker flarum的版本是&#xff0c;用的是 Docker库 https://hub.docker.com/r/crazymax/flarum Github库 https://github.com/crazy-max/docker-flarum

电脑干货:万能驱动--EasyDrv8

目录 万能驱动EasyDrv8 功能介绍 主程序界面 驱动解压与安装 PE环境支持 系统部署环境 桌面环境一键解决方案 万能驱动8电脑版是由IT天空出品的一款智能识别电脑硬件并自动安装驱动的工具&#xff0c;一般又称为it天空万能驱动&#xff0c;万能驱动vip版&#xff0c;简称…

C++中将记录集的数据复制到Excel工作表中的CRange类CopyFromRecordset函数异常怎么捕获

文章目录 一、异常类型及捕获逻辑二、完整代码示例三、关键错误场景与解决方案1. CopyFromRecordset 返回空数据2. COM错误 0x800A03EC3. Excel进程残留4. 内存不足 四、调试与日志记录1. 启用详细日志2. 捕获错误描述3. 调试断点 五、最佳实践 在C中使用 CRange::CopyFromReco…

使用vector构造杨辉三角形

力扣118题&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRows 1…

conda环境下解决gitk乱码模糊

关键词 conda、git、gitk、git gui、模糊、linux、乱码 现象 操作系统&#xff1a;ubuntu24.04 conda版本&#xff1a;25.1.1 正常的终端里gitk显示不会模糊 但是在conda创建的python虚拟环境中使用gitk&#xff0c;字体开始变得模糊不清 分析 根据deepseek的原因原因分析…

Contactile三轴触觉传感器:多维力感赋能机器人抓取

在非结构化环境中&#xff0c;机器人对物体的精准抓取与操作始终面临巨大挑战。传统传感器因无法全面感知触觉参数&#xff08;如三维力、位移、摩擦&#xff09;&#xff0c;难以适应复杂多变的场景。Contactile推出的三轴触觉力传感器&#xff0c;通过仿生设计与创新光学技术…

远程登录服务(ssh)

一、远程登录服务概述 1. 概念 远程登录服务就像是一个神奇的桥梁&#xff0c;它让你能够跨越物理距离&#xff0c;通过网络连接到另一台计算机上进行操作。无论你身在何处&#xff0c;只要有网络连接&#xff0c;你就可以像坐在目标计算机前一样进行各种操作。 2. 功能 分享…

如何在阿里云linux主机上部署Node.Js

在阿里云的Linux服务器上搭建Node.js编程环境可以通过以下步骤完成。这里以常见的 Ubuntu/CentOS 系统为例&#xff0c;提供两种安装方式&#xff08;包管理器、NVM多版本管理&#xff09;&#xff1a; 一、通过包管理器安装&#xff08;适合快速安装指定版本&#xff09; 1. …

VS Code连接远程服务遇到的问题

目录 一、VS Code链接远程服务 二、修改的文件不能保存 三、无法与 "Ip地址" 建立连接: 远程主机密钥已更改&#xff0c;端口转发已禁用. 四、解决远程连接后&#xff0c;每次断开让输入密码问题&#xff0c;实现免密登录 没有秘钥对&#xff0c;免密配置流程&a…

大模型训练 | 智能体知识库 资源收集之心理咨询问答数据集

最近我一直在研究AI大模型相关的内容&#xff0c;想着从现在开始慢慢收集各种各样的资源&#xff0c;万一以后需要训练大模型的时候可以用到&#xff0c;或者自己以后也许会需要。今天我想介绍一组“心理咨询问答数据集”产品&#xff0c;包含9414条心理咨询问答数据&#xff0…

AI Agent开发大全第十一课-超维空间里的语义翻译官:Embedding技术

一、Embedding:数字世界的"翻译官"与"导航仪" 1.1 从字符到向量的魔法 当我们输入"巧克力"三个字时,传统计算机只能识别ASCII码组成的符号序列,而Embedding技术就像给每个词语配备了"超维定位坐标"。通过深度学习模型,它将离散的…

2024年第九届全国固态电池研讨会(脱敏)PPT合集(41份).zip

2024年第九届全国固态电池研讨会&#xff08;脱敏&#xff09;PPT合集&#xff0c;共41份。供大家参考学习。 1、锂金属全固态电池关键材料与器件.pdf 2、聚醚基聚合物锂金属电池.pdf 3、氧化物固态电解质与高能量密度安全固态锂电池.pdf 4、复合固态电解质界面设计工艺探索与…