LSTM进行字符级文本生成(pytorch实现)

文章目录
  • 基于pytorch的LSTM进行字符集文本生成
  • 前言
  • 一、数据集
  • 二、代码实现
    • 1.到入库和LSTM进行模型构建
    • 2.数据预处理函数
    • 3.训练函数
    • 4.预测函数
    • 5.文本生成函数
    • 6.主函数
  • 完整代码
  • 总结

前言

本文介绍了机器学习中深度学习的内容使用pytorch构建LSTM模型进行字符级文本生成任务

一、数据集

https://download.csdn.net/download/qq_52785473/78428834

二、代码实现

1.导入库及LSTM模型构建

代码如下:

# coding: utf-8
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import OneHotEncoder
import torch.nn.functional as Fclass lstm_model(nn.Module):def __init__(self, vocab, hidden_size, num_layers, dropout=0.5):super(lstm_model, self).__init__()self.vocab = vocab  # 字符数据集# 索引,字符self.int_char = {i: char for i, char in enumerate(vocab)}self.char_int = {char: i for i, char in self.int_char.items()}# 对字符进行one-hot encodingself.encoder = OneHotEncoder(sparse=True).fit(vocab.reshape(-1, 1))self.hidden_size = hidden_sizeself.num_layers = num_layers# lstm层self.lstm = nn.LSTM(len(vocab), hidden_size, num_layers, batch_first=True, dropout=dropout)# 全连接层self.linear = nn.Linear(hidden_size, len(vocab))def forward(self, sequence, hs=None):out, hs = self.lstm(sequence, hs)  # lstm的输出格式(batch_size, sequence_length, hidden_size)out = out.reshape(-1, self.hidden_size)  # 这里需要将out转换为linear的输入格式,即(batch_size * sequence_length, hidden_size)output = self.linear(out)  # linear的输出格式,(batch_size * sequence_length, vocab_size)return output, hsdef onehot_encode(self, data):  # 对数据进行编码return self.encoder.transform(data)def onehot_decode(self, data):  # 对数据进行解码return self.encoder.inverse_transform(data)def label_encode(self, data):  # 对标签进行编码return np.array([self.char_int[ch] for ch in data])def label_decode(self, data):  # 对标签进行解码return np.array([self.int_char[ch] for ch in data])

2.数据预处理函数

def get_batches(data, batch_size, seq_len):''':param data: 源数据,输入格式(num_samples, num_features):param batch_size: batch的大小:param seq_len: 序列的长度(精度):return: (batch_size, seq_len, num_features)'''num_features = data.shape[1]num_chars = batch_size * seq_len  # 一个batch_size的长度num_batches = int(np.floor(data.shape[0] / num_chars))  # 计算出有多少个batchesneed_chars = num_batches * num_chars  # 计算出需要的总字符量targets = np.vstack((data[1:].A, data[0].A))  # 可能版本问题,取成numpy比较好reshapeinputs = data[:need_chars].A.astype("int")  # 从原始数据data中截取所需的字符数量need_wordstargets = targets[:need_chars]targets = targets.reshape(batch_size, -1, num_features)inputs = inputs.reshape(batch_size, -1, num_features)for i in range(0, inputs.shape[1], seq_len):x = inputs[:, i: i+seq_len]y = targets[:, i: i+seq_len]yield x, y  # 节省内存

3.训练函数

def train(model, data, batch_size, seq_len, epochs, lr=0.01, valid=None):device = 'cuda' if torch.cuda.is_available() else 'cpu'model = model.to(device)optimizer = torch.optim.Adam(model.parameters(), lr=lr)criterion = nn.CrossEntropyLoss()if valid is not None:data = model.onehot_encode(data.reshape(-1, 1))valid = model.onehot_encode(valid.reshape(-1, 1))else:data = model.onehot_encode(data.reshape(-1, 1))train_loss = []val_loss = []for epoch in range(epochs):model.train()hs = None  # hs等于hidden_size隐藏层节点train_ls = 0.0val_ls = 0.0for x, y in get_batches(data, batch_size, seq_len):optimizer.zero_grad()x = torch.tensor(x).float().to(device)out, hs = model(x, hs)hs = ([h.data for h in hs])y = y.reshape(-1, len(model.vocab))y = model.onehot_decode(y)y = model.label_encode(y.squeeze())y = torch.from_numpy(y).long().to(device)loss = criterion(out, y.squeeze())loss.backward()optimizer.step()train_ls += loss.item()if valid is not None:model.eval()hs = Nonewith torch.no_grad():for x, y in get_batches(valid, batch_size, seq_len):x = torch.tensor(x).float().to(device)  # x为一组测试数据,包含batch_size * seq_len个字out, hs = model(x, hs)# out.shape输出为tensor[batch_size * seq_len, vocab_size]hs = ([h.data for h in hs])  # 更新参数y = y.reshape(-1, len(model.vocab))  # y.shape为(128,100,43),因此需要转成两维,每行就代表一个字了,43为字典大小y = model.onehot_decode(y)  # y标签即为测试数据各个字的下一个字,进行one_hot解码,即变为字符# 但是此时y 是[[..],[..]]形式y = model.label_encode(y.squeeze())  # 因此需要去掉一维才能成功解码# 此时y为[12...]成为一维的数组,每个代表自己字典里对应字符的字典序y = torch.from_numpy(y).long().to(device)# 这里y和y.squeeze()出来的东西一样,可能这里没啥用,不太懂loss = criterion(out, y.squeeze())  # 计算损失值val_ls += loss.item()val_loss.append(np.mean(val_ls))train_loss.append(np.mean(train_ls))print("train_loss:", train_ls)plt.plot(train_loss, label="train_loss")plt.plot(val_loss, label="val loss")plt.title("loop vs epoch")plt.legend()plt.show()model_name = "lstm_model.net"with open(model_name, 'wb') as f:  # 训练完了保存模型torch.save(model.state_dict(), f)

4.预测函数

def predict(model, char, top_k=None, hidden_size=None):device = 'cuda' if torch.cuda.is_available() else 'cpu'model.to(device)model.eval()  # 固定参数with torch.no_grad():char = np.array([char])  # 输入一个字符,预测下一个字是什么,先转成numpychar = char.reshape(-1, 1)  # 变成二维才符合编码规范char_encoding = model.onehot_encode(char).A  # 对char进行编码,取成numpy比较方便reshapechar_encoding = char_encoding.reshape(1, 1, -1)  # char_encoding.shape为(1, 1, 43)变成三维才符合模型输入格式char_tensor = torch.tensor(char_encoding, dtype=torch.float32)  # 转成tensorchar_tensor = char_tensor.to(device)out, hidden_size = model(char_tensor, hidden_size)  # 放入模型进行预测,out为结果probs = F.softmax(out, dim=1).squeeze()  # 计算预测值,即所有字符的概率if top_k is None:  # 选择概率最大的top_k个indices = np.arange(vocab_size)else:probs, indices = probs.topk(top_k)indices = indices.cpu().numpy()probs = probs.cpu().numpy()char_index = np.random.choice(indices, p=probs/probs.sum())  # 随机选择一个字符索引作为预测值char = model.int_char[char_index]  # 通过索引找出预测字符return char, hidden_size

5.文本生成函数

def sample(model, length, top_k=None, sentence="c"):hidden_size = Nonenew_sentence = [char for char in sentence]for i in range(length):next_char, hidden_size = predict(model, new_sentence[-1], top_k=top_k, hidden_size=hidden_size)new_sentence.append(next_char)return "".join(new_sentence)

6.主函数

def main():hidden_size = 512num_layers = 2batch_size = 128seq_len = 100epochs = 2lr = 0.01f = pd.read_csv("../datasets/dev.tsv", sep="\t", header=None)f = f[0]text = list(f)text = ".".join(text)vocab = np.array(sorted(set(text)))  # 建立字典vocab_size = len(vocab)val_len = int(np.floor(0.2 * len(text)))  # 划分训练测试集trainset = np.array(list(text[:-val_len]))validset = np.array(list(text[-val_len:]))model = lstm_model(vocab, hidden_size, num_layers)  # 模型实例化train(model, trainset, batch_size, seq_len, epochs, lr=lr, valid=validset)  # 训练模型model.load_state_dict(torch.load("lstm_model.net"))  # 调用保存的模型new_text = sample(model, 100, top_k=5)  # 预测模型,生成100个字符,预测时选择概率最大的前5个print(new_text)  # 输出预测文本if __name__ == "__main__":main()

本代码还是有很大改进空间,例如进行词语级的文本生成,以及使用word2vec等引入词向量等,都可以是的模型获得更好的效果。

完整代码

# coding: utf-8
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import OneHotEncoder
import torch.nn.functional as Fclass lstm_model(nn.Module):def __init__(self, vocab, hidden_size, num_layers, dropout=0.5):super(lstm_model, self).__init__()self.vocab = vocab  # 字符数据集# 索引,字符self.int_char = {i: char for i, char in enumerate(vocab)}self.char_int = {char: i for i, char in self.int_char.items()}# 对字符进行one-hot encodingself.encoder = OneHotEncoder(sparse=True).fit(vocab.reshape(-1, 1))self.hidden_size = hidden_sizeself.num_layers = num_layers# lstm层self.lstm = nn.LSTM(len(vocab), hidden_size, num_layers, batch_first=True, dropout=dropout)# 全连接层self.linear = nn.Linear(hidden_size, len(vocab))def forward(self, sequence, hs=None):out, hs = self.lstm(sequence, hs)  # lstm的输出格式(batch_size, sequence_length, hidden_size)out = out.reshape(-1, self.hidden_size)  # 这里需要将out转换为linear的输入格式,即(batch_size * sequence_length, hidden_size)output = self.linear(out)  # linear的输出格式,(batch_size * sequence_length, vocab_size)return output, hsdef onehot_encode(self, data):return self.encoder.transform(data)def onehot_decode(self, data):return self.encoder.inverse_transform(data)def label_encode(self, data):return np.array([self.char_int[ch] for ch in data])def label_decode(self, data):return np.array([self.int_char[ch] for ch in data])def get_batches(data, batch_size, seq_len):''':param data: 源数据,输入格式(num_samples, num_features):param batch_size: batch的大小:param seq_len: 序列的长度(精度):return: (batch_size, seq_len, num_features)'''num_features = data.shape[1]num_chars = batch_size * seq_len  # 一个batch_size的长度num_batches = int(np.floor(data.shape[0] / num_chars))  # 计算出有多少个batchesneed_chars = num_batches * num_chars  # 计算出需要的总字符量targets = np.vstack((data[1:].A, data[0].A))  # 可能版本问题,取成numpy比较好reshapeinputs = data[:need_chars].A.astype("int")  # 从原始数据data中截取所需的字符数量need_wordstargets = targets[:need_chars]targets = targets.reshape(batch_size, -1, num_features)inputs = inputs.reshape(batch_size, -1, num_features)for i in range(0, inputs.shape[1], seq_len):x = inputs[:, i: i+seq_len]y = targets[:, i: i+seq_len]yield x, y  # 节省内存def train(model, data, batch_size, seq_len, epochs, lr=0.01, valid=None):device = 'cuda' if torch.cuda.is_available() else 'cpu'model = model.to(device)optimizer = torch.optim.Adam(model.parameters(), lr=lr)criterion = nn.CrossEntropyLoss()if valid is not None:data = model.onehot_encode(data.reshape(-1, 1))valid = model.onehot_encode(valid.reshape(-1, 1))else:data = model.onehot_encode(data.reshape(-1, 1))train_loss = []val_loss = []for epoch in range(epochs):model.train()hs = None  # hs等于hidden_size隐藏层节点train_ls = 0.0val_ls = 0.0for x, y in get_batches(data, batch_size, seq_len):optimizer.zero_grad()x = torch.tensor(x).float().to(device)out, hs = model(x, hs)hs = ([h.data for h in hs])y = y.reshape(-1, len(model.vocab))y = model.onehot_decode(y)y = model.label_encode(y.squeeze())y = torch.from_numpy(y).long().to(device)loss = criterion(out, y.squeeze())loss.backward()optimizer.step()train_ls += loss.item()if valid is not None:model.eval()hs = Nonewith torch.no_grad():for x, y in get_batches(valid, batch_size, seq_len):x = torch.tensor(x).float().to(device)  # x为一组测试数据,包含batch_size * seq_len个字out, hs = model(x, hs)# out.shape输出为tensor[batch_size * seq_len, vocab_size]hs = ([h.data for h in hs])  # 更新参数y = y.reshape(-1, len(model.vocab))  # y.shape为(128,100,43),因此需要转成两维,每行就代表一个字了,43为字典大小y = model.onehot_decode(y)  # y标签即为测试数据各个字的下一个字,进行one_hot解码,即变为字符# 但是此时y 是[[..],[..]]形式y = model.label_encode(y.squeeze())  # 因此需要去掉一维才能成功解码# 此时y为[12...]成为一维的数组,每个代表自己字典里对应字符的字典序y = torch.from_numpy(y).long().to(device)# 这里y和y.squeeze()出来的东西一样,可能这里没啥用,不太懂loss = criterion(out, y.squeeze())  # 计算损失值val_ls += loss.item()val_loss.append(np.mean(val_ls))train_loss.append(np.mean(train_ls))print("train_loss:", train_ls)plt.plot(train_loss, label="train_loss")plt.plot(val_loss, label="val loss")plt.title("loop vs epoch")plt.legend()plt.show()model_name = "lstm_model.net"with open(model_name, 'wb') as f:  # 训练完了保存模型torch.save(model.state_dict(), f)def predict(model, char, top_k=None, hidden_size=None):device = 'cuda' if torch.cuda.is_available() else 'cpu'model.to(device)model.eval()  # 固定参数with torch.no_grad():char = np.array([char])  # 输入一个字符,预测下一个字是什么,先转成numpychar = char.reshape(-1, 1)  # 变成二维才符合编码规范char_encoding = model.onehot_encode(char).A  # 对char进行编码,取成numpy比较方便reshapechar_encoding = char_encoding.reshape(1, 1, -1)  # char_encoding.shape为(1, 1, 43)变成三维才符合模型输入格式char_tensor = torch.tensor(char_encoding, dtype=torch.float32)  # 转成tensorchar_tensor = char_tensor.to(device)out, hidden_size = model(char_tensor, hidden_size)  # 放入模型进行预测,out为结果probs = F.softmax(out, dim=1).squeeze()  # 计算预测值,即所有字符的概率if top_k is None:  # 选择概率最大的top_k个indices = np.arange(vocab_size)else:probs, indices = probs.topk(top_k)indices = indices.cpu().numpy()probs = probs.cpu().numpy()char_index = np.random.choice(indices, p=probs/probs.sum())  # 随机选择一个字符索引作为预测值char = model.int_char[char_index]  # 通过索引找出预测字符return char, hidden_sizedef sample(model, length, top_k=None, sentence="c"):hidden_size = Nonenew_sentence = [char for char in sentence]for i in range(length):next_char, hidden_size = predict(model, new_sentence[-1], top_k=top_k, hidden_size=hidden_size)new_sentence.append(next_char)return "".join(new_sentence)def main():hidden_size = 512num_layers = 2batch_size = 128seq_len = 100epochs = 2lr = 0.01f = pd.read_csv("../datasets/dev.tsv", sep="\t", header=None)f = f[0]text = list(f)text = ".".join(text)vocab = np.array(sorted(set(text)))  # 建立字典vocab_size = len(vocab)val_len = int(np.floor(0.2 * len(text)))  # 划分训练测试集trainset = np.array(list(text[:-val_len]))validset = np.array(list(text[-val_len:]))model = lstm_model(vocab, hidden_size, num_layers)  # 模型实例化train(model, trainset, batch_size, seq_len, epochs, lr=lr, valid=validset)  # 训练模型model.load_state_dict(torch.load("lstm_model.net"))  # 调用保存的模型new_text = sample(model, 100, top_k=5)  # 预测模型,生成100个字符,预测时选择概率最大的前5个print(new_text)  # 输出预测文本if __name__ == "__main__":main()

总结

这个案例他数据预处理的时候,一个序列对应一个序列的关系,例如abcd对应的标签为dabc,而不是一个字符,因此可能后面进行了某些操作使得他变成一个字符对应一个字符标签的操作了吧,从而使得预测的时候,只能通过一个字符预测其后面的字符,这就有点失去循环神经网络精髓的味道了,感觉是割裂字符之间的关系,变成一个普通单纯的分类了。

循环神经网络,因为能够处理序列位置的信息,需要设定一个滑动窗口值,或者说时间步长什么的,作用应该就是保留序列特征,例如abcdef为训练数据,设置滑动窗口为3的话,那么按照正常的序列思路可以划分为abc-d、bcd-e、cde-f作为训练数据的形式,即连续的三个字符对应的标签为其后面一个字符,那么我们训练出来的模型也是需要输入三个字符,然后生成一个字符,再用预测出来的字符加上他前面两个字符再预测新的字符,例如预测的初始序列为abc加入abc预测出来d,那么下一次预测就是bcd作为输入,就像一个窗口一步一步滑动过去一样,窗口的大小就为开始设定的3。

因此对于这个案例,它虽然seq_len=100,即滑动窗口为100,但是它的训练数据就不太对,而且模型预测时也是一个字符预测下一个字符,并没有体现滑动窗口的思想,因此这个代码案例大家可以自己进行改进优化。

下面是对代码部分地方的改动,使得它能够按滑动窗口的思维来进行训练和预测

数据预处理函数

def get_batches(data, batch_size, seq_len):''':param data: 源数据,输入格式(num_samples, num_features):param batch_size: batch的大小:param seq_len: 序列的长度(精度):return: (batch_size, seq_len, num_features)'''num_features = data.shape[1]num_chars = batch_size * seq_len  # 一个batch_size的长度num_batches = int(np.floor(data.shape[0] / num_chars))  # 计算出有多少个batchesneed_chars = num_batches * num_chars  # 计算出需要的总字符量targets = np.vstack((data[1:].A, data[0].A))  # 可能版本问题,取成numpy比较好reshapeinputs = data[:need_chars].A.astype("int")  # 从原始数据data中截取所需的字符数量need_wordstargets = targets[:need_chars]train_data = np.zeros((inputs.shape[0] - seq_len, seq_len, num_features))train_label = np.zeros((inputs.shape[0] - seq_len, num_features))for i in range(0, inputs.shape[0] - seq_len, 1):# inputs就是字符数 * 词向量大小(表示一个字符)# 思路就是abcd中ab-c, bc-d,一共4-3+1个train_data[i] = inputs[i:i+seq_len]  # 每seq_len=100的字符train_label[i] = inputs[i+seq_len-1] # 训练标签就为他后面那个字符print(train_data.shape)print(train_label.shape)for i in range(0, inputs.shape[0] - seq_len, batch_size):  x = train_data[i:i+batch_size] # 每batch_size=128个一起进行训练更新参数y = train_label[i:i+batch_size]  # 对应的128个标签print(x.shape)print(y.shape)print("-----------")yield x, y

模型构建部分

class lstm_model(nn.Module):def __init__(self, vocab, hidden_size, num_layers, dropout=0.5, seq_len=100):super(lstm_model, self).__init__()self.seq_len = seq_lenself.vocab = vocab  # 字符数据集# 索引,字符self.int_char = {i: char for i, char in enumerate(vocab)}self.char_int = {char: i for i, char in self.int_char.items()}# 对字符进行one-hot encodingself.encoder = OneHotEncoder(sparse=True).fit(vocab.reshape(-1, 1))self.hidden_size = hidden_sizeself.num_layers = num_layers# lstm层self.lstm = nn.LSTM(len(vocab), hidden_size, num_layers, batch_first=True, dropout=dropout)# 全连接层self.linear = nn.Linear(hidden_size, len(vocab))def forward(self, sequence, hs=None):# print("==========")# print("forward:", sequence.shape)out, hs = self.lstm(sequence, hs)  # lstm的输出格式(batch_size, sequence_length, hidden_size)print("----", out.shape)# out = out.reshape(-1, self.hidden_size)  # 这里需要将out转换为linear的输入格式,即(batch_size * sequence_length, hidden_size)print("========", out[:, -1].shape)output = self.linear(out[:, -1])  # 只取[bacth_size,hidden_size],即找到batch_size里每个元素的标签吧print("output-----:", output.shape)return output, hsdef onehot_encode(self, data):return self.encoder.transform(data)def onehot_decode(self, data):return self.encoder.inverse_transform(data)def label_encode(self, data):return np.array([self.char_int[ch] for ch in data])def label_decode(self, data):return np.array([self.int_char[ch] for ch in data])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/718755.shtml

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

相关文章

王者荣耀整蛊搭建直播新玩法/obs贴纸配置教程

最近很火的王者荣耀整蛊直播,相信很多玩王者的玩家也想开一个直播,但是看到这种直播娱乐效果很有意思也想搭建一个,这里梦哥给大家出了一期搭建的教程! 进阶版视频教程: 这期的教程是进阶版新玩法升级,具体…

Vue3:使用 Composition API 不需要 Pinia

在 Vue.js 开发的动态环境中,在单个组件中处理复杂的业务逻辑可能会导致笨重的文件和维护噩梦。虽然 Pinia 提供集中式状态管理,但仅依赖它来处理复杂的业务逻辑可能会导致代码混乱。本文探讨了使用 Composition API 的替代方法,说明开发人员…

数据库表 索引

目录 一、索引的分类 1、按存储形式: 1)B-TREE索引: 2)位图索引: 3)反向键索引: 4)基于函数的索引: 2、按唯一性: 1)唯一索引: 3、按列的个数…

代码随想录算法训练营第八天

344. 反转字符串 方法&#xff1a; 方法一&#xff1a; 直接用reverse函数 注意&#xff1a; 代码&#xff1a; class Solution { public:void reverseString(vector<char>& s) {return reverse(s.begin(), s.end());} };运行结果&#xff1a; 方法&#xff1…

解释前端路由的概念,以及单页应用(SPA)和多页应用(MPA)的区别

前端路由是现代Web应用中的一种设计模式&#xff0c;它允许用户在单个网页应用程序&#xff08;SPA&#xff09;内部通过改变URL而无需重新加载整个页面来切换不同的视图或内容。在传统的多页应用&#xff08;MPA&#xff09;中&#xff0c;每访问一个新页面&#xff0c;浏览器…

搜索算法(算法竞赛、蓝桥杯)--双向DFS+二分查找

1、B站视频链接&#xff1a;B26 双向DFS 送礼物_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; int n,m; int g[46];//存储所有物品的质量 int w[1<<23];//存储所有能凑出来的重量 int ans,cnt;//w的个数是cnt//搜索第u个数&#xff0c;和为s; …

Geeker Admin添加若以分离版本的后台作为后台

添加验证码 下载若依赖前后端分离版本&#xff0c;配置好自己数据库&#xff0c;redis连接地址 登录添加验证码 配置自己的若依后端连接地址 添加验证码请求方法 登录页面登录输入框添加验证码&#xff0c;uuid,调用的验证码刷新方法 注意&#xff1a;这里要用响应式定义验证…

5_怎么看原理图之协议类接口之NAND Flash笔记

NAND Flash原理图&#xff1a; 由NAND Flash的原理图可以看出&#xff0c;做为一个存储芯片&#xff0c;只有I/O引脚&#xff0c;并没有地址引脚&#xff0c;怎么传地址&#xff1f;遵循一定的规范&#xff0c;先通过LDATA把地址传出去&#xff0c;再传数据。具体的需要查看芯片…

vue前端数据转换显示

<el-table-column label"项目模板名称" align"center" prop"tempName" width"180" :formatter"templFormat" /> :formatter"templFormat" // 模板名单 optionTempls: [], // datas value templFormat(row,…

HTTP Cookie 你了解多少?

Cookie是什么&#xff1f; 先给大家举个例子&#xff0c;F12 打开浏览器的页面之后&#xff0c;我们能在 Response Headers 的字段里面看到一个header 叫做 Set-Cookie&#xff0c;如下所示 图中包含的 Set-Cookie 为 Set-Cookie:uuid_tt_dd10_20293537580-1709432565344-232…

Transformer模型分布式并行通信量浅析

1.数据并行DP&#xff08;朴素数据并行&#xff0c;Zero数据并行之后补充&#xff09; O ( h 2 ∗ l ) O(h^2*l) O(h2∗l) 每台机器做完自己的梯度后需要做一次All reduce操作来累积梯度&#xff0c;故一个batch计算发送的数据量为每层梯度大小 h 2 h^2 h2乘以层数 l l l 优点…

【李沐论文精读】Resnet精读

论文地址&#xff1a;Deep Residual Learning for Image Recognition 参考&#xff1a;撑起计算机视觉半边天的ResNet【论文精读】、ResNet论文逐段精读【论文精读】、【李沐论文精读系列】 一、导论 深度神经网络的优点&#xff1a;可以加很多层把网络变得特别深&#xff0c;…

力扣周赛387

第一题 代码 package Competition.The387Competitioin;public class Demo1 {public static void main(String[] args) {}public int[] resultArray(int[] nums) {int ans[]new int[nums.length];int arr1[]new int[nums.length];int arr2[]new int[nums.length];if(nums.leng…

Linux系统Docker部署RStudio Server

文章目录 前言1. 安装RStudio Server2. 本地访问3. Linux 安装cpolar4. 配置RStudio server公网访问地址5. 公网远程访问RStudio6. 固定RStudio公网地址 前言 RStudio Server 使你能够在 Linux 服务器上运行你所熟悉和喜爱的 RStudio IDE&#xff0c;并通过 Web 浏览器进行访问…

第二十四章 :Docker 部署 SpringBoot

第二十四章 :Docker SpringBoot 配置文件容器外加载部署 Docker version 25.0.3, build 4debf41 ,Docker Compose version v2.24.2容器运行后,若需修改配置文件,只需修改宿主机的application-prod.yml ,重启容器即可。 Springboot 2.x 版本 部署规划 服务器IP192.168.92…

4. 编写app组件

1. 代码 main.ts // 引入createApp用于创建应用 import {createApp} from "vue"// 引入App根组件 import App from ./App.vue createApp(App).mount(#app) App.vue <!-- vue文件可以写三种标签1. template标签&#xff0c;写html结构2. script 脚本标签&…

判断docker 镜像启动成功 shell脚本

要编写一个Shell脚本来判断Docker镜像是否启动成功&#xff0c;你可以使用docker ps命令来检查容器是否在运行状态。以下是一个简单的Shell脚本示例&#xff0c;用于判断Docker镜像是否成功启动&#xff1a; #!/bin/bash# 指定要检查的容器名称或ID CONTAINER_NAME"your_c…

风险评估是什么意思?与等保测评有什么区别?

最近看到不少小伙伴在问&#xff0c;风险评估是什么意思&#xff1f;与等保测评有什么区别&#xff1f;这里我们就来简单聊聊。 风险评估是什么意思&#xff1f; 风险评估是指对某个特定领域或项目进行全面分析和评估&#xff0c;以确定可能存在的潜在风险和危害&#xff0c;并…

2023全球软件开发大会-上海站:探索技术前沿,共筑未来软件生态(附大会核心PPT下载)

随着信息技术的迅猛发展&#xff0c;全球软件开发大会&#xff08;QCon&#xff09;已成为软件行业最具影响力的年度盛会之一。2023年&#xff0c;QCon再次来到上海&#xff0c;汇聚了众多业界精英、技术领袖和开发者&#xff0c;共同探讨软件开发的最新趋势和实践。 一、大会…

服务器感染了.ma1x0勒索病毒,如何确保数据文件完整恢复?

引言&#xff1a; 网络安全成为至关重要的议题。.ma1x0勒索病毒是当前网络威胁中的一种恶意软件&#xff0c;它的出现给用户带来了极大的困扰。然而&#xff0c;正如任何挑战一样&#xff0c;我们也有方法来面对并克服.ma1x0勒索病毒。本文将全面介绍这种病毒的特点&#xff0…