pytorch_神经网络构建4
文章目录
- 循环神经网络
- LSTM
- 词嵌入
- skip-Gram模型
- N-Gram模型
- 词性预测
- RNN循环神经网络的基础模块实现
- RNN识别图片
- RNN时间序列预测
- 词向量模块
- 词向量运用N-Gram模型
- lstm词性预测
循环神经网络
这个网络主要用来处理序列信息,之前处理图片时大部分是分析图片的结构信息,
什么是序列信息,比如文本,音乐,视频,DNA都可以看做序列信息,这些前后都是有关联的,循环神经网络将会在这些数据中分析他们前后的逻辑,找出关联的部分,从而模拟它们,推导它们的含义和作用,从这个角度看,RNN相比CNN是一次飞跃式进步,这意味着RNN将会产生类似逻辑思维的东西,比如新出的ChatGPT,它已经具备了一定程度的逻辑思维能力,但是从来没有人教给他如何推导,它从那些序列信息中学习到了逻辑思维,模仿了这种逻辑思维,人工智能的潜力在RNN网络中才真正的释放出来!
已经有人在用RNN推导DNA序列和蛋白质结构信息了,人工智能真的能给我们带来不同的视角来观察我们自己!
而文本信息和图片信息的不同之处在于其前后连贯,具备逻辑性,其含义和时间和记忆相关,不再是分类和识别问题,而是涉及到了文本的理解问题
这就让语义分析变得虚无缥缈起来
比如举例,
1.我说汉语,今天我坐飞机到了美国.
2.我说意大利语,今天我坐飞机到了美国.那么我可能是哪个国家的人?
这涉及到语言的逻辑分析,文本的理解,如何让神经网络在接受大量的文本后理解那些语言的含义是一个巨大的问题
有人提出了循环神经网络的概念
即当前的输入输出受到之前"记忆"的影响,即使输入相同,但是因为记忆不同,所以输出也会不同
如果把文本看做一个序列,那么对文本的处理,就可以循环进行,总是如此,对于每个数据输入点都施加记忆的影响,这样循环下去,这就是循环神经网络
当然,上述中的数据流看似每个输入点都被添加了不同的记忆,实际上他们使用了参数共享,施加的是同一记忆,这样就保证不管序列的长短,他们的向其施加的参数是类似的,保证了序列处理的连续性
这种结构为每个词语建立了相应的逻辑映射关系,有助于发现隐含在语言中的逻辑,但是比较明显的问题是如果词语相距甚远而又存在逻辑关系,就会出现强记忆(类似于人类总是对最近的事情记忆尤深)和强遗忘(对相距甚远的记忆进行遗忘)情况,导致逻辑关系不连贯,错误
比如我生在中国,…(差距1000字,介绍中国风景地貌和外国地貌语言,不涉及中国的语言文化),我说汉语,那么就很难把中国和汉语联系起来,这个问题被称为长时依赖问题
于是有人提出了LSTM和GRU来解决这个问题
LSTM
标准RNN:
对输入xt和输出ht公式为
即当前输出和上一步ht-1的输出相关,代表了循环网络记忆的特点
Lstm网络:
Long Short Term Memory networks
网络结构为:
输入输出门控制着结构的输入和输出,而遗忘门控制着记忆的保留度
即决定哪些是相关的,应该保留哪些记忆,这个筛选过程是自动进行的
内部结构为:
这是三序列LSTM结构,A结构相等,对于当前输入xt,输出ht有如下控制:
通过sigmoid先计算出衰减系数Ft,即对于过去的信息Ht-1保留多少
然后根据Ht-1和xt计算出需要保留新信息的多少,即系数It,以及新接受的信息Ct
然后根据两者的衰减系数Ft和It,乘过去的信息和新信息来得到t时刻的真实记忆状态Ct
当然,对于当前的记忆状态Ct,它融合了之前的输入Ht-1和当前的输入Xt,但是它是不必要全部输出的,它只有一部分是有用的
我们使用Ht-1和Xt计算一个系数决定t时刻要从Ct中输出多少记忆状态到Ht
GRU网络结构:
gated Recurrent Unit
gru提出了更新门的概念,它由遗忘门和输入门合成,同时抛弃了记忆状态Ct,而是将结果直接作为记忆状态向后传播
词嵌入
在进行图像识别时使用的是one-hot编码,对于某一类别用1表示,其他则为0,(0,0,0,1,0),表示第四类
然而对于词语来讲,单词动辄上万,而且大量的单词实际上是有联系的,可以进行归类,比如love,like
新的名词层出不穷,如何让神经网络自学习它们的联系,并且对其预测就需要对这些单词使用一种新的编码方式
(其实我认为作为汉语言来讲,3000个词就足以应对生活和各领域所有的场景,在训练LSTM方面优势是显著的,更加便于AI理解,真正恐怖的是英文单词动辄上万,新创造的单词拼写和其他单词几乎毫无关联)
词嵌入的概念是:
对每一个词都进行向量化,含义相近的词语向量相近,这样便于归类
比如有如下四句话,思考主体对象词语之间的关系
猫喜欢玩线团
kitty喜欢玩线团
狗喜欢玩球
人喜欢玩球
然后思考猫,kitty,狗,人这几个词之间的关系,假设这几个点生成在原点附近,哪几个词距离更近呢?
我们把喜欢线团设置为1,可以有猫(1,1),kitty(1,2),把喜欢球设置为-1,狗(-1,1),人(-1,2)
可以观察出猫和kitty距离更近,狗和人距离很近,但是这只是单语句所在的情况,当语句变多时分类有更加复杂的向量和更准确的关系
skip-Gram模型
它的思想是通过一个词周围的词来预测这个词,当然这实际上就在训练词嵌入模型
我们来假设一个滑动窗口,这和图像处理中的滑动窗口概念类似,它在语句序列上移动,它和周围的词相关
我们设定一个滑动窗口移动步长和关联范围,假设关联范围为2,可以得到如下映射关系
核心词和它周围词组成初始向量来表示他们的关系
N-Gram模型
前面我们讲了词嵌入如何得到,接下来我们讲述词嵌入如何来训练自然语言模型
我们的目的是根据已有的单词,去推测未知的单词
比如,他受伤了,他想去__我们很容易想到医院,这就是单词内部的逻辑,而我们希望语言模型能够把受伤和医院通过逻辑推导出来,让语言更加自然,所谓的聊天机器人也是根据我们的问题启发词推测后面我们未知的内容
明白了这一点,那么训练模型,就是如何找到这些单词之间的规律和联系
那么对于一句话来讲,它内部单词的顺序和构成就是以概率存在的,比如,他生病了,他想吃(),后面无形中就已经把房子,汽车,摄像头等一大堆无关紧要的单词排除掉了,而高概率的词,药和西瓜等等会以概率,出现,这就是传统概率学模型
假设它有n个单词,就可以描述为如下公式
这个模型也可以进一步简化,一个词不必与已知的所有词相关,它和前面的部分词相关即可 ,这就是马尔可夫假设
对于这里的条件概率计算,传统方式是统计语料中每个词的概率,然后用贝叶斯公式估计该单词的条件概率,
但是在这里我们可以用词嵌入向量进行平替,然后用RNN进行条件概率计算,然后最大化这个条件概率,更新词嵌入向量,同时用模型来预测某个单词
词性预测
一个单词有不同的词性,比如书,可以是书写,也可以是图书,在英文中,book同理
当然在英文中,是以连续的字符串进行确立的
比如apple,使用lstm逐个字符输入a p p l e得到字符串apple,在最后输出,在这个过程中,单词也能形成一种记忆特性,
然后再根据前面的单词对后面的单词词性进行预测
依次输入 i like book,在最后的输出那里根据前面的单词对后面的单词book进行词性推测,可以推导出这个单词为名词图书,然后可以进一步推断这句话的含义
RNN循环神经网络的基础模块实现
首先看RNN的基础模块,然后再介绍LSTM和GRU如何实现
RNN模块:
pytroch提供了两个函数来实现RNN模块
RNNCell() 函数表示单步模块,只接受序列中的一步,必须传入上一步隐含模块的输出Ht才可进行运算
RNN() 函数可以接受整个序列,隐含上一步的输入默认全0,也可以指定上一步的输出Ht
RNN() 有如下参数:
(输入大小,输出大小,网络层数,激活函数,偏置,数据的格式,输出层是否启用Dropout,是否使用双向RNN默认false)
数据格式:,默认false,格式为(序列长度,批大小,特征维度),true为(批大小,序列长度,特征维度),控制着输入输出数据的格式,一般为true,因为pytroch大部分数据格式都是如此
双向RNN:相比单向RNN可以从前后同时处理序列,可以更好的理解文本上下文信息,但是训练和生成时间更久
(input_size,hidden_size,num_layers,nonlinearty,bias,batch_first,dropout,bidirectional)
RNNcell()只有三个参数,因为其只处理一步:
(input_size,hidden_size,bias,nonlinearty)很少使用它
rnn_single = nn.RNNCell(input_size=100, hidden_size=200)
print(rnn_single.weight_hh)
# 构造一个序列,长为 6,batch 是 5, 特征是 100
x = Variable(torch.randn(6, 5, 100)) # 这是 rnn 的输入格式
# 定义初始的记忆状态,假设上一步200个输出全0
h_t = Variable(torch.zeros(5, 200))
# 传入 rnn
out = []
for i in range(6): # 通过循环 6 次作用在整个序列上h_t = rnn_single(x[i], h_t)out.append(h_t)
print(out[0].shape)
print(len(out))
可以看到结果为5个批次,每个批次长度为6的200特征维度的输出,这样并不符合描述习惯,所以RNN()设置Batch_first为true更符合习惯
rnn_seq = nn.RNN(100, 200,batch_first=True)
# 访问其中的参数
print(rnn_seq.weight_hh_l0)
# 构造一个序列,batch 是 5, 长为 6,特征是 100
x = Variable(torch.randn(5,6, 100)) # 这是 rnn 的输入格式
out, h_t = rnn_seq(x) # 使用默认的全 0 隐藏状态
h_0 = Variable(torch.randn(1, 5, 200))# 自定义隐藏状态
out, h_t = rnn_seq(x, h_0)
print(out.shape)
不是特殊要求,初始隐藏状态我们也会选择全0,即使要求,我们也可以初始化隐藏状态,所以RNN()比RNNCell()使用更多,并且更方便
LSTM:
LSTM具备和RNN类似的使用方式,LSTMCell()和LSTM()
lstm_seq = nn.LSTM(50, 100, num_layers=2,batch_first=True) # 输入维度 50,输出 100,两层
print(lstm_seq.weight_hh_l0)
lstm_input = Variable(torch.randn(3,10, 50)) # bitch为3,序列长度为10,输入维度 50
out, (h, c) = lstm_seq(lstm_input) # 使用默认的全 0 隐藏状态
print(out.shape)
print(h.shape)
print(c.shape)
h_init = Variable(torch.randn(2, 3, 100))
c_init = Variable(torch.randn(2, 3, 100))
out, (h, c) = lstm_seq(lstm_input, (h_init, c_init))
out是最终输出,h代表层输出状态,c代表层记忆状态
GRU模块:
与之类似
gru_seq = nn.GRU(10, 20,batch_first=True)
gru_input = Variable(torch.randn(32, 3,10))
out, h = gru_seq(gru_input)
print(out.shape)
print(h.shape)
思考:为什么第一,二层的权重参数量为(400,100)?
lstm_seq = nn.LSTM(50, 100, num_layers=2,batch_first=True) # 输入维度 50,输出 100,两层
print(lstm_seq.weight_hh_l0.size())
print(lstm_seq.weight_hh_l1.size())
RNN处理序列的方式为我们提供了神经网络的新思路,当为神经网络添加记忆的特性时,很多显而易见的结果才变的显而易见,很容易想到,我们大脑处理信息时也不是单独的一次逻辑推导,而是伴随着我们的见识和阅历来解读新的信息,就像我们看到一张图片一段文字不同的理解一样
RNN识别图片
Normalize()将输入数据标准化,均值为0,标准差为1
tfs.Normalize([0.5], [0.5])含义为将输入数据的每个通道减去均值0.5,除以标准差0.5
我们继续对之前的minist十分类进行训练,查看rnn表现
对数据预处理
# 定义数据
data_tf = tfs.Compose([tfs.ToTensor(),tfs.Normalize([0.5], [0.5]) # 标准化
])
# # 指定文件夹
print(os.listdir(sys.path[0]))
folder_path =r"D:\PGMCode\Mycode\pythonCode\jupyterNoteBook\data"train_set = MNIST(folder_path, train=True, transform=data_tf)
test_set = MNIST(folder_path, train=False, transform=data_tf)train_data = DataLoader(train_set, 64, True, num_workers=4)
test_data = DataLoader(test_set, 128, False, num_workers=4)
定义rnn模型
# 定义模型
class rnn_classify(nn.Module):def __init__(self, in_feature=28, hidden_feature=100, num_class=10, num_layers=2):super(rnn_classify, self).__init__()self.rnn = nn.LSTM(in_feature, hidden_feature, num_layers) # 使用两层 lstm# 将最后一个 rnn 的输出使用全连接得到最后的分类结果self.classifier = nn.Linear(hidden_feature, num_class)def forward(self, x):"""x 大小为 (batch, 1, 28, 28),所以我们需要将其转换成 RNN 的输入形式,即 (28, batch, 28)"""x = x.squeeze() # 去掉 (batch, 1, 28, 28) 中的 1,变成 (batch, 28, 28)x = x.permute(2, 0, 1) # 将最后一维放到第一维,变成 (28, batch, 28)out, _ = self.rnn(x) # 使用默认的隐藏状态,得到的 out 是 (28, batch, hidden_feature)out = out[-1, :, :] # 取序列中的最后一个,大小是 (batch, hidden_feature)out = self.classifier(out) # 得到分类结果return out
进行训练
net = rnn_classify()
criterion = nn.CrossEntropyLoss()optimzier = torch.optim.Adadelta(net.parameters(), 1e-1)
# 开始训练
from utils import train
train(net, train_data, test_data, 10, optimzier, criterion)
十次训练结果就达到了97%,效果显著,然而图像上用rnn效果和cnn差距不大
RNN表现最强势的地方在于文字序列的处理
接下来我们用RNN来预测飞机人次数据
RNN时间序列预测
以下是10年来每个月,飞机人次登记数据,因为是序列数据,我们用前两个月的流量人次作为x,后一个月流量人次作为y进行训练
先查看数据:
folder_path =r"D:\PGMCode\Mycode\pythonCode\jupyterNoteBook\data.csv"
data_csv = pd.read_csv(folder_path, usecols=[1])
print(data_csv)
plt.plot(data_csv)
可以观察到csv中为一维的流量人次数据,10年120个月
数据预处理,清除nan数据,将所有值缩放到[0,1]区间,将前两个月的数据作为x,后一个月作为y处理序列数据
# 数据预处理
data_csv = data_csv.dropna() # 去掉 na
dataset = data_csv.values
dataset = dataset.astype('float32')
max_value = np.max(dataset)
min_value = np.min(dataset)
scalar = max_value - min_value
dataset = list(map(lambda x: x / scalar, dataset))
def create_dataset(dataset, look_back=2):dataX, dataY = [], []for i in range(len(dataset) - look_back):a = dataset[i:(i + look_back)]dataX.append(a)dataY.append(dataset[i + look_back])return np.array(dataX), np.array(dataY)
# 创建好输入输出
data_X, data_Y = create_dataset(dataset)
划分测试集和训练集,调整数据输入格式
numpy中的reshape()函数,(-1,1,2),-1表示该维度大小由其他维度控制,这里-1表示3,
# 划分训练集和测试集,70% 作为训练集
train_size = int(len(data_X) * 0.7)
test_size = len(data_X) - train_size
train_X = data_X[:train_size]
train_Y = data_Y[:train_size]
test_X = data_X[train_size:]
test_Y = data_Y[train_size:]
import torchtrain_X = train_X.reshape(-1, 1, 2)# RNN 读入的数据维度是 (seq, batch, feature)
train_Y = train_Y.reshape(-1, 1, 1)
test_X = test_X.reshape(-1, 1, 2)train_x = torch.from_numpy(train_X)
train_y = torch.from_numpy(train_Y)
test_x = torch.from_numpy(test_X)
构建rnn网络进行训练
from torch import nn
from torch.autograd import Variable
# 定义模型
class lstm_reg(nn.Module):def __init__(self, input_size, hidden_size, output_size=1, num_layers=2):super(lstm_reg, self).__init__()self.rnn = nn.LSTM(input_size, hidden_size, num_layers) # rnnself.reg = nn.Linear(hidden_size, output_size) # 回归def forward(self, x):x, _ = self.rnn(x) # (seq, batch, hidden)s, b, h = x.shapex = x.view(s*b, h) # 转换成线性层的输入格式x = self.reg(x)x = x.view(s, b, -1)return x
net = lstm_reg(2, 4)criterion = nn.MSELoss()
optimizer = torch.optim.Adam(net.parameters(), lr=1e-2)
# 开始训练
for e in range(1000):var_x = Variable(train_x)var_y = Variable(train_y)# 前向传播out = net(var_x)loss = criterion(out, var_y)# 反向传播optimizer.zero_grad()loss.backward()optimizer.step()if (e + 1) % 100 == 0: # 每 100 次输出结果print('Epoch: {}, Loss: {:.5f}'.format(e + 1, loss.item()))
将整个数据集的data_X输入网络进行训练,查看模拟情况
net = net.eval() # 转换成测试模式
data_X = data_X.reshape(-1, 1, 2)
data_X = torch.from_numpy(data_X)
var_data = Variable(data_X)
pred_test = net(var_data) # 测试集的预测结果
# 改变输出的格式
pred_test = pred_test.view(-1).data.numpy()
# 画出实际结果和预测的结果
plt.plot(pred_test, 'r', label='prediction')
plt.plot(dataset, 'b', label='real')
plt.legend(loc='best')
如果使用线性回归模拟效果并不如RNN找到的规律有用,RNN对之前规律的记忆对趋势的把握更加准确
词向量模块
我们知道词向量是用来在神经网网络训练中表示词之间的关系的
这个关系也是神经网络经过训练之后生成的
在pytorch中初始化词向量操作如下
torch.nn.Embedding(m, n)创造了一个单词矩阵,每个单词都被一个n维度的向量标定
生成此矩阵时会默认随机赋予权重
也可以使用规定的权重代替
如果要查看某个单词的权重可以使用 LongTensor类型的坐标调用
# 定义词嵌入
embeds = nn.Embedding(2, 5) # 2 个单词,维度 5
embeds.weight.data = torch.ones(2, 5)
print(embeds.weight)
single_word_embed = embeds(Variable(torch.LongTensor([1])))
print(single_word_embed)
词向量运用N-Gram模型
前面讲述了词向量如何被初始化,现在我们给出一段文字,要求在已知前两个词的前提下预测第三个词
CONTEXT_SIZE = 2 # 依据的单词数
EMBEDDING_DIM = 10 # 词向量的维度
test_sentence = """北 国 风 光 千 里 冰 封 万 里 雪 飘
望 长 城 内 外 惟 余 莽 莽 ; 大 河 上 下 顿 失 滔 滔
山 舞 银 蛇 原 驰 蜡 象 欲 与 天 公 试 比 高
须 晴 日 看 红 装 素 裹 分 外 妖 娆
江 山 如 此 多 娇 引 无 数 英 雄 竞 折 腰
惜 秦 皇 汉 武 略 输 文 采 ; 唐 宗 宋 祖 稍 逊 风 骚
一 代 天 骄 成 吉 思 汗 只 识 弯 弓 射 大 雕
俱 往 矣 数 风 流 人 物 还 看 今 朝
""".split()
接下来我们为每个字构建一个坐标,来标识这个字
trigram = [((test_sentence[i], test_sentence[i+1]), test_sentence[i+2]) for i in range(len(test_sentence)-2)]
print(trigram[0])
# 建立每个词与数字的编码,据此构建词嵌入
vocb = set(test_sentence) # 使用 set 将重复的元素去掉
word_to_idx = {word: i for i, word in enumerate(vocb)}
print(word_to_idx)
创建一个模型,输入词104,标识维度为10,输出维度为104,相当于一个矩阵
# 定义模型
class n_gram(nn.Module):def __init__(self, vocab_size, context_size=CONTEXT_SIZE, n_dim=EMBEDDING_DIM):super(n_gram, self).__init__()self.embed = nn.Embedding(vocab_size, n_dim)self.classify = nn.Sequential(nn.Linear(context_size * n_dim, 128),nn.ReLU(True),nn.Linear(128, vocab_size))def forward(self, x):voc_embed = self.embed(x) # 得到词嵌入voc_embed = voc_embed.view(1, -1) # 将两个词向量拼在一起out = self.classify(voc_embed)return out
net = n_gram(len(word_to_idx))
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr=1e-2, weight_decay=1e-5)
print(net)
开始训练,主要是对特征维度进行更新
for e in range(100):train_loss = 0for word, label in trigram: word = Variable(torch.LongTensor([word_to_idx[i] for i in word])) # 将两个词作为输入print(word)label = Variable(torch.LongTensor([word_to_idx[label]]))print(label)# 前向传播out = net(word)print(out.size())loss = criterion(out, label)train_loss += loss.item()# 反向传播optimizer.zero_grad()loss.backward()optimizer.step()
# if (e + 1) % 20 == 0:print('epoch: {}, Loss: {:.6f}'.format(e + 1, train_loss / len(trigram)))
查看词嵌入预测效果如何:
查看更新后的权重和预测效果
a=net.embed
print(a.weight.size())
idx_to_word = {word_to_idx[word]: word for word in word_to_idx}
net = net.eval()
# 测试一下结果
word, label = trigram[3]
print('input: {}'.format(word))
print('label: {}'.format(label))
print()
word = Variable(torch.LongTensor([word_to_idx[i] for i in word]))
out = net(word)
pred_label_idx = out.max(1)[1].data[0]
predict_word = idx_to_word[int(pred_label_idx)]
print('real word is {}, predicted word is {}'.format(label, predict_word))
lstm词性预测
掌握一句话中每个字的词性对于推导这句话的含义具有重大帮助
从之前的词性预测理论中我们设想了这样一种方式
将每个单词拆分成一个个字母,分析它内在的结构对词性的影响,比如look和looking
然后再通过整个句子对这个单词进行词性推测
我们对两句话进行训练和学习
training_data = [("The dog ate the apple".split(),["DET", "NN", "V", "DET", "NN"]),("Everybody read that book".split(), ["NN", "V", "DET", "NN"])]
word_to_idx = {}
tag_to_idx = {}
for context, tag in training_data:for word in context:if word.lower() not in word_to_idx:word_to_idx[word.lower()] = len(word_to_idx)for label in tag:if label.lower() not in tag_to_idx:tag_to_idx[label.lower()] = len(tag_to_idx)
print(word_to_idx)
print(tag_to_idx)
然后对单词的字母进行编码,为组字母成单词,单词成句做基础工作
alphabet = 'abcdefghijklmnopqrstuvwxyz'
char_to_idx = {}
for i in range(len(alphabet)):char_to_idx[alphabet[i]] = i
print(char_to_idx)
我们查看一下被编码后原来的句子和单词都如何被机器识别,它们都被一个个数字所标记
def make_sequence(x, dic): # 字符编码idx = [dic[i.lower()] for i in x]idx = torch.LongTensor(idx)return idx
a=make_sequence('apple', char_to_idx)
print(a)
print(training_data[1][0])
print(make_sequence(training_data[1][0], word_to_idx))
然后构建单个字符的lstm模型,寻找单个单词的内部结构规律
class char_lstm(nn.Module):def __init__(self, n_char, char_dim, char_hidden):super(char_lstm, self).__init__()self.char_embed = nn.Embedding(n_char, char_dim)self.lstm = nn.LSTM(char_dim, char_hidden)def forward(self, x):x = self.char_embed(x)out, _ = self.lstm(x)return out[-1] # (batch, hidden)
构建词性分类的模型,将单个词性的lstm输出作为结果当词性模型的输入
class lstm_tagger(nn.Module):def __init__(self, n_word, n_char, char_dim, word_dim, char_hidden, word_hidden, n_tag):super(lstm_tagger, self).__init__()self.word_embed = nn.Embedding(n_word, word_dim)self.char_lstm = char_lstm(n_char, char_dim, char_hidden)self.word_lstm = nn.LSTM(word_dim + char_hidden, word_hidden)self.classify = nn.Linear(word_hidden, n_tag)def forward(self, x, word):char = []for w in word: # 对于每个单词做字符的 lstmchar_list = make_sequence(w, char_to_idx)char_list = char_list.unsqueeze(1) # (seq, batch, feature) 满足 lstm 输入条件char_infor = self.char_lstm(Variable(char_list)) # (batch, char_hidden)char.append(char_infor)char = torch.stack(char, dim=0) # (seq, batch, feature)x = self.word_embed(x) # (batch, seq, word_dim)x = x.permute(1, 0, 2) # 改变顺序x = torch.cat((x, char), dim=2) # 沿着特征通道将每个词的词嵌入和字符 lstm 输出的结果拼接在一起x, _ = self.word_lstm(x)s, b, h = x.shapex = x.view(-1, h) # 重新 reshape 进行分类线性层out = self.classify(x)return out
开始训练
net = lstm_tagger(len(word_to_idx), len(char_to_idx), 10, 100, 50, 128, len(tag_to_idx))
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr=1e-2)
# 开始训练
for e in range(300):train_loss = 0for word, tag in training_data:word_list = make_sequence(word, word_to_idx).unsqueeze(0) # 添加第一维 batchtag = make_sequence(tag, tag_to_idx)word_list = Variable(word_list)tag = Variable(tag)print(tag)# 前向传播out = net(word_list, word)print(out)loss = criterion(out, tag)train_loss += loss.item()# 反向传播optimizer.zero_grad()loss.backward()optimizer.step()if (e + 1) % 50 == 0:print('Epoch: {}, Loss: {:.5f}'.format(e + 1, train_loss / len(training_data)))
测试预测效果
net = net.eval()
test_sent = 'The dog ate the apple'
test = make_sequence(test_sent.split(), word_to_idx).unsqueeze(0)
print(test)
out = net(Variable(test), test_sent.split())
print(out)
查看预测效果如何
import numpy as np
keys=tag_to_idx.keys()
speechList=[]
for i in out:temp=i.detach().numpy()for j in keys:if tag_to_idx.get(j)==temp.argmax():speechList.append(j)break
test_sent = 'The dog ate the apple'
print(test_sent)
print(speechList)
可以看到效果不错
相关文章:

pytorch_神经网络构建4
文章目录 循环神经网络LSTM词嵌入skip-Gram模型N-Gram模型词性预测RNN循环神经网络的基础模块实现RNN识别图片RNN时间序列预测词向量模块词向量运用N-Gram模型lstm词性预测 循环神经网络 这个网络主要用来处理序列信息,之前处理图片时大部分是分析图片的结构信息, 什么是序列信…...

外骨骼机器人和人形机器人概览
前言:一点思考 外骨骼机器人和人形机器人都曾随着一些爆品的出现火热过一段时间,但总感觉当前技术条件还不成熟,真正能落地的应用场景不多。马斯克在擎天柱发布会上被问到人形机器人的落地与前景问题时并没有给出明确答案,只是用…...
Java面试题:链表-反转链表
问题描述 给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。 如当输入链表{1,2,3}时,经反转后,原链表变为{3,2,1},…...

el-upload实现上传文件夹
背景:如图一所示,最下面有一个黄色上传文件按钮,为手动上传而且上传区域有上传文件和上传文件夹的区分 所以需要在点击了上传文件夹做特殊处理使得el-upload可以上传文件夹 一、template区域 <el-uploadclass"upload-file"dra…...

京东数据平台(京东数据分析)2023年9月京东冰箱行业品牌销售排行榜!
鲸参谋监测的京东平台9月份冰箱市场销售数据已出炉! 9月份,大家电行业整体下滑,而冰箱作为大家电市场中的重点品类,受行业趋势变动的影响,冰箱销售市场也同样下滑。鲸参谋数据显示,9月在京东平台上…...

【Excel】WPS单元格快速转换表格字母大小写
使用WPS Office打开表格,选择需要处理的单元格或单元格区域。 依次点击「会员专享」选项卡 —>「智能工具箱」。 再点击「格式」—>「大小写」,选择一种大小写转换方式即可。...

【java】【重构一】分模块开发设计实战
目录 一、创建项目 1、先创建一个空项目 2、设置项目SDK等 二、创建父模块 选择springboot 1、创建父模块parent 2、删除多余文件,只保留pom.xml 3、修改pom.xml 4、将部分公共依赖加入到pom 三、创建实体类子模块entity 1、创建实体类子模块entity 2、…...

Cocos Creator3.8 项目实战(十)使用 protobuf详细教程
在 Cocos Creator 中使用 protobuf.js 库可以方便地进行协议的序列化和反序列化。 下面是使用 protobuf.js 的详细说明: 一、protobuf环境安装 1、安装 npm protobuf环境安装安装需要使用 npm 命令进行,因此首先需要安装 npm 。 如果你还没安装 npm …...
第七章:最新版零基础学习 PYTHON 教程—Python 列表(第八节 -在 Python 中获取列表作为用户的输入)
我们经常遇到需要将数字/字符串作为用户输入的情况。在本文中,我们将了解如何使用Python从用户处获取输入列表。 目录 使用Loop在 Python 中获取用户输入的列表 Python3...

Simple RPC - 02 通用高性能序列化和反序列化设计与实现
文章目录 概述设计实现通用的序列化接口通用的序列化实现【推荐】 vs 专用的序列化实现专用序列化接口定义序列化实现 概述 网络传输和序列化这两部分的功能相对来说是非常通用并且独立的,在设计的时候,只要能做到比较好的抽象,这两部的实现…...

简单秒表设计仿真verilog跑表,源码/视频
名称:简单秒表设计仿真 软件:Quartus 语言:Verilog 代码功能: 秒表显示最低计时为10ms,最大为59:99,超出返回00:00 具有复位、启动、暂停三个按键 四个数码管分别显示4个时间数字。 演示…...

【发布】Photoshop ICO 文件格式插件 3.0
备注:本文原文首发于博客园: https://www.cnblogs.com/hoodlum1980/p/17766287.html 【简介】 Photoshop ICO 插件是为 Photoshop 开发的功能扩展插件,使得 Photoshop 可以直接读写 ICO 格式文件。由于 Photoshop 具有强大的像素位图编辑功…...

负载均衡、代理和动静分离的战略
一、Nginx简介 1.1 概述 Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理服务器,特点是占有内存少,并发能力强,能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数 。 1.2正向代理与反向代理 1.2.1正向代理 正向代理:如果把局域网外的 Internet 想象…...
Gitlab用户角色权限Guest、Reporter、Developer、Master、Owner
Gitlab用户在组中有角色权限:Guest、Reporter、Developer、Master、Owner Gitlab权限管理 Guest:可以创建issue、发表评论,不能读写版本库 Reporter:可以克隆代码,不能提交,QA、PM可以赋予这个权限 Deve…...

C#上位机序列9: 批量读写+事件广播+数据类型处理
一、源码结构: 二、运行效果: 三、源码解析 1. 读取配置文件及创建变量信息(点位名称,地址,数据类型(bool/short/int/float/long/double)) 2. 异步任务处理:读任务&…...

科技资讯|2023全球智能手表预估出货1.3亿块,智能穿戴提升AI功能
根据集邦咨询公布的最新报告,受全球经济低迷影响,2023 年全球智能手表出货量预估为 1.3 亿块。苹果以超过 30% 的份额领先,其次是三星(接近 10%)、华为、Garmin、Fitbit 等。 报告认为苹果、三星和华为等主要智能手表…...
技术架构之术
架构特征 1、结构性特征 易理解、可复用、可移植、可扩展、可配置、可维护、可测试 2、运行时特征 可靠性、稳定性、高安全、可伸缩、易用性、可用性、高性能、可观测 3、交付性特征 高效率、高适配、标准化、灵活性、易定制、统一性、开放性 如何开展我们的架构工作 价值分…...

【自用重要】概率论中θ和θ尖的区别【计算时的一般方法】
θ就相当于x,是一个值。 θ尖就相当于X,是一个量。 在做分布函数的时候,最好把θ尖换成Z的形式,因为他们都是量,这样比较好看。 在做不等式的时候,一般把量放在中间进行计算,因为随机变量有分…...

Redis设计与实现笔记 - 数据结构篇
Redis设计与实现笔记 - 数据结构篇 相信在我们日常使用中,会经常跟 Redis 打交道。数据结构 String、Hash、List、Set 和 ZSet 都是常用的数据类型。对于使用场景,我们可以滔滔不绝地说很多,但是我们从来就没有关心过它们的底层实现…...

线性代数-Python-01:向量的基本运算 -手写Vector -学习numpy的基本用法
文章目录 代码目录结构Vector.py_globals.pymain_vector.pymain_numpy_vector.py 一、创建属于自己的向量1.1 在控制台测试__repr__和__str__方法1.2 创建实例测试代码 二、向量的基本运算2.1 加法2.2 数量乘法2.3 向量运算的基本性质2.4 零向量2.5 向量的长度2.6 单位向量2.7 …...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...