Scikit Learn 中用于 SA 的朴素贝叶斯 - 它是如何工作的

数据挖掘 Python scikit-学习 朴素贝叶斯分类器 情绪分析
2021-09-17 11:57:36

好的,所以我从网络上抓取有关电影评论的数据。我也已经有了自己的“词典”或“词典”,其中包含单词及其标签(1-差,2-好,3-好,4-非常好,5-优秀)。

所以输入是电影评论的段落,我使用 Scikit Learn Naive Bayes 来评估每个评论的情绪,这将是一个段落。我想知道它在引擎盖下是如何工作的。我假设它使用了一个词袋概念。

所以,我正在描述我对 Scikit Learn Naive Bayes 如何为 SA 工作的假设。我离现实有多近?

我既不是数据科学家也不是统计学家,但这是我认为在 Scikit Learn 中用于情感分析的朴素贝叶斯算法中发生的事情的总结。

训练阶段

假设我对训练集中的每个段落都使用了 1、2、3、4、5 之类的标签。每个段落都是一个用于培训和评估的单元。

脚步 :-

1) 删除不需要的单词,例如 THE、BUT 和 AND 等

2)读第一个单词说“海滩”,从它的父段落中选择它的标签,说“5”。所以把 5 贴到 BEACH 上,然后放回袋子里。

3)因此,将每个单词与给定标签匹配的次数相加。输入段落中的多个标签可能会出现相同的单词“BEACH”。因此,计算给定单词的每个标签。所以也许 ['BEACH' - 标签 1 - 10]、['BEACH' - 标签 2 - 8] 等等。

4)对所有单词进行上述步骤后,总结给定单词获得某个标签的概率。所以“海滩”可能有标签 1 的 1/6 概率、2 的 2/6 概率、3 的 1/6 概率、4 的 1/6 概率和 5 的 1/6 概率。所以“海滩”的这 5 个概率被放回词袋中。从步骤 3 中删除 Word-label-count 实体,这些实体用于获得这些概率。所以现在每个词在袋子中最多可以有 5 个概率。

评估情绪分析 - 新数据

1)现在当我们输入真实数据时,当它遇到一个单词时,它会检查是否在它的包中找到它。如果不是,它会忽略它

2) 说它在一条评论中找到了 BEACH。它检查标签 2 的“海滩”的最高概率是 2/6。因此它为单词 BEACH 选择标签 2。类似地,它为包中与输入匹配的所有单词选择概率最高的对应标签。

3) 现在它总结了需要计算 SA 的段落的所有单词的所有标签。假设它们加起来为 20。它必须将这 20 转换为 0 到 1 之间的某个位置。所以它使用对数转换将 20 转换为 0 到 1 之间的某个位置。假设为 0.75。

4) 所以 0.75 是这条评论的权重。

这是它的工作原理吗?感谢您的任何意见。

2个回答

收集您的数据

根据您声明的评论,您希望将评论分类为标签(1-差、2-一般、3-好、4-好、5-非常好)。因此,您将训练一个模型,该模型将一组单词(段落)映射到一个代表评分的数字。我假设你也有一些评论的标签,我们称之为你的训练集

我无权访问您的数据,但我有一个类似的虚拟示例,它使用评论并试图将它们归类为对酒店或汽车租赁的评论。我认为这个例子很适合这个目的。

预处理数据

为此,我们可以使用许多技术。例如,一些流行词是bag-of-wordstf-idfn-grams这些技术将接受评论并将其矢量化为一组特征。我们将使用的特征是从训练集中学习的,然后对于进来的新评论也是一样的。我们将在这个例子中使用词袋。

词袋

这种方法有一个我们从训练集中识别出来的单词字典。我们在词干后取所有独特的词。然后我们计算每个单词在评论中出现的次数,即表示给定实例的向量。例如,如果我们的字典看起来像

['汽车','书','测试','哇']

评论是

哇,这车好厉害!!!!!!

结果向量将是

[1, 0, 0, 1]

我们将为每条评论重复这个矢量化过程。然后我们将得到一个矩阵,其中行代表每个评论,列代表这些词在评论中出现的频率。我们称这个矩阵X这是我们的数据集。这些实例中的每一个都有一个标签,我们称之为向量Y. 我们想将每一行映射到X 给它的标签 Y.

假设这是您在汽车/酒店评论的训练数据集中拥有 40 个实例的数据。右侧有相应的标签。标签 0 用于汽车,标签 1 用于酒店。

在此处输入图像描述

矩阵的列 X

['汽车', '乘客', '座位', '驱动器', '动力', '高速公路', '采购', '酒店', '房间', '夜', '工作人员', '水', '地点']

拆分数据

我们将拆分数据以测试模型的准确性

from sklearn.cross_validation import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3)

在此处输入图像描述

应用朴素贝叶斯

from sklearn.naive_bayes import GaussianNB

clf = GaussianNB()
clf = clf.fit(X_train, y_train)
clf.score(X_test, y_test)

这给出了一个结果

1.0

完美分类!


它是如何工作的?

高斯朴素贝叶斯假设每个特征都由高斯分布描述(您可以选择其他可能更适合您的数据的分布,例如多项式)。然后它将假设每个特征完全相互独立。因此我们可以说概率

P(Y=0|X)=P(X0|Y=0)P(X0)...P(Xn|Y=0)P(Xn)

P(Y=1|X)=P(X0|Y=1)P(X0)...P(Xn|Y=1)P(Xn)

为您 n特征。最大的将是我们的标签。如果P(Y=1|X)更大然后我们会说评论是汽车的评论。所以要做到这一点,我们需要训练我们的概率分布的参数P(Xi|Y). 要计算这个术语,我们需要知道分布的参数,在我们的例子中,我们使用的是高斯分布,因此我们需要均值和方差N(μ,θ).

我们将为每个标签构建一个值字典,其中包含每个特征的均值和方差。这是训练阶段!

自制朴素贝叶斯

import csv
import random
import math
import pandas as pd
import numpy as np

class NaiveBayes(object):

    def __init__(self):
        self.groupClass = None
        self.stats = None

    def calculateGaussian(self, x, mean, std):    
        exponent = np.exp(-1*(np.power(x-mean,2)/(2*np.power(std,2))))
        std[std==0] = 0.00001
        return (1 / (np.sqrt(2*math.pi) * std)) * exponent

    def predict(self, x):
        probs = np.ones((len(x), len(self.stats)))

        for ix, instance in enumerate(x):
            for label_ix, label in enumerate(self.stats):
                probs[ix, int(label)] = probs[ix, int(label)] * \
                                      np.prod(self.calculateGaussian(instance, self.stats[label][0], self.stats[label][1]))
        return np.argmax(probs, 1)

    def score(self, x, y):
        pred = self.predict(x)
        return np.sum(1-np.abs(y - pred))/len(x)

    def train(self, x, y):
        self.splitClasses(x, y)
        self.getStats()
        pass

    def splitClasses(self, x, y):
        groupClass = {}

        for instance, label in zip(x, y):
            if not label in groupClass:
                groupClass.update({label: [instance]})
            else:
                groupClass[label].append(instance)
        self.groupClass = groupClass

    def getStats(self):
        stats = {}

        for label in self.groupClass:
            mean = np.mean(np.asarray(self.groupClass[label]), 0)
            std = np.std(np.asarray(self.groupClass[label]), 0)
            stats.update({label: [mean, std]})
        self.stats = stats

clf = NaiveBayes()
clf.train(X_train, y_train)
clf.score(X_test, y_test)

我们再次在测试集上获得了 1.0 的准确度!

在朴素贝叶斯中,您需要两个值:

  • 每个班级的先验: p(cj) 是训练集中每个类的比例。
  • 每一项的条件概率 i 从关于每个类的文件中: p(wi|cj)=count(wi,cj)wVcount(w,cj) 这对应于单词的分数 wi 出现在类文档中的所有单词中 cj (V 是词汇)。

分类规则为 argmaxcjp(cj)p(w|cj)p(w|cj)=wip(wi|cj) 由于独立性假设。

为了防止下溢错误,我们经常使用日志: logp(w|cj)=wilogp(wi|cj)

因此,最后一个词是:要对文档(或段落或任何一段文本)进行分类,您需要对每个词进行分类 i 从中,对于每个班级 j,查看它出现在其中的次数(在类文档中 j),在训练数据中(这是一个概率),并把对数加起来。它会给你j 概率(每个类别一个),并且您选择对应于最大值的类别。

您的问题中不清楚的是标签和情绪分析之间的关系。

有关详细说明和示例,请参阅此内容。