各类神经网络学习:(四)RNN 循环神经网络(下集),pytorch 版的 RNN 代码编写
| 上一篇 | 下一篇 |
|---|---|
| RNN(中集) | 待编写 |
代码详解
pytorch 官网主要有两个可调用的模块,分别是 nn.RNNCell 和 nn.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(Wih⋅x+bih+Whh⋅h+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(U⋅xt+W⋅st−1+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} bih、bhh 。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 W、b 都是自动初始化、可自学习的。
- 类的参数解释:
-
调用展示:
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_size和input_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(WihT⋅x+bih+WhhT⋅ht−1+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(U⋅xt+W⋅st−1+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_layers个RNN堆叠在一起,后
一个RNN接收第一个RNN的隐层状态输出作
为输入,并且计算最终结果。 -
nonlinearity(str):激活函数设置项,默认为'tanh'-------------- 可设置为nonlinearity='relu'。 -
bias(bool):偏置设置项,默认为True---------------------------------- 如果为False则不使用偏置 b i h 、 b h h b_{ih}、b_{hh} bih、bhh 。 -
batch_first(bool):输入输出格式设置项,默认为False-------- 如果为True则用户需要按照
(batch_size, seq_len, input_size)来构造数据格式,
默认是(seq_len, batch_size, input_size)。 -
dropout:神经元随机丢弃概率( 0 ∼ 1 0\sim1 0∼1),默认值: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 L 即seq_len, N N N 即batch_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}) (D∗num_layers,N,Hout) 或 ( D ∗ n u m _ l a y e r s , H o u t ) (D*num\_layers,H_{out}) (D∗num_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,D∗Hout) 或 ( L , D ∗ H o u t ) (L,D*H_{out}) (L,D∗Hout) ------------------------当batch_first=True时为 ( N , L , D ∗ H o u t ) (N,L,D∗H_{out}) (N,L,D∗Hout) 。hidden:类型:tensor,形状: ( D ∗ n u m _ l a y e r s , N , H o u t ) (D*num\_layers,N,H_{out}) (D∗num_layers,N,Hout) 或 ( D ∗ n u m _ l a y e r s , H o u t ) (D*num\_layers,H_{out}) (D∗num_layers,Hout) --------------- 此输出代表了最后一个时刻的隐藏层状态输出。
-
其中的权重 W 、 b W、b W、b 都是自动初始化、可自学习的。
其实输出
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.RNNimport 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
相关文章:
各类神经网络学习:(四)RNN 循环神经网络(下集),pytorch 版的 RNN 代码编写
上一篇下一篇RNN(中集)待编写 代码详解 pytorch 官网主要有两个可调用的模块,分别是 nn.RNNCell 和 nn.RNN ,下面会进行详细讲解。 RNN 的同步多对多、多对一、一对多等等结构都是由这两个模块实现的,只需要将对输入…...
DeepSeek 发布DeepSeek-V3-0324 版本 前端与网页开发能力、推理与多任务能力提升
DeepSeek 发布 DeepSeek-V3-0324 版本 DeepSeek 发布 DeepSeek-V3-0324 版本,在其前代模型 DeepSeek-V3 的基础上进行了显著升级。 该模型专注于中文和多语言文本生成、推理、代码编写等综合能力的提升,支持 Function Calling(函数调用&…...
航班时间 | 第九届蓝桥杯省赛C++A组
小 h 前往美国参加了蓝桥杯国际赛。 小 h 的女朋友发现小 h 上午十点出发,上午十二点到达美国,于是感叹到“现在飞机飞得真快,两小时就能到美国了”。 小 hh 对超音速飞行感到十分恐惧。 仔细观察后发现飞机的起降时间都是当地时间。 由于…...
传输层安全协议 SSL/TLS 详细介绍
传输层安全性协议TLS及其前身安全套接层SSL是一种安全传输协议,目前TLS协议已成为互联网上保密通信的工业标准,在浏览器、邮箱、即时通信、VoIP等应用程序中得到广泛的应用。本文对SSL和TLS协议进行一个详细的介绍,以便于大家更直观的理解和认…...
编程实现自我指涉(self-reference)
从计算机的组成原理出发,编程实现自我指涉(self-reference)本质上是通过代码操纵代码,形成逻辑上的闭环。这种能力不仅是编程语言设计中的一个奇妙现象,更是计算理论、计算机架构、乃至哲学层面的一种深刻映射。让我们…...
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
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
【单元测试】
一、框架 不同的编程语言有不同的测试框架,以下是一些常见的测试框架: 1)Java:JUnit、TestNG2)Python:unittest、pytest3)JavaScript:Jest、Mocha4)C#:NUni…...
【今日EDA行业分析】2025年3月24日
今日 EDA 行业分析:中国在全球格局下的奋进之路 一、引言 在半导体产业的精密体系中,EDA 软件宛如一颗璀璨的明珠,其重要性不言而喻。它不仅是集成电路设计的核心支撑,更是连接芯片设计、制造、封装与测试各环节的关键纽带。今天…...
基于 PHP 内置类及函数的免杀 WebShell
前言 PHP 作为广泛使用的服务端语言,其灵活的内置类(如 DOMDocument)和文件操作机制(.ini、.inc 的自动加载),为攻击者提供了天然的隐蔽通道。通过 动态函数拼接、反射调用、加密混淆 和 伪命名空间 等手法…...
鸿蒙移动应用开发--UI组件布局
实验要求: 制作一个B站视频卡片界面,大致如下图所示,要求应用到线性布局、层叠布局等相关课堂知识。背景图、logo及文本内容不限。 实验环境 :DevEco Studio 实验过程: 步骤1:创建项目 1. 在您的开发环境…...
内核编程十二:打印内核态进程的属性
在Linux内核中,current 是一个宏,用于获取当前正在执行的进程的 task_struct 结构体指针。current 宏返回一个指向当前正在运行的进程的 task_struct 结构体的指针。通过这个指针,内核代码可以访问和修改当前进程的各种属性和状态。 打印单个…...
C++(16)—类和对象(下) ①再探构造函数
文章目录 一、构造函数初始化方式回顾二、初始化列表详解1. 初始化列表语法与特点2. 必须使用初始化列表的成员变量 三、初始化列表的底层机制四、最佳实践五、总结 一、构造函数初始化方式回顾 在C中,构造函数用于初始化对象的成员变量。传统的初始化方式是在构造…...
[新闻.AI]国产大模型新突破:阿里开源 Qwen2.5-VL-32B 与 DeepSeek 升级 V3 模型
(本文借助 Deepseek-R1 协助生成) 在2025年3月24日至25日的短短24小时内,中国AI领域迎来两大重磅开源更新:阿里通义千问团队发布多模态大模型Qwen2.5-VL-32B-Instruct,而DeepSeek则推出编程能力大幅提升的DeepSeek-V3…...
投sci论文自己查重方法
首先进入查重网站科研者之家-Home of Reasearchers 会看到里面有很多小工具(比较高级的是要付费的) 我们找到论文查重的小工具:论文查重——>英文论文自助查重系统 把论文上传...
数值分析作业插值法2
埃尔米特插值 不仅要求函数值重合,而且要求若干阶导数也重合,这种插值问题称为埃尔米特插值问题。 低次埃尔米特插值多项式 二点三次埃尔米特插值多项式 **问题描述:**给定区间 [ x 0 , x 1 ] [x_0, x_1] [x0,x1] 两端点的函数值与导数…...
宝塔docker flarum默认登录账号密码,crazymax/flarum镜像默认登录账号密码
docker flarum默认账号密码 刚创建完毕时的登录账号和密码都是flarum 来源说明 宝塔安装的这个1.8.5版本的docker flarum的版本是,用的是 Docker库 https://hub.docker.com/r/crazymax/flarum Github库 https://github.com/crazy-max/docker-flarum...
TailwindCSS安装教程(PostCSS)
#官方教程简直是一坨,自己跑ai查文章做出来的安装总结,作者开发环境为Vue2VueCLI# 本文为TailwindCSS3.4版本安装教程 1,安装tailwindcss3.4.1 npm install -D tailwindcss3.4.1 2, 初始化TailwindCSS配置文件 npx tailwindcss init 3&…...
电脑干货:万能驱动--EasyDrv8
目录 万能驱动EasyDrv8 功能介绍 主程序界面 驱动解压与安装 PE环境支持 系统部署环境 桌面环境一键解决方案 万能驱动8电脑版是由IT天空出品的一款智能识别电脑硬件并自动安装驱动的工具,一般又称为it天空万能驱动,万能驱动vip版,简称…...
基于Flask的通用登录注册模块,并代理跳转到目标网址
实现了用户密码的加密,代理跳转到目标网址,不会暴露目标路径,未登录的情况下访问proxy则自动跳转到登录页,使用时需要修改配置项config,登录注册页面背景快速修改,可以实现登录注册模块的快速复用。 1.app…...
个人学习编程(3-25) leetcode刷题
验证括号字符串: 用了两个栈来存放。 只需要考虑) 优先用 ( 其次用* 即可 #include <bits/stdc.h> using namespace std;bool checkValidString(char* s){int len strlen(s);stack<int> left_stack,star_stack;for (int i 0; i < len; i){if(s[i] (){left_st…...
vue中实现元素在界面中自由拖动
这是一个使用 Vue 2 实现可拖动 div 的示例。 <!DOCTYPE html> <html> <head><title>Vue 2 可拖动 Div</title><script src"https://cdn.jsdelivr.net/npm/vue2.6.14/dist/vue.js"></script><style>#draggable-div…...
量子计算在密码学中的应用:机遇与挑战并存
引言 在数字化时代的浪潮中,密码学作为信息安全的核心技术,始终扮演着至关重要的角色。从保护个人隐私到保障国家机密,密码学的每一次进步都为信息安全筑牢了防线。然而,随着量子计算技术的飞速发展,传统密码学体系面…...
使用go实现导入Rxcel数据到数据库并渲染到页面上
github.com/360EntSecGroup-Skylar/excelize github.com/tealeg/xlsx 可以使用以上两个库 代码如下: // jsonResult 返回 JSON 格式的结果 func (c *TemplateController) jsonResult(code int, msg string, data interface{}) {c.Data["json"] map[s…...
C++中将记录集的数据复制到Excel工作表中的CRange类CopyFromRecordset函数异常怎么捕获
文章目录 一、异常类型及捕获逻辑二、完整代码示例三、关键错误场景与解决方案1. CopyFromRecordset 返回空数据2. COM错误 0x800A03EC3. Excel进程残留4. 内存不足 四、调试与日志记录1. 启用详细日志2. 捕获错误描述3. 调试断点 五、最佳实践 在C中使用 CRange::CopyFromReco…...
使用vector构造杨辉三角形
力扣118题: 给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。 示例 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、乱码 现象 操作系统:ubuntu24.04 conda版本:25.1.1 正常的终端里gitk显示不会模糊 但是在conda创建的python虚拟环境中使用gitk,字体开始变得模糊不清 分析 根据deepseek的原因原因分析…...
Contactile三轴触觉传感器:多维力感赋能机器人抓取
在非结构化环境中,机器人对物体的精准抓取与操作始终面临巨大挑战。传统传感器因无法全面感知触觉参数(如三维力、位移、摩擦),难以适应复杂多变的场景。Contactile推出的三轴触觉力传感器,通过仿生设计与创新光学技术…...
远程登录服务(ssh)
一、远程登录服务概述 1. 概念 远程登录服务就像是一个神奇的桥梁,它让你能够跨越物理距离,通过网络连接到另一台计算机上进行操作。无论你身在何处,只要有网络连接,你就可以像坐在目标计算机前一样进行各种操作。 2. 功能 分享…...
如何在阿里云linux主机上部署Node.Js
在阿里云的Linux服务器上搭建Node.js编程环境可以通过以下步骤完成。这里以常见的 Ubuntu/CentOS 系统为例,提供两种安装方式(包管理器、NVM多版本管理): 一、通过包管理器安装(适合快速安装指定版本) 1. …...
