朴素贝叶斯(Python)

发布于 2020-06-04  1808 次阅读


朴素贝叶斯简介

朴素贝叶斯算法,它的数学基础是贝叶斯原理,与其他统计学推断方法截然不同,它是建立在主观判断的基础上:在我们不了解所有客观事实的情况下,同样可以先估计一个值,然后根据实际结果不断进行修正。可表达为下图:

朴素贝叶斯是一种统计方法,贝叶斯原理是一种数学概率原理

而在不同条件情况下,事件概率也不相同:

以此种理论为基础产生了朴素贝叶斯这种算法,朴素贝叶斯的所谓“朴素”就是指假设各个分类条件相互独立互不影响干扰,这样算法就能简单很多,但是在实际情况下也不免会有一定误差,生活中真正相互独立的理想化特征还是不多的。

朴素贝叶斯算法的核心内容就是这个式子:

其中右边的概率在数据学习的过程中都是可以得到的,比如说分类要依靠到新闻内容中的某些特征关键字,则学习过程相当于已知文章的类别,去寻找它的一些特征关键词,而文章类别出现的频率和特征关键词在所有文章中的出现频率都是可以统计并计算出来的,从而得到在某些特征出现时预测该文章为某类型的概率。

Python代码

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score
from sklearn.multiclass import OneVsRestClassifier
from sklearn.pipeline import Pipeline
if __name__ == '__main__':
    path = 'D:\\datasource\\'         
    df = pd.read_excel(path + 'our_data.xlsx')  # 读取数据集
    # print(df['sentiment_1'].value_counts())
    # print(df['sentiment_2'].value_counts())
    lens = df.news_content.str.len()   # 统计新闻正文长度
    lens.hist(bins=np.arange(0, 5000, 50))
    plt.show()
    # 一共七类
    sentiment_vocab = ['agreeable', 'believable', 'good', 'hated', 'sad', 'worried', 'objective']
    df = pd.concat([df, pd.DataFrame(columns=sentiment_vocab)], axis=1)
    df = df.fillna(0)           # 若有缺失值,自动填充为0
    # 构造数据集格式,类别标签一共七列,0代表不属于该类,1代表属于
    # 详情可见print(df)输出
    for i in range(len(df)):
        sentiment_1 = df['sentiment_1'].loc[i]
        sentiment_2 = df['sentiment_2'].loc[i]
        if sentiment_1 in sentiment_vocab:
            df[sentiment_1].loc[i] = 1
        if sentiment_2 in sentiment_vocab:
            df[sentiment_2].loc[i] = 1
    print(df)
    # 划分数据集-> 85%作为训练集,15%作为测试集
    # 训练集用于训练情感分类模型,测试集用于测试训练后的模型精度
    train, test = train_test_split(df, random_state=42, test_size=0.15, shuffle=True)
    X_train = train.news_content            # 训练数据为新闻正文
    X_test = test.news_content              # 测试数据为新闻正文
    # Define a pipeline combining a text feature extractor with multi lable classifier
    NB_pipeline = Pipeline([
        ('tfidf', TfidfVectorizer(ngram_range=(1, 2), min_df=3, max_df=0.9, strip_accents='unicode', use_idf=1)),
        ('clf', OneVsRestClassifier(MultinomialNB(
            fit_prior=True, class_prior=None))),
    ])
    # for循环,依次训练这七个情感分类器
    for category in sentiment_vocab:
        print('... Processing {}'.format(category))
        NB_pipeline.fit(X_train, train[category])       # 训练
        prediction = NB_pipeline.predict(X_test)        # 预测
        # print(prediction)
        # compute the testing accuracy
        print('Test accuracy is {}'.format(accuracy_score(test[category], prediction)))
        # 预测两个新闻标题
        result = NB_pipeline.predict_proba(['Detection of asymptomatic cases coronavirus and pass alert experts',
                                            'Map of the expansion of the coronavirus'])
        print(result)       # 第一个数代表是概率,第二个代表不是的概率

对大概需要用到的包的说明:

Scikit-learn(sklearn)是机器学习中常用的第三方模块,对常用的机器学习方法进行了封装,是一种简单高效的数据挖掘和数据分析工具。
Xlrd 是 python 中拿来读取 excel 的库,因为我们用的是 xlsx 格式的 excel数据库,所以这个库需要额外安装。
matplotlib 是基于 Python 语言的开源项目,旨在为 Python 提供一个数据绘图包。
Pandas 用来见检查读写数据,并可以进行绘图统计。
Numpy 支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
pip 是 Python 包管理工具,该工具提供了对 Python 包的查找、下载、安装、卸载的功能。

数据集

接到的任务是分析新闻的情感数据,一共整合了数据1211条,大小1603KB,经过人工标注,各种类型情感分布如下图。

新闻内容长度条形统计图:

数据集特征包括:

file_id(可自行编号),news_id(数据集中已有),sentiment1(必须有),sentiment2(可为 none,部分新闻标注了两个情感),ischina(值为 yes或者 no)五个特征。

代码种划分了85%的数据作为训练集,15%的数据作为测试集。

测试结果

最终准确率如下:

但是高准确率的类型不是真的模型和数据比较完美,而是这些情感类型的数据太少,都判断对了那么准确率就高,但是寥寥几篇新闻完全不能说明它的准确性。以 1000+篇的客观类型来看,84.6%的准确率还是比较可观的,在算法的独立性假设的前提下和我们标注数据会有不准确的情况下,这个结果总体说来还算比较成功。


华科菜鸡计科学生