前言

NLP,即自然语言处理是一组用于处理文本问题的技术。这篇博客源自Kaggle NLP教程open in new window以及简书上对Kaggle的翻译,作者:ApacheCN_飞龙open in new window,对此表示感谢!
从数据加载和清理IMDB电影评论起步,然后应用一个简单的词袋模型,来获取令人惊讶的准确预测。

技术栈:

  • python
  • NLP算法包(nltk)
  • 计算、绘图等其他ML包

一个用Python写的关于NLP和文本处理的整部书open in new window

第一部分代码下载点击下载open in new window

读取数据

第一个文件是py unlabeledTrainData ,其中包含25000个IMDB电影评价,每个评价都带有正面或负面情感标签。

接着,将制表符分隔文件读入Python,使用pandas中的read_csv函数:

import pandas as pd
train = pd.read_csv("labeledTrainData.tsv", header=0, delimiter="\t", quting=3)
# header=0表示文件的第一行包含列名,delimiter=\t表示字段由制表符分隔,quting=3让Python忽略双引号

确保读取25000行和3列,如下所示:

train.shape
(25000, 3)

train.columns.values
array([id, sentiment, review], dtype=object)
# 说明已经读取到训练集

# 查看几条评论
print train["review"][0]

文本可能存在HTML标签,要使用工具将之删除

数据清理和文本预处理

删除HTML标记:BeautifulSoup包

如果没有安装这个包,则要先安装!然后从python中加载包并使用它从评论中提取文本:

from bs4 import BeautifulSoup
# Initialize the BeautifulSoup object on a single movie review     
example1 = BeautifulSoup(train["review"][0])  

# Print the raw review and then the output of get_text(), for 
# comparison
print train["review"][0]
print example1.get_text() # get_text()会提供不带标签的评论文本

处理标点,数字和停止符:NLTK和正则表达式

  • 在考虑如何清理文本时,我们应该考虑我们试图解决的数据问题。对于许多问题,删除标点符号是有意义的。另一方面,在这种情况下,我们正在解决情感分析问题,并且有可能"!!!"或者"😦"可以带有情感,应该被视为单词。在本教程中,为简单起见,我们完全删除了标点符号,但这是你可以自己玩的东西。

  • 与之相似,在本教程中我们将删除数字,但还有其他方法可以处理它们,这些方法同样有意义。例如,我们可以将它们视为单词,或者使用占位符字符串(例如"NUM")替换它们。

  • 要删除标点符号和数字,我们将使用一个包来处理正则表达式,称为re。Python 内置了该软件包;无需安装任何东西。对于正则表达式如何工作的详细说明,请参阅包文档open in new window。现在,尝试以下方法:

import re
# 使用正则表达式执行查找和替换
letters_only = re.sub("[^a-zA-Z]", " ", example1.get_text())

print letters_only

接着,将评论转换为小写并将它们分成单词(NLP术语中称为“分词”):

lower_case = letters_only.lower()        # 转换为小写
words = lower_case.split()               # 分割为单词

最后,处理停止词(诸如:a, and, is, the等)。Python包中内置了停止词列表。从NLTK中导入停止词列表:

# 如果没有安装nltk,请先安装
import nltk
nltk.download() # 下载文本数据集,包含停止词

# 使用nltk获取停止词列表
from nltk.corpus import stopwords
print stopwords.words("english")

# 从“words”中移除停止词
words = [w for w in words if not w stopwords.words("english")]
print words

# 完成所有步骤后,得到
[u'stuff', u'going', u'moment', u'mj', u've', u'started', u'listening', u'music', u'watching', u'odd', u'documentary', u'watched', u'wiz', u'watched', u'moonwalker', u'maybe', u'want', u'get', u'certain', u'insight', u'guy', u'thought', u'really', u'cool', u'eighties', u'maybe', u'make', u'mind', u'whether', u'guilty', u'innocent', u'moonwalker', u'part', u'biography', u'part', u'feature', u'film', u'remember', u'going', u'see', u'cinema', u'originally', u'released', u'subtle', u'messages', u'mj', u'feeling', u'towards', u'press', u'also', u'obvious', u'message', u'drugs', u'bad', u'm', u'kay',.....]

我们还可以对数据做很多其他操作,如porter stemming(词干提取)和Lemmatizing(词形还原)等。都在NLTK包中提供。

为了使代码可以重用,创建一个可以重复使用的函数

def review_to_words(raw_review):
    # 将原始评论转换为单词字符串的函数
    # 输入是单个字符串(原始电影评论),
    # 输出是单个字符串(预处理过的电影评论)
    # 1. 移除 HTML
    review_text = BeautifulSoup(raw_review).get_text() 
    #
    # 2. 移除非字母        
    letters_only = re.sub("[^a-zA-Z]", " ", review_text) 
    #
    # 3. 转换为小写,分成单个单词
    words = letters_only.lower().split()                             
    #
    # 4. 在Python中,搜索集合比搜索列表快得多,
    #    所以将停止词转换为一个集合
    stops = set(stopwords.words("english"))                  
    # 
    # 5. 删除停止词
    meaningful_words = [w for w in words if not w in stops]   
    #
    # 6. 将单词连接成由空格分隔的字符串,
    #    并返回结果。
    return( " ".join( meaningful_words ))

这里有两个新元素:首先,我们将停止词列表转换为不同的数据类型,即集合。 这是为了速度;因为我们将调用这个函数数万次,所以它需要很快,而 Python 中的搜索集合比搜索列表要快得多。

从词袋创建特征(使用sklearn)

现在我们已经整理了我们的训练评论,我们如何将它们转换为机器学习的某种数字表示?一种常见的方法叫做词袋。词袋模型从所有文档中学习词汇表,然后通过计算每个单词出现的次数对每个文档进行建模。例如,考虑以下两句话:

句子1: "The cat sat on the hat"

句子2: "The dog ate the cat and the hat"

从这两个句子中,我们的词汇如下:

{the, cat, sat, on, hat, dog, ate, and}

为了得到我们的词袋,我们计算每个单词出现在每个句子中的次数。在句子 1 中,“the”出现两次,“cat”,“sat”,“on”和“hat”每次出现一次,因此句子 1 的特征向量是:

{the, cat, sat, on, hat, dog, ate, and}

#句子1特征:
{2, 1, 1, 1, 1, 0, 0, 0}
#句子2特征:
{ 3, 1, 0, 0, 1, 1, 1, 1}

在 IMDB 数据中,我们有大量的评论,这将为我们提供大量的词汇。要限制特征向量的大小,我们应该选择最大词汇量。下面,我们使用 5000 个最常用的单词(记住已经删除了停止词)。

使用scikit-learn中的feature_extraction模块来创建词袋特征。

print "Creating the bag of words...\n"
from sklearn.feature_extraction.text import CountVectorizer

# 初始化 "CountVectorizer" 对象,
# 这是 scikit-learn 的一个词袋工具。
vectorizer = CountVectorizer(analyzer = "word",   \
                             tokenizer = None,    \
                             preprocessor = None, \
                             stop_words = None,   \
                             max_features = 5000) 

# fit_transform() 有两个功能:
# 首先,它拟合模型并学习词汇;
# 第二,它将我们的训练数据转换为特征向量。
# fit_transform 的输入应该是字符串列表。
train_data_features = vectorizer.fit_transform(clean_train_reviews)

# Numpy 数组很容易使用,因此将结果转换为数组
train_data_features = train_data_features.toarray()

# 查看训练数据数组现在的样子:
print train_data_features.shape
(25000, 5000) # 它有 25,000 行和 5,000 个特征(每个词汇一个)。

# 词袋模型训练完成,看看词汇表:
vocab = vectorizer.get_feature_names()
print vocab

随机森林

到了这里,我们有词袋的数字训练特征和每个特征向量的原始情感标签,所以让我们做一些监督学习!

print "Training the random forest..."
from sklearn.ensemble import RandomForestClassifier

# 使用 100 棵树初始化随机森林分类器
forest = RandomForestClassifier(n_estimators = 100) 

# 使用词袋作为特征并将情感标签作为响应变量,使森林拟合训练集
# 这可能需要几分钟来运行
forest = forest.fit( train_data_features, train["sentiment"] )

创建提交

剩下的就是在我们的测试集上运行训练好的随机森林并创建一个提交文件。 如果你还没有这样做,请从“数据”页面下载testData.tsv。 此文件包含另外 25,000 条评论和标签;我们的任务是预测情感标签。

请注意,当我们使用词袋作为测试集时,我们只调用transform,而不是像训练集那样调用fit_transform。 在机器学习中,你不应该使用测试集来拟合你的模型,否则你将面临过拟合的风险。 出于这个原因,我们将测试集保持在禁止状态,直到我们准备好进行预测。

# 读取测试数据
test = pd.read_csv("testData.tsv", header=0, delimiter="\t", \
                   quoting=3 )

# 验证有 25,000 行和 2 列
print test.shape

# 创建一个空列表并逐个附加干净的评论
num_reviews = len(test["review"])
clean_test_reviews = [] 

print "Cleaning and parsing the test set movie reviews...\n"
for i in xrange(0,num_reviews):
    if( (i+1) % 1000 == 0 ):
        print "Review %d of %d\n" % (i+1, num_reviews)
    clean_review = review_to_words( test["review"][i] )
    clean_test_reviews.append( clean_review )

# 获取测试集的词袋,并转换为 numpy 数组
test_data_features = vectorizer.transform(clean_test_reviews)
test_data_features = test_data_features.toarray()

# 使用随机森林进行情感标签预测
result = forest.predict(test_data_features)

# 将结果复制到带有 "id" 列和 "sentiment" 列的 pandas dataframe
output = pd.DataFrame( data={"id":test["id"], "sentiment":result} )

# 使用 pandas 编写逗号分隔的输出文件
output.to_csv( "Bag_of_Words_model.csv", index=False, quoting=3 )

恭喜,你已准备好第一次提交! 尝试不同的事情,看看你的结果如何变化。 你可以以不同方式清理评论,为词袋表示选择不同数量的词汇表单词,尝试 Porter Stemming,不同的分类器或任何其他的东西。 要在不同的数据集上试用你的 NLP 招式,你还可以参加我们的烂番茄比赛。 或者,如果你为完全不同的东西做好了准备,请访问深度学习和词向量页面。

学习源简书open in new window,提出感谢!

使用NLP创建Twitter评价分类器的想法

  • 取代人工打标注的过程,提高数据分析、挖掘效率

概述

参照之前的自然语言算法研究博客,得知处理推文是可行的,重点是如何合理的分出推文中的感情色彩和使用哪种分类算法来处理!若研究出结果可用于小规模的舆情分析有一定的价值。

这个想法产生于南京面试【5月13号】之后!目前觉得可行!做这方面工作的研究人员也很多,我只是个初学者!😊

一定会使用到机器学习库或包!

工具初定:Java + NLP + classification-Alg 或者 Python + NLP + classification-Alg

本文首次发布于 YunLongBlogopen in new window, 作者 Laqudeeopen in new window ,转载请保留原文链接.