数据挖掘算法之使用朴素贝叶斯进行文本分类

目录

  1. 概率论相关概念介绍
  2. 贝叶斯法则和朴素贝叶斯
  3. 文本分类

一:概率论基本概念总结
随机变量:描述事件所有可能出现的状态
随机变量分为:离散型随机变量(硬币)和连续型随机变量(汽车行驶速度)
概率:用数值描述一件事发生的可能性,事件A发生的概率用P(A)表示
概率分布:描述每个状态发生的概率
先验概率:指根据以往经验和分析得到的概率。比如抛掷一枚硬币,正面朝上的概率。
后验概率:后验概率的计算要以先验概率为基础。后验概率可以根据通过贝叶斯公式,用先验概率和似然函数计算出来。
条件概率:事件B发生的条件下,事件A发生的概率。表示为P(A|B)
独立事件:事件B发生或不发生对事件A不产生影响,就说事件A与事件B之间存在某种“独立性”。P(AB)=P(A)P(B),则称事件A,B相互独立,简称A,B独立.
联合概率:由两个或两个以上变量共同决定的概率称为联合概率
比如A和B同时发生的概率,就是联合概率。记作:P(A,B)或P(B,A)
联合概率:是条件概率和概率的乘积.
P(A,B)=P(A|B)*P(B)
P(B,A)=P(B|A)*P(A)
P(A,B)=P(B,A)=P(A|B)*P(B)=P(B|A)*P(A)
如图:
在这里插入图片描述
事件A记作:考90-100的学生,P(A)=4➗20=20%
事件B记作:男生,P(B)=10➗20=50%
那么考90-100男生的概率,可以记作P(A,B)=2➗20=10%。
男生中,考90-100的概率,就是在B发生的条件下,A发生的概率:
P(A|B)2➗10=20%。表示男生中,考90-100的概率
P(A,B)=P(A|B)*P(B)=20%*50%=10%
P(A,B)=P(B|A)*P(A)=50%*20%=10%
P(B|A)表示:在90-100的学生中,男生的概率=2➗4=50%
==>P(A|B)*P(B)=P(B|A)*P(A)
==>P(A|B)=P(B|A)*P(A)/P(B)
我们再通过这个例题,来熟悉一下这个公式。
例题:
过年了,爷爷奶奶发红包,有2种类型的红包,50元的和100元的。但爷爷奶奶没有告诉我们他们每种类型的红包是多少个。已知,抽到爷爷的红包概率是7/13,抽到奶奶的红包概率是6/13,抽到100元的概率是6/13,抽到爷爷红包中是100元的概率是4/7。那么请听题,如果抽到了一个100元的红包,这个红包是爷爷的概率是多少
事件A:爷爷的红包
事件B:100元的红包
抽到爷爷红包中是100元的概率是:P(B|A)
求:抽到100元红包,红包是爷爷的概率:P(A|B)
P(A)=7/13,P(B)=6/13,P(B|A)=4/7,那么P(A|B)=P(B|A)*P(A)➗P(B)=2/3。

二:贝叶斯法则
2.1:贝叶斯简介
P(A|B)=P(B|A)*P(A)/P(B),这就是经典的贝叶斯法则。
它的数学核心思想就是通过先验概率和条件概率计算后验概率。
贝叶斯用语言来描述就是:当我们不能准确预知一个事物本质的时候,我们可以依靠和事物本质相关的事件来进行判断,来推测这个事物的本质。
比如,我们怎么推测一个人是有钱人呢?有没有钱,关我x事。

2.2:贝叶斯原理是怎么来的?
贝叶斯先生为了解决一个叫“逆向概率”问题写了一篇文章,尝试解决在没有太多可靠证据的情况下,怎样对一件事物做出更符合数学逻辑的推测。

2.3:什么是“逆向概率”呢?
所谓“逆向概率”是相对“正向概率”而言的。正向概率的问题很容易理解,比如我们已经知道袋子里有10个球,6个黑球,4个白球。那么我们伸手摸一个球,就能预测摸出黑球的概率是多少。
但这种情况往往是上帝视角,也就是已经了解了事情的全貌再做判断。
在现实生活中,我们很难知道事情的全貌,如果知道了,那还努力做个啥。
贝叶斯先生从实际场景出发,提出了一个问题:如果我们事先不知道袋子里面黑球和白球的比例,我们是否可以通过摸出来球的颜色,多次重复实验,来推测出袋子里面黑白球的比例呢?
贝叶斯是建立在主观判断的基础上,在我们不了解客观事实的情况下,经过多次实验,估计一个值,然后根据实际结果不断修正。这也就是学习和机器学习的哲学。大家有什么见解吗?

2.4:朴素贝叶斯
文字描述:在贝叶斯的基础上,假设每个输入的变量是独立的。这是一个很强硬的假设,实际情况是不一定的。但通过这个假设,依然可以解决大部分的复杂问题,而且可以大大提高效率。
比如我们判断文章A属于分类C的概率。接下来,在文本分类中讲。

2.5:朴素贝叶斯法则使用场景:
1.最常用的就是文本分类,情感分析、垃圾邮件识别。这三个场景本质上都是文本分类。
2.对新闻分类(比如给用户推送新闻,根据用户的喜好来推荐新闻,要实现推荐算法,非常重要的就是给新闻进行分类)。推荐算法:
3.垃圾邮件识别、情感分析(通过用户评论,推测用户对产品的喜欢)
4.NLP (Natural Language Processing)自然语言处理

三:文本分类
3.1:现在有一篇文章,判断它属于以下四个分类(政治、金融、体育、娱乐)的哪个分类,怎么判断呢?
思路:我们要对这篇文章进行分词,然后计算每个单词属于这个分类的概率,然后求得组成这篇文章的词语属于这个分类的联合概率。我们就推测这篇文章属于最大概率的分类。

上面我们总结出:P(A|B)=P(B|A)*P(A)/P(B)我们来改进一下这个公式。
已知文章A,由词组W[W1,W2,W3,…WN]组成。

求文章A属于分类C的概率,就是求W[W1,W2,W3,…Wn]属于分类C的概率。朴素贝叶斯中认为,每个输入的变量是独立的,那么也就是
P(C|A)=>P(C|W)=>P(C|W1W2W3…WN)=>P(C|W1)*P(C|W2)*P(C|W3)…*P(C|Wn)

理解:我们求一篇文章属于某个分类的概率,也就是求组成这篇文章的词语属于这个分类的概率。
所以现在我们只需要求一个单词属于这个分类的概率,然后累积。
P(C|W1)=P(W1|C)*P©➗P(W1),会在3.2.3说明。

3.2文本分类的步骤
(1)采集训练样本
采集大量的文章,然后给每一篇文章打上类型标签,这篇文章属于政治、金融、体育、娱乐。
采集方法:人工手动采集入库、从第三方开放平台获取、爬虫获取https://h5.mgzf.com/find
(2)对训练样本进行预处理
我们需要对文本进行转化,让计算机能够理解文本。常用的方法:分词,把一篇文章,转化为一组词语。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import jieba

# 分词效果展示
text = '保持安静,文明阅读'
word_list = list(jieba.cut(text))  # 中文分词

print(word_list)
# ['保持', '安静', ',', '文明', '阅读']

(3)训练模型,获得朴素贝叶斯分类器
训练模型:通过训练数据进行算法模型拟合的过程。
对于朴素贝叶斯而言,训练的过程就是要获取每个分类的先验概率、每个属性的先验概率以及给定某个分类时,出现某个属性的条件概率。
P(C|W1)=P(W1|C)*P©➗P(W1)
P(C|W1):出现单词W1时,属于分类C的概率。
P(W1|C):根据统计,得到分类c中出现单词W1的概率。
P©:分类C在训练数据中出现的概率。
P(W1):单词W1在训练样本中出现的概率。
(4)使用分类器对文章分类预测
把通过训练的算法模型,计算这篇文章属于各个分类的概率,取最大概率的类型。
对于朴素贝叶斯而言,分类预测的过程就是根据训练阶段所获得的先验概率和条件概率,来预估给定一系列属性的情况下属于某个分类的后验概率。
理解看图:图片来源网络
在这里插入图片描述
TIP:随着小数的不断累乘,积会趋近于0,计算机会无法处理,这时候可以采用log,让小数变为绝对值大于1的负数。
使用朴素贝叶斯进行文本分类源码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'naruto'
# __datetime__ = 2019/2/14 14:04

import os
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn import metrics

'''
1.读取训练集和测试集文档
2.对文档进行分词 中文使用jieba(里面包含了中文的停用词、分分词方法),英文使用NTLK(包含了停用词、分词、标注方法)
3.加载停用词表 自己设置停用词文档
4.计算单词的权重TF-IDF值,获得特征矩阵,获得特征矩阵
5.训练模型,获得朴素贝叶斯分类器。这里使用多项式朴素贝叶斯分类器。
(把特征训练集的train_features以及训练集对应的train_labels传递给贝叶斯分类器,
会自动生成一个符合特征空间和对应分类的分类器)
6.使用生成的分类器做预测。predict函数:就是求解后验概率并返回最大的那个。
7.计算准确率。把实际结果和预测结果进行对比。
'''
LABEL_MAP = {'体育': 0, '女性': 1, '文学': 2, '校园': 3}
# 加载停用词
with open('./stopword.txt', 'rb') as f:
    STOP_WORDS = [line.strip().decode('utf-8') for line in f.readlines()]


def load_data(base_path):
    """
    :param base_path: 基础路径
    :return: 分词列表,标签列表
    """
    documents = []
    labels = []
    i = 0

    for root, dirs, files in os.walk(base_path):  # 循环所有文件并进行分词打标
        for file in files:

            label = root.split('/')[-1]  # 因为windows上路径符号自动转成\了,所以要转义下
            if label == 'train' or label == 'test':
                continue
            labels.append(label)
            filename = os.path.join(root, file)
            with open(filename, 'rb') as f:  # 因为字符集问题因此直接用二进制方式读取
                content = f.read().decode('gb18030')
                word_list = list(jieba.cut(content))
                words = [wl for wl in word_list]
                documents.append(' '.join(words))

    return documents, labels


def train_fun(td, tl, testd, testl):
    """
    构造模型并计算测试集准确率,字数限制变量名简写
    :param td: 训练集数据
    :param tl: 训练集标签
    :param testd: 测试集数据
    :param testl: 测试集标签
    :return: 测试集准确率
    """
    # 计算单词的权重TF-IDF值,获得特征矩阵
    tt = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5)
    tf = tt.fit_transform(td)
    # 训练模型,获得朴素贝叶斯分类器
    clf = MultinomialNB(alpha=0.001).fit(tf, tl)
    # 获取测试集的特征矩阵,使用生成的分类器做预测
    test_tf = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5, vocabulary=tt.vocabulary_)
    test_features = test_tf.fit_transform(testd)
    predicted_labels = clf.predict(test_features)
    # 计算模型的准确率
    x = metrics.accuracy_score(testl, predicted_labels)
    return x


def test_fun(train_documents, train_labels, test_document):
    """
    构造模型并计算测试集准确率,字数限制变量名简写
    :param td: 训练集数据
    :param tl: 训练集标签
    :param testd: 测试集数据
    :param testl: 测试集标签
    :return: 测试集准确率
    """
    # 计算单词的权重TF-IDF值,获得特征矩阵
    tt = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5)
    tf = tt.fit_transform(train_documents)
    # 训练模型,获得朴素贝叶斯分类器
    clf = MultinomialNB(alpha=0.001).fit(tf, train_labels)
    # 获取测试集的特征矩阵,使用生成的分类器做预测
    test_tf = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5, vocabulary=tt.vocabulary_)
    test_features = test_tf.fit_transform(test_document)

    predicted_labels = clf.predict(test_features)
    return predicted_labels


# calculate_accuracy()
# 计算分类器的准确率
def calculate_accuracy():
    global train_documents, train_labels, test_documents, x
    # 获取训练数据
    train_documents, train_labels = load_data('./train')
    # 获取测试数据
    test_documents, test_labels = load_data('./test')
    print(test_documents)
    # 计算模型准确率
    x = train_fun(train_documents, train_labels, test_documents, test_labels)
    print(x)


'''
有四个分类,体育、女性、文学、校园
'''


def show(text):
    global train_documents, train_labels, x
    # 获取训练数据
    train_documents, train_labels = load_data('./train')
    # 分词效果展示
    word_list = list(jieba.cut(text))  # 中文分词
    words = [wl for wl in word_list]
    document_list = []
    document_list.append(' '.join(words))
    print(document_list)
    result = test_fun(train_documents, train_labels, document_list)
    print(result)


# 效果展示
text = '人们都说:“生命在于运动。”的确,生命在于运动。同样,每个人也都有自己喜欢的体育运动,而我也有一项我喜欢的体育运动,那就是:“足球。” 我自己认为足球是一项非常有趣的,并且可以使脑筋变得聪明的运动,包括它的技战术演练以及的时候,都可以让你的头脑灵敏起来,视野开阔起来,从而脑子也变得灵敏起来。 我认为足球给我带来了欢乐,每当我进了球或是长途奔袭的时候,那种兴奋与快感无法形容,尤其是进球以后,那种成就感在心中猛然升起,让人难以忘怀。 足球带给我的不仅是快乐,还是动力,它激励着我,激励我更加努力学习,因为我知道,如果想在社会上立足,不管是什么职业,如果没有学历,别人是不会用你的。每当我迷惘,消沉,觉得前途渺茫的时候,足球的声音便会突然在我耳畔响起,激励着我更加努力学习。 我还有一支崇拜的球队:“德国勒沃库森队。'
show(text)

参考文章:
1.极客时间《程序员的数学基础课》
2.极客时间《数据分析实战》

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值