很久时间没有更新博客了,这里我们一起回顾一下前面学习的深度学习的基本知识,然后进行一次实战分析。循环神经网络 ( R N N RNN RNN) 目前是自然语言处理中应用最为火热的一种神经网络,当然前提是不算上 G o o g l e Google Google 新开源的 B E R T BERT BERT , B E R T BERT BERT 相对于 R N N RNN RNN 准确率有很大提升,但是由于训练时间过长等原因,还没有大面积普及。 接下来我们实现在自然语言处理中应用的比较普遍的文本分类和情感分析,个人认为这两个属于同一类型,做法基本相同,我们使用 R N N RNN RNN 的变形 L S T M LSTM LSTM 来实现一个情感分析。
我这里使用的数据是自己在京东上爬的小米8的好评/差评各400条,打好正负标签。 差评:
好评:
将好评、差评放在一起并打乱。 将每条评论使用词嵌入 ( E m b e d d i n g ) (Embedding) (Embedding) 向量化,实现方法可以参考深度学习(十)-AI起名,这里我就不再重复讲解了。 产生的部分词汇表:
句向量:商 品 不 错 , 京 东 让 我 很 失 望 < = > [ 671 , 15 , 1 , 33 , 166 , 13 , 5 , 232 ] 商品不错,京东让我很失望 <=> [671, 15, 1, 33, 166, 13, 5, 232] 商品不错,京东让我很失望<=>[671,15,1,33,166,13,5,232] 在网上有很多争议就是一句话需不需要处理成相同长度,我个人的观点是:如果 b a t c h _ s i z e batch\_size batch_size 为 1 时,完全不需要处理成相同长度,但是如果 b a t c h _ s i z e batch\_size batch_size 大于 1 时,那就必须要处理成相同长度。数据处理好之后,将其按训练集/数据集为 0.7 拆分:其中 d a t a data data 为转为话句向量的数据集组成的列表, l a b e l s labels labels 为对应的标签列表。
num = int(0.7 * len(data)) x_train = data[: num ] y_train = labels[: num ] x_test = data[-num :] y_test = labels[-num :]网络创建依然与深度学习(十)-AI起名相同,LSTM网络创建基本就是相同,需要修改的地方并不是很多。
class LSTM(nn.Module): def __init__(self, vocab_size, embedding_dim, hidden_dim, output_size, num_layers): super(LSTM, self).__init__() self.vocab_size = vocab_size self.embedding_dim = embedding_dim self.hidden_dim = hidden_dim self.output_size = output_size self.num_layers = num_layers self.embeddings = nn.Embedding( self.vocab_size, self.embedding_dim) self.lstm = nn.LSTM(self.embedding_dim, self.hidden_dim, self.num_layers, batch_first=True) self.linear = nn.Linear(self.hidden_dim, self.output_size) self.drop = nn.Dropout(0.2) def forward(self, sentence): batch_size, seq_len = sentence.size() embeds = self.embeddings(sentence) embeds = self.drop(embeds) h_0 = Variable( torch.zeros(self.num_layers, batch_size, self.hidden_dim)) c_0 = Variable( torch.zeros(self.num_layers, batch_size, self.hidden_dim)) output, _ = self.lstm(embeds, (h_0, c_0)) output = output[:, -1, :].view(-1, self.hidden_dim) output = self.linear(output) output = functional.log_softmax(output) return output网络中 v o c a b _ s i z e vocab\_size vocab_size 表示词汇表长度, e m b e d d i n g _ d i m embedding\_dim embedding_dim 为词嵌入维度, h i d d e n _ d i m hidden\_dim hidden_dim 为隐藏层维度, o u t p u t _ s i z e output\_size output_size 为输出维度, n u m _ l a y e r s num\_layers num_layers 为网络层数。其中需要注意的是, L S T M LSTM LSTM 的输入默认为 [ s e q _ l e n , b a t c h _ s i z e , e m b e d d i n g _ d i m ] [seq\_len, batch\_size, embedding\_dim] [seq_len,batch_size,embedding_dim],参数中 b a t c h _ f i r s t batch\_first batch_first 可以决定 b a t c h _ s i z e batch\_size batch_size 的位置,默认为 F a l s e False False, 如果设置为 T r u e True True ,则输入为 [ b a t c h _ s i z , s e q _ l e n , e m b e d d i n g _ d i m ] [batch\_siz, seq\_len, embedding\_dim] [batch_siz,seq_len,embedding_dim],具体需要根据自己习惯来设置。
初始化模型:
model = LSTM(vocab_size=len(word_index), embedding_dim=200, hidden_dim=200, output_size=2, num_layers=2)其中 w o r d _ i n d e x word\_index word_index 为词汇表。我们可以看看模型的结构和参数:
model.parameters定义优化函数与损失函数:
optimizer = torch.optim.Adam(model.parameters(), 1e-3) # 优化器 criterion = nn.CrossEntropyLoss() # 损失函数在自然语言处理时,更多的使用 A d a m Adam Adam 来作为优化函数,因为其具有收敛速度较快且收敛过程较稳定的优点。学习率根据自己的情况来设置,一般大众的是 1 e − 3 1e-3 1e−3,使用时可以从大到小的尝试。
前面举过这么多神经网络的实例,大家应该对训练和测试也不陌生了,如果还有不清楚的童鞋,可以看看前面的例子,动手试试,我这里就不再贴代码出来了,最后看看训练结果:
我们随便找几句话测试看看效果:
