如何使用自然语言工具包 (NLTK) 在 Python 3 中进行情感分析

作者选择了 [开放互联网/言论自由] 基金(https://www.brightfunds.org/funds/open-internet-free-speech) 作为 [写给捐赠] 计划(https://do.co/w4do-cta)的一部分获得捐款。

介绍

今天生成的大量数据是 非结构化,需要处理以生成洞察力。 一些非结构化数据的例子是新闻文章、社交媒体帖子和搜索历史。 分析自然语言并使其产生意义的过程属于自然语言处理(NLP)的领域。 情绪分析是一种常见的NLP任务,涉及将文本或文本部分分类为预定义的情绪。 您将使用自然语言工具包(NLTK)(https://www.nltk.org/),Python中常用的NLP库,来分析文本数据。

在本教程中,您将用不同的数据清理方法准备NLTK包的样本推文的数据集。一旦数据集准备好处理,您将训练一个模型对预分类的推文,并使用该模型将样本推文分类为负面和积极的情绪。

本文假设您熟悉了Python(LINK0)的基本知识(见我们的How To Code in Python 3系列)(LINK1)),主要是使用数据结构、类和方法。

前提条件

*本教程是基于Python版本 3.6.5. 如果您没有安装Python 3,这里有一个指南 安装和设置Python 3的本地编程环境。 *建议熟悉使用语言数据。

步骤 1 – 安装 NLTK 并下载数据

在本教程中,您将使用Python中的NLTK包用于所有NLP任务. 在此步骤中,您将安装NLTK并下载您将使用的样本推文来训练和测试您的模型。

首先,使用「pip」包管理器 安装 NLTK 包:

1pip install nltk==3.3

本教程将使用 NLTK 包的一部分样本推文。首先,通过运行以下命令开始 Python 交互式会话:

1python3

然后,将nltk模块导入 Python 解释器中。

1import nltk

下载 NLTK 包中的样本推文:

1nltk.download('twitter_samples')

运行这个命令从Python解释器下载并存储Tweets本地. 一旦样品下载,它们可供您使用。

您将在教程中稍后使用负面和积极的推文来训练您的模型对情绪分析,没有情绪的推文将用于测试您的模型。

如果您想使用自己的数据集,您可以使用 Twitter API收集特定时间段、用户或哈希标签的推文。

现在你已经导入了NLTK并下载了样本推文,通过输入exit()来退出交互式会话,你已经准备好导入推文并开始处理数据。

步骤2 – 代码化数据

语言在其原始形式不能被机器精确处理,所以你需要处理语言,以便机器更容易理解。

一个代币是文本中的字符序列,作为一个单元。根据你如何创建代币,它们可以由单词,情感符号,标签,链接,甚至单个字符组成。

要开始,创建一个新的 .py 文件,以保持你的脚本. 本教程将使用 nlp_test.py:

1nano nlp_test.py

在此文件中,您首先将导入twitter_samples,以便您可以使用这些数据:

1[label nlp_test.py]
2from nltk.corpus import twitter_samples

这将导入来自NLTK的三个数据集,这些数据集包含各种推文来训练和测试该模型:

  • negative_tweets.json: 5000 条负面情绪的推文
  • positive_tweets.json: 5000 条负面情绪的推文
  • tweets.20150430-223406.json: 20000 条没有情绪的推文

接下来,创建positive_tweets,negative_tweetstext的变量:

1[label nlp_test.py]
2from nltk.corpus import twitter_samples
3
4positive_tweets = twitter_samples.strings('positive_tweets.json')
5negative_tweets = twitter_samples.strings('negative_tweets.json')
6text = twitter_samples.strings('tweets.20150430-223406.json')

twitter_samplesstrings()方法将将数据集中的所有推文打印为字符串,将不同的推文集合设置为变量,使处理和测试更容易。

在使用 NLTK 中的代码器之前,您需要下载一个额外的资源,即punktpunkt模块是一种预先训练的模型,可以帮助您代码化单词和句子。例如,这个模型知道一个名字可能包含一个时期(如S. Daityari)并且在句子中存在这个时期并不一定会结束它。

1python3

在会话中运行以下命令来下载punkt资源:

1import nltk
2nltk.download('punkt')

一旦下载完成,你就可以使用NLTK的代币化器了。NLTK提供了使用.tokenized()方法的推文的默认代币化器。添加一条行来创建一个代币化positive_tweets.json数据集的对象:

1[label nlp_test.py]
2from nltk.corpus import twitter_samples
3
4positive_tweets = twitter_samples.strings('positive_tweets.json')
5negative_tweets = twitter_samples.strings('negative_tweets.json')
6text = twitter_samples.strings('tweets.20150430-223406.json')
7tweet_tokens = twitter_samples.tokenized('positive_tweets.json')

如果您想测试脚本,以便看到.tokenized方法在行动中,请将突出的内容添加到您的nlp_test.py脚本中,这将从positive_tweets.json数据集中标记一个单一的推文:

1[label nlp_test.py]
2from nltk.corpus import twitter_samples
3
4positive_tweets = twitter_samples.strings('positive_tweets.json')
5negative_tweets = twitter_samples.strings('negative_tweets.json')
6text = twitter_samples.strings('tweets.20150430-223406.json')
7tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]
8
9print(tweet_tokens[0])

保存并关闭文件,然后运行脚本:

1python3 nlp_test.py

代币化过程需要一些时间,因为它不是简单的白色空间分裂,经过几分钟的处理,你会看到以下内容:

 1[secondary_label Output]
 2['#FollowFriday',
 3 '@France_Inte',
 4 '@PKuchly57',
 5 '@Milipol_Paris',
 6 'for',
 7 'being',
 8 'top',
 9 'engaged',
10 'members',
11 'in',
12 'my',
13 'community',
14 'this',
15 'week',
16 ':)']

在这里,.tokenized() 方法返回特殊字符,如 @_. 这些字符将在本教程中稍后通过常规表达式删除。

现在你已经看到‘.tokenized()’方法是如何工作的,请确保评论或删除最后一行以从脚本中打印代币化推文,并在行开始时添加一个‘#’:

1[label nlp_test.py]
2from nltk.corpus import twitter_samples
3
4positive_tweets = twitter_samples.strings('positive_tweets.json')
5negative_tweets = twitter_samples.strings('negative_tweets.json')
6text = twitter_samples.strings('tweets.20150430-223406.json')
7tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]
8
9#print(tweet_tokens[0])

您的脚本现在已配置为代币化数据. 在下一步,您将更新脚本以正常化数据。

步骤三:数据正常化

单词有不同的形式 - 例如,,是同一个词汇的各种形式,。 根据你的分析的要求,所有这些版本可能需要被转换为相同的形式,

正常化有助于将具有相同含义但不同的形式的单词组合在一起. 没有正常化,,将被视为不同的单词,即使您可能希望它们被视为相同的单词。

发音是从一个单词中删除贴纸的过程,发音,只使用简单的词汇形式工作,是删除单词尽头的 heuristic过程。

在本教程中,您将使用lematization的过程,该过程将一个单词与词汇的背景和文字中的单词的 morphological analysis正常化。Lematization算法分析了单词的结构和其背景,将其转换为正常化的形式。

在继续使用 lemmatization 之前,请通过在 Python 交互式会话中输入以下内容来下载所需的资源:

1python3

在会话中运行以下命令来下载资源:

1import nltk
2nltk.download('wordnet')
3nltk.download('averaged_perceptron_tagger')

wordnet是帮助脚本确定基础单词的英语语法数据库,您需要averaged_perceptron_tagger资源来确定句子中的单词的背景。

一旦下载,您几乎已经准备好使用Lemmatizer。在运行Lemmatizer之前,您需要确定文本中的每个单词的背景。这是通过标签算法实现的,该算法评估了句子中的单词的相对位置。在Python会话中,导入pos_tag函数,并提供一个代币列表作为一个论点来获得标签。让我们在Python中尝试一下:

1from nltk.tag import pos_tag
2from nltk.corpus import twitter_samples
3
4tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
5print(pos_tag(tweet_tokens[0]))

以下是pos_tag函数的输出。

 1[secondary_label Output]
 2[('#FollowFriday', 'JJ'),
 3 ('@France_Inte', 'NNP'),
 4 ('@PKuchly57', 'NNP'),
 5 ('@Milipol_Paris', 'NNP'),
 6 ('for', 'IN'),
 7 ('being', 'VBG'),
 8 ('top', 'JJ'),
 9 ('engaged', 'VBN'),
10 ('members', 'NNS'),
11 ('in', 'IN'),
12 ('my', 'PRP$'),
13 ('community', 'NN'),
14 ('this', 'DT'),
15 ('week', 'NN'),
16 (':)', 'NN')]

从标签列表中,以下是最常见的项目列表及其含义:

  • NNP:序列,固有,单元
  • NN:序列,常见,单元或质量
  • IN:序列或序列,分为
  • VBG:字符、字符、字符或现有分数
  • VBN:字符,过去分数

此分類上一篇: 眾生,眾生。

一般来说,如果一个标签从NN开始,那么这个词就是一个名词,如果它是VB,那么这个词就是一个词汇。

要将其纳入一个使句子正常化的函数中,您首先应该在文本中生成每个代币的标签,然后使用标签对每个单词进行细节化。

更新「nlp_test.py」檔案,使用下列函數來編制一個句子:

 1[label nlp_test.py]
 2...
 3
 4from nltk.tag import pos_tag
 5from nltk.stem.wordnet import WordNetLemmatizer
 6
 7def lemmatize_sentence(tokens):
 8    lemmatizer = WordNetLemmatizer()
 9    lemmatized_sentence = []
10    for word, tag in pos_tag(tokens):
11        if tag.startswith('NN'):
12            pos = 'n'
13        elif tag.startswith('VB'):
14            pos = 'v'
15        else:
16            pos = 'a'
17        lemmatized_sentence.append(lemmatizer.lemmatize(word, pos))
18    return lemmatized_sentence
19
20print(lemmatize_sentence(tweet_tokens[0]))

此代码导入WordNetLemmatizer类,并将其初始化为变量lemmatizer

函数lemmatize_sentence首先得到一个推文的每个代币的位置标签。在如果声明中,如果标签开始于NN,则将代币分配为名词。

保存并关闭文件,然后运行脚本:

1python3 nlp_test.py

以下是产量:

 1[secondary_label Output]
 2['#FollowFriday',
 3 '@France_Inte',
 4 '@PKuchly57',
 5 '@Milipol_Paris',
 6 'for',
 7 'be',
 8 'top',
 9 'engage',
10 'member',
11 'in',
12 'my',
13 'community',
14 'this',
15 'week',
16 ':)']

你会注意到词语存在改变到它的根形式存在,而词语会员改变到会员

现在你已经成功创建了一个功能来正常化单词,你已经准备好继续去除噪音。

步骤 4 – 从数据中删除噪音

在此步骤中,您将从数据集中删除噪音。 Noise 是文本中不向数据添加含义或信息的任何部分。

例如,语言中最常见的单词被称为 stop words. 一些停止单词的例子是is,thea

在本教程中,您将使用Python中的常规表达式(https://docs.python.org/3.6/howto/regex.html)来搜索和删除这些项目:

  • 超链接 - Twitter中的所有超链接都被转换为URL缩写器 t.co。因此,将它们保留在文本处理中不会为分析增加任何价值。
  • Twitter处理响应 - 这些Twitter用户名之前有一个@符号,不会传达任何含义。

要删除超链接,你需要先搜索一个符串,它匹配一个开始于http://https://的URL,然后是字母,数字或特殊字符。

由于我们将在remove_noise()函数中正常化单词形式,您可以从脚本中评论lemmatize_sentence()函数。

将以下代码添加到您的 nlp_test.py 文件中,以从数据集中删除噪音:

 1[label nlp_test.py]
 2...
 3
 4import re, string
 5
 6def remove_noise(tweet_tokens, stop_words = ()):
 7
 8    cleaned_tokens = []
 9
10    for token, tag in pos_tag(tweet_tokens):
11        token = re.sub('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|'\
12                       '(?:%[0-9a-fA-F][0-9a-fA-F]))+','', token)
13        token = re.sub("(@[A-Za-z0-9_]+)","", token)
14
15        if tag.startswith("NN"):
16            pos = 'n'
17        elif tag.startswith('VB'):
18            pos = 'v'
19        else:
20            pos = 'a'
21
22        lemmatizer = WordNetLemmatizer()
23        token = lemmatizer.lemmatize(token, pos)
24
25        if len(token) > 0 and token not in string.punctuation and token.lower() not in stop_words:
26            cleaned_tokens.append(token.lower())
27    return cleaned_tokens

此代码创建了一个‘remove_noise()’函数,删除噪音,并包含前面提到的正常化和细节化。

然后,代码使用循环从数据集中删除噪音。 为了删除超链接,代码首先搜索一个与 http://https:// 开始的 URL 相匹配的字符串,然后是字母、数字或特殊字符串。

同样,为了删除@提及,代码使用常规表达式代替文本的相关部分,代码使用re库搜索@符号,然后是数字,字母或_,并用空串代替它们。

最后,您可以使用库字符串删除点缀。

除此之外,您还将使用 NLTK 内置的停止单词集删除停止单词,需要单独下载。

从 Python 交互式会话中执行以下命令来下载此资源:

1nltk.download('stopwords')

一旦资源下载,退出交互式会话。

您可以使用 .words() 方法来获取英语中停止单词的列表. 要测试该函数,让我们在我们的样本推文上运行它. 将下列行添加到 nlp_test.py 文件的末尾:

1[label nlp_test.py]
2...
3from nltk.corpus import stopwords
4stop_words = stopwords.words('english')
5
6print(remove_noise(tweet_tokens[0], stop_words))

保存和关闭文件后,重新运行脚本以获得类似于以下的输出:

1[secondary_label Output]
2['#followfriday', 'top', 'engage', 'member', 'community', 'week', ':)']

请注意,该函数删除所有@提及,停止单词,并将单词转换为下载。

在继续下一步的建模练习之前,使用‘remove_noise()’函数来清除积极和消极的推文。评论行以在样本推文上打印‘remove_noise()’的输出,并在‘nlp_test.py’脚本中添加下列内容:

 1[label nlp_test.py]
 2...
 3from nltk.corpus import stopwords
 4stop_words = stopwords.words('english')
 5
 6#print(remove_noise(tweet_tokens[0], stop_words))
 7
 8positive_tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
 9negative_tweet_tokens = twitter_samples.tokenized('negative_tweets.json')
10
11positive_cleaned_tokens_list = []
12negative_cleaned_tokens_list = []
13
14for tokens in positive_tweet_tokens:
15    positive_cleaned_tokens_list.append(remove_noise(tokens, stop_words))
16
17for tokens in negative_tweet_tokens:
18    negative_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

现在你已经添加了清理样本推文的代码,你可能想将原始代币与清理的代币进行比较,以便测试样本推文。

1[label nlp_test.py]
2...
3print(positive_tweet_tokens[500])
4print(positive_cleaned_tokens_list[500])

保存和关闭文件,并运行脚本. 从输出中,你会看到点头和链接已被删除,并将单词转换为下文。

1[secondary_label Output]
2['Dang', 'that', 'is', 'some', 'rad', '@AbzuGame', '#fanart', '!', ':D', 'https://t.co/bI8k8tb9ht']
3['dang', 'rad', '#fanart', ':d']

例如,没有间隙的单词(iLoveYou)将被视为一个单词,并且很难分开这些单词。此外,HiHiiHiiiii将被脚本对待不同,除非你写出某些具体的内容来解决这个问题。

现在你已经看到‘remove_noise()’函数在行动中,请确保评论或从脚本中删除最后两行,以便你可以添加更多:

1[label nlp_test.py]
2...
3#print(positive_tweet_tokens[500])
4#print(positive_cleaned_tokens_list[500])

在此步骤中,您将从数据中删除噪音,以使分析更有效,在下一步中,您将分析数据,以便在样本数据集中找到最常见的单词。

步骤5:确定词密度

对文本数据的最基本的分析形式是抽出单词频率,单个推文的实体太小,无法找出单词的分布,因此,对所有积极的推文都会进行单词频率的分析。

下面的片段定义了 一个生成函数,名为 get_all_words,它将一份推文列表作为一个论点,以提供所有推文代币中的单词列表: 将以下代码添加到您的 nlp_test.py 文件:

1[label nlp_test.py]
2...
3
4def get_all_words(cleaned_tokens_list):
5    for tokens in cleaned_tokens_list:
6        for token in tokens:
7            yield token
8
9all_pos_words = get_all_words(positive_cleaned_tokens_list)

现在你已经编译了推文样本中的所有单词,你可以使用 NLTK 的 FreqDist类来找出哪些最常见的单词。

1[label nlp_test.py]
2from nltk import FreqDist
3
4freq_dist_pos = FreqDist(all_pos_words)
5print(freq_dist_pos.most_common(10))

.most_common() 方法列出了数据中最常见的单词. 保存并关闭这些更改后的文件。

当您现在运行该文件时,您将在数据中找到最常见的术语:

 1[secondary_label Output]
 2[(':)', 3691),
 3 (':-)', 701),
 4 (':d', 658),
 5 ('thanks', 388),
 6 ('follow', 357),
 7 ('love', 333),
 8 ('...', 290),
 9 ('good', 283),
10 ('get', 263),
11 ('thank', 253)]

从这些数据中,你可以看到,情感符实体构成了积极的推文中最常见的一些部分。在继续到下一步之前,请确保您评论印刷前十个代币的脚本的最后一行。

要总结一下,你从nltk中提取了推文,代码化,正常化,并清理了推文以用于模型中。

在下一步中,您将为情绪分析准备数据。

步骤 6 – 为模型准备数据

情绪分析是识别作者对正在撰写的主题的态度的过程,您将创建训练数据集来训练模型,这是一个受监督的学习机器学习过程,需要您将每个数据集与训练的感觉联系起来。

对于培训数据集的简单性和可用性,本教程可以帮助您在两个类别中训练您的模型,积极和消极。

一个模型是使用规则和方程式来描述一个系统的描述,它可以像一个方程式一样简单,它可以预测一个人的体重,考虑到他们的身高。你将构建的情绪分析模型将推文与积极或消极的情绪联系起来。

在数据准备步骤中,您将通过将代币转换为字典表格来准备情绪分析的数据,然后将数据分割为培训和测试目的。

将代码转换为字典

首先,您将准备将数据输入到模型中。您将使用 NLTK 中的 Naive Bayes 分类器来执行建模练习。 请注意,该模型不仅需要一个帖子中的单词列表,还需要一个 Python 字典,用单词作为关键词和值为True

添加以下代码,将推文从清理代币列表转换为用代币和值为True的字典。

1[label nlp_test.py]
2...
3def get_tweets_for_model(cleaned_tokens_list):
4    for tweet_tokens in cleaned_tokens_list:
5        yield dict([token, True] for token in tweet_tokens)
6
7positive_tokens_for_model = get_tweets_for_model(positive_cleaned_tokens_list)
8negative_tokens_for_model = get_tweets_for_model(negative_cleaned_tokens_list)

将数据集分割为培训和测试模型

接下来,您需要为NaiveBayesClassifier类训练准备数据,然后将以下代码添加到文件中,以准备数据:

 1[label nlp_test.py]
 2...
 3import random
 4
 5positive_dataset = [(tweet_dict, "Positive")
 6                     for tweet_dict in positive_tokens_for_model]
 7
 8negative_dataset = [(tweet_dict, "Negative")
 9                     for tweet_dict in negative_tokens_for_model]
10
11dataset = positive_dataset + negative_dataset
12
13random.shuffle(dataset)
14
15train_data = dataset[:7000]
16test_data = dataset[7000:]

此代码将一个积极消极标签附加到每个推文,然后通过连接积极和消极的推文来创建一个数据集

默认情况下,数据包含所有正面的推文,然后是所有负面的推文。在训练模型时,您应该提供一个不包含偏见的数据样本。

最后,该代码将混合数据分为训练和测试的比例为70:30,因此,由于推文数量为10000个,您可以从混合数据集中使用最初的7000条推文来训练模型,最后的3000条用于测试模型。

在此步骤中,您将清理的代币转换为字典表格,随机篡改数据集,并将其分为训练和测试数据。

第7步:构建和测试模型

最后,您可以使用NaiveBayesClassifier类来构建模型,使用.train()方法来训练模型,并使用.accuracy()方法来测试测试数据的模型。

1[label nlp_test.py]
2...
3from nltk import classify
4from nltk import NaiveBayesClassifier
5classifier = NaiveBayesClassifier.train(train_data)
6
7print("Accuracy is:", classify.accuracy(classifier, test_data))
8
9print(classifier.show_most_informative_features(10))

添加代码后保存、关闭和执行文件. 代码的输出将如下:

 1[secondary_label Output]
 2Accuracy is: 0.9956666666666667
 3
 4Most Informative Features
 5                      :( = True Negati : Positi =   2085.6 : 1.0
 6                      :) = True Positi : Negati =    986.0 : 1.0
 7                 welcome = True Positi : Negati =     37.2 : 1.0
 8                  arrive = True Positi : Negati =     31.3 : 1.0
 9                     sad = True Negati : Positi =     25.9 : 1.0
10                follower = True Positi : Negati =     21.1 : 1.0
11                     bam = True Positi : Negati =     20.7 : 1.0
12                    glad = True Positi : Negati =     18.1 : 1.0
13                     x15 = True Negati : Positi =     15.9 : 1.0
14               community = True Positi : Negati =     14.1 : 1.0

准确性被定义为测试数据集中推文的百分比,该模型能够正确地预测情绪。

在显示最具信息性的特征的表中,输出中的每个行都显示了培训数据集中正面和负面标记的推文中代币的发生率。数据中的第一个行表示,在所有包含代币的推文中,负面与正面的代币的比率是2085.61。有趣的是,在正面数据集中似乎有一个代币有:(

接下来,您可以检查模型如何在来自Twitter的随机推文中表现。

1[label nlp_test.py]
2...
3from nltk.tokenize import word_tokenize
4
5custom_tweet = "I ordered just once from TerribleCo, they screwed up, never used the app again."
6
7custom_tokens = remove_noise(word_tokenize(custom_tweet))
8
9print(classifier.classify(dict([token, True] for token in custom_tokens)))

此代码将允许您通过更新与custom_tweet变量相关的字符串来测试自定义推文。

运行脚本来分析自定义文本. 以下是示例中自定义文本的输出:

1[secondary_label Output]
2'Negative'

您还可以检查它是否正确描述积极的推文:

1[label nlp_test.py]
2...
3custom_tweet = 'Congrats #SportStar on your 7th best goal from last season winning goal of the year :) #Baller #Topbin #oneofmanyworldies'

以下是产量:

1[secondary_label Output]
2'Positive'

现在你已经测试了积极和消极的情绪,更新变量来测试一个更复杂的情绪,如 Sarcasm。

1[label nlp_test.py]
2...
3custom_tweet = 'Thank you for sending my baggage to CityX and flying me to CityY at the same time. Brilliant service. #thanksGenericAirline'

以下是产量:

1[secondary_label Output]
2'Positive'

该模型将此示例归类为正面,这是因为训练数据不够全面,以便将语推文归类为负面,如果您希望您的模型能够预测语,则需要提供足够的训练数据来相应训练。

在此步骤中,您构建并测试了模型,您还探索了一些局限性,例如在特定例子中没有检测到 Sarcasm. 您完成的代码仍然有从遵循教程中剩下的文物,因此下一步将指导您将代码与Python的最佳实践相匹配。

步骤 8 – 清理代码(可选)

虽然您已经完成了教程,但建议在nlp_test.py文件中重组代码,以遵循最佳编程实践。

  • 所有导入都应该位于文件的顶部. 来自同一库的导入都应该被组合成一个单一的语句.
  • 所有函数都应该在导入后被定义.
  • 文件中的所有语句都应该在if __name__ ==main:条件下存放。

我们还将通过遵循教程删除评论的代码,以及lemmatize_sentence函数,因为新的remove_noise函数完成了缩写。

以下是「nlp_test.py」的清理版本:

 1from nltk.stem.wordnet import WordNetLemmatizer
 2from nltk.corpus import twitter_samples, stopwords
 3from nltk.tag import pos_tag
 4from nltk.tokenize import word_tokenize
 5from nltk import FreqDist, classify, NaiveBayesClassifier
 6
 7import re, string, random
 8
 9def remove_noise(tweet_tokens, stop_words = ()):
10
11    cleaned_tokens = []
12
13    for token, tag in pos_tag(tweet_tokens):
14        token = re.sub('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|'\
15                       '(?:%[0-9a-fA-F][0-9a-fA-F]))+','', token)
16        token = re.sub("(@[A-Za-z0-9_]+)","", token)
17
18        if tag.startswith("NN"):
19            pos = 'n'
20        elif tag.startswith('VB'):
21            pos = 'v'
22        else:
23            pos = 'a'
24
25        lemmatizer = WordNetLemmatizer()
26        token = lemmatizer.lemmatize(token, pos)
27
28        if len(token) > 0 and token not in string.punctuation and token.lower() not in stop_words:
29            cleaned_tokens.append(token.lower())
30    return cleaned_tokens
31
32def get_all_words(cleaned_tokens_list):
33    for tokens in cleaned_tokens_list:
34        for token in tokens:
35            yield token
36
37def get_tweets_for_model(cleaned_tokens_list):
38    for tweet_tokens in cleaned_tokens_list:
39        yield dict([token, True] for token in tweet_tokens)
40
41if __name__ == "__main__":
42
43    positive_tweets = twitter_samples.strings('positive_tweets.json')
44    negative_tweets = twitter_samples.strings('negative_tweets.json')
45    text = twitter_samples.strings('tweets.20150430-223406.json')
46    tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]
47
48    stop_words = stopwords.words('english')
49
50    positive_tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
51    negative_tweet_tokens = twitter_samples.tokenized('negative_tweets.json')
52
53    positive_cleaned_tokens_list = []
54    negative_cleaned_tokens_list = []
55
56    for tokens in positive_tweet_tokens:
57        positive_cleaned_tokens_list.append(remove_noise(tokens, stop_words))
58
59    for tokens in negative_tweet_tokens:
60        negative_cleaned_tokens_list.append(remove_noise(tokens, stop_words))
61
62    all_pos_words = get_all_words(positive_cleaned_tokens_list)
63
64    freq_dist_pos = FreqDist(all_pos_words)
65    print(freq_dist_pos.most_common(10))
66
67    positive_tokens_for_model = get_tweets_for_model(positive_cleaned_tokens_list)
68    negative_tokens_for_model = get_tweets_for_model(negative_cleaned_tokens_list)
69
70    positive_dataset = [(tweet_dict, "Positive")
71                         for tweet_dict in positive_tokens_for_model]
72
73    negative_dataset = [(tweet_dict, "Negative")
74                         for tweet_dict in negative_tokens_for_model]
75
76    dataset = positive_dataset + negative_dataset
77
78    random.shuffle(dataset)
79
80    train_data = dataset[:7000]
81    test_data = dataset[7000:]
82
83    classifier = NaiveBayesClassifier.train(train_data)
84
85    print("Accuracy is:", classify.accuracy(classifier, test_data))
86
87    print(classifier.show_most_informative_features(10))
88
89    custom_tweet = "I ordered just once from TerribleCo, they screwed up, never used the app again."
90
91    custom_tokens = remove_noise(word_tokenize(custom_tweet))
92
93    print(custom_tweet, classifier.classify(dict([token, True] for token in custom_tokens)))

结论

本教程介绍了您使用Python 3中的nltk库的基本情绪分析模型。 首先,您对推文进行了预处理,通过代币化推文,规范词语,并删除噪音。

一个受监督的学习模型只有其训练数据一样好. 为了进一步加强该模型,您可以考虑添加更多类别,如兴奋和愤怒. 在本教程中,您只是通过构建一个原始模型来擦拭表面。

Published At
Categories with 技术
comments powered by Disqus