欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python_sklearn机器学习算法系列之sklearn.naive_bayes朴树贝叶斯算法

程序员文章站 2024-03-22 13:08:46
...

       本文主要目的是通过一段及其简单的小程序来快速学习python 中sklearn的naive_bayes这一模块的基本操作和使用,注意不是用python纯粹从头到尾自己构建贝叶斯算法,既然sklearn提供了现成的我们直接拿来用就可以了,当然其原理十分重要,这里做一下简单介绍:

P(A|B)=P(A)×P(B|A)/P(B)
用文字表述:后验概率=先验概率×相似度/标准化常量
而朴素贝叶斯算法要解决的问题就是如何求出相似度即:P(B|A)的值[属性/特征]

所谓朴素就是假设属性之间相互独立即P(B|A)=P(B1|A)P(B2|A)P(B3|A)P(B4|A)

scikit-learn根据不同场景提供了三种常用的朴素贝叶斯算法:
如果样本特征的分布大部分是连续值,使用GaussianNB会比较好。
如果样本特征的分大部分是多元离散值,使用MultinomialNB比较合适。例如文本分类单词统计,以出现的次数作为特征值,https://www.jianshu.com/p/845b16559431
如果样本特征是二元离散值或者很稀疏的多元离散值,应该使用BernoulliNB。

三种算法的详细讲解见https://www.cnblogs.com/pinard/p/6074222.html

好了直接看代码(其中都有详细的注释)

GaussianNB:

#GaussianNB(高斯)类
from sklearn import datasets
from sklearn.naive_bayes import GaussianNB
import numpy as np
iris=datasets.load_iris()

#核心代码:其实fit后面还有一个参数即fit(X, y, sample_weight=None),sample_weight表各样本权重数组,假如一共训练8个样本
#则可以写为clf.fit(iris.data[:8], iris.target[:8],sample_weight=np.array([0.05,0.05,0.1,0.1,0.1,0.2,0.2,0.2]))
clf=GaussianNB()
clf.fit(iris.data,iris.target)


'''
#GaussianNB一个重要的功能是有 partial_fit方法,这个方法的一般用在如果训练集数据量非常大,一次不能全部载入
#内存的时候。这时我们可以把训练集分成若干等分,重复调用partial_fit来一步步的学习训练集,非常方便
#在第一次调用partial_fit函数时,必须制定classes参数,在随后的调用可以忽略
clf.partial_fit(iris.data, iris.target,classes=[0,1,2])

'''

#学习后模型中的一些参数
clf.set_params(priors=[0.333, 0.333, 0.333])#这里要设一下各个类标记对应的先验概率,如果不设置直接clf.priors返回的是None(不知道为什么?)
print(clf.priors)                           #获取各个类标记对应的先验概率
print(clf.class_prior_ )                    #同priors一样,都是获取各个类标记对应的先验概率,区别在于priors属性返回列表,class_prior_返回的是数组
print(clf.get_params(deep=True))            #返回priors与其参数值组成字典

print(clf.class_count_)                     #获取各类标记对应的训练样本数
print(clf.theta_)                           #获取各个类标记在各个特征上的均值
print(clf.sigma_)                           #获取各个类标记在各个特征上的方差



#测试数据
data_test=np.array([6,4,6,2])
data=data_test.reshape(1,-1)
Result_predict=clf.predict(data)
Score=clf.score([[6,8,5,3],[5,3,4,2],[4,6,7,2]],[2,0,1],sample_weight=[0.3,0.5,0.2])

Result_predict_proba=clf.predict_proba(data)
Result_predict_log_proba=clf.predict_log_proba(data)
print(Result_predict)                                                               #预测所属类别
print(Result_predict_proba)                                                         #输出测试样本在各个类标记上预测概率值
print(Result_predict_log_proba)                                                     #输出测试样本在各个类标记上预测概率值对应对数值
print(Score)                                                                        #返回测试样本映射到指定类标记上的得分(准确率)

运行结果:

python_sklearn机器学习算法系列之sklearn.naive_bayes朴树贝叶斯算法

MultinomialNB:

#详细地址请见:https://www.jianshu.com/p/845b16559431
import warnings
import numpy as np
from sklearn import metrics
from scipy.stats import sem
from sklearn.pipeline import Pipeline
from sklearn.datasets import fetch_20newsgroups
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer, HashingVectorizer, CountVectorizer

#忽略一些版本不兼容等警告
warnings.filterwarnings("ignore")
from sklearn.cross_validation import cross_val_score, KFold


news = fetch_20newsgroups(subset='all')

'''
#测试news,来了解数据集的构成
print (news.keys())
print (type(news.data), type(news.target), type(news.target_names))
print (news.target_names)
print(news.data[0])
print(news.target_names[news.target[0]])
print (len(news.data))
print (len(news.target))

'''

#原样本有18846个,为了运行快这里只抽取了样本中的188个样本进行实验,即用x_Reduced_sample1,y_Reduced_sample1进行实验
x_Reduced_sample1, x_Reduced_sample2 , y_Reduced_sample1, y_Reduced_sample2 = train_test_split(news.data, news.target, test_size = 0.99)

#划分训练集和测试集(76个)
x_train, x_test, y_train, y_test = train_test_split(x_Reduced_sample1, y_Reduced_sample1, test_size = 0.4)


#pipeline来将多个学习器组成流水线,通常流水线的形式为: 
#将数据标准化的学习器---特征提取的学习器---执行预测的学习器
#除了最后一个学习器之外,前面的所有学习器必须提供transform方法,该方法用于数据转化(例如:归一化,正则化,以及特征提取)
# CountVectorizer,HashingVectorizer,TfidfVectorizer是三种构建特征向量的工具
nbc_1 = Pipeline([
    ('vect', CountVectorizer()),
    ('clf', MultinomialNB()),
                ])
warnings.filterwarnings("ignore")
nbc_2 = Pipeline([
    ('vect', HashingVectorizer(non_negative=True)),
    ('clf', MultinomialNB()),
                ])
nbc_3 = Pipeline([
    ('vect', TfidfVectorizer()),
    ('clf', MultinomialNB()),
                ])
nbcs=[nbc_1, nbc_2, nbc_3]


#分类评价机制:k-折叠交叉验证
def evaluate_cross_validation(clf, X, y, K):
    # 最基础的CV算法,也是默认采用的CV策略,地址见http://blog.sina.com.cn/s/blog_7103b28a0102w70h.html
    cv = KFold(len(y), n_folds=K, shuffle=True, random_state=0)
    # k-折叠交叉验证地址见https://blog.csdn.net/evillist/article/details/61912827
    scores = cross_val_score(clf, X, y, cv=cv)
    #换分K组后每组的准确率(是一个数组)
    print(scores)
    #数组中准确率的平均值(越高越好)
    print(np.mean(scores))
    #数组中准确率平的均值标准误差。
    print(sem(scores))

#测试CountVectorizer,HashingVectorizer,TfidfVectorizer是三种构建特征向量的工具的性能
for nbc in nbcs:
    evaluate_cross_validation(nbc, x_train, y_train, 5)


'''

#优化特征提取提高分类的效果系列

#1:TfidfVectorizer的一个参数token_pattern用于指定提取单词的规则
#  默认的正则表达式是ur"\b\w\w+\b",这个正则表达式只匹配单词边界并考虑到了下划线,也可能考虑到了横杠和点。
#  新的正则表达式是ur"\b[a-z0-9_\-\.]+[a-z][a-z0-9_\-\.]+\b"
#2:TfidfVectorizer的一个参数stop_words这个参数指定的词将被省略不计入到标记词的列表中,
#  比如一些出现频率很高的词(英文中的a或者and等),但是这些词对于特定的主题不能提供任何的先验支持。
#3:MultinomialNB有一个alpha参数,该参数是一个平滑参数,默认是1.0,我们将其设为0.01
#!!!!!!!!!!但是1和2方案运行不通过不知道什么原因,去掉就可以
def get_stop_words():
    result = set()
    for line in open('stopwords_en.txt', 'r').readlines():
        result.add(line.strip())
    return result
stop_words= get_stop_words()
print(stop_words)
nbc_4 = Pipeline([
    ('vect', TfidfVectorizer(
                stop_words=stop_words,                                  #运行时去掉才行(不知道为什么?)
                token_pattern='ur\b[a-z0-9_\-\.]+[a-z][a-z0-9_\-\.]+\b',#运行时去掉才行(不知道为什么?)   
    )),
    ('clf', MultinomialNB(alpha=0.01)),
                ])

evaluate_cross_validation(nbc_4,x_train, y_train, 5)

'''
#fit_prior:布尔型,可选项,默认True,表示是否学习先验概率,参数为False表示所有类标记具有相同的先验概率
#class_prior:类似数组,数组大小为(n_classes,),默认None,是先验概率的值
#具体见https://blog.csdn.net/kancy110/article/details/72763276
nbc_5 = Pipeline([
    ('vect', TfidfVectorizer()),
    ('clf', MultinomialNB(alpha=0.01, class_prior=None, fit_prior=True)),
                ])
#核心代码
nbc_5.fit(x_train,y_train)
y_predict = nbc_5.predict(x_test)

print(nbc_5.score(x_test, y_test))                     #预测准确率
print(metrics.classification_report(y_test,y_predict)) #包含准确率,召回率等信息表
print(metrics.confusion_matrix(y_test,y_predict))      #混淆矩阵

'''
正如https://blog.csdn.net/kancy110/article/details/72763276介绍的那样如果有的场景直接用
MultinomialNB()时就可以完成任务,而不是先通过构建特征向量的工具时,学习后的模型还有很多参数可以看
包括:
class_log_prior_:各类标记的平滑先验概率对数值,其取值会受fit_prior和class_prior参数的影响
intercept_:将多项式朴素贝叶斯解释的class_log_prior_映射为线性模型,其值和class_log_propr相同
feature_log_prob_:指定类的各特征概率(条件概率)对数值,返回形状为(n_classes, n_features)数组
等等

'''

运行结果为:

python_sklearn机器学习算法系列之sklearn.naive_bayes朴树贝叶斯算法

python_sklearn机器学习算法系列之sklearn.naive_bayes朴树贝叶斯算法

BernoulliNB:

#伯努利朴素贝叶斯算法:类似于多项式朴素贝叶斯,也主要用户离散特征分类,
#和MultinomialNB的区别是:MultinomialNB以出现的次数为特征值,而BernoulliNB的特征值为二进制或布尔型特性
import numpy as np  
from sklearn.naive_bayes import BernoulliNB
x=np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[5,6,9,8]])  
y=np.array([1,1,2,3])

#核心代码
clf=BernoulliNB(alpha=2.0,binarize = 3.0,fit_prior=True)
clf.fit(x,y)

'''
#训练后学习模型中的参数
print(np.log(2/4))
print(np.log(1/4))
print(np.log(1/4))
print(clf.class_log_prior_)   #对比上面,这是先验概率对数值,类先验概率等于各类的个数/类的总个数

print(clf.feature_log_prob_ ) #指定类的各特征概率(条件概率)对数值
print(clf.class_count_)       #按类别顺序输出其对应的个数
print(clf.feature_count_)     #各类别各特征值之和,按类的顺序输出,返回形状为[n_classes, n_features] 的数组(不懂?)

'''


#测试数据
x_test=[[1,2,2,5],[7,6,10,9]]                           #数据不能是分数
y_test_predict=clf.predict(x_test)
y_predict_proba=clf.predict_proba(x_test)
y_test_predict_log_proba=clf.predict_log_proba(x_test)
print(y_test_predict)                                   #在测试集x_test上预测,输出x_test对应目标值
print(y_predict_proba)                                  #输出测试样本划分到各个类别的概率值
print(y_test_predict_log_proba)                         #输出测试样本划分到各个类别的概率值的对数
print(clf.score([[3,4,5,4],[1,3,5,6]],[1,3]))           #输出对测试样本的预测准确率的平均值,当然可以加权值这个参数score(X, y, sample_weight=None) 

运行结果:

python_sklearn机器学习算法系列之sklearn.naive_bayes朴树贝叶斯算法

更多算法可以参看博主其他文章,或者github:https://github.com/Mryangkaitong/python-Machine-learning