贝叶斯定理
条件概率:
A 在另外一个事件 B 已经发生条件下的发生概率
贝叶斯公式:
后验概率(新信息出现后的A概率) = 先验概率(A概率) x 可能性函数(新信息带来的调整)
先验概率(Prior probability)
不知道B事件的前提下,我们对A事件概率的一个主观判断。
对应这个例子里就是在不知道女神经常对你笑的前提下,来主观判断出女神喜欢一个人的概率。这里我们假设是50%,也就是不喜欢你,可能不喜欢你的概率都是一半。
可能性函数(Likelyhood)
这是一个调整因子,也就是将先验概率(之前的主观判断)调整到更接近真实概率。
可能性函数你可以理解为新信息过来后,对先验概率的一个调整。比如我们刚开始看到“人工智能”这个信息,你有自己的理解(先验概率-主观判断),但是当你学习了一些数据分析,或者看了些这方面的书后(新的信息),然后你根据掌握的最新信息优化了自己之前的理解(可能性函数-调整因子),最后重新理解了“人工智能”这个信息(后验概率)如果"可能性函数"P(B|A)/P(B)>1,意味着"先验概率"被增强,事件A的发生的可能性变大;如果"可能性函数"=1,意味着B事件无助于判断事件A的可能性;如果"可能性函数"<1,意味着"先验概率"被削弱,事件A的可能性变小。
后验概率(Posterior probability)
B事件发生之后,我们对A事件概率的重新评估。
这个例子里就是在女神冲你笑后,对女神喜欢你的概率重新预测。带入贝叶斯公式计算出P(A|B)=P(A)* P(B|A)/P(B)=50% *1.5=75%因此,女神经常冲你笑,喜欢上你的概率是75%。这说明,女神经常冲你笑这个新信息的推断能力很强,将50%的"先验概率"一下子提高到了75%的"后验概率"。
全概率公式:
有两个一模一样的碗,1号碗里有30个巧克力和10个水果糖,2号碗里有20个巧克力和20个水果糖。
然后把碗盖住。随机选择一个碗,从里面摸出一个巧克力。
问题:这颗巧克力来自1号碗的概率是多少?
朴素贝叶斯
它是一种简单但极为强大的预测建模算法。之所以称为朴素贝叶斯,是因为它假设每个输入变量是独立的。这是一个强硬的假设,实际情况并不一定
朴素贝叶斯做的就是,假设这些身高,体重,性别这些特征之间是没有关系的,互相不影响。那么我们算同时符合这三个特征概率的时候,就可以分开算了就是这个道理了。
1)计算最大的
即最大的
即最大的
2)
离散数据案例
给你一个新的数据:身高“高”、体重“中”,鞋码“中”,请问这个人是男还是女?
连续数据案例
如果给你一个新的数据,身高 180、体重 120,鞋码 41,请问该人是男是女呢?
这里的困难在于,由于身高、体重、鞋码都是连续变量,不能采用离散变量的方法计算概率。而且由于样本太少,所以也无法分成区间计算。怎么办呢?
这时,可以假设男性和女性的身高、体重、鞋码都是正态分布,通过样本计算出均值和方差,也就是得到正态分布的密度函数。有了密度函数,就可以把值代入,算出某一点的密度函数的值。(求连续型随机变量在某一个取值点的概率的时候,可以看当前概率密度函数在该点的函数值,值越大,概率越大。但当前概率密度函数的值不和概率相等,只可以比大小用)
比如,男性的身高是均值 179.5、标准差为 3.697 的正态分布。所以男性的身高为 180 的概率为 0.1069,男性体重为 120 的概率为 0.000382324,男性鞋码为 41 号的概率为 0.120304111。
所以我们可以计算得出:=0.1069 * 0.000382324 * 0.120304111=4.9169e-6
同理我们也可以计算出来该人为女的可能性:=0.00000147489 * 0.015354144 * 0.120306074=2.7244e-9
很明显这组数据分类为男的概率大于分类为女的概率。
sklearn
朴素贝叶斯分类常用于文本分类,尤其是对于英文等语言来说,分类效果很好。它常用于垃圾文本过滤、情感预测、推荐系统等。
- 高斯朴素贝叶斯:特征变量是连续变量,符合高斯分布,比如说人的身高,物体的长度。
- 多项式朴素贝叶斯:特征变量是离散变量,符合多项分布,在文档分类中特征变量体现在一个单词出现的次数,或者是单词的 TF-IDF 值等。注意, 多项式朴素贝叶斯实际上符合多项式分布,不会存在负数,所以传入输入的时候,别用StandardScaler进行归一化数据,可以使用MinMaxScaler进行归一化
- 伯努利朴素贝叶斯:特征变量是布尔变量,符合 0/1 分布,在文档分类中特征是单词是否出现。
MultinomialNB(*, alpha=1.0, fit_prior=True, class_prior=None)
- alpha :为平滑参数。为什么要使用平滑呢?因为如果一个单词在训练样本中没有出现,这个单词的概率就会被计算为 0。但训练集样本只是整体的抽样情况,我们不能因为一个事件没有观察到,就认为整个事件的概率为 0。为了解决这个问题,我们需要做平滑处理。
当 alpha=1 时,使用的是 Laplace 平滑。Laplace 平滑就是采用加 1 的方式,来统计没有出现过的单词的概率。这样当训练样本很大的时候,加 1 得到的概率变化可以忽略不计,也同时避免了零概率的问题。
当 0<alpha<1 时,使用的是 Lidstone 平滑。对于 Lidstone 平滑来说,alpha 越小,迭代次数越多,精度越高。我们可以设置 alpha 为 0.001。
import pandas as pd
import os
import jieba
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB, GaussianNB, BernoulliNB
from sklearn.metrics import accuracy_score
data = pd.read_csv('D:\gitcode\python\data\online_shopping_10_cats.csv')
print(data.head(10))
print(data.isnull().sum())
data.dropna(inplace=True)
print(data['cat'].value_counts())
data = data.sample(frac=0.1, random_state=1)
# 加载停用词
with open('D:\gitcode\python\data\chineseStopWords.txt', 'rb') as f:
STOP_WORDS = [line.strip() for line in f.readlines()]
LABEL_MAP = {'洗发水' : 0, '水果' : 1, '酒店' : 2, '衣服' : 3, '平板' : 4, '计算机' : 5, '书籍' : 6, '手机' : 7, '蒙牛' : 8, '热水器' : 9}
documents, labels = [], []
for i in range(len(data)):
d = data.iloc[i]
try:
word_list = list(jieba.cut(d['review']))
words = [w for w in word_list if w not in STOP_WORDS]
documents.append(' '.join(words))
labels.append(LABEL_MAP[d['cat']])
except:
print(i)
train_x, test_x, train_y, text_y = train_test_split(documents, labels)
# 计算TF-IDF矩阵
tfidf_vec = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5)
new_train_x = tfidf_vec.fit_transform(train_x) # (1570, 15065)
# 测试集用训练集的词典
test_tfidf_vec = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5, vocabulary=tfidf_vec.vocabulary_)
new_test_x = test_tfidf_vec.fit_transform(test_x)
# 建立模型
bayes_model = {}
bayes_model['MultinomialNB'] = MultinomialNB(alpha=0.001)
bayes_model['BernoulliNB'] = BernoulliNB(alpha=0.001)
bayes_model['GaussianNB'] = GaussianNB()
for item in bayes_model.keys():
clf = bayes_model[item]
clf.fit(new_train_x.toarray(), train_y)
pred = clf.predict(new_test_x.toarray())
print(item, "accuracy_score: ", accuracy_score(text_y, pred))
网友评论