使用数据注释改进 NLTK 情感分析

本文是使用 Python 和开源自然语言工具包的情感分析系列的第六篇。在本文中,让我们看看注释我们自己的数据集的过程需要什么。

我们将构建一个库来帮助我们标记和识别 Reddit 评论中的特征,以通过机器学习方法提高自然语言工具包 (NLTK) VADER 情感分析的准确性。

本系列情感分析的目标是使用 Python 和开源自然语言工具包 (NLTK) 构建一个库,用于扫描对 Reddit 帖子的回复并检测发帖者是否使用负面、敌对或其他不友好的语言。

用于 Python 的自然语言工具包 (NLTK) 自然语言处理 (NLP) 库是一个强大的工具,用于对数据语料库进行文本分析。

在使用预训练的 VADER 模型进行 NLTK 情绪分析和NLTK 和机器学习进行情绪分析的文章中,我们使用了一些预配置的数据集和分析工具对从 Reddit 讨论中提取的大量数据执行情绪分析。

从根本上说,如果我们正在寻找像 r/learnpython subreddit 这样的技术社区,那么电影评论可能不是一个很好的训练语料库。如果我们继续迭代和改进我们正在寻找的功能,当移动到评估集(如来自 r/Movies 或 r/MovieDetails 子版块的数据)时,我们可能会获得良好的结果。

当您最终获得太多专门针对训练数据进行调整且无法泛化的特征时,就会发生过度拟合。我们可能能够在预测电影评论时获得更高的准确性,但这并不适合我们的目标用例。

我们可以使用像 UCI 论文评论这样的数据集,它可能使用具有预测性的技术和科学术语,但该数据集是西班牙语,因此可能无法概括。

我们可以使用像路透社新闻文章这样的数据集,但是传达事实和新闻的方式并不涉及技术社区可能会做出的相同的词选择,因此它会遇到与电影评论相同的问题。

相反,让我们看看注释我们自己的数据集的过程需要什么。

为训练创建自定义数据集

为了不让 Reddit API 过载,我们将在训练时临时做一些缓存。

# reddit, submission, and comments were defined as in 
# earlier code listing

from nltk.sentiment.vader import SentimentIntensityAnalyzer
import json

results = {}

analyzer = SentimentIntensityAnalyzer()
for comment in comments:
    score = analyzer.polarity_scores(comment.body)
    results[comment.id] = {
        'score': score,
        'ups': comment.ups,
        'downs': comment.downs,
        'created': comment.created,
        'text': comment.body
    }

    if comment.author:
        results[comment.id]['author'] = comment.author.name
    else:
        results[comment.id]['author'] = 'deleted'

# Store results in a file for annotation
filename = submission.id + '.json'
with open(filename, 'w') as file:
    json.dump(results, file, indent=4)

这为我们提供了一个数据文件,其中包含一些可能对定义特征有用的值。

现在是注释的时候了。我们可以编辑这个文件或创建一个映射来添加我们自己的标签,如下图红色所示。

{
    "fmonppi": {
        "score": {
            "neg": 0.0,
            "neu": 0.981,
            "pos": 0.019,
            "compound": 0.1779
        },
        "ups": 122,
        "downs": 0,
        "created": 1586293145.0,
        "author": "...",
        "text": "To take a non programming approach, suppose you and I both have a $50 bill.  They are of equal value but are not the same as their serial numbers differ.\n\nSo they are equivalent but not identical.\n\nIn Python, == checks for equivalency.  For custom classes you can implement this yourself.  In contrast, is and is not checks to see if two things are identical.  Generally it's used to check if two variable names are aliases of each other and to check for None as there is only NoneType instance.",
        "label": "neutral",
    },
...     
}

我们可以查看这篇文章中的每条评论,并以我们认为信息丰富的方式对其进行标记。例如,我同意 VADER 的分析,即该评论应该是中立的。

许多情绪分析数据集仅指定正面和负面,这将中性评论强制纳入这些分类选项之一,这可能对尝试识别真正有洞察力的评论不利。

我们可以构建工具来帮助自动化注释工作流程。我们不打算详细介绍这些工具,但无论我们使用 CLI 还是 GUI,我们都可以选择强力为所有评论添加标签,或者在多个集合中进行随机抽样并扩大我们的数据集随着时间的推移定期。

使用自定义注释数据集进行训练

使用我们自己的注释数据集,我们现在可以在我们的训练尝试中用它代替现成的电影评论语料库。和以前一样,我们会将有关文本的一些细节与我们为自己选择的标签配对。与电影评论不同,我们不会同时阅读标签相似的内容,但无论如何我们都会随机化,以防评论的顺序在某种程度上有意义。

# return a list of tuple pairs
#    details about a comment
#    a string label for 'positive', 'negative', and 'neutral'
def get_labeled_dataset():
    filename = 'annotated.json'
    with open(filename, 'r') as file:
        annotated = json.loads(file.read())

    dataset = []
    for id in annotated:
        dataset.append((annotated[id], annotated[id]['label']))

    random.shuffle(dataset)
    return dataset

我们没有对我们的get_features()方法做任何实质性的改变,除了将文本直接传递给函数,我们需要从中检索comment['text']

有效特征分析的注意事项

为了改进我们的分析,我们需要建立一个语料库。注释单个帖子还不错,但是我们的电影评论数据集有 2000 个项目,而单个 Reddit 提交可能只有 100 条评论。(我们在Find Data for Natural Language Processing讨论了从 Reddit 收集评论。)

尽管样本量很小,但对我们自己的数据进行注释的努力可以帮助我们了解什么可以做出更好的预测。

VADER 分析仍然是我们功能集的一部分,因为它为我们提供了良好的基线。VADER 值的范围从 -1 到 +1,我们需要选择一个高于和低于其分配正面和负面情绪的阈值。通过将分数与我们的机器学习方法相结合,我们可以通过在分类模型中使用权重来确定该阈值。

这里定义的概念最初是理解评论中的客户情绪,我们的数据源是 r/learnpython subreddit 中的评论。还有哪些其他功能对于理解技术社区的情绪有意义?

  • Reddit 使用赞成和反对的数量来得出有争议的帖子和评论。这也适用于我们。有很多赞成票和反对票的帖子往往是非常积极或消极的。
  • 对于技术观众,通过证明某人对某事的错误,可以推断出许多措辞是否定的。这包括诸如“不正确”、“更好的解释”、“我会避免它”、“你搞错了”、“这种行为是深奥的”、“强烈反对”等短语。
  • 感恩是积极情绪的良好表现,包括“谢谢”和“这很酷”等短语。
  • 以“Well”或“Perhaps”开头的句子通常表示可以解释为否定的评论。
  • 词汇方法可能会遗漏与技术社区相关的其他细节,例如,当评论使用源代码或引用 URL 等外部引用时(可以将其视为增强器,以帮助某人,或指出 Python 增强提案( PEP)建议未遵循)
  • 了解何时提出反问。

最终,标签是主观的,反映了我们自己对数据的偏见和兴趣。我们应该努力在我们的标签和我们如何为这些观察编码特征标记方面保持一致,以获得最准确的结果。

下一步

如果您已阅读我们关于 NLTK 和情感分析的文章,您应该对使用 Python 的内置 NLTK 工具和您自己的机器学习模型进行自然语言处理的主要构建块有基本的了解。

在《使用云 AI 进行情感分析》中,我们将了解一些现在可通过 Amazon Comprehend 和 Microsoft Azure 文本分析等云计算服务获得的复杂 NLP 工具。

发表评论

邮箱地址不会被公开。 必填项已用*标注