自然语言情感分析

简介:

情感分析是基于自然语言处理的分类技术,主要解决的问题是判断一段话是正面的还是负面的。

例如网站上人们会发表评论,商家可以通过情感分析知道用户对产品的评价。还有不少基金公司会利用人们对某公司和行业的看法态度来预测未来股票的跌涨等。

首先处理数据:Keras自带了imdb的数据和调取数据的函数,所以我们直接调用load_data()函数就从亚马孙S3中下载了数据,并给每个词标注了一个索引(index),创建了字典,每段文字的每个词对应了一个数字。

import keras
import numpy as np
from keras.datasets import imdb
import matplotlib.pyplot as plt
(X_train, y_train), (X_test, y_test) = imdb.load_data()
np.reshape(X_train[0], (1, -1))
print(X_train.shape)
print(y_train.shape)
avg_len = list(map(len, X_train))
np.mean(avg_len)
plt.hist(avg_len, bins=range(min(avg_len), max(avg_len) + 50, 50))
plt.show()

跑出来的词频分布直方图是这样的:

 

自然语言情感分析_第1张图片

处理数据有这么几个步骤:

1.文字分词。可以按分隔符,如英文用空格分词

2.建立字典,给每个词标号

3.把段落通过查字典翻译成数字,变成一个array

最后的工作就是做匹配然后进行分析了。

 

建模:

我们遇到了文字长短不均和词与词之间有联系的问题,所以引入了嵌入技术。其实就是给每个词赋一个向量。(在深入学习中叫张量tensor)。含义相近的词赋予的向量也相近。

1.通过多层全连接神经网络模型训练(假设模型中的所有上一层和下一层是相互连接)

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence
import keras
import numpy as np
from keras.datasets import imdb
(X_train, y_train), (X_test, y_test) = imdb.load_data()
m=max(list(map(len, X_train))+ list(map(len, X_test)))
print(m)

#从上图看出有的文本特别长,而平均文本长度在200多,所以这里设定maxword为400,不足则空格填充,多则截除
maxword = 400
X_train = sequence.pad_sequences(X_train, maxlen = maxword)
X_test = sequence.pad_sequences(X_test, maxlen = maxword)
vocab_size = np.max([np.max(X_train[i]) for i in range(X_train.shape[0])]) + 1
#建立序列模型,逐步往上搭网络
model = Sequential()
#第一层:嵌入层定义其矩阵为vocab_size* 64
model.add(Embedding(vocab_size, 64, input_length = maxword))
model.add(Flatten())
#使用relu函数不断搭建全连接神经网络
model.add(Dense(500, activation = 'relu'))
model.add(Dense(500, activation = 'relu'))
model.add(Dense(200, activation = 'relu'))
model.add(Dense(50, activation = 'relu'))
#最后一层用Sigmoid,预测0,1变量的概率
model.add(Dense(1, activation = 'sigmoid'))
#adam optimizer一种优化方法。合理的动态选择每部梯度下降的幅度,控制学习速度
model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
print(model.summary())
model.fit(X_train, y_train, validation_data = (X_test, y_test), epochs = 20,batch_size = 100, verbose = 1)
score = model.evaluate(X_test, y_test)
print(score)

result:

自然语言情感分析_第2张图片

我训练出来的结果精度是84。26%,多迭代几次精度会更高。

全连接神经网络对网络模型没有任何限制,但缺点就是过度拟合。

 

2.卷积神经网络(CNN)训练

from keras.models import Sequential
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence
from keras.layers import Dense, Dropout, Activation, Flatten
import numpy as np
from keras.datasets import imdb
from keras.layers import Conv1D, MaxPooling1D
(X_train, y_train), (X_test, y_test) = imdb.load_data()
m=max(list(map(len, X_train))+ list(map(len, X_test)))
print(m)

maxword = 400
X_train = sequence.pad_sequences(X_train, maxlen = maxword)
X_test = sequence.pad_sequences(X_test, maxlen = maxword)
vocab_size = np.max([np.max(X_train[i]) for i in range(X_train.shape[0])]) + 1
model = Sequential()
model.add(Embedding(vocab_size, 64, input_length = maxword))
model.add(Conv1D(filters = 64, kernel_size = 3, padding = 'same', activation = 'relu'))
model.add(MaxPooling1D(pool_size = 2))
#(Dropout是为了防止模型过拟合,随机地让一部分输入层/隐藏层节点失效
model.add(Dropout(0.25))
model.add(Conv1D(filters = 128, kernel_size = 3, padding = 'same',activation = 'relu'))
model.add(MaxPooling1D(pool_size = 2))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(64, activation = 'relu'))
model.add(Dense(32, activation = 'relu'))
model.add(Dense(1, activation = 'sigmoid'))
model.compile(loss = 'binary_crossentropy', optimizer = 'rmsprop', metrics = ['accuracy'])
print(model.summary())
#对模型进行拟合
model.fit(X_train, y_train, validation_data = (X_test, y_test), epochs = 2, batch_size = 100)
scores = model.evaluate(X_test, y_test, verbose = 1)
print(scores)

词的分析涉及到上下词,然后词群又会对段落文字的意思有影响,决定了该段落是正向还是负向。

传统方法是人为的构造分类的特征,而深度学习中的卷积让神经网络去构造特征。

利用词包(Bag of Words)和TF-IDF(一种用于信息检索与数据挖掘的常用加权技术,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。主要思想就是一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章.

 

3.循环(递归)神经网络训练(RNN)

其实将神经网络模型训练好之后,在输入层给定一个x,通过网络之后就能够在输出层得到特定的y,那么既然有了这么强大的模型,为什么还需要RNN呢?因为它们都只能单独的取处理一个个的输入,上面的卷积神经网络(CNN)可以联系上下词,但那也是在同个输入中。而前一个输入和后一个输入是完全没有关系的。

长短记忆模型(LSTM,long-short term memory)是RNN的一种,可以用来处理情感分类。本质上,它是按时间顺序对信息进行了有效的整合和筛选。RNN所想做到的就是对信息的处理和分析能够做到跟人一样拥有记忆的能力。就是我此刻对于一件事的理解应当要包含我记忆中以前对这类事的信息。就如对段落文字的理解要包含之前提到的事件、人物等。

RNN能拥有“记忆”,是通过一个权重矩阵,可以将上一个时间序列的神经单元的值传递至当前的神经单元,从而使神经网络具备了记忆功能。 LSTM对信息的处理主要是通过矩阵的乘法运算实现的。

RNN的具体原理和公式可参考循环神经网络(RNN)原理通俗解释。

from keras.models import Sequential
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence
from keras.layers import Dense, Dropout, Activation, Flatten
import numpy as np
from keras.datasets import imdb
from keras.layers import Conv1D, MaxPooling1D
from keras.layers import LSTM
(X_train, y_train), (X_test, y_test) = imdb.load_data()
m=max(list(map(len, X_train))+ list(map(len, X_test)))
print(m)
maxword = 400
X_train = sequence.pad_sequences(X_train, maxlen = maxword)
X_test = sequence.pad_sequences(X_test, maxlen = maxword)
vocab_size = np.max([np.max(X_train[i]) for i in range(X_train.shape[0])]) + 1
model = Sequential()
model.add(Embedding(vocab_size, 64, input_length = maxword))
model.add(LSTM(128, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(64, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(32))
model.add(Dropout(0.2))
model.add(Dense(1, activation = 'sigmoid'))
model.compile(loss = 'binary_crossentropy', optimizer = 'rmsprop', metrics = ['accuracy'])
print(model.summary())
model.fit(X_train, y_train, validation_data = (X_test, y_test), epochs = 5, batch_size = 100)
scores = model.evaluate(X_test, y_test)

print(scores)

书本上说预测精确度大致为86.7%,但烧了一天的电脑,CPU都累到罢工了无能帮我跑出来 ̄へ ̄。

GitHub上有一个基于最新版本TensorFlow的Char RNN实现可以玩下。可以实现生成英文、写诗、歌词、小说、生成代码、生成日文等功能。Char-RNN-TensorFlow。

 

有两种主流思想运用到情感分析:

第一种为基于情感词典的情感分析,是指根据已构建的情感词典,计算该文本的情感倾向,即根据语义和依存关系来量化文本的情感色彩。最终分类效果取决于情感词库的完善性,另外需要很好的语言学基础,也就是说需要知道一个句子通常在什么情况为表现为积极或消极。

第二种是基于机器学习,是指选取情感词作为特征词,将文本矩阵化(转为向量),利用logistic Regression, 朴素贝叶斯(Naive Bayes),支持向量机(SVM)等方法进行分类。最终分类效果取决于训练文本的选择以及正确的情感标注。

你可能感兴趣的:(自然语言情感分析)