TowardsDataScience 博客中文翻译 2016~2018(三十三)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 Python 的另一个 Twitter 情感分析—第 10 部分(使用 Doc2Vec/Word2Vec/GloVe 的神经网络)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-10-neural-network-with-a6441269aa3c?source=collection_archive---------3-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Brett Jordan on Unsplash

这是我正在进行的推特情感分析项目的第十部分。你可以从下面的链接找到以前的帖子。

在上一篇文章中,我用 Tf-idf 向量实现了神经网络建模,但发现对于高维稀疏数据,神经网络的性能并不好。在这篇文章中,我将看看从 Doc2Vec 模型或单词向量中输入文档向量与 Tf-idf 向量有什么不同。

*除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

具有 Doc2Vec 的神经网络

在我使用从 Doc2Vec 获得的向量进行神经网络建模之前,我想向您介绍一下我是如何获得这些文档向量的背景。在本系列的第六部分中,我已经使用 Gensim 库实现了 Doc2Vec。

有三种不同的方法用于训练 Doc2Vec。分布式单词包,分布式记忆(Mean),分布式记忆(Concatenation)。这些模型通过 30 个时期的 150 万条推文进行训练,模型的输出是每条推文的 100 个维度向量。在我从每个模型中获得文档向量之后,我尝试将这些向量连接起来(因此连接起来的文档向量有 200 个维度): DBOW + DMM、DBOW + DMC,与使用任何单一纯方法的模型相比,我看到了性能的提高。 Le 和 Mikolov (2014) 在他们的研究论文中已经展示了使用不同的训练方法并将其连接起来以提高性能。

最后,作为 Doc2Vec 训练的前一步,我应用短语建模来检测二元短语和三元短语,并尝试了跨 n-grams 的不同组合。当使用逻辑回归模型进行测试时,我从“unigram DBOW + trigram DMM”文档向量中获得了最佳性能结果。

我将首先从加载 Gensim 的 Doc2Vec 开始,并定义一个提取文档向量的函数,然后加载我训练的 doc2vec 模型。

当馈送到简单的逻辑回归时,连接的文档向量(unigram DBOW + trigram DMM)产生 75.90%的训练集准确度和 75.76%的验证集准确度。

我将尝试不同数量的隐藏层、隐藏节点来比较性能。在下面的代码块中,您会看到我首先将种子定义为“7”,但没有设置随机种子,“np.random.seed()”将在每个模型的开始处定义。这是为了再现不同模型结构的各种结果。

*旁注(再现性):老实说,这花了我一段时间才弄明白。我首先尝试在导入 Keras 之前设置随机种子,并一个接一个地运行模型。然而,如果我在模型运行后定义相同的模型结构,我不能得到相同的结果。但我也意识到,如果我重启内核,并从头开始重新运行代码块,它会给我与上一个内核相同的结果。所以我想,在运行一个模型后,随机种子发生了变化,这就是为什么我不能用相同的结构得到相同的结果,如果我在相同的内核中连续运行它们。无论如何,这就是为什么我每次尝试不同的模型时都设置随机种子。供您参考,我运行 Keras 与 Theano 后端,只使用 CPU 而不是 GPU。如果你在同样的设置下,这应该可以。通过在命令行中启动 Jupyter Notebook,我显式地将 backend 指定为 Theano,如下所示:“KERAS _ back end = the ano Jupyter Notebook”

请注意,并不是下面单元格中加载的所有依赖项都用于这篇文章,而是为了以后使用而导入的。

定义不同的模型结构会是相当重复的代码,所以我只给你两个例子,这样你就可以理解如何用 Keras 定义模型结构。

在尝试了 12 种不同的模型和一系列的隐藏层(从 1 到 3)以及每个隐藏层的一系列隐藏节点(64,128,256,512)之后,下面是我得到的结果。最佳验证准确度(79.93%)来自于第 7 时段的“model_d2v_09”,其具有 3 个隐藏层,每个隐藏层具有 256 个隐藏节点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我知道哪个模型给我的结果最好,我将运行“model_d2v_09”的最终模型,但这次是用 Keras 中的回调函数。在我收到上一篇帖子的评论之前,我对 Keras 中的回调函数还不太熟悉。得到评论后,我做了一些挖掘,找到了 Keras 回调中所有有用的函数。感谢 @rcshubha 的评论。下面是我的 Doc2Vec 最终模型,我用了“checkpoint”和“earlystop”。您可以使用选项设置“检查点”功能,通过以下参数设置,“检查点”将保存最佳执行模型,直到运行点,只有当新的纪元优于保存的模型时,它才会将其保存为新的模型。而“early_stop”我把它定义为监控验证精度,如果 5 个纪元没有超过目前最好的验证精度,它就停止。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我评估我刚刚运行的模型,它会给我与上一个时期相同的结果。

model_d2v_09_es.evaluate(x=validation_vecs_ugdbow_tgdmm, y=y_validation)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是如果我在最佳时期加载保存的模型,那么这个模型将在那个时期给我结果。

from keras.models import load_model
loaded_model = load_model('d2v_09_best_weights.07-0.7993.hdf5')
loaded_model.evaluate(x=validation_vecs_ugdbow_tgdmm, y=y_validation)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你记得用逻辑回归模型用相同的向量表示推文的验证准确性(75.76%),你可以看到将相同的信息输入神经网络会产生明显更好的结果。看到神经网络如何提振密集向量的性能令人惊叹,但最好的验证精度仍然低于 Tfidf 向量+ logistic 回归模型,该模型给了我 82.92%的验证精度。

如果你读过我在 Doc2Vec 上的帖子,或者熟悉 Doc2Vec,你可能知道还可以从训练好的 Doc2Vec 模型中提取每个单词的单词向量。我将继续使用 Word2Vec,并尝试不同的方法,看看是否有任何方法可以优于 Doc2Vec 的结果(79.93%),最终优于 Tfidf + logistic 回归模型(82.92%)。

Word2Vec

为了利用从 Doc2Vec 模型中提取的单词向量,我不能再使用不同 n 元语法的连接向量,因为它们不会包含相同的词汇。因此,在下面,我加载了 unigram DMM 的模型,并为词汇表中的每个单词创建了具有 200 维 unigram DBOW 的连接向量。

在我尝试使用从单词向量计算的文档表示的神经网络之前,我首先要做的是,我将使用各种文档表示方法来拟合逻辑回归,并使用给我最佳验证准确性的方法,我将最终定义一个神经网络模型。

我还会以表格的形式给出所有符合逻辑回归的不同词向量的结果汇总。

从 Doc2Vec 模型中提取的词向量(平均值/总和)

可以有许多不同的方法来用单独的单词向量来提出文档表示向量。一个显而易见的选择是平均它们。对于 tweet 中的每个单词,查看经过训练的 Doc2Vec 是否具有该单词的单词向量表示,如果是,则对整个文档中的单词向量进行求和,同时计算有多少单词被检测为具有单词向量,最后通过将求和的向量除以计数,可以获得整个文档的平均单词向量,该向量与各个单词向量具有相同的维数(在本例中为 200)。

另一种方法是只对单词向量求和,而不对它们进行平均。如果一些 tweet 只有 Doc2Vec 词汇表中的几个单词,而一些 tweet 有 Doc2Vec 词汇表中的大部分单词,这可能会扭曲文档的向量表示。但我会尝试求和与平均,并比较结果。

使用 unigram DBOW + unigram DMM 的平均单词向量的验证准确率为 71.74%,这显著低于从 unigram DBOW + trigram DMM 提取的文档向量(75.76%),并且从本系列的第 6 部分得到的结果中,我知道从 unigram DBOW + unigram DMM 提取的文档向量将给出 75.51%的验证准确率。

我还尝试使用 ScikitLearn 的 scale 函数缩放向量,并看到计算时间的显著改善和精确度的轻微提高。

让我们看看相加的词向量与平均的词向量相比表现如何。

与平均方法相比,求和方法在没有缩放的情况下给了我更高的精度。但是用向量相加的简单逻辑回归需要 3 个多小时来运行。所以我再次尝试缩放这些向量。

令人惊讶!通过缩放,逻辑回归拟合只需 3 分钟!那是相当不同的。使用定标字向量的验证准确度在平均情况下为 72.42%,在求和情况下为 72.51%。

使用 TFIDF 加权(平均值/总和)从 Doc2Vec 模型中提取的词向量

在本系列的第 5 部中,我已经解释了什么是 TF-IDF。TF-IDF 是一种通过计算相对词频率和逆文档频率的乘积来加权每个词的方法。因为它为词汇表中的每个单词给出一个标量值,所以这也可以用作每个单词向量的加权因子。Correa Jr .等人(2017 年)在他们的论文“NILC-南太平洋大学在 SemEval-2017 任务 Twitter 情感分析的多视角集成”中实施了这种 Tf-idf 加权

为了获得每个单词的 Tfidf 值,我首先用 tfidf 矢量器拟合和转换训练集,并创建一个包含“单词”、“tfi df 值”对的字典。此外,我定义了一个函数“get_w2v_general ”,用给定的 Word2Vec 模型获得平均单词向量或总单词向量。最后,我计算单词向量与相应 Tfidf 值的乘积。从下面的代码来看,Tfidf 乘法部分花费了相当多的时间。老实说,我仍然不确定为什么要花这么长时间来计算单词向量的 Tfidf 权重,但 5 个小时后它终于完成了计算。稍后你也可以看到,我尝试了另一种称重方法,但用时不到 10 秒。如果你对此有答案,任何见解将不胜感激。

然后,我可以调用“get_w2v_general”函数,就像我对上述不带加权因子的单词向量所做的一样,然后拟合一个逻辑回归模型。平均值的验证准确率为 70.57%,总和的验证准确率为 70.32%。结果不是我预想的那样,尤其是等了 5 个小时。通过用 Tfidf 值对字向量进行加权,平均和求和的验证精度都下降了约 2%。

使用自定义权重(平均值/总和)从 Doc2Vec 模型中提取的单词向量

在本系列的第三部分中,我定义了一个名为“pos_normcdf_hmean”的自定义指标,这是从 Jason Kessler 在 PyData 2017 Seattle 的演示文稿中借用的指标。如果你想知道更多关于计算的细节,你可以查看我之前的帖子或者你也可以观看杰森·凯斯勒的演讲。为了给你一个高层次的直觉,通过计算 CDF(累积分布函数)转换值的调和平均值,在整个文档中的词频率和在一个类中的词频,你可以得到一个有意义的度量,显示每个词如何与某个类相关。

我在本系列的第三部分中使用了这个度量来可视化令牌,并且在第五部分中再次使用它来创建用于分类目的的自定义词典。我将再次使用它作为单词向量的加权因子,看看它如何影响性能。

平均数的验证准确率为 73.27%,总和的验证准确率为 70.94%。与 Tfidf 加权不同,这次使用自定义加权,当使用平均方法时,它实际上给了我一些性能提升。但是对于求和,这种加权并不比没有加权的字向量表现得更好。

从预训练手套中提取的单词向量(平均值/总和)

GloVe 是由斯坦福 NLP 小组的 Pennington 等人(2014) 提出的另一种向量中的单词表示。

Word2Vec 和 Glove 的区别在于这两个模型如何计算单词向量。在 Word2Vec 中,你得到的单词向量是浅层神经网络的一种副产品,当它试图预测给定周围单词的中心单词或反之亦然。但是使用 GloVe,你得到的词向量是 GloVe 模型的对象矩阵,它使用术语共现矩阵和维度缩减来计算这个。

好消息是,由于最新更新(Gensim 3.2.0),您现在可以轻松加载和使用 Gensim 的预训练手套向量。除了一些预先训练的单词向量,还添加了新的数据集,这也可以使用他们的下载器 API 轻松下载。如果你想了解更多这方面的信息,请查看稀有技术公司的这篇博文。

斯坦福大学 NLP 小组已经公开了他们预先训练的手套向量,其中,有专门用推文训练的手套向量。这听起来绝对值得一试。他们有四个不同版本的推文向量,每个向量都有不同的维度(25,50,100,200 ),对 20 亿条推文进行了训练。你可以在他们的网站上找到更多细节。

在这篇文章中,我将使用 200 维预训练手套向量。(如果您的 Gensim 版本低于 3.2.0,您可能需要更新 Gensim)

通过使用预先训练的手套向量,我可以看到验证准确性显著提高。到目前为止,最好的验证准确性来自具有自定义权重的平均单词向量,这给了我 73.27%的准确性,与此相比,手套向量分别产生 76.27%的平均值和 76.60%的总和。

从预先训练的谷歌新闻 Word2Vec 中提取的词向量(平均值/总和)

有了新更新的 Gensim,我还可以加载著名的预训练谷歌新闻词向量。这些词向量在谷歌新闻数据集(约 1000 亿词)上使用 Word2Vec 模型进行训练,并由谷歌发布。该模型包含 300 维向量,包含 300 万个单词和短语。你可以在谷歌项目档案中找到更多细节。

平均数的验证准确率为 74.96%,总和的验证准确率为 74.92%。尽管它给我的结果比从定制训练的 Doc2Vec 模型中提取的单词向量更好,但它未能胜过手套向量。而谷歌新闻词向量中的向量维度更大。

但是,这是用谷歌新闻训练的,而我使用的手套向量是专门用推特训练的,因此很难直接相互比较。如果 Word2Vec 是专门用推文训练的呢?

单独训练的 Word2Vec(平均值/总和)

我知道我已经尝试了我从 Doc2Vec 模型中提取的单词向量,但是如果我训练单独的 Word2Vec 模型会怎么样?即使 Doc2Vec 模型给出了很好的文档级表示向量,如果我训练纯 Word2Vec,学习单词向量会更有效吗?

为了回答自己的问题,我用 CBOW(连续词袋)和 Skip Gram 模型训练了两个 Word2Vec 模型。在参数设置方面,我设置了与 Doc2Vec 相同的参数。

  • 向量的大小:100 维
  • 负采样:5
  • 窗口:2
  • 最小字数:2
  • alpha: 0.065(每个时期将 alpha 减少 0.002)
  • 纪元数量:30

根据上面的设置,我通过传递“sg=0”定义了 CBOW 模型,通过传递“sg=1”定义了 Skip Gram 模型。

一旦我从两个模型中得到结果,我就把每个单词的两个模型的向量连接起来,这样连接起来的向量就有了每个单词的 200 维表示。

请注意,在第 6 部分,我训练 Doc2Vec 的地方,我使用了从 Gensim 导入的“LabeledSentence”函数。这已经被否决了,因此在这篇文章中我使用了“TaggedDocument”函数。用法是一样的。

单字 CBOW 和单字 Skip Gram 模型的连接向量使用平均和方法分别产生了 76.50%和 76.75%的验证准确率。这些结果甚至比我从手套向量得到的结果还要高。

但请不要将此混淆为一般声明。这是在这种特殊环境下的经验发现。

单独训练的 Word2Vec,带自定义权重(平均值/总和)

最后一步,我将应用我在上面实现的自定义权重,看看这是否会影响性能。

最后,我得到了表现最好的词向量。使用自定义指标加权的平均单词向量(单独训练的 Word2Vec 模型)产生了 77.97%的最佳验证准确率!下面是我在上面尝试的所有结果的表格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Word2Vec 神经网络

选择具有逻辑回归的最佳表现的单词向量来馈送给神经网络模型。这一次我没有尝试各种不同的架构。根据我在使用 Doc2Vec 文档向量的不同架构的试验中观察到的情况,性能最好的架构是具有 3 个隐藏层的架构,每个隐藏层有 256 个隐藏节点。
我将最终拟合一个具有早期停止和检查点的神经网络,这样我可以保存验证准确性方面的最佳性能权重。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

from keras.models import load_model
loaded_w2v_model = load_model('w2v_01_best_weights.10-0.8048.hdf5')
loaded_w2v_model.evaluate(x=validation_w2v_final, y=y_validation)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最佳验证准确率为 80.48%。令人惊讶的是,这甚至比我在上面通过将文档向量输入到神经网络模型中所获得的最佳准确度还要高。

我花了相当长的时间来尝试不同的设置,不同的计算,但我通过所有的尝试和错误学到了一些宝贵的经验。经过专门训练的 Word2Vec,通过精心设计的权重,甚至可以在分类任务中胜过 Doc2Vec。

在下一篇文章中,我将尝试更复杂的神经网络模型,卷积神经网络。我再次希望这能给我的表现带来一些提升。

感谢您的阅读,您可以通过下面的链接找到 Jupyter 笔记本。

https://github . com/tthustle sa/Twitter _ 情操 _ 分析 _ part 10/blob/master/Capstone _ part 10 . ipynb

使用 Python 的另一个 Twitter 情感分析—第 11 部分(CNN + Word2Vec)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-11-cnn-word2vec-41f5e28eda74?source=collection_archive---------0-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Mahdi Bafande on Unsplash

这是我的推特情感分析项目的第 11 部分,也是最后一部分。这是一个漫长的旅程,通过一路上的许多尝试和错误,我学到了无数宝贵的经验教训。我还没有决定我的下一个项目。但我一定会腾出时间开始一个新项目。你可以从下面的链接找到以前的帖子。

*除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

卷积神经网络的准备

在上一篇文章中,我汇总了一条推文中每个单词的单词向量,通过求和或计算平均值来获得每条推文的一个向量表示。然而,为了馈送给 CNN,我们不仅要将每个词向量馈送给模型,还要按照与原始 tweet 相匹配的顺序。

例如,假设我们有一个如下的句子。

“我喜欢猫”

假设我们有每个单词的二维向量表示,如下所示:

我:[0.3,0.5]爱:[1.2,0.8]猫:[0.4,1.3]

有了上面的句子,我们对于整个句子所拥有的向量的维数是 3×2(3:字数,2:向量维数)。

但是还有一件事我们需要考虑。神经网络模型将期望所有数据具有相同的维度,但是在不同句子的情况下,它们将具有不同的长度。这可以用填充来处理。

假设我们有下面的第二句话。

“我也喜欢狗”

用下面的向量表示每个单词:

我:[0.3,0.5],爱:[1.2,0.8],狗:[0.8,1.2],太:[0.1,0.1]

第一句话有 3X2 维向量,但第二句话有 4X2 维向量。我们的神经网络不会接受这些作为输入。通过填充输入,我们决定一个句子中单词的最大长度,如果输入长度短于指定长度,则用零填充剩余的单词。在超过最大长度的情况下,它也会从开头或结尾截断。例如,假设我们决定我们的最大长度为 5。

然后,通过填充,第一个句子将在开头或结尾多 2 个全零的二维向量(您可以通过传递参数来决定),第二个句子将在开头或结尾多 1 个全零的二维向量。现在我们每个句子有 2 个相同维度(5X2)的向量,我们最终可以将它输入到一个模型中。

让我们首先加载 Word2Vec 模型,从中提取单词向量。我已经保存了我在上一篇文章中训练的 Word2Vec 模型,可以很容易地用 Gensim 中的“KeyedVectors”函数加载。我有两个不同的 Word2Vec 模型,一个是 CBOW(连续词包)模型,另一个是 skip-gram 模型。我不会详细说明 CBOW 和 skip-gram 有什么不同,但是如果你想知道更多细节,你可以参考我之前的文章。

from gensim.models import KeyedVectors
model_ug_cbow = KeyedVectors.load('w2v_model_ug_cbow.word2vec')
model_ug_sg = KeyedVectors.load('w2v_model_ug_sg.word2vec')

通过运行下面的代码块,我正在构建一种字典,我可以从中提取单词向量。由于我有两个不同的 Word2Vec 模型,下面的“embedding_index”将有两个模型的连接向量。对于每个模型,我有 100 维的单词向量表示,通过连接,每个单词将有 200 维的向量表示。

embeddings_index = {}
for w in model_ug_cbow.wv.vocab.keys():
    embeddings_index[w] = np.append(model_ug_cbow.wv[w],model_ug_sg.wv[w])

现在我们已经准备好了词向量的参考,但是我们仍然没有准备好我在文章开始解释的格式的数据。Keras 的“Tokenizer”将拆分句子中的每个单词,然后我们可以调用“texts_to_sequences”方法来获得每个句子的顺序表示。我们还需要传递“num_words ”,它是您要使用的词汇的数量,这将在您调用“texts_to_sequences”方法时应用。这可能有点违背直觉。因为如果你检查所有单词索引的长度,它将不是你定义的单词数,而是实际的筛选过程发生在你调用’ texts_to_sequences '方法的时候。

from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequencestokenizer = Tokenizer(num_words=100000)
tokenizer.fit_on_texts(x_train)
sequences = tokenizer.texts_to_sequences(x_train)

以下是原始列车数据的前五个条目。

for x in x_train[:5]:
    print x

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

并且作为顺序数据准备的相同数据如下。

sequences[:5]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每个单词都表示为一个数字,我们可以看到每个句子中的单词数与“序列”中数字的长度相匹配。我们以后可以把每个数字代表的单词联系起来。但是我们仍然没有填充我们的数据,所以每个句子都有不同的长度。让我们来处理这个。

length = []
for x in x_train:
    length.append(len(x.split()))
max(length)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

训练数据中一个句子的最大字数是 40。让我们决定最大长度比这个长一点,比如说 45。

x_train_seq = pad_sequences(sequences, maxlen=45)
x_train_seq[:5]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如您从填充序列中看到的,所有数据现在都转换为具有相同的长度 45,默认情况下,如果句子长度小于最大长度,则在开头使用零填充。如果你想知道更多细节,请查阅 Keras 文档中关于序列预处理的内容。

sequences_val = tokenizer.texts_to_sequences(x_validation)
x_val_seq = pad_sequences(sequences_val, maxlen=45)

在我们将顺序文本数据输入模型之前,还有一件事要做。当我们把一个句子转换成一个序列时,每个单词都用一个整数来表示。实际上,这些数字是每个单词在分词器的单词索引中的存储位置。记住这一点,让我们构建这些单词向量的矩阵,但这次我们将使用单词索引号,以便我们的模型在输入整数序列时可以引用相应的向量。

下面,我在定义字数为 10 万。这意味着我将只关心训练集中最频繁出现的 100,000 个单词。如果我不限制字数,总词汇量也就 20 多万。

num_words = 100000
embedding_matrix = np.zeros((num_words, 200))
for word, i in tokenizer.word_index.items():
    if i >= num_words:
        continue
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        embedding_matrix[i] = embedding_vector

作为健全性检查,如果嵌入矩阵已经正确生成。在上面,当我看到训练集的前五个条目时,第一个条目是“恨你”,这个的顺序表示是[137,6]。让我们看看第 6 个嵌入矩阵是否与单词“you”的向量相同。

np.array_equal(embedding_matrix[6] ,embeddings_index.get('you'))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们完成了数据准备。在我们进入 CNN 之前,我想再测试一件事(抱歉耽搁了)。当我们提供这种数据的顺序向量表示时,我们将在 Keras 中使用嵌入层。使用嵌入层,我可以通过预定义的嵌入,我在上面准备了‘Embedding _ matrix ’,或者嵌入层本身可以在整个模型训练时学习单词嵌入。另一种可能性是,我们仍然可以提供预定义的嵌入,但使其可训练,以便它将在模型训练时更新向量的值。

为了检查哪种方法执行得更好,我定义了一个简单的具有一个隐藏层的浅层神经网络。对于这个模型结构,我不会试图通过调整参数来优化模型,因为这篇文章的主要目的是实现 CNN。

from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers import Flatten
from keras.layers.embeddings import Embedding

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结果,最好的验证准确度来自第三种方法(微调预训练的 Word2Vec ),为 82.22%。训练准确率最好的是第二种方法(从零开始学习单词嵌入),为 90.52%。使用预先训练的 Word2Vec 而不更新其向量值在训练和验证中显示出最低的准确性。然而,有趣的是,在训练集准确性方面,微调预训练的词向量不能胜过通过嵌入层从头学习的词嵌入。在我尝试以上三种方法之前,我的第一个猜测是,如果我微调预先训练的词向量,它会给我最好的训练精度。

将预训练的单词向量馈送给嵌入层以进行更新,就像向嵌入层提供第一初始化准则,以便它可以更有效地学习特定于任务的单词向量。但结果有些违反直觉,在这种情况下,事实证明,最好强制嵌入层从头开始学习。

但是过早的概括可能是危险的。为此,我将在 CNN 的背景下再次比较三种方法。

卷积神经网络

您可能已经看到了卷积神经网络(CNN)如何处理图像数据。有很多好的资源可以让你学习 CNN 的基础知识。就我而言,Adit Deshpande 的博客文章“

Image courtesy of

machinelearninguru.com

在上面的 GIF 中,我们有一个 3X3 维的过滤器(核矩阵),对数据(图像矩阵)进行卷积,计算元素相乘结果的总和,并将结果记录在特征图上(输出矩阵)。如果我们想象每一行数据都是一个句子中的一个单词,那么它将不会有效地学习,因为过滤器一次只查看单词向量的一部分。上述 CNN 是所谓的 2D 卷积神经网络,因为滤波器在 2 维空间中移动。

我们对用词向量表示的文本数据所做的是利用 1D 卷积神经网络。如果过滤器的列宽与数据列宽相同,那么它没有空间横向跨越,只能纵向跨越。比如我们的句子用 45X200 矩阵表示,那么一个过滤器列宽也会有 200 列,行的长度(高度)就类似于 n-gram 的概念。如果过滤器高度为 2,过滤器将遍历文档,使用所有二元模型计算上述计算,如果过滤器高度为 3,它将遍历文档中的所有三元模型,依此类推。

如果应用步长为 1 到 45X200 矩阵的 2X200 滤波器,我们将得到 44X1 维的输出。在 1D 卷积的情况下,输出宽度在这种情况下将仅为 1(滤波器数量=1)。使用下面的公式可以很容易地计算出输出高度(假设您的数据已经被填充)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在哪里

h:输入数据高度

Fh:过滤器高度

学生:步幅大小

现在让我们尝试添加更多的过滤器到我们的 1D 卷积层。如果我们将 100 个步长为 1 的 2X200 滤镜应用于 45X200 矩阵,你能猜出输出维度吗?

正如我在上面已经提到的,现在输出宽度将反映我们应用的过滤器的数量,所以答案是我们将有 44X100 维输出。定义结构后,还可以通过查看模型摘要来检查每个输出层的尺寸。

from keras.layers import Conv1D, GlobalMaxPooling1D
structure_test = Sequential()
e = Embedding(100000, 200, input_length=45)
structure_test.add(e)
structure_test.add(Conv1D(filters=100, kernel_size=2, padding='valid', activation='relu', strides=1))
structure_test.summary()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,如果我们添加全局最大池层,那么池层将从每个过滤器中提取最大值,输出维度将是一个一维向量,长度与我们应用的过滤器数量相同。这可以直接传递到一个致密层上,无需展平。

structure_test = Sequential()
e = Embedding(100000, 200, input_length=45)
structure_test.add(e)
structure_test.add(Conv1D(filters=100, kernel_size=2, padding='valid', activation='relu', strides=1))
structure_test.add(GlobalMaxPooling1D())
structure_test.summary()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,让我们定义一个简单的 CNN 在一条 tweet 上遍历二元模型。来自全局最大池层的输出将被馈送到完全连接的层,最后是输出层。我将再次尝试三种不同的输入,从 Word2Vec 提取的静态单词向量,使用嵌入层从头开始学习单词嵌入,通过训练更新 Word2Vec 单词向量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最佳验证准确度来自通过训练更新的词向量,在第 3 时段,验证准确度为 83.25%。通过观察训练损失和准确度,似乎从零开始学习的单词嵌入倾向于过度适应训练数据,并且通过馈送预训练的单词向量作为权重初始化,它稍微更一般化并且最终具有更高的验证准确度。

但是终于!我有一个比 Tf-Idf + logistic 回归模型更好的结果!我已经用 Doc2Vec、Word2Vec 尝试了各种不同的方法,希望胜过使用 Tf-Idf 输入的简单逻辑回归模型。具体可以看看之前的帖子。Tf-Idf + logistic 回归模型的验证准确率为 82.91%。现在我终于开始看到 Word2Vec +神经网络优于这个简单模型的可能性。

让我们看看是否可以通过定义一个更精细的模型结构来做得更好。我将在下面实现的 CNN 架构的灵感来自于 Zhang,y .,& Wallace,b .(2015)“用于句子分类的卷积神经网络的灵敏度分析(和从业者指南”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image courtesy of Zhang, Y., & Wallace, B. (2015) “A Sensitivity Analysis of (and Practitioners’ Guide to) Convolutional Neural Networks for Sentence Classification

基本上,上面的结构实现了我们上面用二元模型过滤器所做的事情,但不仅仅是二元模型,还有三元模型和四元模型。然而,这不是线性堆叠的层,而是平行的层。在卷积层和最大池层之后,它简单地连接来自 bigram、trigram 和 fourgram 的最大池结果,然后在它们之上构建一个输出层。

我下面定义的模型基本上和上面的图片一样,但是不同的是,我在输出层之前添加了一个完全连接的隐藏层,并且我的输出层将只有一个 Sigmoid 激活的输出节点,而不是两个。

还有 Y. Kim(2014)的另一篇著名论文《用于句子分类的卷积神经网络》。https://arxiv.org/pdf/1408.5882.pdf

在这篇论文中,他利用“通道”概念实现了更复杂的方法。该模型不仅经历不同的 n 元语法,他的模型具有多通道(例如,一个通道用于静态输入单词向量,另一个通道用于单词向量输入,但是将它们设置为在训练期间更新)。但在这篇文章中,我不会通过多渠道的方法。

到目前为止,我只使用了 Keras 的顺序模型 API,这与我上面定义的所有以前的模型都很好,因为模型的结构只是线性堆叠的。但是正如你从上面的图片中看到的,我将要定义的模型有平行的层,这些层接受相同的输入,但是做它们自己的计算,然后结果将被合并。在这种神经网络结构中,我们可以使用 Keras functional API

Keras functional API 可以处理多输入多输出、共享层、共享输入等。用顺序 API 定义这些类型的模型不是不可以,但是当你想保存训练好的模型时,函数式 API 可以让你简单的保存模型并加载,但是用顺序 API 就很难了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

from keras.callbacks import ModelCheckpointfilepath="CNN_best_weights.{epoch:02d}-{val_acc:.4f}.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max')model.fit(x_train_seq, y_train, batch_size=32, epochs=5,
                     validation_data=(x_val_seq, y_validation), callbacks = [checkpoint])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

from keras.models import load_model
loaded_CNN_model = load_model('CNN_best_weights.02-0.8333.hdf5')
loaded_CNN_model.evaluate(x=x_val_seq, y=y_validation)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最佳验证准确率为 83.33%,略好于使用二元模型过滤器的简单 CNN 模型,后者产生 83.25%的验证准确率。我甚至可以定义一个具有更多隐藏层的更深结构,或者甚至利用 Yoon Kim(2014)实施的多通道方法,或者尝试不同的池大小以查看性能差异,但我现在就说到这里。然而,如果你碰巧尝试了更复杂的 CNN 结构,并得到了结果,我很乐意听到它。

使用测试集的最终模型评估

到目前为止,我已经在验证集上测试了模型,以决定特征提取调整和模型比较。现在我将最终用测试集检查最终结果。我将比较两种不同的模型:1 .Tf-Idf + logistic 回归,2。Word2Vec + CNN。作为比较的另一个衡量标准,我还将绘制两个模型的 ROC 曲线。

from sklearn.feature_extraction.text import TfidfVectorizer
tvec = TfidfVectorizer(max_features=100000,ngram_range=(1, 3))
tvec.fit(x_train)
x_train_tfidf = tvec.transform(x_train)
x_test_tfidf = tvec.transform(x_test)
lr_with_tfidf = LogisticRegression()
lr_with_tfidf.fit(x_train_tfidf,y_train)
yhat_lr = lr_with_tfidf.predict_proba(x_test_tfidf)
lr_with_tfidf.score(x_test_tfidf,y_test)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

sequences_test = tokenizer.texts_to_sequences(x_test)
x_test_seq = pad_sequences(sequences_test, maxlen=45)
yhat_cnn = loaded_CNN_model.predict(x_test_seq)
loaded_CNN_model.evaluate(x=x_test_seq, y=y_test)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后的结果如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

感谢您的阅读。你可以从下面的链接找到 Jupyter 笔记本。

https://github . com/tthustle sa/Twitter _ 情操 _ 分析 _ part 11/blob/master/Capstone _ part 11 . ipynb

另一个使用 Python 的 Twitter 情感分析——第 2 部分

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-2-333514854913?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这篇博文是我目前在伦敦大会上为我的顶点项目所做的 Twitter 情绪分析项目的第二部分。你可以在这里找到第一部

重新清理数据

在我继续学习 EDA 和数据可视化之前,我对数据清理部分做了一些修改,因为我在上一篇文章中定义的数据清理函数存在错误。

我意识到的第一个问题是,在清理过程中,否定词被分成两部分,当我过滤长度超过一个音节的标记时,撇号后面的“t”消失了。这使得像“不可以”这样的词最终和“可以”一样。对于情感分析来说,这似乎不是一件小事。

我意识到的第二个问题是,有些 url 链接不是以“http”开头的,有时人们会以“www.websitename.com”的形式粘贴链接。当我将 url 地址正则表达式模式定义为“https?😕/[A-Za-z0–9。/]+'.这种正则表达式模式的另一个问题是它只检测字母、数字、句点和斜杠。这意味着如果它包含任何其他特殊字符,如“=”、“_”、“~”等,它将无法捕获 url 的一部分。

第三个问题是 twitter ID 的 regex 模式。在之前的清理函数中,我将其定义为’ @[A-Za-z0–9]+',但是稍微用谷歌了一下,我发现 twitter ID 也允许下划线符号作为可以与 ID 一起使用的字符。除下划线符号外,只允许字母和数字字符。

下面是更新的数据清理功能。清洗的顺序是

  1. 增加马力
  2. 物料清单删除
  3. url 地址(’ http:'模式),twitter ID 删除
  4. url 地址(’ www。图案)移除
  5. 小写字母的
  6. 否定处理
  7. 删除数字和特殊字符
  8. 符号化和连接
**import** **pandas** **as** **pd**  
**import** **numpy** **as** **np**
**import** **matplotlib.pyplot** **as** **plt**
plt.style.use('fivethirtyeight')

%matplotlib inline
%config InlineBackend.figure_format = 'retina'**import** **re**
**from** **bs4** **import** BeautifulSoup
**from** **nltk.tokenize** **import** WordPunctTokenizer
tok = WordPunctTokenizer()

pat1 = r'@[A-Za-z0-9_]+'
pat2 = r'https?://[^ ]+'
combined_pat = r'|'.join((pat1, pat2))
www_pat = r'www.[^ ]+'
negations_dic = {"isn't":"is not", "aren't":"are not", "wasn't":"was not", "weren't":"were not",
                "haven't":"have not","hasn't":"has not","hadn't":"had not","won't":"will not",
                "wouldn't":"would not", "don't":"do not", "doesn't":"does not","didn't":"did not",
                "can't":"can not","couldn't":"could not","shouldn't":"should not","mightn't":"might not",
                "mustn't":"must not"}
neg_pattern = re.compile(r'\b(' + '|'.join(negations_dic.keys()) + r')\b')

**def** tweet_cleaner_updated(text):
    soup = BeautifulSoup(text, 'lxml')
    souped = soup.get_text()
    **try**:
        bom_removed = souped.decode("utf-8-sig").replace(u"**\ufffd**", "?")
    **except**:
        bom_removed = souped
    stripped = re.sub(combined_pat, '', bom_removed)
    stripped = re.sub(www_pat, '', stripped)
    lower_case = stripped.lower()
    neg_handled = neg_pattern.sub(**lambda** x: negations_dic[x.group()], lower_case)
    letters_only = re.sub("[^a-zA-Z]", " ", neg_handled)
    *# During the letters_only process two lines above, it has created unnecessay white spaces,*
    *# I will tokenize and join together to remove unneccessary white spaces*
    words = [x **for** x  **in** tok.tokenize(letters_only) **if** len(x) > 1]
    **return** (" ".join(words)).strip()

更新清理函数后,我重新清理了数据集中的全部 160 万个条目。你可以从我的上一篇中找到清洁过程的细节。

清理之后,我将清理后的数据导出为 csv 格式,然后加载为数据框,如下图所示。

csv = 'clean_tweet.csv'
my_df = pd.read_csv(csv,index_col=0)
my_df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

my_df.info()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据中似乎有一些空条目,让我们进一步调查。

my_df[my_df.isnull().any(axis=1)].head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

np.sum(my_df.isnull().any(axis=1))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

my_df.isnull().any(axis=0)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

似乎有 3981 个条目的文本列为空。这很奇怪,因为原始数据集没有空条目,因此如果清理后的数据集中有任何空条目,那一定是在清理过程中发生的。

df = pd.read_csv("./trainingandtestdata/training.1600000.processed.noemoticon.csv",header=None)
df.iloc[my_df[my_df.isnull().any(axis=1)].index,:].head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过查看原始数据中的这些条目,似乎只有文本信息,要么是 twitter ID,要么是 url 地址。无论如何,这些是我决定为情感分析丢弃的信息,所以我将丢弃这些空行,并更新数据框。

my_df.dropna(inplace=True)
my_df.reset_index(drop=True,inplace=True)
my_df.info()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

词云

我选择的第一个文本视觉化是有争议的单词 cloud。词云通过根据单个词的频率成比例地调整其大小,然后以随机排列的方式呈现它们,来表示词在文档中的用法。围绕 word cloud 有很多争论,我有点同意那些反对使用 word cloud 作为数据分析的人的观点。对 word cloud 的一些担忧是,它仅支持最粗略的文本分析,并且它通常应用于文本分析不合适的情况,并且它让查看者自己找出数据的上下文,而不提供叙述。

但是在推文的情况下,文本分析是最重要的分析,它以一种快速和肮脏的方式提供了关于什么样的词在语料库中频繁出现的一般想法。所以,我将试一试,并找出还有哪些方法可以用于文本可视化。

对于 wordcloud,我使用了 python 库 word cloud。

neg_tweets = my_df[my_df.target == 0]
neg_string = []
**for** t **in** neg_tweets.text:
    neg_string.append(t)
neg_string = pd.Series(neg_string).str.cat(sep=' ')**from** **wordcloud** **import** WordCloud

wordcloud = WordCloud(width=1600, height=800,max_font_size=200).generate(neg_string)
plt.figure(figsize=(12,10))
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有些大词可以被解释成中性词,如“今天”、“现在”等。我可以看到一些较小的单词在负面推文中是有意义的,比如“该死”、“啊”、“小姐”、“坏”等等。但是有“爱”在相当大的尺寸,所以我想看看发生了什么。

**for** t **in** neg_tweets.text[:200]:
    **if** 'love' **in** t:
        **print** t

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好吧,即使推文包含“爱”这个词,在这些情况下,它是负面情绪,因为推文混合了像“爱”但“想念”这样的情绪。或者有时以讽刺的方式使用。

pos_tweets = my_df[my_df.target == 1]
pos_string = []
**for** t **in** pos_tweets.text:
    pos_string.append(t)
pos_string = pd.Series(pos_string).str.cat(sep=' ')wordcloud = WordCloud(width=1600, height=800,max_font_size=200,colormap='magma').generate(pos_string) plt.figure(figsize=(12,10)) plt.imshow(wordcloud, interpolation="bilinear") plt.axis("off") plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我又一次看到一些自然的大字体单词,“今天”、“现在”,但是像“哈哈”、“爱”、“棒极了”这样的单词也很突出。

有趣的是,“工作”这个词在负面词云中相当大,但在正面词云中也相当大。这可能意味着许多人表达了对工作的负面情绪,但也有许多人对工作持积极态度。

为更多数据可视化做准备

为了让我在下一步实现一些数据可视化,我需要词频数据。推文中使用了什么样的词,以及在整个语料库中使用了多少次。我使用计数矢量器来计算术语频率,尽管计数矢量器也用于拟合、训练和预测,但在这个阶段,我将只提取术语频率进行可视化。

计数矢量器有一些可用的参数选项,例如移除停用词、限制最大项数。然而,为了首先获得数据集的全貌,我实现了包含停用词,并且不限制最大术语数。

**from** **sklearn.feature_extraction.text** **import** CountVectorizer
cvec = CountVectorizer()
cvec.fit(my_df.text)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

len(cvec.get_feature_names())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好了,看起来计数矢量器已经从语料库中提取了 264,936 个单词。

!重要更新(10/01/2018) :我刚刚意识到,我不必经历我下面做的所有批处理。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

是啊!我下面做的所有批处理和计算都可以用少得多的代码行来完成(虽然不完全是一行)。一旦使用拟合的计数矢量器转换数据,就可以直接从稀疏矩阵中获得术语频率。而这一切都可以在不到一秒的时间内完成!如果你看了下面,你会发现我花了将近 40 分钟才得到术语频率表。我想我用最艰难的方式学到了这一课。直接从稀疏矩阵中获得频率项的代码如下。

neg_doc_matrix = cvec.transform(my_df[my_df.target == 0].text)
pos_doc_matrix = cvec.transform(my_df[my_df.target == 1].text)
neg_tf = np.sum(neg_doc_matrix,axis=0)
pos_tf = np.sum(pos_doc_matrix,axis=0)
neg = np.squeeze(np.asarray(neg_tf))
pos = np.squeeze(np.asarray(pos_tf))
term_freq_df = pd.DataFrame([neg,pos],columns=cvec.get_feature_names()).transpose()

我将在下面留下我最初写的,作为对我自己愚蠢的提醒。这个故事的寓意是,如果你可以直接用稀疏矩阵工作,你绝对应该不用转换成密集矩阵!

对于下面的部分,我不得不经历许多试验和错误,因为内存使用超载。如果代码需要时间来实现,但仍然在运行,这是可以的,但这不是块运行多长时间的问题,我的 mac book pro 只是简单地放弃了,要么杀死内核,要么冻结。经过无数次尝试,我终于成功地批量处理了数据。

我一直犯的错误是,当我分割文档矩阵时,我试图在’ document _ matrix . to array()[start _ index,end_index]‘中分割它,我最终意识到,因为我试图首先将整个 documnet_matrix 转换为数组,然后从那里分割,无论我如何更改批处理大小,我可怜的 macbook pro 都无法处理请求。在我将切片更改为’ document_matrix[start_index,end_index]之后。toarray()',我的 mac book pro 为我做了一件非常棒的工作。

此外,在处理以下任务的过程中,您的 mac book 可以在寒冷的冬天成为一个出色的取暖设备。在亚洲,我们称之为“一石二鸟”。不客气

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Cats are the best at finding warm spots in winter!

document_matrix = cvec.transform(my_df.text)
my_df[my_df.target == 0].tail()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

%%time
neg_batches = np.linspace(0,798179,100).astype(int)
i=0
neg_tf = []
**while** i < len(neg_batches)-1:
    batch_result = np.sum(document_matrix[neg_batches[i]:neg_batches[i+1]].toarray(),axis=0)
    neg_tf.append(batch_result)
    **if** (i % 10 == 0) | (i == len(neg_batches)-2):
        **print** neg_batches[i+1],"entries' term freuquency calculated"
    i += 1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

my_df.tail()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

%%time
pos_batches = np.linspace(798179,1596019,100).astype(int)
i=0
pos_tf = []
**while** i < len(pos_batches)-1:
    batch_result = np.sum(document_matrix[pos_batches[i]:pos_batches[i+1]].toarray(),axis=0)
    pos_tf.append(batch_result)
    **if** (i % 10 == 0) | (i == len(pos_batches)-2):
        **print** pos_batches[i+1],"entries' term freuquency calculated"
    i += 1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

neg = np.sum(neg_tf,axis=0)
pos = np.sum(pos_tf,axis=0)
term_freq_df = pd.DataFrame([neg,pos],columns=cvec.get_feature_names()).transpose()
term_freq_df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

term_freq_df.columns = ['negative', 'positive']
term_freq_df['total'] = term_freq_df['negative'] + term_freq_df['positive']
term_freq_df.sort_values(by='total', ascending=False).iloc[:10]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好了,术语频率数据框已经创建好了!正如你所看到的,最常见的单词都是停用词,如“to”、“the”等。你可能想知道为什么要经历所有繁重的处理,而不删除停用词,也不限制最大词数,以获得停用词占主导地位的词频率?因为我真的很想用上面得到的结果来检验齐夫定律。我需要停止字!你会明白我的意思。

我会在下一篇文章中告诉你更多关于齐夫定律的内容,我保证会有更多的可视化。你会发现上面的频率计算并不是毫无意义的。

和往常一样,你可以从下面的链接找到 Jupyter 笔记本。

https://github . com/tthustle sa/Twitter _ 情操 _ 分析 _ part 2/blob/master/Capstone _ part 3-copy 1 . ipynb

另一个使用 Python 的 Twitter 情感分析——第 3 部分(Zipf 定律,数据可视化)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-3-zipfs-law-data-visualisation-fc9eadda71e7?source=collection_archive---------2-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Samuel Ramos on Unsplash

这是 Twitter 情绪分析项目的第三部分,我目前正在为伦敦大会的数据科学沉浸式课程做准备。你可以在下面找到之前文章的链接。

[## 另一个使用 Python 的 Twitter 情感分析—第 1 部分

距离我上次发帖已经有一段时间了。我不在灵媒期间,我的生活发生了很多事情。我终于收集了我的…

towardsdatascience.com](/another-twitter-sentiment-analysis-bb5b01ebad90) [## 另一个使用 Python 的 Twitter 情感分析——第 2 部分

这篇博文是我目前正在为我的顶点计划做的 Twitter 情绪分析项目的第二部分…

medium.com](https://medium.com/@rickykim78/another-twitter-sentiment-analysis-with-python-part-2-333514854913)

在第二篇博文的末尾,我创建了一个词频数据框架,看起来像这样。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些索引是来自 tweets 数据集的令牌(“sentitement 140”),而“负”和“正”列中的数字表示该令牌在负推和正推中出现的次数。

齐夫定律

齐夫定律首先由法国速记员让·巴普蒂斯特·埃斯图普提出,后来以美国语言学家乔治·金斯利·齐夫的名字命名。齐夫定律指出,一小部分单词一直在使用,而绝大多数很少使用。这没什么好奇怪的,我们知道我们非常频繁地使用一些词,如“the”、“of”等,而我们很少使用像“aardvark”这样的词(aardvark 是一种原产于非洲的动物物种)。然而,有趣的是,“给定一些自然语言话语的语料库,任何单词的频率都与其在频率表中的排名成反比。因此,最频繁出现的单词的出现频率大约是第二频繁出现的单词的两倍,第三频繁出现的单词的三倍,等等

如果你想更多地了解齐夫定律,我推荐下面的 Youtube 视频。

Zipf 定律可以写成如下形式:第 r 个最频繁出现的单词的频率 f®与下式成比例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们看看 tweet 标记和它们的频率在图上是什么样子的。

y_pos = np.arange(500)
plt.figure(figsize=(10,8))
s = 1
expected_zipf = [term_freq_df.sort_values(by='total', ascending=False)['total'][0]/(i+1)**s for i in y_pos]
plt.bar(y_pos, term_freq_df.sort_values(by='total', ascending=False)['total'][:500], align='center', alpha=0.5)
plt.plot(y_pos, expected_zipf, color='r', linestyle='--',linewidth=2,alpha=0.5)
plt.ylabel('Frequency')
plt.title('Top 500 tokens in tweets')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 X 轴上是频率的等级,从左到右从最高等级到第 500 等级。y 轴是在语料库中观察到的频率(在本例中为“Sentiment140”数据集)。需要注意的一点是,大多数情况下的实际观测值并不严格遵循 Zipf 分布,而是遵循一种“近似 Zipfian”分布的趋势。

尽管我们可以看到该图遵循 Zipf 定律的趋势,但在排名较高的单词中,它看起来有更多的区域在预期的 Zipf 曲线之上。

另一种绘制方式是在对数-对数图上,X 轴是对数(等级),Y 轴是对数(频率)。通过在双对数标度上绘图,结果将在图上产生大致线性的线。

from pylab import *
counts = term_freq_df.total
tokens = term_freq_df.index
ranks = arange(1, len(counts)+1)
indices = argsort(-counts)
frequencies = counts[indices]
plt.figure(figsize=(8,6))
plt.ylim(1,10**6)
plt.xlim(1,10**6)
loglog(ranks, frequencies, marker=".")
plt.plot([1,frequencies[0]],[frequencies[0],1],color='r')
title("Zipf plot for tweets tokens")
xlabel("Frequency rank of token")
ylabel("Absolute frequency of token")
grid(True)
for n in list(logspace(-0.5, log10(len(counts)-2), 25).astype(int)):
    dummy = text(ranks[n], frequencies[n], " " + tokens[indices[n]], 
                 verticalalignment="bottom",
                 horizontalalignment="left")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们再次看到一条大致线性的曲线,但是在较高等级的单词上偏离了预期的线,并且在较低等级,我们看到实际的观察线位于预期的线性线之下。

至少,我们证明了即使是 tweet 令牌也遵循“近似 Zipfian”分布,但这让我对 Zipf 定律的偏离产生了好奇。即使法律本身规定实际观察遵循“近齐夫曼”而不是严格受法律约束,但我们在更高等级中观察到的预期线以上的区域只是偶然吗?还是说 tweets 比其他文本语料库更多地使用了频繁词?与其他文本语料库相比,有统计学上的显著差异吗?

尽管所有这些听起来像是非常有趣的研究课题,但它超出了这个项目的范围,我将不得不转向数据可视化的下一步。

Tweet 令牌可视化

在了解了标记在整个语料库中的分布之后,我脑海中的下一个问题是两个不同类别(积极和消极)中的标记有何不同。这一次,停用词不会有太大帮助,因为相同的高频词(如“the”、“to”)在两个类中会同样频繁地出现。如果这两个类都被停用词支配,我就不能得到有意义的结果。因此,我决定删除停用词,并用 countvectorizer 将 max_features 限制为 10,000。

我不会重复计数矢量化的步骤,因为在我之前的博客文章中已经以类似的方式完成了。但是它将会在我的 Jupyter 笔记本上,我会在这篇文章的最后分享。总之,在计数矢量化之后,我们现在有了 10,000 个没有停用词的标记的标记频率数据,如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们来看看条形图上负面推文的前 50 个词是什么。

y_pos = np.arange(50)
plt.figure(figsize=(12,10))
plt.bar(y_pos, term_freq_df2.sort_values(by='negative', ascending=False)['negative'][:50], align='center', alpha=0.5)
plt.xticks(y_pos, term_freq_df2.sort_values(by='negative', ascending=False)['negative'][:50].index,rotation='vertical')
plt.ylabel('Frequency')
plt.xlabel('Top 50 negative tokens')
plt.title('Top 50 tokens in negative tweets')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

即使前 50 名的一些标记可以提供一些关于负面推文的信息,一些中性词,如“只是”,“天”,是最常见的标记之一。尽管这些是真正的高频词,但很难说这些词都是负面推特中的重要词,这些负面推特描述了负面阶层的特征。

让我们也来看看条形图上的前 50 个积极标志。

y_pos = np.arange(50)
plt.figure(figsize=(12,10))
plt.bar(y_pos, term_freq_df2.sort_values(by='positive', ascending=False)['positive'][:50], align='center', alpha=0.5)
plt.xticks(y_pos, term_freq_df2.sort_values(by='positive', ascending=False)['positive'][:50].index,rotation='vertical')
plt.ylabel('Frequency')
plt.xlabel('Top 50 positive tokens')
plt.title('Top 50 tokens in positive tweets')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同样,中性词如“只是”,“天”,在排名中相当靠前。

如果我们把一个单词的负频率标在 X 轴上,正频率标在 Y 轴上,会怎么样呢?

import seaborn as sns
plt.figure(figsize=(8,6))
ax = sns.regplot(x="negative", y="positive",fit_reg=False, scatter_kws={'alpha':0.5},data=term_freq_df2)
plt.ylabel('Positive Frequency')
plt.xlabel('Negative Frequency')
plt.title('Negative Frequency vs Positive Frequency')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

大部分词在 X 轴和 Y 轴上都在 10000 以下,看不出正负频率有什么有意义的关系。

为了提出一个有意义的度量标准,可以表征每个类别中的重要标志,我借用了 Jason Kessler 在 PyData 2017 Seattle 中提出的度量标准。在演讲中,他展示了一个名为 Scattertext 的 Python 库。尽管我没有使用这个库,但作为一种可视化文本数据的方式,在从频率数据中过滤有意义的符号时,在散点图中使用的度量是非常有用的。

让我们探索一下我们能从每个令牌的频率中得到什么。直观地说,如果一个单词在一个类中比另一个类中出现得更频繁,这可以很好地衡量该单词对描述该类有多大意义。在下面的代码中,我将其命名为“pos_rate ”,正如您从代码的计算中可以看到的,这被定义为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

term_freq_df2['pos_rate'] = term_freq_df2['positive'] * 1./term_freq_df2['total']
term_freq_df2.sort_values(by='pos_rate', ascending=False).iloc[:10]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

pos_rate 最高的词在负面推文中的频率为零,但这些词的整体频率太低,不能将其作为正面推文的指导原则。

另一个指标是一个单词在课堂上出现的频率。这被定义为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

term_freq_df2['pos_freq_pct'] = term_freq_df2['positive'] * 1./term_freq_df2['positive'].sum()
term_freq_df2.sort_values(by='pos_freq_pct', ascending=False).iloc[:10]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但由于 pos_freq_pct 只是频率总和的比例,因此 pos_freq_pct 的等级与正频率完全相同。

我们现在可以做的是将 pos_rate、pos_freq_pct 组合在一起,得出一个既反映 pos_rate 又反映 pos_freq_pct 的指标。尽管这两个值的取值范围都是从 0 到 1,但 pos_rate 的取值范围实际上要宽得多,从 0 到 1,而所有 pos_freq_pct 值都被压缩在小于 0.015 的范围内。如果我们对这两个数字进行平均,pos_rate 将过于占优势,并且不会有效地反映这两个指标。

所以这里我们用调和平均值代替算术平均值。由于数字列表的调和平均值强烈倾向于列表中最少的元素,因此(与算术平均值相比)它倾向于减轻较大异常值的影响,并加重较小异常值的影响正实数 x1,x2,…xn 的调和平均值 H 定义为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

from scipy.stats import hmeanterm_freq_df2['pos_hmean'] = term_freq_df2.apply(lambda x: (hmean([x['pos_rate'], x['pos_freq_pct']])                                                               if x['pos_rate'] > 0 and x['pos_freq_pct'] > 0 else 0), axis=1)

term_freq_df2.sort_values(by='pos_hmean', ascending=False).iloc[:10]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

调和平均秩似乎与 pos_freq_pct 相同。通过计算谐波平均值,小值(在这种情况下,pos_freq_pct)的影响过于严重,最终主导了平均值。这同样与频率值排名完全相同,并没有提供多少有意义的结果。

接下来我们可以尝试的是获得 pos_rate 和 pos_freq_pct 的 CDF(累积分布函数)值。CDF 可以解释为“X 的分布函数,在 X 处取值,是 X 取值小于等于 X 的概率”。通过计算 CDF 值,我们可以看到 pos_rate 或 pos_freq_pct 的值在累积方式分布中的位置。在下面的代码结果中,我们可以看到单词“welcome”的 pos_rate_normcdf 为 0.995625,pos_freq_pct_normcdf 为 0.999354。这意味着大约 99.56%的令牌将采用小于或等于 0.91535 的 pos_rate 值,99.99%的令牌将采用小于或等于 0.001521 的 pos_freq_pct 值。

接下来,我们像前面一样计算这两个 CDF 值的调和平均值。通过计算调和平均值,我们可以看到,pos_normcdf_hmean 度量提供了一个更有意义的方法来衡量一个单词在类中的重要性。

from scipy.stats import normdef normcdf(x):
    return norm.cdf(x, x.mean(), x.std())term_freq_df2['pos_rate_normcdf'] = normcdf(term_freq_df2['pos_rate'])term_freq_df2['pos_freq_pct_normcdf'] = normcdf(term_freq_df2['pos_freq_pct'])term_freq_df2['pos_normcdf_hmean'] = hmean([term_freq_df2['pos_rate_normcdf'], term_freq_df2['pos_freq_pct_normcdf']])term_freq_df2.sort_values(by='pos_normcdf_hmean',ascending=False).iloc[:10]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下一步是对每个单词的负频率进行同样的计算。

term_freq_df2['neg_rate'] = term_freq_df2['negative'] * 1./term_freq_df2['total']term_freq_df2['neg_freq_pct'] = term_freq_df2['negative'] * 1./term_freq_df2['negative'].sum()term_freq_df2['neg_hmean'] = term_freq_df2.apply(lambda x: (hmean([x['neg_rate'], x['neg_freq_pct']])                                                                if x['neg_rate'] > 0 and x['neg_freq_pct'] > 0                                                                else 0), axis=1)

term_freq_df2['neg_rate_normcdf'] = normcdf(term_freq_df2['neg_rate'])term_freq_df2['neg_freq_pct_normcdf'] = normcdf(term_freq_df2['neg_freq_pct'])term_freq_df2['neg_normcdf_hmean'] = hmean([term_freq_df2['neg_rate_normcdf'], term_freq_df2['neg_freq_pct_normcdf']])term_freq_df2.sort_values(by='neg_normcdf_hmean', ascending=False).iloc[:10]

现在让我们看看这些值是如何转换成一个图的。为了比较,我先画出 neg_hmean vs pos_hmean,以及 neg _ normcdf _ hme an vs pos _ normcdf _ hme an。

plt.figure(figsize=(8,6))
ax = sns.regplot(x="neg_hmean", y="pos_hmean",fit_reg=False, scatter_kws={'alpha':0.5},data=term_freq_df2)
plt.ylabel('Positive Rate and Frequency Harmonic Mean')
plt.xlabel('Negative Rate and Frequency Harmonic Mean')
plt.title('neg_hmean vs pos_hmean')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

和刚才的正反频率差不了多少。CDF 调和平均值怎么样?

plt.figure(figsize=(8,6))
ax = sns.regplot(x="neg_normcdf_hmean", y="pos_normcdf_hmean",fit_reg=False, scatter_kws={'alpha':0.5},data=term_freq_df2)
plt.ylabel('Positive Rate and Frequency CDF Harmonic Mean')
plt.xlabel('Negative Rate and Frequency CDF Harmonic Mean')
plt.title('neg_normcdf_hmean vs pos_normcdf_hmean')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

似乎速率 CDF 和频率 CDF 的调和平均值在图上创建了一个有趣的模式。如果一个数据点靠近左上角,它更为积极,如果靠近右下角,它更为消极。

这是一个很好的指标,它从频率中创造了一些有意义的洞察力,但是对于文本数据,将每个标记显示为一个点缺少关于每个数据点代表哪个标记的重要信息。对于 10,000 个点,很难在图上标注所有的点。对于这一部分,我尝试了几种方法,得出的结论是,直接在图上标注数据点不是很实际,也不太可行。

所以我采取了另一种方法,用散景进行交互式绘图。Bokeh 是 Python 的一个交互式可视化库,它以 D3.js 的风格创建图形。Bokeh 可以以 HTML 格式输出结果,也可以在 Jupyter 笔记本中输出结果。而下面是散景创造的剧情。

from bokeh.plotting import figure
from bokeh.io import output_notebook, show
from bokeh.models import LinearColorMapper
from bokeh.models import HoverTooloutput_notebook()
color_mapper = LinearColorMapper(palette='Inferno256', low=min(term_freq_df2.pos_normcdf_hmean), high=max(term_freq_df2.pos_normcdf_hmean))p = figure(x_axis_label='neg_normcdf_hmean', y_axis_label='pos_normcdf_hmean')p.circle('neg_normcdf_hmean','pos_normcdf_hmean',size=5,alpha=0.3,source=term_freq_df2,color={'field': 'pos_normcdf_hmean', 'transform': color_mapper})hover = HoverTool(tooltips=[('token','[@index](http://twitter.com/index)')])
p.add_tools(hover)
show(p)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由于互动图不能插入到 Medium post 中,我附上了一张图片,但不知何故散景图也不能在 GitHub 上显示。所以我把这个分享给你可以访问的链接。

[## 散景图

s3.eu-west-2.amazonaws.com](https://s3.eu-west-2.amazonaws.com/ricksimages/hover.html)

有了上面的散景图,你可以通过将鼠标悬停在点上来查看每个数据点代表什么。例如,左上角的点表示“感谢”、“欢迎”、“祝贺”等。右下角的一些记号是“悲伤”、“伤害”、“死亡”、“疼痛”等等。而且每个点的颜色都是在 Python 中的“Inferno256”颜色图中组织的,所以黄色是最正的,而黑色是最负的,颜色随着从负到正逐渐从黑到紫到橙再到黄。

根据我稍后将使用哪个模型来对正面和负面推文进行分类,这个度量也可以派上用场。

项目的下一阶段是模型制作。在这种情况下,分类器会将每条推文分为正面或负面类别。我会继续通过媒体分享我的进步。

感谢您的阅读,您可以从下面的链接找到 Jupyter 笔记本。

https://github . com/tthustle sa/Twitter _ 情操 _ 分析 _ part 3/blob/master/Capstone _ part 3-copy 2 . ipynb

使用 Python 的另一个 Twitter 情感分析—第 4 部分(计数矢量器、混淆矩阵)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-4-count-vectorizer-b3f4944e51b5?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Souvik Banerjee on Unsplash

这是我正在进行的 Twitter 情绪分析项目的第 4 部分。你可以从下面的链接找到以前的帖子。

[## 另一个使用 Python 的 Twitter 情感分析——第 3 部分(Zipf 定律,数据可视化)

这是我目前正在做的 Twitter 情绪分析项目的第三部分,作为通用…

towardsdatascience.com](/another-twitter-sentiment-analysis-with-python-part-3-zipfs-law-data-visualisation-fc9eadda71e7) [## 另一个使用 Python 的 Twitter 情感分析——第 2 部分

这篇博文是我目前正在为我的顶点计划做的 Twitter 情绪分析项目的第二部分…

towardsdatascience.com](/another-twitter-sentiment-analysis-with-python-part-2-333514854913) [## 另一个使用 Python 的 Twitter 情感分析—第 1 部分

距离我上次发帖已经有一段时间了。我不在灵媒期间,我的生活发生了很多事情。我终于收集了我的…

towardsdatascience.com](/another-twitter-sentiment-analysis-bb5b01ebad90)

在第 3 部分,我主要关注 EDA 和数据可视化,现在是时候为模型构建做准备了!

培训/开发/测试分割

在我们可以训练任何模型之前,我们首先考虑如何拆分数据。这里我选择将数据分成三个部分:训练、开发、测试。我参考了吴恩达关于如何拆分数据的“ deeplearning.ai ”课程。

  • 训练集:用于学习的数据样本
  • 开发集(保留交叉验证集):用于调整分类器参数的数据样本,并提供模型的无偏评估。
  • 测试集:仅用于评估最终模型性能的数据样本。

我决定分割数据的比例是 98/1/1,98%的数据作为训练集,1%用于开发集,最后 1%用于测试集。这个比率背后的基本原理来自于我的整个数据集的大小。该数据集有超过 150 万个条目。在这种情况下,整个数据中只有 1%给了我 15000 多个条目。这对于评估模型和优化参数来说绰绰有余。

另一种方法是将数据分为训练集和测试集,并在训练集上运行 k-fold 交叉验证,这样就可以对模型进行无偏见的评估。但是考虑到数据的大小,我决定只使用训练集来训练一个模型,并在 dev 集上进行评估,这样我就可以快速测试不同的算法,并迭代地运行这个过程。

如果你想更详细地了解用于建模的数据分割,我推荐一篇来自“机器学习大师”的博客文章。该博客有大量关于数据科学广泛主题的文章,强烈推荐。

一旦我加载了清理过的 tweets 数据集,我运行如下的数据分割。注意,我已经将数据拆分了两次,第一次拆分了 train 和 dev+test,第二次拆分了 dev 和 test。

x = my_df.text
y = my_df.target
from sklearn.cross_validation import train_test_split
SEED = 2000x_train, x_validation_and_test, y_train, y_validation_and_test = train_test_split(x, y, test_size=.02, random_state=SEED)x_validation, x_test, y_validation, y_test = train_test_split(x_validation_and_test, y_validation_and_test, test_size=.5, random_state=SEED)print "Train set has total {0} entries with {1:.2f}% negative, {2:.2f}% positive".format(len(x_train),                                                                     (len(x_train[y_train == 0]) / (len(x_train)*1.))*100,                                                                           (len(x_train[y_train == 1]) / (len(x_train)*1.))*100)print "Validation set has total {0} entries with {1:.2f}% negative, {2:.2f}% positive".format(len(x_validation),                                                                          (len(x_validation[y_validation == 0]) / (len(x_validation)*1.))*100,                                                                       (len(x_validation[y_validation == 1]) / (len(x_validation)*1.))*100)print "Test set has total {0} entries with {1:.2f}% negative, {2:.2f}% positive".format(len(x_test),                                                          (len(x_test[y_test == 0]) / (len(x_test)*1.))*100,                                                           (len(x_test[y_test == 1]) / (len(x_test)*1.))*100)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基线

在比较各种机器学习算法时,baseline 提供了一个比较的参考点。最流行的基线是零规则(ZeroR) 。ZeroR 分类器简单地预测多数类别(类)。尽管在 ZeroR 中没有可预测性,但它对于确定基线性能作为其他分类方法的基准是有用的。从上面的验证集类划分可以看出,多数类为负,为 50.40%,这意味着如果一个分类器对每个验证数据都预测为负,那么它将获得 50.40%的准确率。

我想比较验证结果的另一个基线是 T extBlob 。TextBlob 是一个用于处理文本数据的 python 库。除了其他有用的工具,如词性标注,n-gram,该软件包内置了情感分类。这是一个所谓的开箱即用的情感分析工具,除了零精度之外,我还会记住我从 TextBlob 情感分析中获得的精度,以查看我的模型表现如何。

from textblob import TextBlob
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report, confusion_matrixtbresult = [TextBlob(i).sentiment.polarity for i in x_validation]
tbpred = [0 if n < 0 else 1 for n in tbresult]conmat = np.array(confusion_matrix(y_validation, tbpred, labels=[1,0]))confusion = pd.DataFrame(conmat, index=['positive', 'negative'],
                         columns=['predicted_positive','predicted_negative'])print "Accuracy Score: {0:.2f}%".format(accuracy_score(y_validation, tbpred)*100)
print "-"*80
print "Confusion Matrix\n"
print confusion
print "-"*80
print "Classification Report\n"
print classification_report(y_validation, tbpred)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

TextBlob 情感分析在验证集上产生 60.65%的准确度,这比空准确度(50.40%)高 10.25%。

特征抽出

如果我们想在机器学习算法中使用文本,我们必须将它们转换成数字表示。其中一种方法叫做单词袋法。单词袋模型忽略了语法和单词的顺序。一旦我们有了一个语料库(文本数据),那么首先,基于整个语料库创建一个词汇表。然后,基于从语料库建立的词汇,每个文档或数据条目被表示为数字向量。

计数矢量器

使用计数矢量器,我们仅仅计算每个文本中单词的出现次数。例如,假设我们在一个语料库中有 3 个文档:“我爱狗”、“我讨厌狗和编织”、“编织是我的爱好和激情”。如果我们从这三个句子中构建词汇,并将每个文档表示为计数向量,它将如下图所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是如果语料库的规模变大,词汇的数量就会变得太大而无法处理。以我的 150 万条推文,如果不限制词汇量的话,我的词汇量将超过 26 万。这意味着训练数据的形状将在 1,500,000 x 260,000 左右,这听起来太大了,无法训练各种不同的模型。所以我决定限制词汇表的数量,但是我也想看看性能如何随着词汇表数量的不同而变化。

我想探索的另一件事是停用词。停用词是不包含重要意义的词,如“the”、“of”等。人们通常认为,删除停用词是一个必要的步骤,将提高模型性能。但是我想亲眼看看这是不是真的。所以我在有和没有停用词的情况下做了同样的测试,并比较了结果。此外,我还定义了自己的自定义停用词表,其中包含了语料库中最常用的 10 个词:" to “、” the “、” my “、” it “、” and “、” you “、” not “、” is “、” In “、” for "。

我选择的评估不同计数向量的模型是逻辑回归。与 KNN 或随机森林等模型相比,它是一种线性模型,因此在计算上可扩展到大数据。一旦我有了最佳数量的特征,并决定是否删除停用词,那么我将使用所选数量的词汇计数向量尝试不同的模型。

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from time import time

下面我定义了两个函数来迭代训练不同数量的特征,然后检查验证集上逻辑回归的准确性。

def accuracy_summary(pipeline, x_train, y_train, x_test, y_test):
    if len(x_test[y_test == 0]) / (len(x_test)*1.) > 0.5:
        null_accuracy = len(x_test[y_test == 0]) / (len(x_test)*1.)
    else:
        null_accuracy = 1\. - (len(x_test[y_test == 0]) / (len(x_test)*1.))
    t0 = time()
    sentiment_fit = pipeline.fit(x_train, y_train)
    y_pred = sentiment_fit.predict(x_test)
    train_test_time = time() - t0
    accuracy = accuracy_score(y_test, y_pred)
    print "null accuracy: {0:.2f}%".format(null_accuracy*100)
    print "accuracy score: {0:.2f}%".format(accuracy*100)
    if accuracy > null_accuracy:
        print "model is {0:.2f}% more accurate than null accuracy".format((accuracy-null_accuracy)*100)
    elif accuracy == null_accuracy:
        print "model has the same accuracy with the null accuracy"
    else:
        print "model is {0:.2f}% less accurate than null accuracy".format((null_accuracy-accuracy)*100)
    print "train and test time: {0:.2f}s".format(train_test_time)
    print "-"*80
    return accuracy, train_test_timecvec = CountVectorizer()
lr = LogisticRegression()
n_features = np.arange(10000,100001,10000)def nfeature_accuracy_checker(vectorizer=cvec, n_features=n_features, stop_words=None, ngram_range=(1, 1), classifier=lr):
    result = []
    print (classifier)
    print "\n"
    for n in n_features:
        vectorizer.set_params(stop_words=stop_words, max_features=n, ngram_range=ngram_range)
        checker_pipeline = Pipeline([
            ('vectorizer', vectorizer),
            ('classifier', classifier)
        ])
        print "Validation result for {} features".format(n)
        nfeature_accuracy,tt_time = accuracy_summary(checker_pipeline, x_train, y_train, x_validation, y_validation)
        result.append((n,nfeature_accuracy,tt_time))
    return result

然后,我通过调用上面定义的“nfeature_accuracy_checker”来检查不同数量的特性的有效性。此外,我定义了前 10 个常用术语的自定义停用词来比较结果。注意,‘term _ freq _ df . CSV’是我用语料库从项目的前一部分创建的文件。

csv = 'term_freq_df.csv'
term_freq_df = pd.read_csv(csv,index_col=0)
term_freq_df.sort_values(by='total', ascending=False).iloc[:10]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

只是为了仔细检查这 10 个单词是否真的包含在 SKLearn 的停用单词列表中,我运行了如下的小代码,看到所有的 10 个单词也在 SKLearn 的停用单词列表中。

from sklearn.feature_extraction import texta = frozenset(list(term_freq_df.sort_values(by='total', ascending=False).iloc[:10].index))
b = text.ENGLISH_STOP_WORDS
set(a).issubset(set(b))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

my_stop_words = frozenset(list(term_freq_df.sort_values(by='total', ascending=False).iloc[:10].index))

现在,我可以在三种不同的条件下运行“nfeature_accuracy_checker”。第一个带停用词删除,第二个带自定义停用词删除,第三个不带停用词删除。

print "RESULT FOR UNIGRAM WITHOUT STOP WORDS\n"
feature_result_wosw = nfeature_accuracy_checker(stop_words='english')print "RESULT FOR UNIGRAM WITH STOP WORDS\n"
feature_result_ug = nfeature_accuracy_checker()print "RESULT FOR UNIGRAM WITHOUT CUSTOM STOP WORDS (Top 10 frequent words)\n"
feature_result_wocsw = nfeature_accuracy_checker(stop_words=my_stop_words)

我会用一个图表来显示上述准确性检查的结果。

nfeatures_plot_ug = pd.DataFrame(feature_result_ug,columns=['nfeatures','validation_accuracy','train_test_time'])
nfeatures_plot_ug_wocsw = pd.DataFrame(feature_result_wocsw,columns=['nfeatures','validation_accuracy','train_test_time'])
nfeatures_plot_ug_wosw = pd.DataFrame(feature_result_wosw,columns=['nfeatures','validation_accuracy','train_test_time'])plt.figure(figsize=(8,6))
plt.plot(nfeatures_plot_ug.nfeatures, nfeatures_plot_ug.validation_accuracy, label='with stop words')
plt.plot(nfeatures_plot_ug_wocsw.nfeatures, nfeatures_plot_ug_wocsw.validation_accuracy,label='without custom stop words')
plt.plot(nfeatures_plot_ug_wosw.nfeatures, nfeatures_plot_ug_wosw.validation_accuracy,label='without stop words')
plt.title("Without stop words VS With stop words (Unigram): Accuracy")
plt.xlabel("Number of features")
plt.ylabel("Validation set accuracy")
plt.legend()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过查看评估结果,删除停用词不会提高模型性能,但保留停用词会产生更好的性能。我不会说删除停用词不能每次都帮助模型性能,但是根据经验发现,在这个特定的设置中,保留停用词可以提高模型性能。

二元模型

根据维基百科,“n-gram 是来自给定文本或语音序列的 n 个项目的连续序列”。换句话说,n-grams 就是你能在源文本中找到的所有长度为 n 的相邻单词或字母的组合。下图很好地展示了 n 元语法是如何从源文本中构建出来的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这个项目中,我将把单词包扩展到三元模型,看看它如何影响性能。

print "RESULT FOR BIGRAM WITH STOP WORDS\n"
feature_result_bg = nfeature_accuracy_checker(ngram_range=(1, 2))print "RESULT FOR TRIGRAM WITH STOP WORDS\n"
feature_result_tg = nfeature_accuracy_checker(ngram_range=(1, 3))

运行上述代码后,我将 unigram、bigram 和 trigram 的结果一起绘制在一个图表上,如下所示。

nfeatures_plot_tg = pd.DataFrame(feature_result_tg,columns=['nfeatures','validation_accuracy','train_test_time'])
nfeatures_plot_bg = pd.DataFrame(feature_result_bg,columns=['nfeatures','validation_accuracy','train_test_time'])
nfeatures_plot_ug = pd.DataFrame(feature_result_ug,columns=['nfeatures','validation_accuracy','train_test_time'])plt.figure(figsize=(8,6))
plt.plot(nfeatures_plot_tg.nfeatures, nfeatures_plot_tg.validation_accuracy,label='trigram')
plt.plot(nfeatures_plot_bg.nfeatures, nfeatures_plot_bg.validation_accuracy,label='bigram')
plt.plot(nfeatures_plot_ug.nfeatures, nfeatures_plot_ug.validation_accuracy, label='unigram')
plt.title("N-gram(1~3) test result : Accuracy")
plt.xlabel("Number of features")
plt.ylabel("Validation set accuracy")
plt.legend()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每个 n 元语法的最佳验证集精度如下。

  • unigram: 80,000 和 90,000 个特征,验证准确率 80.28%
  • bigram: 70,000 个特征,验证准确率 82.25%
  • 三元模型:80,000 个特征,验证准确率 82.44%

下面我定义了另一个函数来更仔细地观察每个 n-gram 的最佳性能特征。下面的函数不仅报告准确性,而且给出混淆矩阵和分类报告。

def train_test_and_evaluate(pipeline, x_train, y_train, x_test, y_test):
    if len(x_test[y_test == 0]) / (len(x_test)*1.) > 0.5:
        null_accuracy = len(x_test[y_test == 0]) / (len(x_test)*1.)
    else:
        null_accuracy = 1\. - (len(x_test[y_test == 0]) / (len(x_test)*1.))
    sentiment_fit = pipeline.fit(x_train, y_train)
    y_pred = sentiment_fit.predict(x_test)
    accuracy = accuracy_score(y_test, y_pred)
    conmat = np.array(confusion_matrix(y_test, y_pred, labels=[0,1]))
    confusion = pd.DataFrame(conmat, index=['negative', 'positive'],
                         columns=['predicted_negative','predicted_positive'])
    print "null accuracy: {0:.2f}%".format(null_accuracy*100)
    print "accuracy score: {0:.2f}%".format(accuracy*100)
    if accuracy > null_accuracy:
        print "model is {0:.2f}% more accurate than null accuracy".format((accuracy-null_accuracy)*100)
    elif accuracy == null_accuracy:
        print "model has the same accuracy with the null accuracy"
    else:
        print "model is {0:.2f}% less accurate than null accuracy".format((null_accuracy-accuracy)*100)
    print "-"*80
    print "Confusion Matrix\n"
    print confusion
    print "-"*80
    print "Classification Report\n"
    print classification_report(y_test, y_pred, target_names=['negative','positive'])

在运行定义的函数之前,让我简单解释一下混淆矩阵分类报告。为了评估模型的性能,可以使用许多不同的指标。下面我将讨论二元分类的情况,其中目标变量只有两类要预测。在这个项目中,类别要么是“负的”,要么是“正的”。

一个显而易见的绩效衡量标准是准确性。它是模型在整个数据集的数量上对该类进行正确预测的次数。但是在分类的情况下,这可以进一步分解。下面是混淆矩阵的表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在上面的矩阵中,每一行表示实际类中的实例,而每一列表示预测类中的实例,并且它也可以通过交换行和列来表示(实际类的列,预测类的行)。所以我上面说的精度(ACC)可以表达如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当数据中类的分布非常均衡时,准确性可以让您很好地了解模型的执行情况。但是,当您有倾斜的数据时,例如,其中一个类在您的数据集中占主导地位,那么准确性可能不足以评估您的模型。假设你有一个包含 80%正类和 20%负类的数据集。这意味着,通过预测每个数据进入正类,模型将获得 80%的准确性。在这种情况下,您可能希望进一步探究混淆矩阵,并尝试不同的评估指标。

可以有 9 个不同的指标,只是来自混淆矩阵的数字组合,但我将特别讨论其中的两个,以及结合这两个的另一个指标。

“”(也叫阳性预测值)告诉你预测为阳性的数据实际上有多大比例是阳性的。换句话说,在所有阳性预测数据集中,真阳性的比例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

"回忆(也称为敏感度、命中率、真阳性率)告诉您实际为阳性的数据被预测为阳性的比例。换句话说,所有实际阳性数据中真正阳性的比例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下图是癌症诊断的混淆矩阵。如果你认为“癌症”是阳性类别,“非癌症”是阴性类别,这个图像很好地解释了如何根据混淆矩阵来考虑精确度和召回率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,F1 分数是精确度和召回率的调和平均值。调和平均值是一种特殊类型的平均值,用于处理单位平均值,如比率和比率。因此,通过计算这两个指标的调和平均值,您可以很好地了解模型在精确度和召回率方面的表现。公式如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

%%time
tg_cvec = CountVectorizer(max_features=80000,ngram_range=(1, 3))
tg_pipeline = Pipeline([
        ('vectorizer', tg_cvec),
        ('classifier', lr)
    ])
train_test_and_evaluate(tg_pipeline, x_train, y_train, x_validation, y_validation)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从上面的分类报告中,我们可以看到,模型在否定类中的准确率略高,在肯定类中的召回率也较高。但是这是通过计算 F1 分数得出的平均值,对于这两个类,我们得到了正类和负类几乎相同的 F1 分数。还有一种通过绘制 ROC 曲线来可视化模型性能的方法,但我将在后面更详细地解释。

在这篇文章中,我研究了基于用计数矢量器提取的特征的逻辑回归是如何执行的。在下一篇文章中,我将试验 Tfidf 矢量器,看看结果有什么不同。

感谢您阅读这篇长文!你可以从下面的链接找到上面代码的 Jupyter 笔记本。

https://github . com/tthustle sa/Twitter _ 情操 _ 分析 _ part 4/blob/master/Capstone _ part 4-copy 2 . ipynb

使用 Python 的另一个 Twitter 情感分析—第 5 部分(Tfidf 矢量器、模型比较、词汇方法)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-5-50b4e87d9bdd?source=collection_archive---------2-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Nathaniel Shuman on Unsplash

这是我正在进行的推特情感分析项目的第五部分。你可以从下面的链接找到以前的帖子。

在上一部分中,我尝试使用计数矢量器来提取特征并将文本数据转换成数字形式。在这一部分,我将使用另一种称为 Tfidf 矢量器的特征提取技术。

Tfidf 矢量器

TFIDF 是将文本数据转换为数字形式的另一种方式,是词频-逆文档频的简称。它产生的向量值是这两项的乘积;TF 和 IDF。

我们先来看词频。我们已经用计数矢量器查看了词频,但是这一次,我们还需要一个步骤来计算相对频率。假设我们的语料库中有两个文档,如下所示。

  1. 我喜欢狗
  2. 我讨厌狗和编织

每个文档中每个术语的相对术语频率计算如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

例如,如果我们计算文档 1 和文档 2 中“I”的相对词频,结果如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来,我们需要得到逆文档频率,它通过下面的计算来衡量一个单词对于区分每个文档的重要性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们计算“I”的逆文档频率,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一旦我们有了 TF 和 IDF 的值,现在我们可以计算 TFIDF 如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按照我们示例的情况,两个文档中术语“I”的 TFIDF 如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如您所看到的,术语“I”在两个文档中出现的次数相同,TFIDF 得分为 0,这意味着该术语在区分文档时并没有真正提供信息。其余部分与计数矢量器相同,TFIDF 矢量器将计算文档中术语的得分,并将文本数据转换为数字形式。

一旦实例化了 Tfidf 矢量器,将 Tfidf 转换后的数据拟合到逻辑回归,并检查不同数量的特征的验证准确性。

在这篇文章中,当我提到代码块时,我会附上一个要点链接,而不是将整个代码作为片段直接粘贴在文章中,此外,你也可以从我将在这篇文章结尾分享的链接中找到整个 Jupyter 笔记本。

因为我也有来自计数矢量器的结果,我在以前的帖子中尝试过,我将它们一起绘制在同一个图形上进行比较。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从上面的图表中,我们可以看到,在计数矢量器和 TFIDF 矢量器中包含二元模型和三元模型提高了模型性能。对于每种从一元到三元的情况,TFIDF 都比计数矢量器产生更好的结果。

算法比较

我用逻辑回归得到的最好结果是通过使用包含多达 100,000 个特征(包括三元模型)的 TFIDF 矢量器。在这种情况下,我将首先拟合各种不同的模型,并比较它们的验证结果,然后将建立一个包含前 5 个模型的集成(投票)分类器。

考虑到数据的大小和模型的可扩展性,我没有包括一些计算量大的模型,如 KNN、随机森林。模型的微调将在我尝试其他不同的文本数据矢量化之后进行。

我不会详细解释每个模型是如何工作的,因为这不是这篇文章的目的。你可以在网上找到许多有用的资源,但如果我收到许多关于某个特定算法的问题或请求,我会尝试为所选的模型单独写一篇文章。

(请注意,在下面的“classifier_comparator”函数中,我调用了另一个自定义函数“accuracy_summary ”,它报告与空精度相比的验证精度,以及训练和评估所用的时间。)

比较的结果如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看起来逻辑回归是我表现最好的分类器。

集成分类器的结果如下,该集成分类器从来自上述结果的前 5 个模型(线性回归、线性 SVC、多项式 NB、岭分类器、被动-主动分类器)中获得投票。注意,我没有在投票分类器中包括“具有基于 L-1 的特征选择的线性 SVC”模型,因为它与线性 SVC 是相同的模型,除了它首先通过 L-1 正则化过滤掉特征,并且比较没有特征选择的线性 SVC 的结果显示出更好的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

投票分类器的验证集准确率为 82.47%,比单独的逻辑回归的 82.92%要差。

词汇法

我上面演示的是文本分类问题的机器学习方法,它试图通过在带标签的数据集上训练分类器来解决问题。另一个著名的情感分析方法是词汇法。在词汇方法中,情感的定义是基于对单个单词和/或短语的分析;经常使用情感词典:在文本中搜索词典中的情感词汇项,计算它们的情感权重,并应用一些聚合权重函数。”http://www.dialog-21.ru/media/1226/blinovpd.pdf

在本系列的第 3 部分中,我计算了“正率 CDF”和“正频率百分比 CDF”的调和平均值,这些给了我在语料库中正面和负面术语的良好表示。如果它成功地过滤了哪些术语对每个类是重要的,那么这也可以用于词汇方式的预测。

所以我决定做一个简单的预测器,利用我计算的谐波平均值。下面我将介绍术语频率的计算,以及获得‘pos _ normcdf _ hme an’的步骤,但这次我仅从训练集中计算术语频率。(*由于我了解到不需要将稀疏矩阵转换为密集矩阵来计算术语频率,所以我直接从稀疏矩阵计算频率)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你想更详细地了解我用来得出“pos_norcdf_hmean”最终值的公式,你可以在本系列的第 3 部分中找到。

我决定的积极性得分的计算相当简单明了。对于文档中的每个单词,在我构建词汇表的 10,000 个单词的列表中查找它,并获得相应的“pos_normcdf_hmean”值,然后为文档计算平均“pos_normcdf_hmean”值。如果从构建的 10,000 个术语中找不到任何单词,则产生范围在 0 到 1 之间的随机概率。我从一个文档中得到的单个值被处理为该文档是正类的概率。

通常情况下,词法方法会将许多其他方面纳入计算,以完善预测结果,但我将尝试一个非常简单的模型。

对于“pos_hmean”的平均值,我决定阈值为 0.56,这意味着如果“pos_hmean”的平均值大于 0.56,分类器将其预测为正类,如果它等于或小于 0.56,则将其预测为负类。由上述模型得到的结果为 75.96%。准确度不如使用计数矢量器或 TFIDF 矢量器的逻辑回归,但与 null 准确度相比,准确度高 25.56%,甚至与 TextBlob 情感分析相比,我的简单自定义词典模型的准确度高 15.31%。对于这样一个简单的计算来说,这是一个令人印象深刻的结果,并且还考虑到“pos_normcdf_hmean”仅使用训练集计算的事实。

在下一篇文章中,我将尝试实现 Doc2Vec,看看性能是否会变得更好。

感谢您的阅读,您可以通过下面的链接找到 Jupyter 笔记本。

https://github . com/tthustle sa/Twitter _ 情操 _ 分析 _ part 5/blob/master/Capstone _ part 4-copy 3 . ipynb

使用 Python 的另一个 Twitter 情感分析—第 6 部分(Doc2Vec)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-6-doc2vec-603f11832504?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Markus Winkler on Unsplash

这是我正在进行的推特情感分析项目的第六部分。你可以从下面的链接找到以前的帖子。

*除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

在我们跳到 doc2vec 之前,先提一下 word2vec 会比较好。Word2vec 是一组用于产生单词嵌入的相关模型。这些模型是浅层的两层神经网络,经过训练可以重建单词的语言上下文。”

Word2vec 不是一个单一的算法,而是由两种技术组成——CBOW(连续单词包)和 Skip-gram 模型。这两种技术都学习作为单词向量表示的权重。对于语料库,CBOW 模型从周围上下文单词的窗口中预测当前单词,而 Skip-gram 模型在给定当前单词的情况下预测周围上下文单词。在 Gensim 包中,在实现 Word2Vec 时,可以通过传递参数“sg”来指定是使用 CBOW 还是 Skip-gram。默认情况下(sg=0),使用 CBOW。否则(sg=1),使用 skip-gram。

例如,假设我们有下面的句子:“我喜欢狗”。当给定“我”、“狗”作为输入时,CBOW 模型试图预测单词“爱”,另一方面,当给定单词“爱”作为输入时,Skip-gram 模型试图预测“我”、“狗”。

下图更正式地展示了这两个模型是如何工作的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是,用作单词向量的实际上不是这些模型的预测结果,而是经过训练的模型的权重。通过提取权重,这样的向量以某种抽象的方式来表示单词的“含义”。如果想更详细的了解 word2vec 模型是如何工作的,有一篇欣荣(2016) 的很棒的论文,详细的讲解了模型的每一步。

那 doc2vec 是什么?Doc2vec 使用与 word2vec 相同的逻辑,但是将其应用于文档级。根据 Le 和 Mikolov(2014) ,“每个段落被映射到一个唯一的向量,由矩阵 D 中的一列表示,每个单词也被映射到一个唯一的向量,由矩阵 w 中的一列表示。段落向量和单词向量被平均或连接以预测上下文中的下一个单词……段落标记可以被认为是另一个单词。它起到了记忆的作用,记住了当前上下文或者段落主题中缺少的内容。”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

DM:这是类似于 Word2vec 中 CBOW 模型的 Doc2Vec 模型。段落向量是通过在基于上下文单词和上下文段落推断中心单词的任务上训练神经网络而获得的。

DBOW:这是 Doc2Vec 模型对 Word2Vec 中的 Skip-gram 模型的模拟。段落向量是通过训练神经网络来获得的,该神经网络的任务是在给定从段落中随机采样的单词的情况下,预测段落中单词的概率分布。

我使用 Python 库 Gensim 实现了 Doc2Vec 模型。在 DM 模型的情况下,我实现了平均方法和连接方法。这是受乐和 Mikolov (2014) 的研究论文的启发。在他们的论文中,他们用两种不同的方法实现了 DM 模型,一种是平均计算过程,另一种是串联计算方法。这在 Gensim 的教程中也有展示。

以下是我用来获取每条推文向量的方法。

  1. 分布式单词包
  2. 分布式存储器级联
  3. 分布式存储装置
  4. DBOW + DMC
  5. DBOW + DMM

利用从上述模型中获得的向量,我拟合了一个简单的逻辑回归模型,并在验证集上评估了结果。

作为准备,除了加载所需的依赖项,我们还需要使用 Gensim 的 LabeledSentence 函数用唯一的 id 标记每条 tweet。

为了训练 Doc2Vec,我使用了整个数据集。这背后的基本原理是 doc2vec 训练是完全无人监督的,因此没有必要保留任何数据,因为它是未标记的。这一基本原理的灵感来自于 Lau 和 Baldwin (2016) 在他们的研究论文《doc2vec 的实证评估与文档嵌入生成的实际见解》中的基本原理

同样的基本原理也应用于 Gensim 的 Doc2Vec 教程。在 IMDB 教程中,向量训练发生在数据集的所有文档上,包括所有训练/测试/开发集。

分布式单词包

我们先训练纯 DBOW 模型。请注意,由于其训练方式,DBOW 模型不会在单词级别产生任何有意义的向量。但是当我们谈到分布式内存模型时,我们也要看看单词向量。

据 Gensim 的开发者拉迪姆·řehůřek 说,“这种算法运行方式的一个警告是,由于学习率在数据迭代过程中下降,在训练期间只在单个带标签的句子中看到的标签将以固定的学习率进行训练。这经常产生不太理想的结果。”

下面的迭代实现了带有附加混洗的显式多遍 alpha 缩减方法。这已经在 Gensim 的 IMDB 教程中介绍过了。

在上面的代码块中,我还定义了一个函数“get_vectors”来从训练好的 doc2vec 模型中提取文档向量,这个函数也将在其他 doc2vec 模型中重用。

用逻辑回归在验证集上测试的准确度是 73.89%。尽管 DBOW 模型不学习单个单词的含义,但作为输入到分类器的特征,它似乎正在完成它的工作。

但它似乎没有胜过计数矢量器或 Tfidf 矢量器(Tfidf 矢量器具有 100,000 个特征,使用逻辑回归的验证集准确率为 82.92%)。

分布式存储器串联

现在让我们转到分布式内存模型,看看它是如何执行的。我将首先尝试用串联法进行训练。

不幸的是,验证集上的准确率是 66.47%,这有点令人失望。但这并不意味着该模型未能在单词级别学习到有效的向量表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过在训练后查看与“facebook”相似的单词,看起来该模型恰当地抓住了 SNS,web 服务的含义。此外,该模式还成功地捕捉到了“小”的比较级形式,即“大”和“更大”。上面的代码行就像要求模型将与单词“bigger”和“small”相关联的向量相加,同时减去“big”等于顶部的结果,“small”。

分布式存储装置

我们试试另一种训练 DM 模型的方法。

验证集准确率为 72.56%,远优于 DMC 模型,略低于 DBOW 模型。我们也来看看它学到了什么。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看起来它已经很好地理解了“好”的含义,模型为“好”选择的最相似的词是“太好了”。太好了!

组合模型

由于我有来自三个不同模型的文档向量,现在我可以将它们连接起来,看看它是如何影响性能的。下面我定义了一个简单的函数来连接来自不同模型的文档向量。

DBOW + DMC 模型的验证集准确率为 74.58%,比纯 DBOW 模型(73.89%)有所提高。让我们试试另一种组合。

这次通过将 DBOW 和 DMM 结合在一起,我得到了 75.51%的验证集准确率。

对于 unigram,我了解到以不同的组合连接文档向量可以提高模型性能。我从单一模型得到的最好的验证准确率是 DBOW 的 73.89%。通过连接向量,我用 DBOW+DMM 模型得到了 75.51%的最高验证准确率。

在下一篇文章中,我将看看使用 Gensim 的短语建模,并将其应用于 Doc2Vec,看看这是否会影响性能。

感谢您的阅读,您可以通过下面的链接找到 Jupyter 笔记本。

https://github . com/tthustle a/Twitter _ 情操 _ 分析 _ part 6/blob/master/Capstone _ part 4-copy 4 . ipynb

使用 Python 的另一个 Twitter 情感分析—第 7 部分(短语建模+ Doc2Vec)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-7-phrase-modeling-doc2vec-592a8a996867?source=collection_archive---------3-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Raphael Schaller on Unsplash

这是我正在进行的推特情感分析项目的第 7 部分。你可以从下面的链接找到以前的帖子。

在上一篇文章中,我实现了 Doc2Vec,并用从 Doc2Vec 模型中获得的文档向量尝试了一个简单的逻辑回归。不幸的是,在情感分析任务中,100 维文档向量并没有胜过 100,000 维 Tfidf 特征。这一次,我将尝试短语建模,看看能否进一步提高 Doc2Vec 向量的性能。

*除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

短语建模

另一件可以用 Gensim 库实现的事情是短语检测。它类似于 n-gram,但它不是通过滑动窗口来获得所有的 n-gram,而是检测经常使用的短语并将它们粘在一起。

这已经由 Mikolov 等人介绍过了。al (2013) ,并且提出学习短语的向量表示,该短语具有不是其单个单词的意思的简单组合的意思。“这样,我们可以在不增加词汇量的情况下形成许多合理的短语.”

Patrick Harrison 在 2016 年 DC PyData 大会上也对 Gensim 的短语建模进行了非常直观的解释。

下面的公式简单地表达了短语建模。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中:

  • count(A)是 token (token 是 NLP 字段中词汇或单词的另一个单词)在语料库中出现的次数
  • count(B)是记号 B 在语料库中出现的次数
  • count(A B)是单词 A B 在语料库中按顺序出现的次数
  • n 是语料库词汇的总大小
  • count_min 是用户定义的参数,用于确保接受的短语出现的次数最少(Gensim 的短语函数中的默认值为 5)
  • threshold 是一个用户定义的参数,用于控制模型在接受两个单词作为短语之前需要它们之间的关系有多强(Gensim 的短语函数中使用的默认阈值是 10.0)

好,让我们看看这实际上是如何工作的。

现在我们有了一个二元模型,它将检测两个单词的常用短语,并将它们粘在一起。例如,假设我们有一个句子“纽约市长在那里”,看看如果我们将这个句子输入到 bigram 短语模型中会发生什么。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从上面的例子可以看出,通过 tweets 语料库,它已经学会了“纽约”这个常用短语。所以现在给“bigram”输入分隔“new”和“york”的标记,它会自动把它们组合成一个单词“new_york”。

让我们用 tweet 数据集中的一个训练数据来测试二元模型。以下是推文原文。(是的,这的确非常令人难过)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们把这句话输入二元模型,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到二元模型已经将“vanilla_ice”识别为一个短语。但如果它只能抓到“香草 _ 冰”而抓不到“香草 _ 冰淇淋”,那么有时候“香草 _ 冰”可以是别的意思。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我稍后将回到这一点。

现在让我们用这个二元模型来转换我们的语料库。

在我获得检测到二元语法短语的语料库后,我经历了与 unigram 相同的 Doc2Vec 过程。

检测到二元模型的分布式单词包

在下面的代码块中,你会发现一些在没有导入的情况下使用的依赖项,以及自定义的函数“get_vectors”。你可以在这篇文章的最后找到 Jupyter 笔记本的完整版本。

关于验证的准确性,我将在后面向您展示直到 trigram 之前尝试过的所有 doc2vec 模型。

检测到带有 bigram 的 DMC(分布式内存连接)

与 DBOW 模型不同,DM 模型也可以学习每个单词有意义的语义向量表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因为现在我们有二元短语检测语料库,如果我们寻找与“纽约”最相似的词,模型说它是“纽约”,这非常令人惊讶,你也可以看到其他城市名称,如“芝加哥”、“柏林”等。

检测到带有二元模型的 DMM(分布式内存装置)

组合模型

和我在上一篇文章中所做的一样,我尝试了两种组合模型:DBOW + DMC,DBOW + DMM。你可以在我最后分享的 Jupyter 笔记本里找到代码。

三元模型

如果我们在二元模型检测的语料库上再次运行相同的短语检测,现在它将检测三元模型短语。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

终于!香草冰淇淋!

我再次用 trigram detected 语料库运行了三个不同的 doc2vec 模型,下面是我用不同的 doc2vec 模型从 unigram 到 trigram 得到的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我能得到的最好的验证精度来自 dbow+dmm 模型。

DMM 模型往往随着 n-gram 的增加而表现更好,而纯 DBOW 模型往往随着 n-gram 的增加而表现更差。组合的模型是(即 dbow +dmc)和(dbow +dmm)用二元模型产生较低的结果,用三元模型产生较高的结果,但是考虑到这些差异都在小数位,可能很难说短语检测对组合的模型结构有影响。(请注意,这是在这种特定环境下的经验发现,但如果你想用你选择的语料库尝试这一点,我肯定想知道这是否在不同的情况下成立。)

在我进入下一步之前,我想再做一件事,那就是创建跨不同 n 元文法的联合向量。通过查看上表,对于 DBOW 模型,unigram 表现最佳,因此我将使用来自 unigram DBOW 模型的向量,并将其与 trigram DMM 向量结合在一起。

“unigram DBOW + trigram DMM”模型的验证准确性为 75.76%,略好于“trigram DBOW + DMM”模型,但差异仍然在小数点位置,我不确定是否可以说这是一个显著的改进。

在下一篇文章中,我将使用来自 Doc2Vec 和 Tfidf 稀疏矩阵的向量实现神经网络模型,并将结果与简单的逻辑回归进行比较。

感谢您的阅读,您可以通过下面的链接找到 Jupyter 笔记本。

https://github . com/tthustle sa/Twitter _ 情操 _ 分析 _ part 7/blob/master/Capstone _ part 4-copy 5 . ipynb

用 Python 进行的另一个 Twitter 情感分析—第 8 部分(降维:Chi2,PCA)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-8-dimensionality-reduction-chi2-pca-c6d06fb3fcf3?source=collection_archive---------2-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Markus Spiske on Unsplash

这是我正在进行的推特情感分析项目的第 8 部分。你可以从下面的链接找到以前的帖子。

在上一篇文章中,我已经将短语建模与 doc2vec 模型结合起来,并看到验证准确性略有提高,我将继续讨论神经网络,看看 ANN 如何提高性能。但是我决定绕道而行,尝试对我从 Tfidf 矢量器和 Doc2Vec 矢量获得的特征进行降维。

到目前为止,在特征提取方面,我尝试了三种不同的方法:count vectorizer、Tfdif vectorizer、doc2vec。我得到的最好的验证结果如下。

分类器:逻辑回归(L2 正则化,正则化强度:1.0)

  • 计数矢量器(80,000 个特征,n 元语法范围:1,2,3,停用词移除:X) — 82.44%
  • tfidf 矢量器(100,000 个特征,n 元语法范围:1,2,3,停用词移除:X) — 82.92%
  • Doc2Vec (unigram DBOW + trigram DMM:每条推文的 200 维向量总数)— 75.76%

除此之外,我还使用词法方法自定义了分类器。

  • 自定义词典分类器(决策阈值设置为 0.56) — 75.96%

除了词法方法之外,模型所需的特征数量似乎相当大,所以我决定看看是否可以减少 Tfidf 矢量器和 doc2vec 矢量的特征维数。Doc2Vec 模型中的矢量为 200 维,与 Tfidf 矢量器的 100,000 个特征相比,听起来非常小。但是这 200 维向量是全实数的稠密矩阵,而 10 万个特征是零很多的稀疏矩阵。因此,在计算方面,Doc2Vec 向量也需要一些时间来计算。因此,如果我可以减少维度,那么它将有助于运行模型的超参数调整的各种设置。

首先,让我们尝试使用卡方特征选择对 Tfidf 向量进行降维。

*除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

Chi2 特征选择

在 Scikit-learn 库中,有三种方法可用于稀疏矩阵的特征选择,如 Tfidf 向量或计数向量。通过查看文档,您可以看到 chi2、mutual_info_regression、mutual_info_classif 将在不使数据密集的情况下处理数据。在我的情况下,我有 150 万条推文,并希望从 10 万个特征中减少维度,因此将其转换为密集矩阵不是一个选项。它不适合我的内存。

卡方统计测量特征(在这种情况下,推文中的一个术语)和类别(推文是正面还是负面)之间缺乏独立性。

你可以首先把一条推文中的一个术语和这条推文所属的类别之间的关系想象成一个列联表。列联表只是显示频率分布的表的一个花哨的词。

假设我们的语料库中有如下三个句子。

  1. 我喜欢狗
  2. 我讨厌狗
  3. 我喜欢狗和烹饪

假设每条推文的情绪等级是积极的,消极的,积极的。(顺便说一句,我喜欢狗和烹饪,也喜欢猫)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们将’ t ‘定义为我们正在查看的特定术语,在本例中为“狗”,将’ c ‘定义为类,因为该类只有两个类,所以它将是 1(正)或 0(负)。使用列联表,其中 A 为’ t 发生的次数, c 为正,B 为’ t ‘发生的次数,【C】为负,C 为’ t 未发生的次数, c 为正,最后 D 为’ t 未发生的次数, c 为负。现在我们准备计算卡方统计量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 N 是样本总数,术语“狗”的卡方得分是 3!由于卡方测量的是特征和类之间缺乏独立性,如果某个特征与其他特征相比具有较高的卡方得分,则意味着该特征对于预测类是有用的。

我将首先将训练数据转换为 100,000 个特征的 Tfidf 向量,并查看 chi2 选择了哪些特征作为有用的特征。让我们把我们得到的分数画在图上,看看哪些单词特征对预测有用。我将在下面的图表中只列出前 20 个特征,但是只要你的电脑屏幕允许,你可以尽可能多的列出来。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

chi2 选择的最有用的特征是“谢谢”这个词,我假设这主要来自于积极的推文。它选择的第二个最有用的特征是“悲伤”这个词,这次我猜它来自负面推文。如果考虑 chi2 是如何计算的,它不仅在预测正类的术语上得分高,而且在预测负类的术语上得分高。

既然现在我们已经了解了 chi2 特征选择是如何工作的,那么让我们将维度减少到不同数量的特征,并检查验证集的准确性。

还有一件事。当您拟合和转换语料库时,Tfidf 矢量器可以首先限制特征的数量。我想比较相同特征数量下的验证准确性:1)当特征数量受到 Tfidf 矢量化阶段的限制时,2)当使用 chi2 统计将特征数量从 100,000 个特征减少时。

*在下面的代码块中,我绘制了我在不同的 max 特性上运行 Tfidf 矢量器得到的结果,你也可以在本文末尾的 Jupyter 笔记本上找到完整的代码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在上图中,红色虚线是来自降维的验证集精度,蓝色线是拟合 Tfidf 矢量器时首先限制特征数量的结果。我们可以看到,使用 Tfidf 矢量器首先限制要素的数量比从较大的要素中减少维度会产生更好的结果。这不是一个笼统的说法,而是我在这个特定背景下的发现。如果你在其他语料库中有不同的结果,我很想知道它有什么不同。

主成分分析

PCA 是一种降维工具,可用于将一大组变量降维为一个仍包含原始集合中大部分信息的小集合。这听起来很酷,你可以减少数据的特征,但不能保留大部分需要的信息。但是如果你尝试过谷歌搜索“PCA”,你可能会知道它会给你返回所有听起来很难的术语,如“特征值”、“特征向量”、“矩阵投影”等。

在这篇文章中,我不会详细介绍 PCA 实际上是如何计算的,但会尽量保持直观的水平,这样任何阅读这篇文章的人都可以理解它的基础知识,并用 Python 实现。

PCA 所做的是转换坐标系,使坐标轴成为我们整体数据的最简洁、信息最丰富的描述符。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上图摘自徐萌在 PCA 上的博客文章。我发现徐萌的解释非常有助于直观地理解这个概念。您在图(A)中看到的形状是三维的,但如果我们关注数据的形状,而不是轴,形状本身就是平面的二维表面。通过运行 PCA,我们为数据找到新的坐标,这将最好地描述数据是如何形成的。第一个主成分是解释数据中最大差异的成分。在图(B)中,我们看到通过绘制“组件 1”线,它能够保留最分散的数据点的信息。通过添加“成分 2”行,这条“成分 2”行解释了我们数据中的第二大差异。下一步是将原始数据转换到我们新发现的轴上,这个轴是二维的,而不是原来的三维。图©中的最终结果给了我们一个很好的画面,展示了即使我们已经放弃了第三维,数据是如何仅用二维来形成的。

并且在实现数据的这种变换时使用特征向量和特征值。特征向量指定通过原始坐标空间的方向,而特征值指示其对应特征向量方向上的变化量。

如果你想更深入地了解 PCA 的概念,还有一些我觉得有用的博客文章。

接下来,让我们尝试用 PCA 降低 doc2vec 向量的维数。我们还可以将结果绘制在图表上,看看将特征的数量减少到一个较小的主成分集是否可行,以及给定数量的主成分可以解释多少关于原始特征的方差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在上图中,红线代表累计解释方差,蓝线代表每个主成分的解释方差。通过看上面的图表,尽管红线不是完美的直线,但非常接近直线。这样好吗?不。这意味着每个主成分对方差解释的贡献几乎相等,基于主成分分析降低维度没有多大意义。这一点从蓝线也可以看出来,蓝线非常接近底部的一条直线。

有点令人失望的是,在我处理 tweets 文本数据的具体案例中,维数约减并没有太大的帮助。当首先使用 Tfidf 矢量器限制特征时,Tfidf 矢量显示出比随后降低维度更好的结果,并且 doc2vec 矢量似乎通过其 200 维特征空间携带大致相似的信息量。

同样,这不是一个普遍的说法,这只是我用我的特殊数据发现的。特别是主成分分析,当它应用于数字特征时,我看到它成功地将数据的维度从 100 个或更多的特征减少到大约 10 个特征,同时能够解释 90%的数据差异。

如果您对这篇文章的神经网络建模有所期待,很抱歉我不得不绕道而行,但在下一篇文章中,我肯定会进行神经网络建模。一如既往的感谢您的阅读。

您可以通过以下链接找到 Jupyter 笔记本:

https://github . com/tthustle a/Twitter _ 情操 _ 分析 _ part 8/blob/master/Capstone _ part 4-copy 6 . ipynb

另一个使用 Python 的 Twitter 情感分析——第 9 部分(使用 Keras 的 Tfidf 向量的神经网络)

原文:https://towardsdatascience.com/another-twitter-sentiment-analysis-with-python-part-9-neural-networks-with-tfidf-vectors-using-d0b4af6be6d7?source=collection_archive---------3-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Alina Grubnyak on Unsplash

这是我正在进行的推特情感分析项目的第 9 部分。你可以从下面的链接找到以前的帖子。

在前一篇文章中,在尝试神经网络建模之前,我走了一条实现降维的弯路。在这篇文章中,我将首先用 100,000 个特征的 Tfidf 向量实现神经网络,包括高达三元模型。

*除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

人工神经网络

我的第一个想法是,如果逻辑回归是表现最好的分类器,那么这个想法可以扩展到神经网络。就其结构而言,逻辑回归可以被认为是一个没有隐含层,只有一个输出节点的神经网络。从下面的图片可以更清楚的看到这种关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我不会详细讲述神经网络是如何工作的,但是如果你想知道更多的细节,你可以看看我之前写的关于用 Python 从零开始实现神经网络的文章。但是对于这篇文章,我不会从头开始实现它,而是使用一个名为 Keras 的库。Keras 更像是一个包装器,可以运行在其他库之上,比如 Theano 或 TensorFlow。它是最易于使用的库之一,具有直观的语法和强大的功能。如果你像我一样是神经网络建模的新手,我认为 Keras 是一个很好的起点。

带 Tfidf 矢量器的人工神经网络

我得到的性能最好的 Tfidf 向量有 100,000 个特征,包括多达逻辑回归三元模型。验证准确率为 82.91%,而训练集准确率为 84.19%。我想看看神经网络是否能提高我现有的 Tfidf 向量的性能。

我将首先从加载所需的依赖项开始。为了使用 TensorFlow 后端运行 Keras,您需要安装 TensorFlow 和 Keras。

以下 NN 模型的结构在输入层中有 100,000 个节点,然后在应用了 Relu 激活函数的隐藏层中有 64 个节点,最后是应用了 sigmoid 激活函数的一个输出层。神经网络有不同类型的优化技术,您可以使用模型定义不同的损失函数。下面的模型使用 ADAM 优化,和二进制交叉熵损失。

ADAM 是一种优化算法,用于更新参数和最小化神经网络的成本,这被证明是非常有效的。它结合了两种优化方法:RMSProp 和 Momentum。同样,我将重点分享我从实现中获得的结果,但如果你想正确理解亚当是如何工作的,我强烈推荐吴恩达的“ deeplearning.ai ”课程。他用非常直观的方式解释了神经网络的复杂概念。如果您想要更多关于该主题的深入材料,还可以看看 Kingma & Ba (2014)的研究论文“ ADAM:一种随机优化的方法”。

在输入数据和训练模型之前,我还需要处理一件事。Keras NN 模型不能直接处理稀疏矩阵。数据必须是密集阵列或矩阵,但将 150 万个 Tfidf 向量的整个训练数据转换为密集阵列将无法容纳在我的 RAM 中。所以我必须定义一个函数,它生成 iterable generator 对象,这样它就可以输入到 NN 模型中。注意,输出应该是一个生成器类对象,而不是直接返回数组,这可以通过使用“yield”而不是“return”来实现。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看起来该模型在 2 个时期后具有最佳验证准确性,并且在此之后,它不能一般化,因此验证准确性缓慢降低,而训练准确性增加。但如果你还记得我从逻辑回归得到的结果(训练准确率:84.19%,验证准确率:82.91%),你可以看到,上述神经网络在验证方面未能跑赢逻辑回归。

让我们看看归一化输入是否对性能有任何影响。

然后我重新定义了模型,用我从上面规格化器得到的“x_train_tfidf_norm”重新改装了模型。

结果几乎和没有标准化时一样。在这一点上,我意识到 Tfidf 已经通过它的计算方法归一化了。Tfidf 中的 TF(词频)不是绝对频率而是相对频率,通过将 idf(逆文档频率)乘以相对词频值,以跨文档的方式进一步归一化该值。

拒绝传统社会的人

如果模型的问题是一个糟糕的概括,那么我可以在模型中添加另一个东西。尽管神经网络是一个非常强大的模型,但有时过度适应训练数据可能是一个问题。辍学是一种解决这个问题的技术。如果你熟悉机器学习中的系综模型概念,辍学也可以看出一脉相承。根据 Hinton 等人(2012 年)的研究论文“通过防止特征检测器的共同适应来改善神经网络”“减少测试集误差的一个好方法是对大量不同网络产生的预测进行平均。做到这一点的标准方法是训练许多单独的网络,然后将这些网络中的每一个应用于测试数据,但是这在训练和测试期间都是计算昂贵的。随机退出使得在合理的时间内训练大量不同的网络成为可能。

Dropout 是模拟好像我们训练许多不同的网络,并通过在整个训练过程中以一定的概率随机省略隐藏节点来平均它们。使用 Keras,只需在模型架构中添加一行就可以轻松实现。让我们看看 20%的辍学率下模型性能如何变化。(*我将收集所有结果,并在最后以表格形式呈现。)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过 5 个历元,训练集精度没有达到没有丢失的模型的精度,但是验证精度没有下降到与之前的模型一样低。尽管退出给模型增加了一些概括性,但与逻辑回归结果相比,验证准确性仍然表现不佳。

洗牌

我可以尝试另一种方法来防止过度拟合。通过为每个时期以相同的顺序呈现数据,模型有可能学习到也包括训练数据的噪声的参数,这最终导致过度拟合。这可以通过改变我们提供给模型的数据的顺序来改善。下面,我在批处理生成器函数中添加了洗牌功能,并尝试使用相同的模型结构,比较了结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

具有非混洗训练数据的同一模型的训练准确率为 87.36%,验证准确率为 79.78%。改组后,训练准确率下降到 84.80%,但 5 个时期后的验证准确率增加到 82.61%。看起来洗牌确实提高了模型在验证集上的表现。我注意到的另一件事是,无论有无洗牌,无论有无掉线,验证准确性往往在 2 个时期后达到峰值,之后逐渐下降。

我还尝试了同样的模型,其中有 20%的数据丢失,这次只有 2 个时期,我将在最后分享结果。

学习率

当我在学习吴恩达的“ deeplearning.ai ”课程时,他表示,他试图改进神经网络模型的第一件事是调整学习速率。我决定听从他的建议,用这个模型尝试不同的学习速度。请注意,除了学习率之外,“β_ 1”、“β_ 2”和“ε”的参数设置为原始论文“ADAM:A Method for random Optimization”中的默认值,作者为 Kingma 和 Ba (2015)。

在尝试了四种不同的学习率(0.0005,0.005,0.01,0.1)之后,没有一个比默认的学习率 0.001 表现得更好。

增加节点数量

也许我可以尝试增加隐藏节点的数量,看看它对性能有什么影响。下面的模型在隐藏层有 128 个节点。

在 128 个隐节点的情况下,验证精度接近逻辑回归的性能。我可以通过增加隐藏层的数量做进一步的实验,但是要运行上面的 2 个时期,需要 5 个小时。考虑到逻辑回归用了不到一分钟的时间来拟合,即使神经网络可以进一步改进,这看起来也不是一种有效的方法。

下面是一个表格,列出了我从上面尝试不同模型得到的所有结果。请注意,我比较了 2 个时期的性能,因为有些模型只运行了 2 个时期。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

除 ANN_8(学习率为 0.1)外,模型性能仅在小数部分有变化,最佳模型为 ANN_9(一个隐层 128 个节点),验证准确率为 82.84%。

因此,在这种特殊情况下,神经网络模型未能胜过逻辑回归。这可能是由于文本数据的高维度和稀疏特性。我还找到一篇研究论文,比较了模型性能和高维数据。根据 Caruana 等人(2008 年)的“高维监督学习的经验评估”,逻辑回归显示出与神经网络一样好的性能,在某些情况下甚至优于神经网络。

通过以上所有的尝试,我学到了一些宝贵的经验。实现和调整神经网络是一个高度迭代的过程,包括许多试验和错误。尽管神经网络是逻辑回归的更复杂版本,但它并不总是优于逻辑回归,有时对于高维稀疏数据,逻辑回归可以以比神经网络少得多的计算时间提供良好的性能。

在下一篇文章中,我将使用从上一篇文章中获得的 Doc2Vec 向量实现一个神经网络。希望使用像 Doc2Vec 这样的密集向量,神经网络可能会有所提高。手指交叉。

一如既往的感谢您的阅读。你可以从下面的链接找到整个 Jupyter 笔记本。

https://github . com/tthustle sa/Twitter _ 情操 _ 分析 _ part 9/blob/master/Capstone _ part 4-copy 7 . ipynb

除了条形图之外的任何东西:条形图的 10 个最佳替代品

原文:https://towardsdatascience.com/anything-but-bars-the-10-best-alternatives-to-bar-graphs-fecb2aaee53a?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你想展示一个对比,但又不能画出另一个条形图,该怎么办?

这个问题我不是随便问的。条形图或折线图可以说明绝大多数数据;他们是 dataviz 世界的两大主力。

但是说实话:一个接一个的条形图让厌烦。这时你就想有一两个备选方案。

这里有 10 个最好的方法来用条形图展示没有 T5 的比较*。*

为什么我们如此频繁地使用条形图

最常见的图表类型——折线图、条形图和饼图——之所以常见是有原因的。

每种图形类型都专门讲述一个特定类型的故事。线形图显示了随时间变化的趋势。饼状图(以及它们的甜甜圈兄弟)显示了整体的部分。当涉及到比较时,条形图真正闪耀。

条形图利用了人类判断距离的自然能力。我们很擅长确定哪种形状最长,以及最长多少。条形图通过用矩形代替数字来利用这种能力。

折线图、条形图和饼图很常见,因为它们是描述每种故事类型的最简单、最有效的方式。

场景:比较一个变量的值

我有时会参加由 Olga Tsubiks 领导的项目事业数据挑战,该项目让数据可视化人员处理非营利和事业驱动的数据。他们最近特别报道了环境署关于保护区的数据。因为我最近一直在处理数据,所以我想用它作为今天的例子。

该数据集覆盖了全球数十万个保护区,每个保护区都有详细的位置、面积、治理等信息。

像这样显示多方面数据的方法有很多,但今天我们保持简单。我们只是比较一下每个北美国家有多少被划入保护区。(为了便于计算,我忽略了跨越国界的海洋保护区和公园。)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们的条形图非常简单:三个国家的三个数字。从占总面积的百分比来看,墨西哥似乎在北美留出了最多的土地,其次是美国和加拿大。

条形图完成了工作,但它可能更令人兴奋。让我们看看还能利用这些数据做些什么。

1.行图表

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

*“等一下,”*你可能会说,“这张图看起来非常熟悉。”

你是对的。条形图基本上是旋转了 90 度的条形图。但这并不完全是欺骗。这种微妙的变化可能会派上用场。

如果您的数据标签有点长,比如说您想拼出“美利坚合众国”,垂直条形图将很快用尽空间。Excel 通常将标签切换到垂直或对角线方向,但这两种方向都很难阅读。

行图表解决了这个问题,它提供了更多的布局灵活性,同时保持了条形图粗犷的外观和魅力(以及有效性)。如果您正在编写报告,您可以排列图表以匹配一列文本的宽度,而不占用太多垂直空间。

2.放射状柱形图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

径向柱形图是一个自身卷曲的条形图。在左边的例子中,我加入了中美洲,让事情变得更有趣。(相关说明:干得好,危地马拉!)

与本文中的大多数其他图表不同,我在 Illustrator 中制作了这个径向柱形图。据我所知,Excel 里是没办法做出来的。

说实话,我对径向柱形图百感交集。一方面,它非常引人注目,可以很好地配合“达到我们的目标”的主题。另一方面,读者很难比较数值,因为没有两列是真正并排的。

为了帮助解决这个问题,我添加了标签和微弱的同心环。标签告诉读者精确的数值,而环帮助读者测量距离,就像 Excel 默认的条形图一样。

3.圆环图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

啊,我们的老朋友甜甜圈图。不久前,我写了一篇关于环形图的文章,但要点是:环形图本质上是饼图和条形图的混合体。你读它就像一个条形图,但它有一个友好的,有空间意识的饼图形状。

你会注意到我这里用的是面积,而不是百分比。这是一排百分比的图表。这是表示数据的错误方式——您能看出为什么吗?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

This donut chart is WRONG — please don’t do this!

这不仅仅是百分比加起来不到 100。如果你把数字分组,人们会认为它们所代表的事物属于同一类。

在横道图中,将百分比放在单独的行上可以清楚地看出每个数字代表了不同的 T4 国家的覆盖率。但是当我把这些百分比放到同一个饼状图中时,他们现在似乎说这些国家保护了同一块陆地的 17%、13%和 22%——完全不正确。

4.堆积横排图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你空间有限,也许是时候把你的鸭子排成一排了。堆叠横排图将数据排成一行,因此所有数据都在一条相对较窄的线上。把它想象成一个展平的圆环图——这就是为什么面积而不是百分比又回来了。

和圆环图一样,我们需要小心我们的暗示。堆积一行百分比会发出与第二个圆环图相同的不正确的信息。

5.泡泡图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在气泡图中,每个圆圈的面积反映了数字的大小——在这种情况下,是每个国家受保护土地的百分比。之前,我已经讨论了使用圆形的挑战和潜在的陷阱,但是我知道,如果你正在寻找一种友好、引人注目的方式来表示数据,圆形仍然是很棒的。

我已经在上面的例子中排列了泡泡,但是你也可以根据你布局的需要将它们聚集成一个圆形或者其他形状。别忘了你的标签!当数值相对接近时(如上),它们可以帮助读者进行精确的比较,从而化险为夷。

6.核标准情报中心

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

圈子很好玩,但是和手头的话题没有太大关系。在这里,我用树木代替了我们的泡泡来代表受保护的森林覆盖。

我喜欢对所有类别使用相同的图标,以帮助我的读者直接比较国家。如果美国有一个松果,萨尔瓦多有一片香蕉叶,每个图标的差异可能会掩盖不同的大小。简而言之:保持简单,让你的数据闪闪发光。

7.点阵

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点阵对于突出整体的一部分非常有用。在上面的例子中,我们仅用它来说明美国的土地保护。整个矩阵代表所有美国土地,而橙色圆圈代表已被保护的部分。

像本文中的其他图表一样,您仍然需要注意如何组合您的数字。如果你想比较这三个国家,你可以把三个矩阵并排放在一起——但明显是分开的。如果他们走得太近,你可能会给你的读者错误的想法。

点阵也可以很好地组合多个类别——只要这样做有意义。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在上面的例子中,我重新计算了每个国家的保护区,这次是作为整个北美大陆的一部分。通过在同一个矩阵中为每个国家使用不同的颜色,我可以显示每个国家对整体的贡献。

8.象形图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

象形图用图像取代了条形图中枯燥的矩形;在这种情况下,我们的老朋友森林。在我的图表中,每一个百分点都有一棵树,但是你总是可以以不同的方式缩放——一棵树可以代表 5%或 10 万平方公里,这取决于你对数据的需求。

9.Choropleth

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

choropleth 使用颜色饱和度来表示值;在上面的例子中,它是每个国家保护的土地的百分比。

标签对于 choropleth 地图来说非常重要,因为你的读者不能只盯着你的地图说*“是的,那个橙色的阴影刚好占 17%。”颜色给你的读者一个关于价值的暗示,但是你仍然需要一个标签来完成这个想法。*

我在 Illustrator 中制作了这些,但显然也可以使用插件在 Excel 中制作它们。这个教程好像知道怎么回事 —试一试请反馈!

10.那个大的旧号码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后但并非最不重要的:大老的号码。如果你只有 1-2 个数字需要强调,简单地写出来也没什么不好。

记住:永远不要为了说明而说明;只有对你的读者有帮助的时候才这么做!

Excel、Word 和许多其他在线和离线工具可以为你冰冷的、硬邦邦的数据带来一点艺术性。

你最喜欢哪个条形图?我错过了哪些?

请在下面的评论中告诉我们!

原载于 2017 年 5 月 30 日hypsypops.com

Apache Kafka 和 Apache Flume 入门(将数据导入 HDFS)

原文:https://towardsdatascience.com/apache-kafka-and-flume-installation-guide-import-data-from-kafka-to-hdfs-c908b0df034c?source=collection_archive---------5-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image Source: www.kafka.apache.org

本文包含 Apache Kafka 安装、创建 Kafka 主题、发布和订阅主题消息的完整指南。此外,它还包含 Apache Flume 安装指南以及如何使用 Apache Flume 将 Kafka 主题消息导入 HDFS。

1.总说明

  • Hadoop 版本:3.1.0
  • 阿帕奇卡夫卡版本:1.1.1
  • Apache Flume 版本:1.8.0
  • 操作系统:Ubuntu 16.04
  • Java 版本:Java 8

2.先决条件

2.1.安装 Java

阿帕奇卡夫卡需要 Java。要确保安装了 Java,首先更新操作系统,然后尝试安装它:

sudo apt-get updatesudo apt-get upgradesudo add-apt-repository -y ppa:webupd8team/javasudo apt-get install oracle-java8-installer

2.2.安装动物园管理员

Apache Kafka 需要安装 Zookeeper 服务,因为它使用它来维护节点心跳、配置和选举领导者。

sudo apt-get install zookeeperd

默认情况下,zookeeper 使用端口 2181,安装后会自动运行。使用 telnet 命令检查 Zookeeper 是否正在运行:

telnet localhost 2181

当 telnet 提示符打开时,写下“你还好吗”命令:

ruok

如果一切正常,它将返回 imok 消息。

2.3.创建具有 sudo 权限的非超级用户帐户

因为 Kafka 是一个网络应用程序,它可能使用多个节点,所以最好创建一个具有 sudo 权限的服务用户。

sudo adduser — system — no-create-home — disabled-password — disabled-login kafkauser

3.安装和配置 Kafka 服务器

3.1.下载卡夫卡

首先,我们需要下载 Kafka 二进制包。

wget [http://www-eu.apache.org/dist/kafka/1.1.1/kafka_2.11-1.1.1.tgz](http://www-eu.apache.org/dist/kafka/1.1.1/kafka_2.11-1.1.1.tgz)

现在,我们需要提取 tgz 包。我们选择将 Kafka 安装在/opt/kafka 目录中:

sudo tar xvf kafka_2.11–1.1.1.tgz -–directory /opt/kafka -–strip 1

Kafka 将它的日志存储在磁盘上的/tmp 目录下,最好创建一个新的目录来存储日志

sudo mkdir /var/lib/kafkasudo mkdir /var/lib/kafka/data

3.2.配置 Kafka

现在,我们需要编辑 Kafka 服务器配置文件。

sudo gedit /opt/kafka/config/server.properties

默认情况下,Kafka 不允许我们删除主题。为了能够删除主题,找到并更改该行(如果没有找到,就添加它)。

delete.topic.enable = true

现在,我们需要更改日志目录:

log.dirs=/var/lib/kafka/data

此外,我们可以调整日志删除的时间间隔(Kafka 在特定时间后或根据磁盘大小删除日志):

log.retention.hours=168 # according to timelog.retention.bytes=104857600 # according to disk size

3.3.更改目录权限

我们需要在日志目录和 kafka 安装目录上授予 kafkauser 访问权限:

sudo chown –R kafkauser:nogroup /opt/kafkasudo chown –R kafkauser:nogroup /var/lib/kafka

3.4.开始卡夫卡

要启动 Apache Kafka 服务,可以使用以下命令:

sudo /opt/kafka/bin/kafka-server-start.sh /opt/kafka/ config/server.properties

如果服务器已经成功启动,您应该会看到以下输出:

[2018–07–23 21:43:48,279] WARN No meta.properties file under dir /var/lib/kafka/data/meta.properties (kafka.server.BrokerMetadataCheckpoint)[2018–07–23 21:43:48,516] INFO Kafka version : 0.10.0.1 (org.apache.kafka.common.utils.AppInfoParser)[2018–07–23 21:43:48,525] INFO Kafka commitId : a7a17cdec9eaa6c5 (org.apache.kafka.common.utils.AppInfoParser)[2018–07–23 21:43:48,527] INFO [Kafka Server 0], started (kafka.server.KafkaServer)[2018–07–23 21:43:48,555] INFO New leader is 0 (kafka.server.ZookeeperLeaderElector$LeaderChangeListener)

要将 Kafka 作为后台进程启动,可以使用 nohup 命令

sudo nohup /opt/kafka/bin/kafka-server-start.sh /opt/kafka/ config/server.properties /var/lib/kafka/data/kafka.log 2>&1 &

现在,您有一个 Kafka 服务器正在运行并监听端口 9092。

3.5.启动时将 Kafka 作为服务启动

首先,我们需要在/etc/systemd/system 中创建一个服务单元文件

sudo gedit /etc/systemd/system/kafka.service

卡夫卡.服务

[Unit]Description=High-available, distributed message brokerAfter=network.target[Service]User=kafkaExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties[Install]WantedBy=multi-user.target

此外,使用可以将日志转发到另一个文件,这样您系统日志就不会被占用

ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties > /opt/kafka/server.log

要启动创建的服务,请使用以下命令:

sudo systemctl start kafka.service

在操作系统启动时自动启动服务

sudo systemctl enable kafka.service

您可以使用以下命令检查您的服务状态:

sudo systemctl status kafka.service

3.6.使用卡夫卡主题

3.6.1.创造一个卡夫卡主题

要创建 Kafka 主题,我们必须使用 kafka-topics.sh 脚本文件,并且我们需要指定 zookeeper 地址、复制因子、分区因子和主题名称:

/opt/kafka/bin/kafka-topics.sh — create — zookeeper localhost:2181 — replication-factor 1 — partitions 1 — topic testKafka

3.6.2.列出可用主题

要列出所有主题,请使用以下命令:

/opt/kafka/bin/kafka-topics.sh — list — zookeeper localhost:2181

3.6.3.发布和订阅消息

要将消息发布到主题中,我们必须使用 kafka-console-producer.sh 脚本,并且我们必须指定 kafka 服务器地址和主题名称:

/opt/kafka/bin/kafka-console-producer.sh — broker-list localhost:9092 — topic testKafka

然后,我们需要打开另一个终端,并使用 kafka-console-consumer.sh 脚本创建一个订户。我们需要传递 Kafka 服务器地址和主题名称

/opt/kafka/bin/kafka-console-consumer.sh — bootstrap-server localhost:9092 — topic test — from-beginning

在第一个终端(生产者)中,输入任意消息(例如:Hello!!)它必须出现在第二个终端中。

3.6.4.将文本文件导入 Kafka 主题

要在 Kafka 主题中打开一个文本文件,您需要使用带有管道的 cat 命令:

cat filename.txt | /opt/kafka/bin/kafka-console-producer.sh — broker-list localhost:9092 — topic testKafka

3.7.Kafka 多节点集群

此外,我们可以在多个节点上运行它,以实现数据冗余和意外故障转移。假设我们有 3 个节点:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们需要遵循我们之前提到的相同步骤,并添加一些内容:

1.在/opt/Kafka/config/server . properties 中:

a.每个节点必须有一个唯一的 broker.id 属性

for node-2 broker.id=1for node-3 broker.id=2

b.更改 zookeeper.connect 的值,使其列出所有带有端口的 zookeeper 主机

zookeeper.connect=10.0.1.1:2181,10.0.1.2:2181,10.0.1.3:2181

2.我们必须改变动物园管理员的设置。使用编辑器 sudo gedit/etc/zookeeper/conf/zoo . CFG 打开 zoo.cfg 文件,并添加以下几行:

server.0=10.0.1.1:2888:3888server.1=10.0.1.2:2888:3888server.2=10.0.1.3:2888:3888

3.重新启动 Zookeeper 服务

sudo systemctl restart zookeeper.service

4.安装和配置 Apache Flume

要从 Kafka 主题中读取消息并存储到 HDFS 中,我们需要安装 Apache Flume。该应用程序用于将非结构化和半结构化数据存储到 HDFS 中。

4.1.下载水槽

首先,我们需要下载 apache flume 二进制包

wget “http://www-eu.apache.org/dist/flume/1.8.0/apache_flume-1.8.0-bin.tar.gz"

现在我们需要提取。gz 包。我们选择将 Kafka 安装在/opt/kafka 目录中:

sudo tar -xvf apache_flume-1.8.0-bin.tar.gz –-directory /opt/flume –-strip 1

4.2.配置水槽

您需要编辑**“/etc/profile”**、 ~/。bashrc" 文件并添加以下几行

export FLUME_HOME= /opt/flumeexport PATH=$PATH:$FLUME_HOME/bin/

要应用这些更改,请使用 source ~/。巴沙尔司令部。

完成后,flume 代理会自动启动。要确保 flume 安装成功,您可以运行以下命令:

flume-ng –help

要将数据导入 HDFS,首先我们需要在您的主目录中创建一个日志文件。

gedit ~/access.log

写入任何数据并保存。

在/opt/flume/conf 中创建一个文件 “flume.conf” 文件,并将以下数据写入其中:

flume1.sources = kafka-source-1flume1.channels = hdfs-channel-1flume1.sinks = hdfs-sink-1flume1.sources.kafka-source-1.type = org.apache.flume.source.kafka.KafkaSourceflume1.sources.kafka-source-1.zookeeperConnect = localhost:2181flume1.sources.kafka-source-1.topic = testKafkaflume1.sources.kafka-source-1.batchSize = 100flume1.sources.kafka-source-1.channels = hdfs-channel-1flume1.channels.hdfs-channel-1.type = memoryflume1.sinks.hdfs-sink-1.channel = hdfs-channel-1flume1.sinks.hdfs-sink-1.type = hdfsflume1.sinks.hdfs-sink-1.hdfs.writeFormat = Textflume1.sinks.hdfs-sink-1.hdfs.fileType = DataStreamflume1.sinks.hdfs-sink-1.hdfs.filePrefix = test-eventsflume1.sinks.hdfs-sink-1.hdfs.useLocalTimeStamp = trueflume1.sinks.hdfs-sink-1.hdfs.path = /data/kafka/%{topic}/%y-%m-%dflume1.sinks.hdfs-sink-1.hdfs.rollCount=100flume1.sinks.hdfs-sink-1.hdfs.rollSize=0flume1.channels.hdfs-channel-1.capacity = 10000flume1.channels.hdfs-channel-1.transactionCapacity = 1000

请注意,flume1 是 flume 代理名称。

下面,一些参数描述:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,您需要运行 flume 代理从 Kafka 主题中读取数据,并将其写入 HDFS。

flume-ng agent -n flume1 -c conf -f flume.conf — Dflume.root.logger=INFO,console

注意:代理名称由-n FileAgent 指定,并且必须与-f conf/flume.conf 中给出的代理名称相匹配

数据现在将通过以下路径转储到 HDFS 位置

/tmp/kafka/%{topic}/%y-%m-%d

%{topic} > >卡夫卡题目名称

%y-%m-%d >

5.参考

[1]“阿帕奇卡夫卡官方文档”,阿帕奇,[在线]。可用:http://kafka.apache.org。【访问日期 2018 年 07 月 15 日】。

[2]“Apache Flume 官方文档”,Apache,[在线]。可用:http://flume.apache.org。【访问时间 2018 年 07 月 20 日】。

[3] Sarad,“如何在 Ubuntu 16.04 上安装 Kafka”,Hevo,2017 年 8 月 20 日。【在线】。可用:【https://hevodata.com/blog/how-to-install-kafka-on-ubuntu. 【2018 年 06 月 30 日获取】。

[4]“15 分钟内完成 Kafka 设置”,ETL-Tools,[在线]。可用:http://ETL-tools . info/en/examples/Kafka-setup-in-15-minutes . htm .【25 07 2018 访问】。

[5] hitjethva,“在 Ubuntu 16.04 上安装和配置 Apache Kafka”,DevOps,2016 年 10 月 3 日。【在线】。可用:https://devo PS . profit bricks . com/tutorials/install-and-configure-Apache-Kafka-on-Ubuntu-1604-1/。【访问时间 2018 年 07 月 15 日】。

[6] M. Litwintschik,“Hadoop 3 单节点安装指南”,2018 年 3 月 19 日。【在线】。可用:http://www . tech . marksblogg . com/Hadoop-3-single-node-install-guide . html【2018 年 10 月 06 日访问】。

[7]“栈溢出问答”,栈溢出,[在线]。可用:https://www.Stackoverflow.com。

[8] Gwen Shapira 和 Jeff Holoman,“Flafka: Apache Flume 遇到 Apache Kafka 进行事件处理”,Cloudera,2014 年 11 月 6 日。【在线】。可用:http://blog . cloud era . com/blog/2014/11/flafka-Apache-flume-meets-Apache-Kafka-for-event-processing/。【访问日期 2018 年 06 月 15 日】。

[9] S. Team,“Apache Flume 安装教程—初学者指南”,Data Flair,2016 年 8 月 22 日。【在线】。可用:https://data-flair . training/blogs/Apache-flume-installation-tutorial。【访问日期 2018 年 06 月 20 日】。

Apache Spark 的 n00bs 指南

原文:https://towardsdatascience.com/apache-spark-101-3f961c89b8c5?source=collection_archive---------1-----------------------

我写这篇指南是为了帮助我理解 Spark 的基本底层功能,它在 Hadoop 生态系统中的位置,以及它如何在 Java 和 Scala 中工作。我希望它能像帮助我一样帮助你。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

什么是火花?

Spark 是一个通用计算引擎,在内存框架中。它允许您以脚本方式在各种语言中执行实时和批处理工作,具有强大的容错能力。你为什么要关心火花是什么?坦率地说,它解决了 Hadoop MapReduce 的许多缺点,比 Hadoop MapReduce 快 10 到 100 倍。 Spark 是数据科学的大事;使用 Spark 的一些著名组织有:亚马逊、NASA 喷气推进实验室、IBM 和日立。这篇文章的目标是给你一个关于 Spark 提供的功能,它的基本内部工作的快速概述,并让你对 Spark 有多棒有所了解。

激发大数据环境中的背景

Spark 被设计为与外部集群管理器或它自己的独立管理器一起工作。Spark 也依赖于分布式存储系统来运行,它从该系统中调用它想要使用的数据。支持以下系统:

集群管理器:

  • Spark 独立管理器
  • Hadoop 纱线
  • 阿帕奇 Mesos

分布式存储系统:

  • Hadoop 分布式文件系统(HDFS)
  • MapR 文件系统(MapR-FS)
  • 卡桑德拉
  • OpenStack Swift
  • 亚马逊 S3
  • 条纹羚

出于健康的原因,我将只关注 Hadoop 生态系统环境中的 Spark。

Spark Core 提供了一个平台,解决了 Hadoop MapReduce 的许多缺点,因为它允许我们不再需要将任务分解为小的 atom 作业,也不再需要与在分布式系统开发上构建解决方案的复杂性进行争论。

赛门铁克注: 术语 Hadoop 可互换使用,指 Hadoop 生态系统Hadoop MapReduceHadoop HDFS 。在网上看到“Spark 取代 Hadoop”或“Spark 是新的 Hadoop”的说法是很常见的,然后倾向于相信他们的意思是 Spark 正在取代所有的 Hadoop 服务,但是!他们真正的意思是,Spark 正在许多用例中扮演 Hadoop MapReduce 功能的角色。

Spark Core 非常通用,在设计时就考虑到了 Hadoop 生态系统;它可以与 MapReduce 一起工作,或者为 PIG、HIVE 和 SEARCH 提供一个替代平台。参见图 1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Spark Core 还带来了自己的一套有用的 API:

Spark Streaming: 管理来自各种来源的实时数据。它允许通过在实时流上实现 ML Lib 和 Graphx 来计算实时结果。

GraphX: 一个非常强大的处理图形并行计算的库。不要把这个和“Power Point graphs”混淆,这个库是关于数学中的一个领域,叫做图论和对象间成对关系的建模。

ML Lib: 在原生分布式环境中对大型数据集运行机器学习算法的库。与 Python 或 Matlab 中更强大的机器学习库相比,该库仍处于起步阶段。

Spark SQL: 允许使用 SQL 采石场来挖掘非关系分布式数据库。

Spark Steaming、GraphX、MLLib 和 Spark SQL 都将在适当的时候获得自己的文章,但与此同时,请不要犹豫,去查阅官方文档【1】【2】【3】【4】

什么会产生火花,火花?

在最高的抽象层次上,Spark 由三个组件组成,这三个组件使它成为唯一的 Spark;司机、执行者和 DAG。

司机和执行者

Spark 采用主从架构。驱动程序协调许多分布式工作器,以便以分布式方式执行任务,而资源管理器处理资源分配以完成任务。

驾驶员

把它想象成“管弦乐队”。驱动程序是主方法运行的地方。它将程序转换成任务,然后将任务调度给执行器。司机有三种不同的方式与执行者沟通;Broadcast、Take、DAG——这些稍后会详细说明。

执行者——“工人”

执行器在 JVM 实例中执行驱动程序委派的任务。执行器在 Spark 应用程序开始时启动,通常在应用程序的整个生命周期内运行。这种方法允许在应用程序的整个生命周期中,当不同的任务被载入和执行时,数据被持久化在内存中。

与此形成鲜明对比的是,Hadoop MapReduce 中的 JVM 工作环境会针对每个任务关闭和打开。其结果是,Hadoop 必须在每个任务的开始和结束时对磁盘执行读写操作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

驱动程序与执行器的通信

驱动程序可以通过几种方法与执行器通信。作为开发人员或数据科学家,了解不同类型的通信及其用例非常重要。

  1. 广播动作:驱动程序将必要的数据传输给每个执行器。此操作最适用于一百万条记录以下的数据集,即+/-1gb 的数据。这项行动可能会成为一项非常昂贵的任务。
  2. 采取行动:驱动程序从所有执行者那里获取数据。这个动作可能是非常昂贵和危险的动作,因为驱动程序可能耗尽存储器,并且网络可能变得不堪重负。
  3. DAG 动作:这是三个动作中花费最少的一个。它将控制流逻辑从驱动程序传输到执行器。

系统要求

Spark 比 Hadoop MapReduce 有相当大的性能增益,但它也有较高的操作成本,因为它在内存中操作,并需要高带宽网络环境(建议+10Gb/s)。建议 Spark 集群中的内存至少应与您需要处理的数据量一样大。如果没有足够的内存来完成一项任务,Spark 有几种方法可以将数据溢出到磁盘上。了解更多硬件要求和建议。

达格

DAG 是一个有向无环图,它概括了从 A 点到 b 点所需的一系列步骤。Hadoop MapReduce 与大多数其他计算引擎一样,独立于 DAG 工作。这些独立于 DAG 的计算引擎依赖于 HIVE 或 PIG 等脚本平台将作业链接在一起,以实现所需的结果。Spark 在比较中的强大之处在于它能够识别 DAG 并主动管理 DAG。这使得 Spark 能够优化作业流以获得最佳性能,并允许回滚和作业冗余功能。

请看图 3。我将通过讨论 DAG 的组件来详细说明它是如何工作的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1)来源

数据源可以是 Spark 支持的任何数据源。其中包括:HDFS、关系数据库、CSV 文件等。稍后您将看到,我们在环境上下文设置中对此进行了定义。

2) RDD

弹性分布式数据集本质上是不能改变的数据集。这些实体存在于记忆中,并且本质上是不可改变的。由于这种不变性;在现有 RDD 上执行每次转换后,都会创建一个新的 RDD。这种设计的结果是冗余;如果在 DAGs 执行中的任何一点出现故障,则可以回滚到正常工作状态,并重新尝试失败的操作/转换。

原始形式的 rdd 没有模式,但是可以使用一种叫做 DataFrames 的东西来扩展。DataFrames 向其中包含的数据集添加模式功能;这在处理关系数据集时非常有用。

3)转型

转变把一个 RDD 变成了另一个 RDD。一些示例转换包括:

  1. 地图
  2. reduceByKey
  3. GroupByKey
  4. JoinByKey
  5. SparkSQL

4)行动

动作是检索数据以回答问题的任何东西。一些例子是:数一数,各取所需。

执行 DAG
Spark 做了一件叫做懒惰评估的事情。DAG 本身是由转换构建的,但是在调用动作之前什么也不会发生。当一个动作被执行时,Spark 将查看 DAG,然后在它需要执行什么工作来达到它被要求做的动作步骤的上下文中优化它。当 DAG 最终被执行时,驱动程序向集群上的执行器发出转换命令。

阿帕奇水槽 API

Apache Flume 的开发理念是允许开发人员使用适用于非分布式编程的相同代码创建可以在分布式系统上运行的程序。换句话说,Apache Flume 允许我们编写可以在单线程和多线程机器上运行的代码,没有任何问题。Apache Flume 的含义是,我们现在可以在本地机器上运行代码并进行调试,同时确保它可以在我们的 Spark Hadoop 集群上运行。更进一步的含义是,您可以从集群中提取数据,并在本地机器上运行它,以进行测试和开发。

支持以下语言:

  • 斯卡拉
  • Java 语言(一种计算机语言,尤用于创建网站)
  • 计算机编程语言
  • 稀有

为了演示 Spark 的一些内部工作方式,我将在 ScalaFlume 和 JavaFlume 中运行一个字数统计示例。

在 Scala 中

第 1 到 2 行初始化我们的 Spark 上下文并定义我们的源。在第 3 行,我们定义了初始 RDD。在第 4 到 6 行中,我们定义了我们的 RDD 的转换,并定义了一些新的 RDDS。注意第 7 行,没有代码被执行;只有我们的达格人建立起来了。在第 7 行,我们终于有了一个执行转换的动作。值得注意的是,分布在集群中的唯一工作是蓝色的,因为那些 lambda 表达式是由执行程序运行的转换!其他一切都在驱动程序上执行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Scala 宣传侧记: Scala 是一种构建在 JVM 编译器之上的令人惊叹的语言。它为具有 OOP 背景的开发人员提供了一个环境,使他们能够轻松地适应函数式编程思维,这是分布式计算编程的最佳选择。Scala 通过同时支持面向对象和函数式编程范例来做到这一点。你为什么要在乎?Spark 是使用 Scala 构建的,因此 Spark 中的最新特性将总是首先在 Scala 中实现。与其他语言相比,Scala 在处理大型数据集时也提供了最好的性能——举个例子:Scala 大约比 Python 快 10 到 225 倍,这取决于用例。Scala 也被数据科学和分布式计算领域的一些大公司使用,比如亚马逊和谷歌。我希望这段宣传已经说服了你,至少给 Scala 一个好奇的眼神。

在 JAVA 中

蓝色突出显示的代码是转换并构建 DAG。更重要的是,注意本质上每个转换都是一个对象,然后被发送到所有的分布式执行器。这也发生在 Scala 示例中,但是 lambda 表达式隐藏了这一层交互。在驱动程序执行第 27 行中的动作代码(用红色突出显示)之前,集群中的执行器不会执行转换对象。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

最后,我希望这篇文章能够帮助您理解 Spark 成为如此有趣和强大的数据科学和数据工程平台的基础。

这篇文章的要点应该是:

  • Spark Core 可以与 Hadoop MapReduce 并行工作,或者取代它。
  • Spark 比其他计算引擎快!火花速度来自于这样一个事实,即认知的 DAG,并可以优化它;它通过在整个作业中保持 JVM 状态,将数据保存在内存中,最终目标是最小化对磁盘的 I/O。
  • Spark 有一些很棒的数据科学和数据工程 API,用于机器学习、图论、数据流和 SQL。
  • Spark 中需要认知的主要组件是驱动程序和执行程序。这两个组件通过由 Spark 直接管理的 DAG 进行操作。有一种称为转换的东西,它构建 DAG 并从现有的 RDD 生成新的 RDD。RDD 是一个不可变的数据实体,它提供:借助 DAG 实现冗余和回滚功能。DAG 仅在动作被执行后才被执行。
  • Apache Flume 允许您在本地机器上用少数几种成熟的编程语言编写程序,用于开发和调试目的。同样的 Apache Flume 代码可以部署到一个分布式系统中,不需要任何修改。Scala 太棒了。

文献学

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值