数据挖掘实战(七)--使用朴素贝叶斯进行社会媒体挖掘

一、朴素贝叶斯分类算法

贝叶斯定理公式如下:

表示“在A发生的情况下,B发生的概率”。

在数据挖掘中,A通常是观察样本个体(也就是物特征),B为被测个体所属的类别。那么上述公式如下:

我们可以用上述公式进行分类。但是一个物体包含多个特征。对于公式

我们先假设特征1,特征2,特征3...相互独立,那么,有以下结论:

所以有以下公式:

因此,朴素贝叶斯公式如下:

因为

在所有的类别取值相同,所以贝叶斯的判定标准为:

我们已经能够计算出不同特征的特征值在不同类别下的P值(或者说比较标准h),然后我们通过P值的大小,以判断某一条数据属于哪一个类别。

朴素贝叶斯算法优缺点

优点: 在属性相关性较小时效果较好,可以处理多类别问题;算法逻辑简单,易于实现 ;

缺点: 在属性个数比较多或者属性之间相关性较大时,分类效果不好;

二、加载数据集

我们实验的目的是根据消息的内容,判断消息中的Python是不是指编程语言。在数据集中,数据是以json格式保存的,在json中“text”表示推文内容:

# 推文数据集
data_file = './data/python_tweets.json'
# 类别数据集
class_file = './data/python_classes.json'

data_list = []
class_list = []

# 加载推文
with open(data_file) as f:
    for line in f:
        # 如果内容为空
        if(len(line.strip()) == 0):
            continue
        data_list.append(json.loads(line)["text"])
# 加载类别
with open(class_file) as f:
    class_list = json.loads(f.read())
import numpy as np
class_list = np.array(class_list)
data_list = np.array(data_list)

数据集我们已经加载完毕了,然后我们就要从文本中提取特征。

三、文本转换器

文本的语言、长短以及来源都是一种特征,根据不同的需求我们需要提取不同的特征。那怎么把文本转换成算法可以处理的形式呢?

多种测量方法能够帮上忙。比如,平均词长和平均句长可用来预测文本的可读性。除此之外,还有很多其他类型的特征,比如我们接下来要用到的单词是否出现。

词袋模型:统计数据集中每一条推文中每种单词出现的情况。有多种统计方法:

  • 统计每一种单词出现的次数。比如说“go go go, come on”中"go"出现了三次

  • 统计每一种单词出现的词率。比如说“go go go, come on”中"go"的词频是(包括逗号)

  • 统计每一种单词是否出现。比如说“go go go, come on”中"go"出现了为True

  • 词频-逆文档频率法

这里我们使用第三种方法,那么首先第一个步骤就是我们得对其进行分词。与中文的jieba分词类似,不过这里我们是将一个单词分为一个词。这里使用NLTK库进行分词,使用如下:

from nltk import word_tokenize
wt = word_tokenize("long time no see, i miss you very much.")
print(wt)

这里我们自定义一个转换器,目的是对数据集进行预处理。在下面的代码中主要是对推文进行分词,然后将出现过的词进行保存。

class NLTKBOW(TransformerMixin):
    def fit(self, X, y=None):
        return self
    def transform(self,X):
        #         words = []
        #         for document in X:
        #             words_dict = defaultdict(int)
        #             for word in word_tokenize(document):
        #                 words_dict[word] += 1
        #             words.append(words_dict)
        #         return words
        return [
            {
                word: True for word in word_tokenize(document)
            }for document in X
        ]
n = NLTKBOW()
xn = n.fit_transform(data_list)

for i in range(len(xn)):
    print("第{0}条推文:\t".format(i+1))
    print('{')
    for key in xn[i]:
        print(key+":"+str(xn[i][key])+",")
    print("}")

通过转化,部分数据如下:

四、字典转化成矩阵

通过上面的操作我们获得了一个字典的列表,但是对于sklean的分类器,它并不直接支持这些数据格式的操作,所以,我们需要将这些数据转成矩阵,这里我们可以使用DictVectorizer(也是一个转化器,可以用于流水线)进行操作。举个官方的例子:

from sklearn.feature_extraction import DictVectorizer
D = [{'foo': 1, 'bar': 1}, {'foo': 1, 'baz': 1}, {'baz': 1, 'dd': 1}]
dv = DictVectorizer(sparse=False)
y = dv.fit_transform(D)
x = dv.feature_names_
print(x)
print(y)

五、创建流水线

因为本章使用朴素贝叶斯算法,数据集只包含二值特征,因此 我们使用专门用于二值特征分类的 BernoulliNB 分类器 。

# 1)用NLTK的word_tokenize函数,将原始文档转换为由单词及其是否出现组成的字典
# 2)用scikit-learn中的DictVectorizer转换器将字典转换为向量矩阵,这样朴素贝叶斯分类器就能使用第一步中抽取的特征
from sklearn.feature_extraction import DictVectorizer
# 3)训练朴素贝叶斯分类器
from sklearn.naive_bayes import BernoulliNB
from sklearn.pipeline import Pipeline
pipline = Pipeline([('布袋模型转换器', NLTKBOW()),
                    ('字典列表转矩阵', DictVectorizer(sparse=True)),
                    ('朴素贝叶斯分类器', BernoulliNB())], verbose=True)
from sklearn.model_selection import cross_val_score
scores = cross_val_score(pipline, data_list, class_list, scoring='accuracy')
print("Score: {}".format(np.mean(scores)))

scoring='accuracy',准确率为63%

scoring='f1',准确率为40%

六、从模型中获取更多有用的特征

借助流水线的named_steps属性和步骤名(创建流水线对象时,我们自己定义的),就能访问流水线每一个步骤。例如,可以像下面这样访问分别访问布袋模型转换器、字典列表转矩阵和朴素贝叶斯模型。

model = pipline.fit(data_list, class_list)
nk = model.named_steps['布袋模型转换器'].fit_transform(data_list)
print(nk)
dv = model.named_steps['字典列表转矩阵'].fit_transform(nk)
# 打印特征名
fea_name = model.named_steps['字典列表转矩阵'].feature_names_
print(fea_name)
# 按COO的存储方式打印稀疏矩阵
print(dv)

nk:对每条推文进行分词并保存为字典,字典的key就是一个词。

fea_name:691个特征。经过DictVectorizer转换器将字典转化成矩阵后,矩阵的列标签(也就是特征)。

dv:[95,691] 经过DictVectorizer(sparse=True)转化的矩阵,sparse参数:是否存储为稀疏矩阵。稀疏矩阵的存储方式有多种,如:DOK(Dictionary of keys)、COO(Coordinate list)、CSR和CSC。本节我们选择的是DOO。DOO坐标格式:三个数组row,col,value,分别存储非零元素坐标的行,列以及非零值。理论上稀疏矩阵中的元素在存储时顺序是任意的,但是为了方便元素访问,存储时先按照先左后右,先上后下顺序进行存储(left to right, top to buttom)。如下所示。(0,11)代表第一条推文中特征索引值为11对应的特征(即‘-’)出现了一次,(0,74)代表第一条推文中特征索引值为74对应的特征出现了一次。(94,156)代表第95条推文中特征索引值为156对应的特征出现了一次。

从模型中抽取每个单词的对数概率,类BernoulliNB的feature_log_prob_属性,指定类的各特征概率(条件概率)对数值。

# 抽取每个单词的对数概率(每个单词为类别0和类别1的对数概率)
feature_probabilities = model.named_steps['朴素贝叶斯分类器'].feature_log_prob_  # 等价于 print(pipline.feature_log_prob_)
print(feature_probabilities)

# 按概率数组排序,选出所属类别1排名在前的几个特征,输出的是特征索引值,不是实际的特征名称。
top_features = np.argsort(feature_probabilities[1], axis=0)[:50]
print(top_features)

将特征索引值映射为特征名称。类DictVectorizer的feature_names_属性记录了特征名称和索引值的映射关系。通过在DictVectorizer的feature_names_属性中进行查找,找到最佳特征的名称。

for i, feature_index in enumerate(top_features):
    print(feature_index, model.named_steps['字典列表转矩阵'].feature_names_[feature_index],
          np.exp(feature_probabilities[1][feature_index]))

七、小结

(1)本章研究的是文本挖掘——特征的抽取、应用及扩展方法,具体研究任务是根据语境消除词语的歧义——即一条消息中的Python是否指编程语言。

(2)我们用朴素贝叶斯分类器对文本进行分类,该分类器是以贝叶斯定理为基础,它使用数据来更新模型,而不是像频率论者那样从模型出发。这有助于整合新数据到模型中,利用新数据来更新模型和使用先验知识。此外,基于各特征相互独立的朴素假设,便于计算各特征出现在给定类别的概率,而不用考虑各特征之间复杂的相关性。

(3)我们用词语是否出现作为特征值——即消息是否含有某个词,这种模型①叫作词袋模型。虽然它丢掉了词语在句子中的位置等信息,但它在很多数据集上表现不凡。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值