【实验15】LSTM的记忆能力实验
目录
1 模型构建
1.1 LSTM层
1.1.1 自定义LSTM算子
1.1.2 nn.LSTM
1.1.3 将自定义LSTM与pytorch内置的LSTM进行对比
1.2 模型汇总
2 模型训练
2.1 训练指定长度的数字预测模型
2.2 多组训练
2.3 损失函数展示
3 模型评价
4 完整代码
5 LSTM模型门状态和单元状态的变化
5.1 更新LSTM模块
5.2 加载模型
5.3 完整代码
参考链接
点击查看作业
1 模型构建
使用实验14中定义Model_RNN4SeqClass模型,并构建 LSTM 算子。只需要实例化 LSTM ,并传入Model_RNN4SeqClass模型,就可以用 LSTM 进行数字求和实验。
1.1 LSTM层
1.1.1 自定义LSTM算子
按照上述步骤,自定义LSTM算子,代码如下:
class LSTM(nn.Module):def __init__(self, input_size, hidden_size, Wi_attr=None, Wf_attr=None, Wo_attr=None, Wc_attr=None,Ui_attr=None, Uf_attr=None, Uo_attr=None, Uc_attr=None, bi_attr=None, bf_attr=None,bo_attr=None, bc_attr=None):super(LSTM, self).__init__()self.input_size = input_sizeself.hidden_size = hidden_size# 初始化模型参数if Wi_attr==None:Wi= torch.zeros(size=[input_size, hidden_size], dtype=torch.float32)else:Wi = torch.tensor(Wi_attr, dtype=torch.float32)self.W_i = torch.nn.Parameter(Wi)if Wf_attr==None:Wf=torch.zeros(size=[input_size, hidden_size], dtype=torch.float32)else:Wf = torch.tensor(Wf_attr, dtype=torch.float32)self.W_f = torch.nn.Parameter(Wf)if Wo_attr==None:Wo=torch.zeros(size=[input_size, hidden_size], dtype=torch.float32)else:Wo = torch.tensor(Wo_attr, dtype=torch.float32)self.W_o =torch.nn.Parameter(Wo)if Wc_attr==None:Wc=torch.zeros(size=[input_size, hidden_size], dtype=torch.float32)else:Wc = torch.tensor(Wc_attr, dtype=torch.float32)self.W_c = torch.nn.Parameter(Wc)if Ui_attr==None:Ui = torch.zeros(size=[hidden_size, hidden_size], dtype=torch.float32)else:Ui = torch.tensor(Ui_attr, dtype=torch.float32)self.U_i = torch.nn.Parameter(Ui)if Uf_attr == None:Uf = torch.zeros(size=[hidden_size, hidden_size], dtype=torch.float32)else:Uf = torch.tensor(Uf_attr, dtype=torch.float32)self.U_f = torch.nn.Parameter(Uf)if Uo_attr == None:Uo = torch.zeros(size=[hidden_size, hidden_size], dtype=torch.float32)else:Uo = torch.tensor(Uo_attr, dtype=torch.float32)self.U_o = torch.nn.Parameter(Uo)if Uc_attr == None:Uc = torch.zeros(size=[hidden_size, hidden_size], dtype=torch.float32)else:Uc = torch.tensor(Uc_attr, dtype=torch.float32)self.U_c = torch.nn.Parameter(Uc)if bi_attr == None:bi = torch.zeros(size=[1,hidden_size], dtype=torch.float32)else:bi = torch.tensor(bi_attr, dtype=torch.float32)self.b_i = torch.nn.Parameter(bi)if bf_attr == None:bf = torch.zeros(size=[1,hidden_size], dtype=torch.float32)else:bf = torch.tensor(bf_attr, dtype=torch.float32)self.b_f = torch.nn.Parameter(bf)if bo_attr == None:bo = torch.zeros(size=[1,hidden_size], dtype=torch.float32)else:bo = torch.tensor(bo_attr, dtype=torch.float32)self.b_o = torch.nn.Parameter(bo)if bc_attr == None:bc = torch.zeros(size=[1,hidden_size], dtype=torch.float32)else:bc = torch.tensor(bc_attr, dtype=torch.float32)self.b_c = torch.nn.Parameter(bc)# 初始化状态向量和隐状态向量def init_state(self, batch_size):hidden_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)cell_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)return hidden_state, cell_state# 定义前向计算def forward(self, inputs, states=None):# inputs: 输入数据,其shape为batch_size x seq_len x input_sizebatch_size, seq_len, input_size = inputs.shape# 初始化起始的单元状态和隐状态向量,其shape为batch_size x hidden_sizeif states is None:states = self.init_state(batch_size)hidden_state, cell_state = states# 执行LSTM计算,包括:输入门、遗忘门和输出门、候选内部状态、内部状态和隐状态向量for step in range(seq_len):# 获取当前时刻的输入数据step_input: 其shape为batch_size x input_sizestep_input = inputs[:, step, :]# 计算输入门, 遗忘门和输出门, 其shape为:batch_size x hidden_sizeI_gate = F.sigmoid(torch.matmul(step_input, self.W_i) + torch.matmul(hidden_state, self.U_i) + self.b_i)F_gate = F.sigmoid(torch.matmul(step_input, self.W_f) + torch.matmul(hidden_state, self.U_f) + self.b_f)O_gate = F.sigmoid(torch.matmul(step_input, self.W_o) + torch.matmul(hidden_state, self.U_o) + self.b_o)# 计算候选状态向量, 其shape为:batch_size x hidden_sizeC_tilde = F.tanh(torch.matmul(step_input, self.W_c) + torch.matmul(hidden_state, self.U_c) + self.b_c)# 计算单元状态向量, 其shape为:batch_size x hidden_sizecell_state = F_gate * cell_state + I_gate * C_tilde# 计算隐状态向量,其shape为:batch_size x hidden_sizehidden_state = O_gate * F.tanh(cell_state)return hidden_state
测试一下:
if __name__ == "__main__":Wi_attr = [[0.1, 0.2], [0.1, 0.2]]Wf_attr = [[0.1, 0.2], [0.1, 0.2]]Wo_attr = [[0.1, 0.2], [0.1, 0.2]]Wc_attr = [[0.1, 0.2], [0.1, 0.2]]Ui_attr = [[0.0, 0.1], [0.1, 0.0]]Uf_attr = [[0.0, 0.1], [0.1, 0.0]]Uo_attr = [[0.0, 0.1], [0.1, 0.0]]Uc_attr = [[0.0, 0.1], [0.1, 0.0]]bi_attr = [[0.1, 0.1]]bf_attr = [[0.1, 0.1]]bo_attr = [[0.1, 0.1]]bc_attr = [[0.1, 0.1]]lstm = LSTM(2, 2, Wi_attr=Wi_attr, Wf_attr=Wf_attr, Wo_attr=Wo_attr, Wc_attr=Wc_attr,Ui_attr=Ui_attr, Uf_attr=Uf_attr, Uo_attr=Uo_attr, Uc_attr=Uc_attr,bi_attr=bi_attr, bf_attr=bf_attr, bo_attr=bo_attr, bc_attr=bc_attr)inputs = torch.as_tensor([[[1, 0]]], dtype=torch.float32)hidden_state = lstm(inputs)print(hidden_state)
运行结果:
tensor([[0.0594, 0.0952]], grad_fn=<MulBackward0>)
1.1.2 nn.LSTM
pytorch框架已经内置了LSTM的API torch.nn.LSTM
,其与自己实现的LSTM不同点在于其实现时采用了两个偏置,同时矩阵相乘时参数在输入数据前面。
# 这里创建一个随机数组作为测试数据,数据shape为batch_size x seq_len x input_size
batch_size, seq_len, input_size = 8, 20, 32
inputs = torch.randn(size=[batch_size, seq_len, input_size])# 设置模型的hidden_size
hidden_size = 32
torch_lstm = nn.LSTM(input_size, hidden_size)
self_lstm = LSTM(input_size, hidden_size)self_hidden_state = self_lstm(inputs)
torch_outputs, (torch_hidden_state, torch_cell_state) = torch_lstm(inputs)print("self_lstm hidden_state: ", self_hidden_state.shape)
print("torch_lstm outpus:", torch_outputs.shape)
print("torch_lstm hidden_state:", torch_hidden_state.shape)
print("torch_lstm cell_state:", torch_cell_state.shape)
运行结果:
自定义LSTM模型的隐藏状态形状: torch.Size([8, 32])
PyTorch内置LSTM模型的输出形状: torch.Size([8, 20, 32])
PyTorch内置LSTM模型的隐藏状态形状: torch.Size([1, 20, 32])
PyTorch内置LSTM模型的细胞状态形状: torch.Size([1, 20, 32])
1.1.3 将自定义LSTM与pytorch内置的LSTM进行对比
if __name__ == "__main__":torch.seed()# 这里创建一个随机数组作为测试数据,数据shape为batch_size x seq_len x input_sizebatch_size, seq_len, input_size, hidden_size = 2, 5, 10, 10inputs = torch.randn([batch_size, seq_len, input_size])# 设置模型的hidden_sizetorch_lstm = nn.LSTM(input_size, hidden_size, bias=True)# 获取torch_lstm中的参数,并设置相应的paramAttr,用于初始化lstmprint(torch_lstm.weight_ih_l0.T.shape)chunked_W = torch.split(torch_lstm.weight_ih_l0.T, split_size_or_sections=10, dim=-1)chunked_U = torch.split(torch_lstm.weight_hh_l0.T, split_size_or_sections=10, dim=-1)chunked_b = torch.split(torch_lstm.bias_hh_l0.T, split_size_or_sections=10, dim=-1)Wi_attr = chunked_W[0]Wf_attr = chunked_W[1]Wc_attr = chunked_W[2]Wo_attr = chunked_W[3]Ui_attr = chunked_U[0]Uf_attr = chunked_U[1]Uc_attr = chunked_U[2]Uo_attr = chunked_U[3]bi_attr = chunked_b[0]bf_attr = chunked_b[1]bc_attr = chunked_b[2]bo_attr = chunked_b[3]self_lstm = LSTM(input_size, hidden_size, Wi_attr=Wi_attr, Wf_attr=Wf_attr, Wo_attr=Wo_attr, Wc_attr=Wc_attr,Ui_attr=Ui_attr, Uf_attr=Uf_attr, Uo_attr=Uo_attr, Uc_attr=Uc_attr,bi_attr=bi_attr, bf_attr=bf_attr, bo_attr=bo_attr, bc_attr=bc_attr)# 进行前向计算,获取隐状态向量,并打印展示self_hidden_state = self_lstm(inputs)torch_outputs, (torch_hidden_state, _) = torch_lstm(inputs)print("torch SRN:\n", torch_hidden_state.detach().numpy().squeeze(0))print("self SRN:\n", self_hidden_state.detach().numpy())
运行结果:
torch.Size([10, 40])
torch SRN:[[ 0.2969815 0.1086378 0.05495247 0.16001733 -0.01765362 -0.01666818-0.4510294 0.20638691 -0.09251023 0.09739175][ 0.23277274 -0.10821889 0.03411719 -0.11256714 -0.02222441 0.098610050.00121753 -0.06674305 -0.00696032 -0.02799534][-0.15640028 0.073895 0.06848664 -0.2405297 -0.07884839 -0.096839210.02928804 0.13920753 -0.10820512 -0.2054754 ][ 0.18748651 0.05720734 0.02512662 0.03938162 0.0495715 -0.080139640.07909831 0.01476525 -0.03023764 -0.06460781][ 0.0621758 -0.06849629 -0.13514322 -0.16372547 0.13364998 -0.049754380.08765104 -0.0199671 -0.05091303 -0.16918302]]
self SRN:[[ 0.25378907 -0.214644 -0.19686568 0.09091267 0.03282058 0.122642930.23509862 0.0867407 0.06242546 -0.076696 ][ 0.07579923 0.04447011 0.0274142 -0.23055007 0.01518452 -0.117584030.05007537 0.03515109 -0.20356342 -0.21308717]]Process finished with exit code 0
可以看到,两者的输出基本是一致的。
1.2 模型汇总
使用实验十四的Model_RNN4SeqClass作为预测模型,不同在于在实例化时将传入实例化的LSTM层。
导入所需的模块:
from model1 import load_data,DataLoader,Model_RNN4SeqClass,DigitSumDataset
2 模型训练
2.1 训练指定长度的数字预测模型
# 训练轮次
num_epochs = 500
# 学习率
lr = 0.001
# 输入数字的类别数
num_digits = 10
# 将数字映射为向量的维度
input_size = 32
# 隐状态向量的维度
hidden_size = 32
# 预测数字的类别数
num_classes = 19
# 批大小
batch_size = 8
# 模型保存目录
save_dir = "./checkpoints"# 可以设置不同的length进行不同长度数据的预测实验
def train(length):print(f"\n====> Training LSTM with data of length {length}.")# 固定随机种子np.random.seed(0)random.seed(0)torch.manual_seed(0)# 加载长度为length的数据data_path = f"../实验14-循环神经网络(1)SRN记忆能力-梯度爆炸/SRN记忆能力/datasets/{length}"train_examples, dev_examples, test_examples = load_data(data_path)train_set, dev_set, test_set = DigitSumDataset(train_examples), DigitSumDataset(dev_examples), DigitSumDataset(test_examples)train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch_size)dev_loader = torch.utils.data.DataLoader(dev_set, batch_size=batch_size)test_loader = torch.utils.data.DataLoader(test_set, batch_size=batch_size)# 实例化模型base_model = LSTM(input_size, hidden_size)model = Model_RNN4SeqClass(base_model, num_digits, input_size, hidden_size, num_classes)# 指定优化器optimizer = torch.optim.Adam(lr=lr, params=model.parameters())# 定义评价指标metric = Accuracy()# 定义损失函数loss_fn = nn.CrossEntropyLoss()# 基于以上组件,实例化Runnerrunner = RunnerV3(model, optimizer, loss_fn, metric)# 进行模型训练model_save_path = os.path.join(save_dir, f"best_lstm_model_{length}.pdparams")runner.train(train_loader, dev_loader, num_epochs=num_epochs, eval_steps=100, log_steps=100,save_path=model_save_path)return runner
2.2 多组训练
lstm_runners = {}
lengths = [10, 15, 20, 25, 30, 35]
for length in lengths:runner = train(length)lstm_runners[length] = runner
运行结果:
====> Training LSTM with data of length 10.
[Train] epoch: 0/500, step: 0/19000, loss: 2.83505
[Train] epoch: 2/500, step: 100/19000, loss: 2.77561
[Evaluate] dev score: 0.09000, dev loss: 2.86460
[Evaluate] best accuracy performence has been updated: 0.00000 --> 0.09000
[Train] epoch: 5/500, step: 200/19000, loss: 2.48144
.....
====> Training LSTM with data of length 15.
[Train] epoch: 0/500, step: 0/19000, loss: 2.83505
[Train] epoch: 2/500, step: 100/19000, loss: 2.78581
[Evaluate] dev score: 0.07000, dev loss: 2.86551
.....====> Training LSTM with data of length 20.
[Train] epoch: 0/500, step: 0/19000, loss: 2.83505
[Train] epoch: 2/500, step: 100/19000, loss: 2.76947
[Evaluate] dev score: 0.10000, dev loss: 2.85964
[Evaluate] best accuracy performence has been updated: 0.00000 --> 0.10000
......====> Training LSTM with data of length 30.
[Train] epoch: 0/500, step: 0/19000, loss: 2.83505
[Train] epoch: 2/500, step: 100/19000, loss: 2.78386
[Evaluate] dev score: 0.12000, dev loss: 2.86110
......
[Train] epoch: 492/500, step: 18700/19000, loss: 0.05709
[Evaluate] dev score: 0.87000, dev loss: 0.55586
[Train] epoch: 494/500, step: 18800/19000, loss: 0.05657
[Evaluate] dev score: 0.89000, dev loss: 0.54544
[Evaluate] best accuracy performence has been updated: 0.88000 --> 0.89000
[Train] epoch: 497/500, step: 18900/19000, loss: 0.04575
[Evaluate] dev score: 0.87000, dev loss: 0.54134
[Evaluate] dev score: 0.83000, dev loss: 0.61010
[Train] Training done!
2.3 损失函数展示
# 画出训练过程中的损失图
for length in lengths:runner = lstm_runners[length]save_path = os.path.dirname(f'./images/6.6_{length}.pdf')# 如果目录不存在,则创建它if not os.path.exists(save_path):os.makedirs(save_path)plot_training_loss(runner, save_path, sample_step=100)
【分析】对比下面实验十四中普通循环网络的可视化结果,可见LSTM模型在序列长度增加时,收敛情况比SRN模型更好。但是随着序列长度的增加,训练集上的损失逐渐不稳定,验证集上的损失整体趋向于变大,这说明当序列长度增加时,保持长期依赖的能力同样在逐渐变弱。
3 模型评价
# =================模型测试=================
lstm_dev_scores = []
lstm_test_scores = []
for length in lengths:print(f"Evaluate LSTM with data length {length}.")runner = lstm_runners[length]# 加载训练过程中效果最好的模型model_path = os.path.join(save_dir, f"best_lstm_model_{length}.pdparams")runner.load_model(model_path)# 加载长度为length的数据data_path = f"../实验14-循环神经网络(1)SRN记忆能力-梯度爆炸/SRN记忆能力/datasets/{length}"train_examples, dev_examples, test_examples = load_data(data_path)test_set = DigitSumDataset(test_examples)test_loader = DataLoader(test_set, batch_size=batch_size)# 使用测试集评价模型,获取测试集上的预测准确率score, _ = runner.evaluate(test_loader)lstm_test_scores.append(score)lstm_dev_scores.append(max(runner.dev_scores))for length, dev_score, test_score in zip(lengths, lstm_dev_scores, lstm_test_scores):print(f"[LSTM] length:{length}, dev_score: {dev_score}, test_score: {test_score: .5f}")
运行结果:
Evaluate LSTM with data length 10.
Evaluate LSTM with data length 15.
Evaluate LSTM with data length 20.
Evaluate LSTM with data length 25.
Evaluate LSTM with data length 30.
Evaluate LSTM with data length 35.
[LSTM] length:10, dev_score: 0.73, test_score: 0.69000
[LSTM] length:15, dev_score: 0.8, test_score: 0.84000
[LSTM] length:20, dev_score: 0.74, test_score: 0.72000
[LSTM] length:25, dev_score: 0.41, test_score: 0.44000
[LSTM] length:30, dev_score: 0.89, test_score: 0.85000
[LSTM] length:35, dev_score: 0.89, test_score: 0.80000
可视化一下:
# 在不同长度的验证集和测试集数据上的表现,绘制成图片进行观察=======================
plt.plot(lengths, lstm_dev_scores, '-o', color='#e8609b', label="LSTM Dev Accuracy")
plt.plot(lengths, lstm_test_scores,'-o', color='#000000', label="LSTM Test Accuracy")# 绘制坐标轴和图例
plt.ylabel("accuracy", fontsize='large')
plt.xlabel("sequence length", fontsize='large')
plt.legend(loc='lower left', fontsize='x-large')fig_name = "./images/6.12.pdf"
plt.savefig(fig_name)
plt.show()
运行结果:
对比下图实验十四的模型测试结果,可以看出LSTM模型的准确率显著高于SRN模型,表明LSTM模型保持长期依赖的能力要优于SRN模型(得益于LSTM最核心的门控机制).
4 完整代码
'''
@Function: 实现数字求和任务测试LSTM网络的记忆能力,验证LSTM在参数学习时可以有效解决长程依赖问题
@Author: lxy
@Date: 2024/12/7
'''
import os
import random
import torch
import torch.nn as nn
import numpy as np
from Runner import Accuracy,RunnerV3,plot_training_loss
from LSTMselfdefine import LSTM
import sys
from model1 import load_data,DataLoader,Model_RNN4SeqClass,DigitSumDataset
import matplotlib.pyplot as plt# ===============模型训练===================
# 训练轮次
num_epochs = 500
# 学习率
lr = 0.001
# 输入数字的类别数
num_digits = 10
# 将数字映射为向量的维度
input_size = 32
# 隐状态向量的维度
hidden_size = 32
# 预测数字的类别数
num_classes = 19
# 批大小
batch_size = 8
# 模型保存目录
save_dir = "./checkpoints"# 可以设置不同的length进行不同长度数据的预测实验
def train(length):print(f"\n====> Training LSTM with data of length {length}.")# 固定随机种子np.random.seed(0)random.seed(0)torch.manual_seed(0)# 加载长度为length的数据data_path = f"../实验14-循环神经网络(1)SRN记忆能力-梯度爆炸/SRN记忆能力/datasets/{length}"train_examples, dev_examples, test_examples = load_data(data_path)train_set, dev_set, test_set = DigitSumDataset(train_examples), DigitSumDataset(dev_examples), DigitSumDataset(test_examples)train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch_size)dev_loader = torch.utils.data.DataLoader(dev_set, batch_size=batch_size)test_loader = torch.utils.data.DataLoader(test_set, batch_size=batch_size)# 实例化模型base_model = LSTM(input_size, hidden_size)model = Model_RNN4SeqClass(base_model, num_digits, input_size, hidden_size, num_classes)# 指定优化器optimizer = torch.optim.Adam(lr=lr, params=model.parameters())# 定义评价指标metric = Accuracy()# 定义损失函数loss_fn = nn.CrossEntropyLoss()# 基于以上组件,实例化Runnerrunner = RunnerV3(model, optimizer, loss_fn, metric)# 进行模型训练model_save_path = os.path.join(save_dir, f"best_lstm_model_{length}.pdparams")runner.train(train_loader, dev_loader, num_epochs=num_epochs, eval_steps=100, log_steps=100,save_path=model_save_path)return runner# ========================多组训练====================
lstm_runners = {}
lengths = [10, 15, 20, 25, 30, 35]
for length in lengths:runner = train(length)lstm_runners[length] = runner# 画出训练过程中的损失图
for length in lengths:runner = lstm_runners[length]save_path = os.path.dirname(f'./images/6.6_{length}.pdf')# 如果目录不存在,则创建它if not os.path.exists(save_path):os.makedirs(save_path)plot_training_loss(runner, save_path, sample_step=100)
# =================模型测试=================
lstm_dev_scores = []
lstm_test_scores = []
for length in lengths:print(f"Evaluate LSTM with data length {length}.")runner = lstm_runners[length]# 加载训练过程中效果最好的模型model_path = os.path.join(save_dir, f"best_lstm_model_{length}.pdparams")runner.load_model(model_path)# 加载长度为length的数据data_path = f"../实验14-循环神经网络(1)SRN记忆能力-梯度爆炸/SRN记忆能力/datasets/{length}"train_examples, dev_examples, test_examples = load_data(data_path)test_set = DigitSumDataset(test_examples)test_loader = DataLoader(test_set, batch_size=batch_size)# 使用测试集评价模型,获取测试集上的预测准确率score, _ = runner.evaluate(test_loader)lstm_test_scores.append(score)lstm_dev_scores.append(max(runner.dev_scores))for length, dev_score, test_score in zip(lengths, lstm_dev_scores, lstm_test_scores):print(f"[LSTM] length:{length}, dev_score: {dev_score}, test_score: {test_score: .5f}")# 在不同长度的验证集和测试集数据上的表现,绘制成图片进行观察=======================
plt.plot(lengths, lstm_dev_scores, '-o', color='#e8609b', label="LSTM Dev Accuracy")
plt.plot(lengths, lstm_test_scores,'-o', color='#000000', label="LSTM Test Accuracy")# 绘制坐标轴和图例
plt.ylabel("accuracy", fontsize='large')
plt.xlabel("sequence length", fontsize='large')
plt.legend(loc='lower left', fontsize='x-large')fig_name = "./images/6.12.pdf"
plt.savefig(fig_name)
plt.show()
5 LSTM模型门状态和单元状态的变化
5.1 更新LSTM模块
class LSTM(nn.Module):def __init__(self, input_size, hidden_size, para_attr=xavier_uniform):super(LSTM, self).__init__()self.input_size = input_sizeself.hidden_size = hidden_size# 初始化模型参数self.W_i = torch.nn.Parameter(para_attr(torch.empty(size=[input_size, hidden_size], dtype=torch.float32)))self.W_f = torch.nn.Parameter(para_attr(torch.empty(size=[input_size, hidden_size], dtype=torch.float32)))self.W_o = torch.nn.Parameter(para_attr(torch.empty(size=[input_size, hidden_size], dtype=torch.float32)))self.W_c = torch.nn.Parameter(para_attr(torch.empty(size=[input_size, hidden_size], dtype=torch.float32)))self.U_i = torch.nn.Parameter(para_attr(torch.empty(size=[hidden_size, hidden_size], dtype=torch.float32)))self.U_f = torch.nn.Parameter(para_attr(torch.empty(size=[hidden_size, hidden_size], dtype=torch.float32)))self.U_o = torch.nn.Parameter(para_attr(torch.empty(size=[hidden_size, hidden_size], dtype=torch.float32)))self.U_c = torch.nn.Parameter(para_attr(torch.empty(size=[hidden_size, hidden_size], dtype=torch.float32)))self.b_i = torch.nn.Parameter(para_attr(torch.empty(size=[1, hidden_size], dtype=torch.float32)))self.b_f = torch.nn.Parameter(para_attr(torch.empty(size=[1, hidden_size], dtype=torch.float32)))self.b_o = torch.nn.Parameter(para_attr(torch.empty(size=[1, hidden_size], dtype=torch.float32)))self.b_c = torch.nn.Parameter(para_attr(torch.empty(size=[1, hidden_size], dtype=torch.float32)))# 初始化状态向量和隐状态向量def init_state(self, batch_size):hidden_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)cell_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)return hidden_state, cell_state# 定义前向计算def forward(self, inputs, states=None):batch_size, seq_len, input_size = inputs.shape # inputs batch_size x seq_len x input_sizeif states is None:states = self.init_state(batch_size)hidden_state, cell_state = states# 定义相应的门状态和单元状态向量列表self.Is = []self.Fs = []self.Os = []self.Cs = []# 初始化状态向量和隐状态向量cell_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)hidden_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)# 执行LSTM计算,包括:隐藏门、输入门、遗忘门、候选状态向量、状态向量和隐状态向量for step in range(seq_len):input_step = inputs[:, step, :]I_gate = F.sigmoid(torch.matmul(input_step, self.W_i) + torch.matmul(hidden_state, self.U_i) + self.b_i)F_gate = F.sigmoid(torch.matmul(input_step, self.W_f) + torch.matmul(hidden_state, self.U_f) + self.b_f)O_gate = F.sigmoid(torch.matmul(input_step, self.W_o) + torch.matmul(hidden_state, self.U_o) + self.b_o)C_tilde = F.tanh(torch.matmul(input_step, self.W_c) + torch.matmul(hidden_state, self.U_c) + self.b_c)cell_state = F_gate * cell_state + I_gate * C_tildehidden_state = O_gate * F.tanh(cell_state)# 存储门状态向量和单元状态向量self.Is.append(I_gate.numpy().copy())self.Fs.append(F_gate.numpy().copy())self.Os.append(O_gate.numpy().copy())self.Cs.append(cell_state.numpy().copy())return hidden_state
5.2 加载模型
使用新的LSTM模型,重新实例化一个runner,使用序列长度为10的模型进行此项实验,因此需要加载序列长度为10的模型。
# 训练轮次
num_epochs = 500
# 学习率
lr = 0.001
# 输入数字的类别数
num_digits = 10
# 将数字映射为向量的维度
input_size = 32
# 隐状态向量的维度
hidden_size = 32
# 预测数字的类别数
num_classes = 19
# 批大小
batch_size = 8
# 模型保存目录
save_dir = "./checkpoints"# 实例化模型
base_model = LSTM(input_size, hidden_size)
model = Model_RNN4SeqClass(base_model, num_digits, input_size, hidden_size, num_classes)
# 指定优化器
optimizer = torch.optim.Adam(lr=lr, params=model.parameters())
# 定义评价指标
metric = Accuracy()
# 定义损失函数
loss_fn = torch.nn.CrossEntropyLoss()
# 基于以上组件,重新实例化Runner
runner = RunnerV3(model, optimizer, loss_fn, metric)length = 10
# 加载训练过程中效果最好的模型
model_path = os.path.join(save_dir, f"best_lstm_model_{length}.pdparams")
runner.load_model(model_path)
接下来,给定一条数字序列,并使用数字预测模型进行数字预测,这样便会将相应的门状态和单元状态向量保存至模型中. 然后分别从模型中取出这些向量,并将这些向量进行绘制展示。代码实现如下:
import seaborn as sns
def plot_tensor(inputs, tensor, save_path, vmin=0, vmax=1):tensor = np.stack(tensor, axis=0)tensor = np.squeeze(tensor, 1).Tplt.figure(figsize=(16, 6))# vmin, vmax定义了色彩图的上下界ax = sns.heatmap(tensor, vmin=vmin, vmax=vmax)ax.set_xticklabels(inputs)ax.figure.savefig(save_path)plt.show()
# 定义模型输入
inputs = [6, 7, 0, 0, 1, 0, 0, 0, 0, 0]
X = torch.tensor(inputs.copy())
X = X.unsqueeze(0)
# 进行模型预测,并获取相应的预测结果
logits = runner.predict(X)
predict_label = torch.argmax(logits, dim=-1)
print(f"predict result: {predict_label.numpy()[0]}")# 输入门
Is = runner.model.rnn_model.Is
plot_tensor(inputs, Is, save_path="./images/6.13_I.pdf")
# 遗忘门
Fs = runner.model.rnn_model.Fs
plot_tensor(inputs, Fs, save_path="./images/6.13_F.pdf")
# 输出门
Os = runner.model.rnn_model.Os
plot_tensor(inputs, Os, save_path="./images/6.13_O.pdf")
# 单元状态
Cs = runner.model.rnn_model.Cs
plot_tensor(inputs, Cs, save_path="./images/6.13_C.pdf", vmin=-5, vmax=5)
运行结果:
predict result: 13
输入门:
遗忘门:
输出门:
单元状态:
【分析】
当LSTM处理序列数据[6, 7, 0, 0, 1, 0, 0, 0, 0, 0]的过程中单元状态和门数值的变化图,其中横坐标为输入数字,纵坐标为相应门或单元状态向量的维度,颜色的深浅代表数值的大小。
当输入门遇到不同位置的数字0时,保持了相对一致的数值大小,表明对于0元素保持相同的门控过滤机制,避免输入信息的变化给当前模型带来困扰;、
当遗忘门遇到数字1后,遗忘门数值在一些维度上变小,表明对某些信息进行了遗忘;随着序列的输入,输出门和单元状态在某些维度上数值变小,在某些维度上数值变大,表明输出门在根据信息的重要性选择信息进行输出,同时单元状态也在保持着对预测重要的一些信息 。
5.3 完整代码
'''
@Function: 观察当LSTM在处理一条数字序列的时候,相应门和单元状态
@Author: lxy
@Date: 2024/12/7
'''
import torch.nn.functional as F
from torch.nn.init import xavier_uniform
import os
import random
import torch
import torch.nn as nn
import numpy as np
from Runner import Accuracy,RunnerV3,plot_training_loss
import sys
from model1 import load_data,DataLoader,Model_RNN4SeqClass,DigitSumDataset
import matplotlib.pyplot as plt# 更新LSTM和相关参数,定义相应列表进行存储这些门和单元状态在每个时刻的向量
class LSTM(nn.Module):def __init__(self, input_size, hidden_size, para_attr=xavier_uniform):super(LSTM, self).__init__()self.input_size = input_sizeself.hidden_size = hidden_size# 初始化模型参数self.W_i = torch.nn.Parameter(para_attr(torch.empty(size=[input_size, hidden_size], dtype=torch.float32)))self.W_f = torch.nn.Parameter(para_attr(torch.empty(size=[input_size, hidden_size], dtype=torch.float32)))self.W_o = torch.nn.Parameter(para_attr(torch.empty(size=[input_size, hidden_size], dtype=torch.float32)))self.W_c = torch.nn.Parameter(para_attr(torch.empty(size=[input_size, hidden_size], dtype=torch.float32)))self.U_i = torch.nn.Parameter(para_attr(torch.empty(size=[hidden_size, hidden_size], dtype=torch.float32)))self.U_f = torch.nn.Parameter(para_attr(torch.empty(size=[hidden_size, hidden_size], dtype=torch.float32)))self.U_o = torch.nn.Parameter(para_attr(torch.empty(size=[hidden_size, hidden_size], dtype=torch.float32)))self.U_c = torch.nn.Parameter(para_attr(torch.empty(size=[hidden_size, hidden_size], dtype=torch.float32)))self.b_i = torch.nn.Parameter(para_attr(torch.empty(size=[1, hidden_size], dtype=torch.float32)))self.b_f = torch.nn.Parameter(para_attr(torch.empty(size=[1, hidden_size], dtype=torch.float32)))self.b_o = torch.nn.Parameter(para_attr(torch.empty(size=[1, hidden_size], dtype=torch.float32)))self.b_c = torch.nn.Parameter(para_attr(torch.empty(size=[1, hidden_size], dtype=torch.float32)))# 初始化状态向量和隐状态向量def init_state(self, batch_size):hidden_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)cell_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)return hidden_state, cell_state# 定义前向计算def forward(self, inputs, states=None):batch_size, seq_len, input_size = inputs.shape # inputs batch_size x seq_len x input_sizeif states is None:states = self.init_state(batch_size)hidden_state, cell_state = states# 定义相应的门状态和单元状态向量列表self.Is = []self.Fs = []self.Os = []self.Cs = []# 初始化状态向量和隐状态向量cell_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)hidden_state = torch.zeros(size=[batch_size, self.hidden_size], dtype=torch.float32)# 执行LSTM计算,包括:隐藏门、输入门、遗忘门、候选状态向量、状态向量和隐状态向量for step in range(seq_len):input_step = inputs[:, step, :]I_gate = F.sigmoid(torch.matmul(input_step, self.W_i) + torch.matmul(hidden_state, self.U_i) + self.b_i)F_gate = F.sigmoid(torch.matmul(input_step, self.W_f) + torch.matmul(hidden_state, self.U_f) + self.b_f)O_gate = F.sigmoid(torch.matmul(input_step, self.W_o) + torch.matmul(hidden_state, self.U_o) + self.b_o)C_tilde = F.tanh(torch.matmul(input_step, self.W_c) + torch.matmul(hidden_state, self.U_c) + self.b_c)cell_state = F_gate * cell_state + I_gate * C_tildehidden_state = O_gate * F.tanh(cell_state)# 存储门状态向量和单元状态向量self.Is.append(I_gate.numpy().copy())self.Fs.append(F_gate.numpy().copy())self.Os.append(O_gate.numpy().copy())self.Cs.append(cell_state.numpy().copy())return hidden_state
# 训练轮次
num_epochs = 500
# 学习率
lr = 0.001
# 输入数字的类别数
num_digits = 10
# 将数字映射为向量的维度
input_size = 32
# 隐状态向量的维度
hidden_size = 32
# 预测数字的类别数
num_classes = 19
# 批大小
batch_size = 8
# 模型保存目录
save_dir = "./checkpoints"# =======================实例化模型===========================
base_model = LSTM(input_size, hidden_size)
model = Model_RNN4SeqClass(base_model, num_digits, input_size, hidden_size, num_classes)
# 指定优化器
optimizer = torch.optim.Adam(lr=lr, params=model.parameters())
# 定义评价指标
metric = Accuracy()
# 定义损失函数
loss_fn = torch.nn.CrossEntropyLoss()
# 基于以上组件,重新实例化Runner
runner = RunnerV3(model, optimizer, loss_fn, metric)length = 10
# 加载训练过程中效果最好的模型
model_path = os.path.join(save_dir, f"best_lstm_model_{length}.pdparams")
runner.load_model(model_path)import seaborn as sns
def plot_tensor(inputs, tensor, save_path, vmin=0, vmax=1):tensor = np.stack(tensor, axis=0)tensor = np.squeeze(tensor, 1).Tplt.figure(figsize=(16, 6))# vmin, vmax定义了色彩图的上下界ax = sns.heatmap(tensor, vmin=vmin, vmax=vmax)ax.set_xticklabels(inputs)ax.figure.savefig(save_path)plt.show()
# 定义模型输入
inputs = [6, 7, 0, 0, 1, 0, 0, 0, 0, 0]
X = torch.tensor(inputs.copy())
X = X.unsqueeze(0)
# 进行模型预测,并获取相应的预测结果
logits = runner.predict(X)
predict_label = torch.argmax(logits, dim=-1)
print(f"predict result: {predict_label.numpy()[0]}")# 输入门
Is = runner.model.rnn_model.Is
plot_tensor(inputs, Is, save_path="./images/6.13_I.pdf")
# 遗忘门
Fs = runner.model.rnn_model.Fs
plot_tensor(inputs, Fs, save_path="./images/6.13_F.pdf")
# 输出门
Os = runner.model.rnn_model.Os
plot_tensor(inputs, Os, save_path="./images/6.13_O.pdf")
# 单元状态
Cs = runner.model.rnn_model.Cs
plot_tensor(inputs, Cs, save_path="./images/6.13_C.pdf", vmin=-5, vmax=5)
参考链接
参考链接: |
老师的博客园 |
飞桨AI Studio星河社区-人工智能学习与实训社区 |
LSTM从入门到精通 |
如何构建LSTM神经网络模型_lstm模型-CSDN博客 ---->写的很详细强推! |
相关文章:
【实验15】LSTM的记忆能力实验
目录 1 模型构建 1.1 LSTM层 1.1.1 自定义LSTM算子 1.1.2 nn.LSTM 1.1.3 将自定义LSTM与pytorch内置的LSTM进行对比 1.2 模型汇总 2 模型训练 2.1 训练指定长度的数字预测模型 2.2 多组训练 2.3 损失函数展示 3 模型评价 4 完整代码 5 LSTM模型门状态和单元状态的…...
SSH克隆github项目
1、生成密钥 ssh-keygen -t rsa -C "你的邮箱xxx.com" 全程回车即可(不用输入ras文件名及密码)、为了方便下面的公钥查看 2、配置公钥 查看公钥内容 cat c:\Users\xxx\.ssh\id_rsa.pub(修改为自己的路径及名字) 将公钥内容复制并粘贴至…...
计算机网络ENSP课设--三层架构企业网络
本课程设计搭建一个小型互联网,并模拟Internet的典型Web服务过程。通过此次课程设计,可以进一步理解Internet的工作原理和协议过程,并提高综合知识的运用能力和分析能力。具体目标包括: (1)掌握网络拓扑的…...
Node.js系统模块
【图书介绍】《Node.jsMongoDBVue.js全栈开发实战》-CSDN博客 《Node.jsMongoDBVue.js全栈开发实战(Web前端技术丛书)》(邹琼俊)【摘要 书评 试读】- 京东图书 (jd.com) 2.2.1 什么是系统模块 由于Node.js运行环境提供的API都是以模块化的方式进行开…...
React - useActionState、useFormStatus与表单处理
参考文档:react18.3.1官方文档 一些概念: React 的 Canary 和 Experimental 频道是 React 团队用于发布和测试新功能的渠道。 useActionState useActionState 是一个可以根据某个表单动作的结果更新 state 的 Hook。 const [state, formAction, isPe…...
GC常见垃圾回收算法,JVM分代模型
如何判断是垃圾?引用计数器和Root可达性算法 如何进行清除?标记清除、复制、标记整理 堆分代模型?Eden,Surevivor,Tenuring 一个对象从创建到消亡的过程? 对象什么时候进入老年代? 一、GC&a…...
深入探索 JVM:原理、机制与实战
一、JVM 概述 JVM(Java Virtual Machine)是 Java 程序运行的核心组件,它提供了一个独立于硬件和操作系统的执行环境,使得 Java 程序能够在不同平台上具有跨平台的特性。 JVM 主要由以下几部分组成: 类装载器…...
前端成长之路:HTML(2)
HTML中有两个非常重要的标签——表格和表单,在介绍之前需要先了解表格和表单的区别:表格是用于展示数据的;表单是用于提交数据的。本文主要介绍表格。 表格标签 表格主要是用于显示、展示数据的,并非是页面布局。它可以使本来难…...
python基础:(七)类
目录 一.创建和使用类二.使用类和实例2.1给属性指定默认值2.2修改属性的值2.2.1直接修改属性的值2.2.2通过方法修改属性的值2.2.3通过方法对属性的值进行递增 三.继承3.1子类的方法__init__()3.2给子类定义属性和方法3.3重写父类的方法 四.导入类4.1语法--1:4.2语法--2 前言 p…...
Spring AOP基础、快速入门
介绍 AOP,面向切面编程,作为面向对象的一种补充,将公共逻辑(事务管理、日志、缓存、权限控制、限流等)封装成切面,跟业务代码进行分离,可以减少系统的重复代码和降低模块之间的耦合度。切面就是…...
Golang使用etcd构建分布式锁案例
在本教程中,我们将学习如何使用Go和etcd构建分布式锁系统。分布式锁系统对于管理对分布式系统中共享资源的并发访问至关重要。它有助于维护一致性,防止竞争条件,并确保在任何给定时间只有一个进程独占访问资源。 我们将使用Go作为编程语言&am…...
深度学习:基于MindSpore的极简风大模型微调
什么是PEFT?What is PEFT? PEFT(Parameter Efficient Fine-Tuning)是一系列让大规模预训练模型高效适应于新任务或新数据集的技术。 PEFT在保持大部分模型权重冻结,只修改或添加一小部份参数。这种方法极大得减少了计算量和存储开销&#x…...
如何在 Android 项目中实现跨库传值
背景介绍 在一个复杂的 Android 项目中,我们通常会有多个库(lib),而主应用程序(app)依赖所有这些库。目前遇到的问题是,在这些库中,libAd 需要获取 libVip 的 VIP 等级状态…...
HTML:表格重点
用表格就用table caption为该表上部信息,用来说明表的作用 thead为表头主要信息,效果加粗 tbody为表格中的主体内容 tr是 table row 表格的行 td是table data th是table heading表格标题 ,一般表格第一行的数据都是table heading...
STM32 出租车计价器系统设计(一) 江科大源码改写
STM32 出租车计价器系统设计 功能目标 驱动步进电机模拟车轮旋转,并实现调速功能。 设置车轮周长和单价,检测车轮转速和运转时间。 计算并显示行驶里程和价格。 硬件材料 28BYJ48 五线四相步进电机和 ULN2003 驱动板模块 测速传感器模块 嵌入式小系统…...
Git基础操作快速入门
Git是一个免费开源分布式版本控制工具,是由Linux的作者Linus开发的第二个伟大作品。2005年由于BitKeeper软件公司对Linux社区停止了免费使用权。Linus迫不得己自己开发了一个分布式版本控制工具,从而Git诞生了 目前使用Git作为版本控制的开源软件&#…...
vue‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
在Windows操作系统中,安装了nodeJs之后,并且也安装了vue依赖包,但是在cmd控制台运行vue的时候,会报错:vue‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。针对这个问题我提供如下解决办法,并且是有效的。 一、原因分析 关于尝试这个问题的主要原因,我分析主要…...
JAVA安全—SpringBoot框架MyBatis注入Thymeleaf模板注入
前言 之前我们讲了JAVA的一些组件安全,比如Log4j,fastjson。今天讲一下框架安全,就是这个也是比较常见的SpringBoot框架。 SpringBoot框架 Spring Boot是由Pivotal团队提供的一套开源框架,可以简化spring应用的创建及部署。它提…...
Milvus向量数据库05-常见问题整理
Milvus向量数据库05-常见问题整理 1-什么是PipeLine 这张图展示了一个文档处理和搜索系统的架构,主要分为两个部分:Ingestion Pipeline(摄取管道)和 Search Pipeline(搜索管道)。下面是对图中各部分的详细…...
strncpy在复制含有多个\0的字符串时遇到的问题
strncpy在复制含有多个\0的字符串的时候,会产生截断,因为strncpy在读取源字符串的时候,遇到了\0,函数会认为该字符串已经结束了,然后会向目标字符串内填充\0。 char buffer[100] "ak\0jl";for (int i 0; i…...
C++作业3
作业1: 1.定义一个矩形类Rec,包含私有属性length、width,包含公有成员方法: void set_length(int l);//设置长度 Void set_width(int w);//设置宽度 Int get_length();//获取长度,将长度的值返回给调用处 Int get_widt…...
重生之我在学Vue--第1天 Vue 3 基础与开发环境搭建
重生之我在学Vue–第1天 Vue 3 基础与开发环境搭建 文章目录 重生之我在学Vue--第1天 Vue 3 基础与开发环境搭建前言一、Vue 3 的特点与核心概念二、搭建开发环境1. 安装 Node.js2. 使用 Vite 创建 Vue 3 项目创建项目进入项目目录并安装依赖启动开发服务器 3. 理解项目结构 三…...
企业经营数据分析系统:提升决策能力的利器
搭建企业经营数据分析系统是当今企业绕不开的话题,企业想要在竞争激烈的市场当中突围而出,需要对于企业内部的各种数据了然于胸,同时对于外部的数据也有敏锐的把握能力,因此企业构建自身的经营性数据分析系统就显得尤其重要。作为…...
Linux笔记9 DNS域名解析服务器
简介 DNS(Domain Name System)是互联网上的一项服务,它作为将域名和IP地址相互映射的一个分 布式数据库,能够使人更方便的访问互联网。 DNS使用的是53端口, 通常DNS是以UDP这个较快速的数据传输协议来查询的&#x…...
鸿蒙高级开发者认证的主观题试题及答案
以下是一份鸿蒙高级开发者认证的主观题试题及答案示例,涵盖了鸿蒙开发中的多个关键技术和应用场景相关内容,希望对你有所帮助: 一、论述题(每题 20 分,共 60 分) 1. 阐述鸿蒙操作系统中分布式软总线的工作原理、核心优势以及在多设备协同应用开发场景下的应用方式,并举…...
leetcode_547 省份数量
该题主要运用了图的连通性 接着使用染色法解决该问题 染色法:标记所有节点为false 访问后 将其标记位true class Solution {int n; // 代表n个数据bool colors[201]; // 标记是否访问到void dfs(vector<vector<int>>& isConnected, int u) { // …...
【开源】一款基于SpringBoot 的全开源充电桩平台
一、下载项目文件 下载源码项目文件口令:动作璆璜量子屏多好/~d1b8356ox2~:/复制口令后,进入夸克网盘app即可保存(如果复制到夸克app没有跳转资源,可以复制粘贴口令到夸克app的搜索框也可以打开(不用点搜索按钮&#…...
react antd tabs router 基础管理后台模版
在构建 React 后台管理系统时,使用标签页的方式展示路由是一种高效且用户友好的设计模式。这种实现方式通常允许用户在多个页面之间快速切换,并保留页面的状态,类似于浏览器的多标签页功能。 需求分析 1.动态标签页:根据用户的导…...
uniapp uni-table最简单固定表头
需求:固定表头数据,在网上找了半天,啥都有,就是一直实现不了,最后更改代码实现 1.效果 2.主要代码讲解完整代码 表格的父级一定要设置高度,不然会错位,我看网上说设置position:fixed…...
从0到1实现项目Docker编排部署
在深入讨论 Docker 编排之前,首先让我们了解一下 Docker 技术本身。Docker 是一个开源平台,旨在帮助开发者自动化应用程序的部署、扩展和管理。自 2013 年推出以来,Docker 迅速发展成为现代软件开发和运维领域不可或缺的重要工具。 Docker 采…...
Mac软件推荐
Mac软件推荐 截图SnipasteXnipBob 快捷启动Raycast 系统检测Stats 解压缩The UnarchiverKeka(付费) 视频播放IINA 视频下载Downie(付费) 屏幕刘海TopNotchMediaMate(付费)NotchDrop(付费&#x…...
No.4 笔记 探索网络安全:揭开Web世界的隐秘防线
在这个数字时代,网络安全无处不在。了解Web安全的基本知识,不仅能保护我们自己,也能帮助我们在技术上更进一步。让我们一起深入探索Web安全的世界,掌握那些必备的安全知识! 1. 客户端与WEB应用安全 前端漏洞࿱…...
Unity-Webview 使用指南
Unity-Webview 使用指南 Unity-Webview 主に gree/unity-webview のリファクタリング。本家を元に改良してく! [这里是图片001] 项目地址: https://gitcode.com/gh_mirrors/uni/Unity-Webview Unity-Webview 是一个专为 Unity 开发的 WebView 插件,使开…...
【Vue】自定义指令、插槽
目录 自定义指令 是什么 作用 使用方法 定义 使用 自定义指令配合绑定数据 语法 自定义指令的简写 语法 使用时机 插槽 什么是插槽 默认(匿名)插槽 编辑插槽的默认值 具名插槽 使用方法 简写 使用示例 作用域插槽 自定义指令 是什…...
AI - RAG中的状态化管理聊天记录
AI - RAG中的状态化管理聊天记录 大家好,今天我们来聊聊LangChain和LLM中一个重要的话题——状态化管理聊天记录。在使用大语言模型(LLM)的时候,聊天记录(History)和状态(State)管理是非常关键的。那我们先…...
微服务网关SpringCloudGateway、Kong比较
网关产品 1. Spring Cloud Gateway 基本信息 Spring Cloud Gateway是Spring Cloud生态系统中的一个组件,基于Spring 5、Project Reactor和Spring Boot 2构建。它旨在为微服务架构提供一种简单而有效的API网关解决方案。 功能特点 路由功能强大:使用Rou…...
MVC基础语法
文章目录 项目地址一、MVC的传值方式1.1 ViewBag和ViewData传值1.1.1 ViewBag1.1.2 ViewData 1.2 视图模型传值(ViewModel) 二、HttpConntext上下文三、中间件 项目地址 教程作者:誉尚学教育教程地址: https://www.bilibili.com…...
Web day09 会话技术 JWT令牌 Filter Interceptor
目录 会话技术: 1.Cookie: 2.Session: 3.令牌技术: JWT令牌: 生成JWT令牌: 校验JWT令牌(解析生成的令牌) 登陆时下发令牌: 过滤器Filter: 拦截器Inte…...
OpenCV相机标定与3D重建(14)用于组合两个旋转和平移(R|T)变换函数composeRT()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::composeRT 是 OpenCV 库中的一个函数,用于组合两个旋转和平移(R|T)变换。这个函数可以将两个连续的刚体变…...
leetcode33.搜索旋转排序数组
整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], ..., nums[n-1], nums[0], nums[1], ..…...
TMS Software:TMS BIZ产品——TMS XData
TMS XData 用于多层REST/JSON HTTP/HTTPS应用服务器开发和ORM远程处理的Delphi框架。 TMS扩展数据可同时用于以下框架: VCLWEBFMX TMS XData可同时用于以下操作系统/浏览器: TMS XData可同时用于以下IDE: 功能概述 基于REST/JSON架构风格的…...
leecode中的面试100题
isalnum函数用于检查一个字符是否为字母或数字。它的参数是一个int类型 isupper() 是大写 islower() 是小写 toupper() 变成大写 tolower() 变成小写 do while 首先不管怎么 先执行do一次 然后执行完了之后 在判断while如果符合while里面就继续执行do vector容器中insert…...
不同类型的集成技术——Bagging、Boosting、Stacking、Voting、Blending简述
目录 一、说明 二、堆叠 2.1 堆叠的工作原理: 2.2 例子: 2.3 堆叠的优点: 三、投票(简单投票) 3.1 例子: 3.2 投票的优点: 四、装袋和投票之间的区别 五、混合 6.1 混合的主要特征: …...
【从零开始入门unity游戏开发之——C#篇01】理论开篇
文章目录 前言前置条件什么是编程?什么是代码?什么是编程语言?常见的编程语言什么是C#?学习Unity为什么要先学习C#?选择适合自己的IDE集成开发环境VSCode安装和环境配置VSCode调试模式专栏推荐完结 前言 这个系列我想…...
TCP的“可靠性”(上)
目录 TCP的“可靠性”(上)确认应答(可靠性传输的基础)超时重传连接管理(三次握手,四次挥手) TCP的“可靠性”(上) 想必大家都或多或少的听说过TCP的特性:有连…...
Windows平台Unity3D下如何低延迟低资源占用播放RTMP或RTSP流?
技术探讨 自2017年我们发布跨平台的低延迟Unity下的RTSP|RTMP直播播放器后,Unity下的直播体验有了质的提升,特别是RTMP,从大家认知里面的几秒钟,直接缩减到100-300ms,满足了绝大多数场景下低延迟的技术诉求。今天就Un…...
burp的编解码,日志,比较器
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...
Vercel部署前端部署
Vercel 部署 今天要讲的是如何对别人向自己的开源仓库提的PR进行自动代码审核 1. 注册并登录Vercel 访问 Vercel官网点击右上角的"Sign Up"选择使用GitHub、GitLab、Bitbucket或邮箱注册完成注册流程并登录 2. 连接代码仓库 在Vercel仪表板,点击"New Proje…...
Jenkins相关的Api接口调用详解
Jenkins API是Jenkins持续集成和持续部署(CI/CD)平台提供的一组接口,允许外部程序通过HTTP请求与Jenkins进行交互。以下是对Jenkins API使用的简介: 一、Jenkins API的主要功能 作业管理:通过API,可以创建、配置、删除以及查询作业(Job)。构建触发:可以远程触发新的构…...
HBU深度学习实验15-循环神经网络(2)
LSTM的记忆能力实验 飞桨AI Studio星河社区-人工智能学习与实训社区 (baidu.com) 长短期记忆网络(Long Short-Term Memory Network,LSTM)是一种可以有效缓解长程依赖问题的循环神经网络.LSTM 的特点是引入了一个新的内部状态&am…...