当前位置:   article > 正文

神经网络学习笔记_双路卷积神经网络和lstm神经网络

双路卷积神经网络和lstm神经网络

   近年来,深度学习技术在自然语言处理、计算机视觉等多个人工智能领域得 到了广泛的应用,获得了很大的成功。传统的机器学习算法通常结构较浅,比如支持向量机和逻辑回归等算法。浅结构模型很难学习复杂的功能,对自然语言处理等复杂任务的学习能力比较有限,通常需要手动定义特征。

   深度学习模型表现力强,比如循环神经网络、卷积神经网络、长短期记忆神经网络、门控循环单元等,能很好地适应复杂的函数,从数据中自动学习有用的功能,从而减轻人为的干预。

常用神经网络介绍

神经网络概述

   多层感知机是具有深层结构的初期神经网络,通常由输入层、隐藏层、输出层三个层次构成,下图就是一个标准的三层神经网络模型。但是,由于梯度消失和梯度爆炸的缺点,难以优化具有深层结构的神经网络。到 2006 年为止, Hinton 等提出了可靠的神经网络模型。使用无监督的方法预先训练各层的参数,并将其作为深度模型的初始参数使用,从而解决了深度神经网络难以优化的问题。

   
    下图是一个神经元结构图,其中 x i x_i xi 代表输入信息,一般为外部信息或者上层的输出部分, w i w_i wi 对应到每个 x i x_i xi 的权值。

   
    首先将输入部分进行加权求和,并加上神经网络的额外输入偏移值,最后利用下面公式的表征函数进行转换。
g ( x ) = f ( ∑ i = 1 n x i w i − b ) g(x)=f(\sum_{i=1}^{n}x_iw_i-b) g(x)=f(i=1nxiwib)
   转换完之后,利用激活函数将非线性引入神经网络,通常用到的激活函数包括 s i g m o i d sigmoid sigmoid函数、 t a n h tanh tanh函数等,不同的激活函数的计算方法与值域也不同。下面公式是 t a n h tanh tanh函数的计算方法,其输出范围是 ( − 1 , 1 ) (-1,1) (11)
t a n h ( x ) = e x − e − x e x + e − x tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}} tanh(x)=ex+exexex
   将多个上述基本神经元进行组合,就可以构成一个神经网络。

循环神经网络

   循环神经网络(Recurrent Neural Networks,RNN)是指一个随着时间的推移, 重复发生的结构。RNN 对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息。RNN 之所以被称之为循环,是因为它对序列的每一个部分都执行相同的任务,从而能够充分利用上下文的信息,而传统的神经网络的输入都是彼此相互独立的。除此之外,RNN 能够记忆处理过的信息,在处理长序列信息时效果更显著。

   上图是RNN的展开图,其中, X X X 表示输入的向量, U U U表示从输入到隐藏层计算需要的权值矩阵, S S S表示由上一时刻的隐藏层输出的权值矩阵, V V V表示从隐藏层到输出之间计算需要的权值矩阵。 t t t时刻的输入向量 s t s_t st首先通过 U U U S S S两个矩阵计算出其隐藏层的状态,计算过程如下面公示所示。
s t = f ( U x t + S s t − 1 ) s_t=f(U_{x_t}+S_{s_{t-1}}) st=f(Uxt+Sst1)
   然后通过 V V V计算并归一化,得到输出结果 o t o_t ot,其计算过程如下面公式所示。
o t = s o f t m a x ( V s t ) o_t=softmax(Vs_t) ot=softmax(Vst)
   与前馈神经网络模型相比,循环神经网络能够让隐藏层的神经元相互交流, 但它也存在一些问题,比如梯度爆炸和梯度消失等问题。

长短期记忆神经网络

   长短期记忆神经网络(Long-Short Term Memory,LSTM)是一种特殊的 RNN, 它能够学习长期的依赖关系,是为了解决 RNN 长时期依赖出现的梯度爆炸和梯 度消失的问题而出现的。它在处理各种各样的问题上表现出色,现在自然语言处理等领域已广泛使用。双向长短期记忆神经网络(Bi-directional Long Short Term Memory, BiLSTM)在 LSTM的基础上,结合了输入序列在前向和后向两个方向上的信息,而能够更充分的考虑到未来的上下文信息。
   下图是LSTM的模块结构图。

    LSTM有三个不同的门来控制信息的交互:输入门 i t i_t it、遗忘门 f t f_t ft、输出门 o t o_t ot。对于 t t t时刻的输入 x t x_t xt,在 t − 1 t-1 t1时刻生成 h t − 1 h_{t-1} ht1 c t − 1 c_{t-1} ct1,其中 c t − 1 c_{t-1} ct1的状态决定 t t t时刻的输入是否可用,遗忘 t − 1 t-1 t1时刻存储的记忆,并输出生成的状态。以下公式描述了上述过程:
i t = σ ( W x i x t + W h i h t − 1 + W c i c t − 1 + b i ) i_t=\sigma (W_{xi}x_t+W_{hi}h_{t-1}+W_{ci}c_{t-1}+b_i) it=σ(Wxixt+Whiht1+Wcict1+bi)
f t = σ ( W x f x t + W h f h t − 1 + W c f c t − 1 + b f ) f_t=\sigma (W_{xf}x_t+W_{hf}h_{t-1}+W_{cf}c_{t-1}+b_f) ft=σ(Wxfxt+Whfht1+Wcfct1+bf)
g t = t a n h ( W x c x t + W h c h i − 1 + W c c c t − 1 + b c ) g_t=tanh(W_{xc}x_t+W_{hc}h_{i-1}+W_{cc}c_{t-1}+b_c) gt=tanh(Wxcxt+Whchi1+Wccct1+bc)
c t = i t g t + f t c t − 1 c_t=i_tg_t+f_tc_{t-1} ct=itgt+ftct1
o t = σ ( W x o x t + W h o h i − 1 + W c o c t + b o ) o_t=\sigma(W_{xo}x_t+W_{ho}h_{i-1}+W_{co}c_{t}+b_o) ot=σ(Wxoxt+Whohi1+Wcoct+bo)
h t = o t t a n h ( c t ) h_t=o_ttanh(c_t) ht=ottanh(ct)

   BiLSTM由两个LSTM所组成,一个正向的LSTM利用过去的信息进行计算,一个逆向的LSTM利用未来的信息进行计算,最后将同一位置的两个输出拼接进行输出。这样在某一时刻,能够同时利用该时刻与前一时刻的信息。由于BiLSTM 能够同时利用过去时刻和未来时刻的信息,因此相较于单向的LSTM, 其得到的结果更加准确。下图是BiLSTM的示意图。

门控循环单元

   门控循环单元(Gated Recurrent Unit,GRU) 是经改进的一种RNN。和 LSTM 一样,也是为了解决长期记忆和反向传播中的梯度等问题而提出来的。除了GRU的输入输出部分与RNN 相同,GRU 模型首先利用上一个传输下来的状态 h t − 1 h_{t-1} ht1与当前节点的输入 x t x_t xt来获取两个门控状态,再使用重置门控来得到重置后的数据 r t r_t rt,以及更新后的数据 z t z_t zt,最后将单元状态与输出合并为一个状态 h t h_t ht,下图是具体的模型。

   一个 GRU 模型可以形式化的表示为:
r t = σ ( w r ⋅ ) r_t=\sigma (w_r\cdot ) rt=σ(wr)
z t = σ ( w z ⋅ [ h t − 1 , x t ] ) z_t=\sigma(w_z\cdot [h_{t-1},x_t]) zt=σ(wz[ht1,xt])
h t ^ = t a n h ( w h ⋅ [ r t ⋅ h t − 1 , x t ) \widehat{h_t}=tanh(w_h\cdot[r_t\cdot h_ {t-1},x_t) ht =tanh(wh[rtht1,xt)
y t = σ ( w o ⋅ h t ) y_t=\sigma(w_o\cdot h_t) yt=σ(woht)
h t = ( 1 − z t ) ⋅ h t − 1 + z t ⋅ h t ^ h_t=(1-z_t)\cdot h_{t-1}+z_t\cdot \widehat{h_t} ht=(1zt)ht1+ztht
   其中,σ 表示模型用到的激活函数,一般设置为sigmoid函数;重置之后的数据用 tanh 函数进行激活; x t x_t xt代表运行到t时刻的的输入部分; h t h_t ht代表 t 时刻的输出部分; z t z_t zt代表更新门; r t r_t rt代表重置门,GRU 的参数更新方式是基于沿时间反向传播的算法。

卷积神经网络

   LeCun 等在1989年提出了卷积神经网络(Convolutional Neural Networks,CNN ),该网络能够对输入的内容进行局部感知,提取出事物的特征。早先 CNN 大多在图像处理这一领域大量使用,后来很多学者利用其对该事物进行分类、识别、预测和决策。

    如上图所示,CNN 由卷积层、池化层、全连接层组成。对于输入的信息,首先利用不同的卷积核对输入的信息进行特征提取。其次经过池化层筛选卷积层输出中的局部信息,有效控制过拟合。最后通过全连接层将前面经过多次 卷积后高度抽象化的特征进行整合和归一化。

    以一个解决文本分类任务的卷积神经网络为例介绍其每一层的实现。假设该网络模型的输入是含有 n 个词的文本 T=(x1,x2,…,xn),首先利用下面公式进行卷积运算。
x 1 n = x 1 ⊕ x 2 ⊕ … ⊕ x n x_{1n}=x_1\oplus x_2\oplus…\oplus x_n x1n=x1x2xn
    其中 ⊕ \oplus 表示卷积操作, x i : i + j x_{i:i+j} xi:i+j 表示从第 i 个词语到第 i+j 个词语进行卷积运算。w 代表卷积核,h 代表卷积核的长度,b代表卷积核的偏移值,f 代表一个非线性函数。则计算从第 i 个词语到第 i+h个词语的特征的公式如下所示。
c i = f ( w ⋅ x i : i + h + b ) c_i=f(w\cdot x_{i:i+h}+b) ci=f(wxi:i+h+b)
    将每个词语在不同窗口大小中计算出的特征值整合在一个集合中,接下来进行最大池化操作,如以下公式所示。
c ^ = m a x ( c 1 , c 2 , … , c n − h ) \widehat {c}=max(c_1,c_2,…,c_{n-h}) c =max(c1,c2,,cnh)
    这个最大值 c ^ \widehat {c} c 就是该卷积核对应的特征值。最后经过全连接层进行整合和归一化,对文本的各种分类情况输出一个概率,根据得到的概率就能实现文本分类任务。

实验

    情感分析的对象最小粒度是词汇,但是表达一个情感的最基本的单位则是句子,词汇虽然能描述情感的基本信息,但是单一的词汇缺少对象及关联程度,且不同的词汇组合起来得到的情感程度不同甚至倾向都相反,因此以句子为基本单位是最为合理的。

    目前情感分析使用的方法有:
(1)基于词典的方法:通过预先定义一系列的情感词典和规则,对文本进行分词分句,计算情感值来作为文本的情感倾向判断依据。
(2)基于机器学习的方法:对于情感极性的判断,将目标情感分为三类:正(positive)、中(neutral)、负(negative)。对训练文本进行人工标注,然后进行有监督的机器学习过程,并对测试结果用模型来预测结果。
(3)基于深度学习的方法:基于机器学习的方法需要手动设计特征,工作量较大,而深度学习模型(如LSTM)可以从文本中自动提取特征。

    下面分别采用机器学习和深度学习的方法进行情感分析,并对比性能。

数据集来源

    数据为从京东爬取的产品评论数据,原始数据共215033条,下图为数据示例:
在这里插入图片描述

数据的预处理

筛选数据

    从原始数据集中抽取品牌为美的的产品评论数据,共55774条。再对原始数据去除重复的评论并对用词进行压缩,去重后的评论共53049条。

标注

    利用SnowNLP包对评论进行类标标注,节省人工标注成本。

import csv, codecs
from snownlp import SnowNLP

with codes.open(inputfile, 'r', encoding = 'utf-8') as inf:
    for line in inf:
        if not line.strip():
            continue
        sentscore = round((SnowNLP(line.strip()).sentiments-0.5)*20)
        if sentscore > 0:
            outf_pos.write(str(sentscore)+'\t'+line.strip()+'\n')
        else  sentscore < 0:
            outf_neg.write(str(sentscore)+'\t'+line.strip()+'\n')
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

替换标点符号

    读入正负例数据并拼接完成之后,利用正则表达式替换标点符号。

data_combine['word_punc'] = data_combine['words'].apply(lambda s: re.sub(r'[%s]+'%desl, "",s))
data_combine['word_cuts'] = data_combine['words_punc'].apply(lambda s: list(jieba.cut(s)))
  • 1
  • 2

去除停用词

   去除评论中的停用词:

data_combine['word_cuts_stop'] = data_combine['words_cuts'].apply(lambda s: [i for i in s if i not in stop_list])
  • 1

    经过上述预处理操作后,得到最终的数据集,下图为数据集中情感倾向为正和负的评论截图:

   

   

    数据集中正负评论的中位数分布如下图所示,可以看出负向评论较多。

基于机器学习的方法

抽取特征

   使用TF-IDF特征进行抽取:

from sklearn.feature_extraction.text import TfidVectorizer

vectorizer = TfidVectorizer()
X = vectorizer.fit_transform(data_combine['space_words'])
Y = np.array(list(data_combine['label']), dtype=np.int32)
  • 1
  • 2
  • 3
  • 4
  • 5

   划分数据集并训练以及测试模型,得到最终分类结果:

from sklearn.model_selection import train_test_split
from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score

#划分数据集
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

#分类器
clf = LinearSVC()

#训练模型
clf.fit(X_train, Y_train)

#测试模型
prediction = clf.predict(X_test)
accuracy_score(prediction, Y_test)


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

   最终实验准确率为:

0.8854
  • 1

基于深度学习的方法

   在基于深度学习的方法中,采用基于LSTM的模型进行训练测试。

词嵌入

   一个句子包含多个词,句子的长度不同,因此,直接把句子所有词的向量拼接,则句子向量长度就不统一,后续算法无法进行。因此,需要将句子固定相同的长度。将长度超过16的字符串截断,长度不足16的字符串补零。

from gensim.models import Word2Vec

def return_w2vvalue(s):
    try:
        return emotion_w2v[s]
    except:
        return [0]*60
    
def modify_words_lenth(s):
    if len(s)<=16:
        return s+[' ']*(16-len(s))
    else:
        return s[:16]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

   将截取后的词按照训练好的词向量转换:

data_combine['words_cut_stop_modify'] = data_combine['words_cuts_stop'].apply(lambda s: modify_words_lenth(s))

data_combine['words_trans_w2v'] = data_combine['words_cuts_stop_modify'].apply(lambda s: [return_w2v_value(i) for i in s])


  • 1
  • 2
  • 3
  • 4
  • 5

   划分数据集为训练集和测试集,其中,将特征数据x转换成NLM维度,N表示语句长度,L表示每句话长度,M表示每句话中每个词对应的词向量长度。将目标数据y转换成N* class维度,其中,N表示语句个数,class代表分类个数。

import numpy as np

x_train, x_test, y_train, y_test = train_test_split(data_combine['words_trans_w2v'], data_combine['label'],test_size=0.2)

x_train_modify = np.array(list(x_train))
x_test_modify = np.array(list(x_test))

y_train_modify = np.array(pd.get_dummies(y_train))
y_test_modify = np.array(pd.get_dummies(y_test))


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

模型训练及测试

   构建神经网络模型,模型的第一层输入参数为(16,60),表示句子长度为16,词向量维度为60。输出层为2个节点,使用softmax激活函数。

from keras.models import Sequential
from keras.layer.core import Dense, Activation
import time

start = time.time()

#构建模型
model = Sequential()
model.add(LSTM(22, imput_shape = (16,60), dropout = 0.5, activation = 'sigmoid'))
model.add(Dense(2, activation = 'softmax'))
model.compile(loss='categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy'])

#训练模型
history = model.fit(x_train_modify, y_train_modify, batch_size = 64, epochs = 10)

end = time.time()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

   训练过程截图:
在这里插入图片描述

   预测代码及结果如下所示:

from sklearn.metrics import accuracy_score

prediction = [np.argmax(i) for i in model.predict(x_test_modify)]
accuracy_score(prediction, y_test)
  • 1
  • 2
  • 3
  • 4
0.8912
  • 1

总结

   通过分析上述实验结果,可以看出基于深度学习的方法结果更好。同时,神经网络的应用更加广泛,在其他领域的各项任务中也取得了不错的效果。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/240624
推荐阅读
相关标签
  

闽ICP备14008679号