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)

在这里插入图片描述
可以看到效果不错

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

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

相关文章

Kafka SASL认证授权(五)ACL源码解析

Kafka SASL认证授权(五)ACL源码解析。 官网地址:https://kafka.apache.org/ 一、ACL检查流程解析 一起看一下kafka server的启动与监听流程: Kafka -> KafkaServer -> SocketServer、KafkaRequestHandler 其中KafkaServer做相关的初始化,包括SocketServer 与 han…

django无法导入第三方库

引子 有的人可能会很困惑,为什么自己在pip中安装了某个包,但是在django中死活无法导入。 在cmd中能够导入。 启动django,总是无法导入。 本文将会用一分钟解决你的困惑。 正文 那么本文以上述的第三方库dj_db_conn_pool为例,…

STM32 BootLoader设置

编写bootloader程序: 直接复制下面代码到自己程序中。 typedef void (*iapfun)(void); //定义一个函数类型的参数. iapfun jump2app; //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) {MSR MSP, r0 //set Main Stack valueBX r14 }//跳转到…

软件工程与计算总结(十三)详细设计中的模块化与信息隐藏

一.模块化与信息隐藏思想 1.设计质量 好的设计要着重满足以下3方面:可管理性、灵活性、可理解性好的设计需要侧重于间接性和可观察性——简洁性使得系统模块易于管理(理解和分解)、开发(修改与调试)和复用。实践者都…

BI零售数据分析:以自身视角展开分析

随着零售业务不断扩展,市场竞争不断加剧,各层级的销售管理人员都急需一张能快速查看销售数据分析报表,能从中知道自己管辖内的业务最近或过去的情况,并依次为依据科学优化销售管理措施。这就要求零售数据分析报表信息足够多、数据…

Mac硬盘检测工具

Mac硬盘检测软件是一款用于检测和诊断Mac硬盘健康状态的工具,帮助用户及时发现潜在的硬盘问题,避免数据丢失和系统故障。通过全面的检测和报告功能,用户可以更好地了解自己的硬盘状况,确保数据的安全和可靠。给大家介绍几款好用的…

PhotoShop批量压缩图片

打开photoshop,在顶部的菜单栏选择文件》脚本》图像处理器。 选择合适的参数,运行即可。

postman请求400错误-日期LocalData

错误日志参考 [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type java.lang.String to required type java.time.LocalDate; neste…

电脑D盘文件凭空消失了?切记3招,轻松恢复文件!

“由于我c盘内存不够了,我就将部分重要的文件保存到了d盘,今天打开d盘后才发现我这些文件凭空消失了。这究竟是什么呀?还有机会找回这些消失的d盘文件吗?” D盘作为电脑中一个重要的磁盘,很多电脑用户也会选择将文件保…

6.(vue3.x+vite)路由传参query与params区别

前端技术社区总目录(订阅之前请先查看该博客) 效果截图 一:路由传参有两种方式:params与query params与query区别 1:param,路由带“/”,query带“?” 2:query传过来的参数会显示到地址栏中 而params传过来的参数可以显示参数或隐藏参数到地址栏中(vue-router 4.1.4不…

Flutter笔记:发布一个电商中文货币显示插件Money Display

Flutter笔记 电商中文货币显示插件 Money Display 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/article/details/1338…

【性能测试】使用JMeter对code论坛进行压力测试

1.项目介绍 项目简介 code 论坛是一个技术交流社区。主要功能有发布帖子,查看帖子,评价帖子,删除帖子,点赞帖子,站内信,个人中心,修改个人信息等。是一个基于 Spring 的前后端分离项目。 项目链…

分享一下微信小程序怎么添加成绩查询插件

微信小程序如何添加成绩查询插件 一、引言 微信小程序是一种方便快捷的应用程序,可以在微信中使用。随着教育的不断发展,学校和家长对于学生的成绩查询需求也越来越高。通过在微信小程序中添加成绩查询插件,可以为学生和家长提供更加便捷的…

微信小程序获取手机号(2023年10月 python版)[无需订阅]

技术栈: 1. 微信开发者工具中的调试基础库版本:3.1.2。 2. 后台:django。 步骤: 1. 首先在后台django项目的定时任务中增加一个下载access_token函数,并把得到的access_token保存在数据库中(其实随便哪里…

正向代理——流量代理

文章目录 流量代理1. 正向代理2. 反向代理3. 流量转发工具4. 实验4.1 实验环境4.2 reGeorg工具 流量代理 1. 正向代理 正向代理是客户端和其他所有服务器(重点:所有)的代理者 2. 反向代理 反向代理是客户端和所要代理的服务器之间的代理。…

嵌入式和 Java选哪个?

今日话题,嵌入式和 Java 走哪个?对于嵌入式领域有浓厚兴趣的人,并不会比Java行业薪资低,处于上中游水平。特别是从2020年开始,嵌入式领域受益于芯片产业的兴起,表现出了强劲的增长势头。薪资水平受多方面因素影响。以…

7款最佳的图片编辑App

无论你是设计师需要调整界面图片大小,还是摄影师需要剪图片,追求完美的比例,还是日常照片,需要P图片,或多或少会有剪图片的需求,如何选择一个简单和轻的剪图软件应用程序,不是一件容易的事情。本…

【Hello Algorithm】暴力递归到动态规划(三)

暴力递归到动态规划(三) 最长公共子序列递归版本动态规划 最长回文串子序列方法一方法二递归版本动态规划 象棋问题递归版本动态规划 咖啡机问题递归版本动态规划 最长公共子序列 这是leetcode上的一道原题 题目连接如下 最长公共子序列 题目描述如下…

kafka安装和使用的入门教程

这篇文章简单介绍如何在ubuntu上安装kafka,并使用kafka完成消息的发送和接收。 一、安装kafka 访问kafka官网Apache Kafka,然后点击快速开始 紧接着,点击Download 最后点击下载链接下载安装包 如果下载缓慢,博主已经把安装包上传…

旧手机热点机改造成服务器方案

如果你也跟我一样有这种想法, 那真的太酷了!!! ok,前提是得有root,不然体验大打折扣 目录 目录 1.做一个能爬墙能走百度直连的热点机(做热点机用) 2.做emby视频服务器 3.做文件服务, 存取文件 4.装青龙面板,跑一些定时任务 5.做远程摄像头监控 6.做web服务器 7.内网穿…