《python实现RNN情感分析设计.docx》由会员分享,可在线阅读,更多相关《python实现RNN情感分析设计.docx(8页珍藏版)》请在第一文库网上搜索。
1、python实现RNN情感分析本次实验对ac11mdb电影评价数据集进行深度学习,用pytorch构建和训练基于循环神经网络1STM的模型,并利用此模型对于给定的电影评论文本进行预测,判断改评论是正面的还是负面的。试验后准确率高达98%。一.实现方法1、 RNNRNN(recurrentneura1network,循环神经网络),在一般的神经网络由输入层、隐藏层、输出层构成。RNN在处理序列数据上是高效的,在此模型中有着一些特殊的信号决定了此模型是否需要记住上下文信息。他们可以从上一个时间步获取信息并传递到下一个时间步中。下图是一个标准循环神经网络的图像。RNN按下图所示时间顺序展开,在t时刻
2、,网络读入第t个输入xt,以及前一时刻状态值ht-1(向量表示,h表示初始化为0的向量),从而计算出本时刻隐藏层的状态值ht,若函数表示为f,则公式表示为:ht=f(tzht-1)=(Wxht+Whhht-1+bh):其中,WXh是输入层到隐藏层的矩阵参数,Whh为隐藏层到隐藏层的矩阵参数,bh为隐藏层偏置参数。RNN隐藏层的状态向量被送入一个SoftmaX分类器,然后判断其情感;2、 1STM保留了文本中的长期依赖信息,通过对循环层的刻意设计避免了长期依赖和梯度消失问题。输入单元输入数据X(t),隐藏层输出hh(t),在这些单元中,隐藏层表达复杂,主要分为4个部分:输入门i、输出门0、遗忘门
3、f、记忆控制器C,将1STM表示函数记为F,ht=F(xtzht-1);it(Wxix,+Whihhi+FFm+6)f1=(xx1+Ar.+cm+6z)c1f1Oc1.+i1Otanh(%M必瓦i+九)o1=(Wxox,-WhJt1.+Wcoc1+bo)h1otIanh(C,)其中W及b是模型参数,tanh是双曲正切函数二,大致思路在这里我们将使用RNN(循环神经网络如图5所示)对电影评论进行情感分析,结果为positive或negative,分别代表积极和消极的评论。至于为什么使用RNN而不是普通的前馈神经网络,是因为RNN能够存储序列单词信息,得到的结果更为准确。这里我们将使用一个带有标签
4、的影评数据集进行训练模型。将单词传入到嵌入层而不是使用ONE-HOT编码,是因为词嵌入是一种对单词数据更好的表/Ko在嵌入层之后,新的表示将会进入1STM细胞层。最后使用一个全连接层作为输出层。我们使用Sigmiod作为激活函数,因为我们的结果只有positivenegative两个表示情感的结果。输出层将是一个使用sigmoid作为激活函数的单一的单元。三,具体程序1、导入并读取数据集fnameos.path.join(DATA-ROOX,ac11mdb-v1.tar.gz)符压缩文件进行解乐ifnotos.path.exists(os.path.join(DATA_ROOXac11mdb*
5、):Pmtr从乐缩包解乐”)withtarfi1e.open(fname,r,)asf:fextracta11(DAA-R00H解乐文件到此指定路径fromtqdmimporttqdm/可查看读取数据的进程defread-imdb(fo1der,trainrdata.rtar,Edataac11mdb*):data()for1abe1in(posr*negJ:fo1der-nameeos.path.jon(data_rootrfo1der;1abe1)/拼接文件路径如E:dataad1mdbtrainposforfi1eintqdm(os.1istdir(fb1derwname):/os.1i
6、stdir(fo1der-ame)i取文件路径下的所有文件名,并存入列及中withopen(os.path.join(fo1der_name(fi1ef,rb,)asf:reviewf.read().decode(,utf8).rep1ace(n,)-ower()data.append(reviev61if1abe1pose1se0)/将每个文本读取的内容和对应的标签存入data列表中QndomShUffIe(data)/打乱data列表中的数据排列顺序returndata2、数据预处理通常而言,未标注好的数据具有大量的噪声,噪声会对模型的效果产生直接的影响,所以在使用这些数据前,应当对数据进
7、行数据预处理,比如分词、标注、空间向量转换等。/空格分词defgetjokenzedjrib(data):Paramdata:1istof(string,1abe1deftokener(text):returntok.1ower()fortokitext.sp1it(,)1return(tokener(review)forreview,_Indata/只从data中读取rev1ew(评论)内容而不读取标签(1abe1),对review使用tokenizer方法进行分词/创建词典defget-vocabjmdbdata):tokenized.data=ge1_tokenizedmdb(data)
8、/调用gejtokenize1irndbo空格分词方法荻取到分词后的数据tokenized-datacounter=co11ections.Couter(tkforstintokenized-datafortkinSt)/读取tokeniZe(1data列表中5个句子的每个词,放入列表中。/co11ections.Counter()H法可计算出列表中所有不重如的词数总和returnVocab.Vocab(countecmin-freq=5/去掉词领小于5的词data列衣中的用行数据进行处理,将词转换为索引,并使用行数据等长defProCeSSjmdb(data,vocab):maxjen=50
9、0用条评论通过截断或者补0,使得长度变成500defpad(x):returnx(:maxjen)if1en(x)max-1ee1se+(0)(maxJen1en(x)/x(:maxjen)只获取前maxen个词/x*(0)(maxJen1en(x)词数小于maxjen,用Pad=O补长到maxJentokeized-data=ge1_tokenizedmdbdata)/调用方法获取分词后的数据features=torch.tensor(pad(vocab.stoi(wordforwordinwords)!forwordsintokenized-data1)/将词转换为vocab词典中对应词的
10、索引1abe1s=torch.tensor(scorefor,sreindata)returnfeatures,1abe1s3、创建数据迭代器/创建数据迭代器batch.size=64train_set=Data.TensorDataset(*processjmdb(train-data,vocab)test.set=Data.TensorDatasetCproce$s_imdb(test_data,vocab)trainjter=Data.Data1oader(train-set,batch_size.True)test-iter=Data.Data1oader(test-set,batch
11、_size)UforX,yintrainjter4、构建循环神经网络/c1assBiRNN(nn.Modu1e):def_init_($e1f,vocab,embed-sizefnum_hiddens,num_1ayer$):super(BiRNN,se1f)._init_OSe1fembedding=nn.Embedding(1en(vocab),embed-size)se1f.encoder=nn.1STM(input_size=embed_size,hidden_size=num_hiddens,num-1ayers=num_1ayers,#batch-first=True,bidire
12、ctiona1=TrueSe1tdecoder=nn.1inear(4*num_hiddens,2)defforward(se1f1inputs):/inputs:batch.size,seq.1en,1STM需要将序列长度(seqen昨为第一堆,所以需要将输入转置后再提取词特征/输出形状outputs:(seq_1en,batch_size,embedding.dimembeddings=se1f.embedding(inpts.permute(1,0)/rnn.1STM只传入输入embeddings,因此只返回最后一层的除液层在各时间步的隐藏状态./outputs形状是(seqen,bat
13、ch-size,2*num-hiddens)outputs,_=se1f.encoder(embeddings)/连结初始时间步和最终时间步的隐液状态作为全连接层输入./它的形状为:batch_$ize,4*num_hidden$encoding=torch.cat(outputs(01outputs-1),dim=-1)outs=se1f.decoder(encoding)returnouts5、数据集训练/评估defeva1uate_accuracy(data_iter,net,device=None):ifdeviceisNoneandisinstance(net,torch.nn.Mo
14、du1e):/如果没指定device就使用net的devicedevice=1ist(net.parafetersO)O.deviceacjsum,n=0.0,0withtorch.no-grad():forX,yindata-iteifisinstance(netorch.nn.Modu1e):net.eva1()#评估模式这会关闭drop。Utacc_sum+=(net(X.to(device),argmax(dim=1)=y.to(device).f1oat().sum.cpuitem()net.train()/改回训练模式e1se:/自定义的模型,3.13节之后不会用到,不考虑GPUi
15、f(is-training,innet._code_.co_vamames):/如果有is.training这个参数/将israining设置成Fa1Seacc-sum+=(net(X,isjraining=Fa1se).argma(dim=1)-y).f!oat0sum0.item()e1se:acc-sum+=(net(X).argma(dim=1)=y).f1oat0.sumQ.item()n+=y.shape(0returnacc_sum/n/训练deftrain(trainjter,test-iter,netr1oss,optimizer,device,num_epochs):net=net.to(device)PrintCtrainingon,1device)batch_count=0f