基于numpy和pandas的文本情感分析之电影评论分类

Juvenile

发布日期: 2019-03-04 15:02:50 浏览量: 631
评分:
star star star star star star star star star_border star_border
*转载请注明来自write-bug.com

摘 要

本次课程设计的目的是能够学会利用numpy、pandas等python中常用的数据分析库做数据分析,所以我选择了kaggle竞赛上的一道题目来做练习:电影评论分类,地址:https://www.kaggle.com/c/word2vec-nlp-tutorial 。本次课程设计主要用到的文本预处理有网页解析,文本抽取,正则表达式等。

一、实验目的

利用提供的训练数据集训练学习模型,训练完成后,使之能够对测试集中的评论进行正确的分类。

二、数据集说明

数据集一共包含50000个IMDB电影评论,专门用于情绪分析。评论的情绪是二元的,也就是说,label只有0(负面评论)和1(正面评论)。训练集的25000个评论与25000个测试集评论不存在相同的任何电影(即数据不重叠)。此外,kaggle官网还提供了另外50000条IMDB评论,但是没有任何评级标签。

官网提供的文件一共四个,说明如下:

文件名 说明
labeledTrainData 训练集,该文件以制表符分隔,并且有一个标题行,后跟25000行,每行包含一个id,情绪和文本。
testData 测试集,制表符分隔文件有一个标题行,后跟25000行,每行包含一个ID和文本。任务是预测每个人的情绪。
unlabeledTrainData 没有标签的额外训练集。制表符分隔文件有一个标题行,后跟50,000行,每行包含一个ID和文本。
sampleSubmission 如果要参加比赛,需要以此文件的格式提交文件

数据文件中,各个字段的说明如下:

  • Id :每个评论的唯一ID

  • sentiment :评论的情绪; 1表示正面评价,0表示负面评价

  • review :评论文本

三、试验过程

3.1 使用import导入本次实验需要用到的库

  1. # import所需库
  2. import os
  3. import re
  4. import numpy as np
  5. import pandas as pd
  6. from bs4 import BeautifulSoup # 用于解析网页
  7. from sklearn.feature_extraction.text import CountVectorizer
  8. from sklearn.ensemble import RandomForestClassifier
  9. from sklearn.metrics import confusion_matrix
  10. import nltk
  11. #下载停用词和其他语料会用到
  12. #nltk.download()
  13. from nltk.corpus import stopwords

导入的库中需要特别说明的有:

  • re:这是python中的正则表达式库,在评论文本的预处理时,需要将标点符号全部去掉,因为标点对情绪的判断并没有太多帮助

  • numpy,pandas:kaggle官网提供的数据都是以表格的形式组织的,利用numpy,pandas这两个库可以很方便的对数据进行操作

  • sklearn:在建立分类模型时,我选择了随机森林,可以利用sklearn库中自带的模型直接开始拟合数据

  • nltk:这是一个英文的自然语言工具包,里面包含很多语料,本次实验可以使用其中的stopwords进行文本预处理,去掉一些没有实际意义的词

3.2 用pandas读入训练数据

  1. datafile = os.path.join('.', '2. data', 'labeledTrainData.tsv')
  2. df = pd.read_csv(datafile, sep='\t', escapechar='\\')

接下来,可以看看导入的数据一共有多少条,同时看看前几条数据。

  1. print('Number of reviews: {}'.format(len(df)))
  2. print(df.head())
  3. print(df['review'][0])

输出内容如下图所示:

从输出的第一条评论文本中可以发现,其中有很多类似于<br />的html标签,接下就对这些评论文本做预处理。

3.3 文本预处理

对影评数据做预处理,大概有以下环节:去掉html标签、移除标点、切分成词/token、去掉停用词、重组为新的句子。

定义一个显示函数,方便后面查看清洗后的数据。

  1. def display(text, title):
  2. print('\n'+title)
  3. print("\n----------我是分割线-------------\n")
  4. print(text)

为了提高实验效率,先拿一条评论文本来做清洗,成功后再对所有数据进行清洗。

取出第一条评论文本保存在raw_example中,并打印出来。

  1. raw_example = df['review'][0]
  2. display(raw_example, '原始数据')

输出内容如下图所示:

接下来,去掉html标签:

  1. example = BeautifulSoup(raw_example, 'html.parser').get_text()
  2. display(example, '去掉HTML标签的数据')

输出内容如下图所示:

观察结果发现,<br />的html标签已经全部清除。

接下来,利用正则表达式,移除标点(全部替换为空格)。

  1. example_letters = re.sub(r'[^a-zA-Z]', ' ', example)
  2. display(example_letters, '去掉标点的数据')

输出内容如下图所示:

以下操作将所有字母转换为小写,同时做分词。

  1. words = example_letters.lower().split()
  2. display(words, '纯词列表数据')

输出内容如下图所示:

接下来,去掉停用词。

  1. stopwords = {}.fromkeys([ line.rstrip() for line in open('2. stopwords.txt')])
  2. words_nostop = [w for w in words if w not in stopwords]
  3. display(words_nostop, '去掉停用词数据')

输出内容如下图所示:

通过以上一些列操作,完成了对单条评论文本的预处理工作,观察发现结果可以接受,所以接下来把所有训练集中的评论都做如上操作。

为了方便,定义一个清洗数据的函数。

  1. eng_stopwords = set(stopwords) # 设置停止词
  2. # 定义清洗数据的函数
  3. def clean_text(text):
  4. text = BeautifulSoup(text, 'html.parser').get_text() # 去掉网页标签
  5. text = re.sub(r'[^a-zA-Z]', ' ', text) # 利用正则表达式去掉标点
  6. words = text.lower().split() # 转小写+分词
  7. words = [w for w in words if w not in eng_stopwords] # 去掉停止词
  8. return ' '.join(words)

为了将清洗后的评论文本添加到dataframe里,所以添加一列clean_review用于保存清洗后的数据。

  1. # 每一行数据都做clean_text操作
  2. df['clean_review'] = df.review.apply(clean_text)

3.4 训练模型

通过以上的文本预处理之后,就可以来训练模型了。但是在此之前还需要做的一件事情是将处理后的词列表转换为计算机能识别的词向量,这里我采用了bag of words的方法,词向量的长度是5000。

  1. # 抽取bag of words特征(用sklearn的CountVectorizer)
  2. vectorizer = CountVectorizer(max_features = 5000)
  3. train_data_features = vectorizer.fit_transform(df.clean_review).toarray()
  4. print("训练数据形状:\n", train_data_features.shape)
  5. print("训练数据:\n", train_data_features)

输出内容如下图所示:(这里由于每条词向量长度太长了,所以就省略显示了)

将词列表转换为词向量后开始训练模型,这里我选取的是随机森林。

  1. # 训练分类器(随机森林) 一共100棵树
  2. forest = RandomForestClassifier(n_estimators = 100)
  3. forest = forest.fit(train_data_features, df.sentiment) # 训练模型

最后训练完成后,再来看看在训练集上做predict的效果如何。

  1. # 在训练集上做个predict看看效果如何
  2. print("训练集测试结果:\n",confusion_matrix(df.sentiment, forest.predict(train_data_features)))

输出内容如下图所示:(这里采用了混淆矩阵来做结果的保存)

根据实验结果发现,只有一条评论错了,结果还是很可观的,接下来就要用测试集的数据来进行预测了。

3.5 预测测试集数据

在预测之前先删掉后面不会用到的占用内存的变量。

  1. del df
  2. del train_data_features

接下来,读取测试数据,读取完后对评论文本做与测试集评论文本一样的数据清洗工作,最后打印出来看看。

  1. datafile = os.path.join('.', '2. data', 'testData.tsv')
  2. df = pd.read_csv(datafile, sep='\t', escapechar='\\')
  3. print('Number of reviews: {}'.format(len(df)))
  4. df['clean_review'] = df.review.apply(clean_text) # 数据清洗工作
  5. print("测试数据如下:\n", df.head())

输出内容如下图所示:

通过实验结果发现,测试集也多了一列清洗后的评论文本。

接下来将清洗后的评论文本转换为词向量,并查看其转换后的形状和数据。

  1. # 将测试数据也转换为训练数据的词向量形式
  2. test_data_features = vectorizer.transform(df.clean_review).toarray()
  3. print("测试数据形状:\n", test_data_features.shape)
  4. print("测试数据:\n", test_data_features)

输出内容如下图所示:

接下来将转换好的数据输入模型做预测,结束后打印出预测结果。

  1. # 用训练好的模型预测
  2. result = forest.predict(test_data_features)
  3. output = pd.DataFrame({'id':df.id, 'sentiment':result})
  4. print("测试数据预测结果如下:\n", output.head())

输出内容如下图所示:(数据太多,所以只显示五条)

最后将预测的结果保存为csv文件。

  1. # 保存为csv文件
  2. output.to_csv(os.path.join('.', '2. data', 'Bag_of_Words_model.csv'), index=False)

四、实验总结

由于工程实践的选题是有关于自然语言处理的,所以最近也在自学相关的知识,正好老师又布置了此次作业,所以我就选取了一个NLP小项目,把它整理了一下。通过这次实验,不仅巩固了课堂上老师所讲的理论知识,同时还自己动手总结了一篇实验报告,感觉收获颇丰,其中包括课中所学习到的numpy、pandas等库的基本使用方法,除此之外,对于文本预处理,词向量模型的构建(bag of words、word2vec)也有了些许自己的体会。

上传的附件 cloud_download 基于numpy和pandas的文本情感分析之电影评论分类.7z ( 1.59mb, 3次下载 )
error_outline 下载需要15点积分

发送私信

我依旧深信时间是良药虽苦口,但有效

13
文章数
18
评论数
最近文章
eject