活动地址:CSDN21天学习挑战赛
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。
随着技术对企业的进步起着越来越重要的作用,情感分析正成为各种商业案例中的常用工具,企业使用情绪分析技术得到客户对企业业务、产品和相关主题的感受。
情感分析基本上是用于识别并分类一段文本或语料库中所表达的情感的一种方法,为了确定他人对特定主题、产品等的态度是积极的、消极的还是中立的,使用NLP对应地将文档分类为正面、中性或负面。
加载数据集并计算相关属性。首先从加载情感数据集开始,提取文本和相应的情感标签,仅保留数据集中必要的列。
这些数据最初来自Crowdflower’s data for everyone数据库(https://www.figure-eight.com/data-for-everyone/)。
最初的数据来源是支持者浏览了数以万计关于俄亥俄州8月初共和党(GOP)辩论的推文后,对支持者进行的情感分析和数据分类。支持者被问及推文是否相关,提到了哪个候选人,提到了什么主题和针对一些特定推文的情感。最终得到的数据集已经删除掉了一些不相关消息,并作为代码存储库的一部分直接可用。
接下来,放弃中性情感,因为我们的目标是区分正面推文和负面推文,然后对推文过滤,只保留有效的文本和单词,最后,将最大特征数量值定义为2 000,并使用分词器进行向量化处理将文本转换为序列,将该序列作为网络的输入:
import csv
from numpy import array, asarray, zeros
from keras.preprocessing.text import one_hot, Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense, SpatialDropout1D, LSTM
from keras.layers import Flatten
from keras.layers.embeddings import Embedding
import pandas as pd
import re
from sklearn.model_selection import train_test_split
# read input document
X = pd.read_csv('/Users/manpreet.singh/git/deeplearning/deeplearning-keras/ch08/sentiment-analysis/Sentiment.csv')
X = X[['text', 'sentiment']]
X = X[X.sentiment != 'Neutral']
X['text'] = X['text'].apply(lambda x: x.lower())
X['text'] = X['text'].apply((lambda x: re.sub('[^a-zA-z0-9\s]', '', x)))
print(X)
Keras中的tokenizer API有几种方法可以帮助我们处理文本以适用于神经网络模型,这里使用fit_on_texts方法,另外使用word_index查看单词索引。
1.Keras为我们提供了text_to_word_sequence API,可用于将文本拆分为单词列表:
maxFeatures = 2000
tokenizer = Tokenizer(num_words=maxFeatures, split=' ')
tokenizer.fit_on_texts(X['text'].values)
encodeDocuments = tokenizer.texts_to_sequences(X['text'].values)
print(encodeDocuments)
然后使用Keras库中的pad_sequences()函数将文档填充到最大长度29,如下所示。其中默认填充值为0.0,但可以通过value参数指定首选值来进行更改。
填充可以在序列的开头或结尾使用,体现为pre-或post-序列填充,如下所示:
max_length = 29
paddedDocuments = pad_sequences(encodeDocuments, maxlen=max_length, padding='post')
接下来,如前所述,利用预装的GloVe进行词嵌入。基本上,GloVe提供了一套预训练的词嵌入流程,我们会使用60亿词和100维的数据训练的GloVe,即glove.6B.100d.txt。如果查看文件,我们可以在每一行上看到一个令牌(单词),后面跟着权重(100个数字)。
因此,我们将整个GloVe词嵌入文件作为词嵌入数组的字典加载到内存中:
inMemoryGlove = dict()
f = open('/Users/manpreet.singh/git/deeplearning/deeplearning-keras/ch08/embeddings/glove.6B.100d.txt')
for line in f:
values = line.split()
word = values[0]
coefficients = asarray(values[1:], dtype='float32')
inMemoryGlove[word] = coefficients
f.close()
print(len(inMemoryGlove))
标签转换为1和0,分别对应正面值和负面值
labels = []
for i in X['sentiment']:
if i == 'Positive':
labels.append(1)
else:
labels.append(0)
labels = array(labels)
学习模型旨在对以后未知数据集做出良好的预测。但问题是,完全在现有的数据集上创建模型,如何获得未知数据?一种方法是将数据集分成两组,称为训练集和测试集,作为原始数据集的子集。
数据集通常被分成训练集和测试集。训练集包含特征向量和相应的输出或标签,模型用于学习以泛化到其他数据集。创建测试数据集(或子集)以测试模型的预测是否精准。从scikit-learn的model_selection子库中导入train_test_split函数以拆分训练集和测试集,如下所示:
X_train, X_test, Y_train, Y_test = train_test_split(paddedDocuments,labels, test_size = 0.33, random_state = 42)
print(X_train.shape,Y_train.shape)
print(X_test.shape,Y_test.shape)
现在,为训练数据集中的每个单词创建一个嵌入矩阵。通过迭代Tokenizer.word_index中的所有单词并从加载的GloVe中定位嵌入权重向量来实现这一点。
输出是权重矩阵,但仅适用于训练集中的单词,代码如下:
trainingToEmbeddings = zeros((maxFeatures, 100))
for word, i in tokenizer.word_index.items():
if i < 2001:
gloveVector = inMemoryGlove.get(word)
if gloveVector is not None:
trainingToEmbeddings[i] = gloveVector
Keras模型是一系列层。通过创建一个新的序贯模型并通过添加层来创建网络拓扑,定义好模型之后,使用Tensorflow作为后端进行编译,此后端选择最佳方式来表示网络,从而使得训练过程和预测过程在给定硬件上以最佳方式运行,代码如下:
model = Sequential()
model.add(Embedding(maxFeatures, 100, weights=[trainingToEmbeddings], input_length=max_length, trainable=False))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
print(model.summary())
在给定的数据集或文档上执行模型。训练过程运行固定的迭代次数。除此之外还可以设置网络权重更新时的评估实例数,即批量大小,利用batch_size参数进行设置,如下所示:
`batch_size = 32
model.fit(X_train, Y_train, epochs=50, batch_size=batch_size, verbose=0)`
最后,在给定文档中对神经网络的性能进行评估。通过以下代码可知完成这个情感分析任务的准确率约为81%:
loss, accuracy = model.evaluate(X_test, Y_test, verbose=0)
print('Accuracy: %f' % (accuracy * 100))