机器学习之贝叶斯算法

首先,贝叶斯公式

                          

这个公式是由联合概率公式推导出来的:

P(A,B)=P(A|B)P(B)=P(B|A)P(A)

P(A)叫做先验概率,P(A|B)叫做后验概率,P(A,B)叫做联合概率

如果在机器学的视角下,我们把A理解成“类别标签”,把B理解成“具有某种特征”。这样贝叶斯公司可以理解为

而应用这个算法最常见的场景就是针对垃圾邮件的分类判断了

即,判断P(‘垃圾邮件’|‘具有某种特征’)  是否大于1/2

例如,我们收到一封邮件,里面的内如是“我司可以办理正规发票(保真)17%增值税发票点数优惠”。那么我们要做的就是

判断P(‘垃圾邮件’|‘我司可以办理正规发票(保真)17%增值税发票点数优惠’)是否大于1/2!

而这里我们又到用了分词技术。(如结巴分词等)

我们可以将这个公式转化成

P(‘垃圾邮件’|‘我司可以办理正规发票(保真)17%增值税发票点数优惠’)=P(‘垃圾邮件’|(‘我’,‘司’,‘可’,‘办理’,‘正规发                                                                                                                                  票’,‘保真’,‘增值税’,‘发票’,‘点数’,‘优惠’))

这里我们用A标示‘垃圾邮件’,B标示分词词组(‘我’,‘司’,‘可’,‘办理’,‘正规发票’,‘保真’,‘增值税’,‘发票’,‘点数’,‘优惠’)

根据贝叶斯公式可以将上式转换成

P(B|A)P(A)/P(B)形式

这里P(B|A)是P((‘我’,‘司’,‘可’,‘办理’,‘正规发票’,‘保真’,‘增值税’,‘发票’,‘点数’,‘优惠’)|‘垃圾邮件’)

而根据传说中的条件独立假设

可以将P((‘我’,‘司’,‘可’,‘办理’,‘正规发票’,‘保真’,‘增值税’,‘发票’,‘点数’,‘优惠’)|‘垃圾邮件’)转换成

P(‘我’|‘垃圾邮件’)*P(‘司’|‘垃圾邮件’)*....*P(‘点数’|‘垃圾邮件’)*P(‘优惠’|‘垃圾邮件’)

这样,这个例子里面就转换成了对P(‘我’|‘垃圾邮件’)等的概率计算。我们在训练集中,需要进行统计得出这个写概率

例如,P(‘发票’|‘垃圾邮件’)=垃圾邮件中所有‘发票’出现的次数/垃圾邮件中所有词语出现的次数

这样整个判断垃圾邮件的分类问题,就转换成了一个统计概率问题。这种分类问题就能得以解决。

上述这种增加了条件独立假设的贝叶斯方法叫做朴素贝叶斯方法。由上面的例子可以看出,朴素贝叶斯方法是很简单的。

但是,但是,但是

朴素贝叶斯存在这一个问题,就是在它眼里是没有词语之间的顺序的。

如刚才上例。

P((‘我’,‘司’,‘可’,‘办理’,‘正规发票’)|‘垃圾邮件’)=P(‘我’|‘垃圾邮件’)*P(‘司’|‘垃圾邮件’)*...*P(‘正规发票’|‘垃圾邮件’)

由于乘法满足交换律,那么上面可以认为是

P(‘我’|‘垃圾邮件’)*P(‘司’|‘垃圾邮件’)*...*P(‘正规发票’|‘垃圾邮件’) = P(‘正规发票’|‘垃圾邮件’)*...*P(‘司’|‘垃圾邮件’)*P(‘我’|‘垃圾邮件’)=P((‘正规发票’,‘可’,‘办理’,‘我’,‘司’)|‘垃圾邮件’)

这个语句就尴尬了!

不过,朴素贝叶斯在实际应用中的效率是很高的。效果好的出奇。

这里我们继续介绍

朴素贝叶斯的三种模型

1,多项式模型

      重复的词语我们视为其出现多次

2,伯努利模型

      重复的词语我们只视为出现一次。这种方法更加简洁和简单,但是它丢失了词频信息,最后的效果也差一些。

3,混合模型

      在计算句子的概率时,不考虑词语出现的次数,但是在统计计算词语的概率(例如P(‘词语’|‘垃圾邮件’))时,考虑重复词语出现的次数

                              

平滑技术

平滑技术是针对于那些在验证是没有出现过的词,它们的概率是0,在贝叶斯算法中如果乘以0的话就会失去意义。所以要对这些进行平滑处理。

这里的平滑处理就是对分子进行加1处理。即拉普拉斯平滑处理法(使每一个未出现的词语出现一次)。

平滑技术不止这一种方法。还有很多,平滑技术是一种很复杂的处理技术。

还有古德图灵平滑,线性插值法,回退法(K-Z回退)等

最常见应用场景

  • 文本分类/垃圾文本过滤/情感判别:这大概会朴素贝叶斯应用做多的地方了,即使在现在这种分类器层出不穷的年代,在文本分类场景中,朴素贝叶斯依旧坚挺地占据着一席之地。因为多分类很简单,同时在文本数据中,分布独立这个假设基本是成立的。而垃圾文本过滤(比如垃圾邮件识别)和情感分析(微博上的褒贬情绪)用朴素贝叶斯也通常能取得很好的效果。
  • 多分类实时预测:这个是不是不能叫做场景?对于文本相关的多分类实时预测,它因为上面提到的优点,被广泛应用,简单又高效。
  • 推荐系统:是的,你没听错,是用在推荐系统里!!朴素贝叶斯和协同过滤(Collaborative Filtering)是一对好搭档,协同过滤是强相关性,但是泛化能力略弱,朴素贝叶斯和协同过滤一起,能增强推荐的覆盖度和效果。

朴素贝叶斯训练/建模

下面我们提提怎么快速用朴素贝叶斯训练模型吧。scikit-learn里面有3种不同类型的朴素贝叶斯:

  • 高斯分布型:用于classification问题,假定属性/特征是服从正态分布的。
  • 多项式型:用于离散值模型里。比如文本分类问题里面我们提到过,我们不光看词语是否在文本中出现,也得看出现的次数。如果总词数为n,出现词数为m的话,说起来有点像掷骰子n次出现m次这个词的场景。
  • 伯努利型:这种情况下最后得到的特征只有0(没出现)和1(出现过)。

根据你的数据集,可以选择scikit-learn中以上任意一种朴素贝叶斯,我们直接举个简单的例子,用高斯分布型朴素贝叶斯建模:

# 我们直接取iris数据集,这个数据集有名到都不想介绍了...
# 其实就是根据花的各种数据特征,判定是什么花
from sklearn import datasets
iris = datasets.load_iris()
iris.data[:5]
#array([[ 5.1,  3.5,  1.4,  0.2],
#       [ 4.9,  3. ,  1.4,  0.2],
#       [ 4.7,  3.2,  1.3,  0.2],
#       [ 4.6,  3.1,  1.5,  0.2],
#       [ 5. ,  3.6,  1.4,  0.2]])

#我们假定sepal length, sepal width, petal length, petal width 4个量独立且服从高斯分布,用贝叶斯分类器建模
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)
right_num = (iris.target == y_pred).sum()
print("Total testing num :%d , naive bayes accuracy :%f" %(iris.data.shape[0], float(right_num)/iris.data.shape[0]))
# Total testing num :150 , naive bayes accuracy :0.960000

朴素贝叶斯之文本主题分类器

这是朴素贝叶斯最擅长的应用场景之一,对于不同主题的文本,我们可以用朴素贝叶斯训练一个分类器,然后将其应用在新数据上,预测主题类型。

而文本分析则是文本主题分类器的重要前提

下面我们简单介绍一下------文本分类器

停用词


1.语料中大量出现
2.没啥大用
例如

Tf-idf:关键词提取

比如现在我有一篇文章《中国的蜜蜂养殖》首先我们进行一个词频(Term Frequency,缩写为TF)统计。发现出现次数最多的是----“的” 、 “是” 、 “在” ----这一类最常用的词(停用词),我们先去掉停用词,然后再进行词频统计。“中国” 、 “蜜蜂” 、 “养殖” 这三个词的出现次数一样多,重要性是一样的。但是,"中国"是很常见的词,相对而言,"蜜蜂"和"养殖"不那么常见。

这时候使用"逆文档频率"(Inverse Document Frequency,缩写为IDF)
如果某个词比较少见,但是它在这篇文章中多次出现,那么它很可能就反映了这篇文章的特性。正是我们所需要的关键词

我们还是以上面那个文章举例

《中国的蜜蜂养殖》 :假定该文长度为1000个词,"中国"、 "蜜蜂"、 "养殖"各出现20次,则这三个词的"词频"(TF)都为0.02。

搜索Google发现,包含"的"字的网页共有250亿张,假定所有文章都包含‘的’。这就相当于中文网页总数。包含"中国"的网页共有62.3亿张,包含"蜜蜂"的网页为0.484亿张,包含"养殖"的网页为0.973亿张
计算TF-IDF后

相似度
 

句子A:我喜欢看电视,不喜欢看电影。
句子B:我不喜欢看电视,也不喜欢看电影。

那我们要看这两个句子的相似度

首先我们需要分词

句子A:我/喜欢/看/电视,不/喜欢/看/电影。
句子B:我/不/喜欢/看/电视,也/不/喜欢/看/电影。
语料库:我,喜欢,看,电视,电影,不,也。(所有不重复的词)
词频(出现了多少次):
句子A:我 1,喜欢 2,看 2,电视 1,电影 1,不 1,也 0。
句子B:我 1,喜欢 2,看 2,电视 1,电影 1,不 2,也 1。
词频向量:
句子A:[1, 2, 2, 1, 1, 1, 0]
句子B:[1, 2, 2, 1, 1, 2, 1]

利用计算相似度

 

下面我们采用一个实际的例子来进行文本分类器

import pandas as pd
import jieba

导入需要的库

数据源我们采用搜狗实验室提供的数据源

http://www.sogou.com/labs/resource/ca.php

我们需要请原数据进行处理,提取出标题,内容,URL等有用信息。

df_news = pd.read_table('./data/val.txt',names=['category','theme','URL','content'],encoding='utf-8')
df_news = df_news.dropna()
df_news.head()

这里为了掩饰,选择小的数据val.txt。

部分数据展示

下面进行分词

content = df_news.content.values.tolist()
print (content[1000])

首先将content里面的内容转换成list的格式。打印一个新闻如下

然后利用结巴分词

content_S = []
for line in content:
    current_segment = jieba.lcut(line)
    if len(current_segment) > 1 and current_segment != '\r\n': #换行符
        content_S.append(current_segment)

分词后我们再次打印刚才的那个新闻信息

content_S[1000]

['阿里巴巴', '集团', '昨日', '宣布', ',', '将', '在', '集团', '管理', '层面', '设立', '首席', '数据', '官', '岗位', '(', 'C', 'h', 'i', 'e', 'f', '\u3000', 'D', 'a', 't', 'a', '\u3000', 'O', 'f', 'f', 'i', 'c', 'e', 'r', ')', ',', '阿里巴巴', 'B', '2', 'B', '公司', 'C', 'E', 'O', '陆兆禧', '将', '会', '出任', '上述', '职务', ',', '向', '集团', 'C', 'E', 'O', '马云', '直接', '汇报', '。', '>', '菹', 'ぃ', '和', '6', '月初', '的', '首席', '风险', '官', '职务', '任命', '相同', ',', '首席', '数据', '官亦为', '阿里巴巴', '集团', '在', '完成', '与', '雅虎', '股权', '谈判', ',', '推进', '“', 'o', 'n', 'e', '\u3000', 'c', 'o', 'm', 'p', 'a', 'n', 'y', '”', '目标', '后', ',', '在', '集团', '决策', '层面', '新增', '的', '管理', '岗位', '。', '0', '⒗', '锛', '团', '昨日', '表示', ',', '“', '变成', '一家', '真正', '意义', '上', '的', '数据', '公司', '”', '已', '是', '战略', '共识', '。', '记者', '刘夏']

之后我们进行dataFrame处理

df_content=pd.DataFrame({'content_S':content_S})
df_content.head()

下面我们要做的就是进行数据清洗,去掉停用词,首先先拿到一个停用词表,停用词表https://pan.baidu.com/s/17-fb6JD0hS1qcBPfDKyGkw 其实停用词表是可以自己总结添加的。每个人有不一样的停用词表。根据实际业务需求修改停用词表。

stopwords=pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8')
stopwords.head(20)

下面进行清洗停用词操作

def drop_stopwords(contents,stopwords):
    contents_clean = []
    all_words = []
    for line in contents:
        line_clean = []
        for word in line:
            if word in stopwords:
                continue
            line_clean.append(word)
            all_words.append(str(word))
        contents_clean.append(line_clean)
    return contents_clean,all_words
    #print (contents_clean)
        

contents = df_content.content_S.values.tolist()    
stopwords = stopwords.stopword.values.tolist()
contents_clean,all_words = drop_stopwords(contents,stopwords)

清理完后,再次查看

df_content=pd.DataFrame({'contents_clean':contents_clean})
df_content.head()

df_all_words=pd.DataFrame({'all_words':all_words})
df_all_words.head()

TF-IDF :提取关键词

import jieba.analyse
index = 1000
print (df_news['content'][index])
content_S_str = "".join(content_S[index])  
print ("  ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))
阿里巴巴集团昨日宣布,将在集团管理层面设立首席数据官岗位(Chief Data Officer),阿里巴巴B2B公司CEO陆兆禧将会出任上述职务,向集团CEO马云直接汇报。>菹ぃ和6月初的首席风险官职务任命相同,首席数据官亦为阿里巴巴集团在完成与雅虎股权谈判,推进“one company”目标后,在集团决策层面新增的管理岗位。0⒗锛团昨日表示,“变成一家真正意义上的数据公司”已是战略共识。记者刘夏
阿里巴巴  集团  首席  岗位  数据    

其中jieba.analyse.extract_tags方法是关键,topK是选取多少个关键词。

下面我们就要用贝叶斯进行分类

首先加入label

df_train=pd.DataFrame({'contents_clean':contents_clean,'label':df_news['category']})
df_train.tail()

查看label有少种类

df_train.label.unique()
array(['汽车', '财经', '科技', '健康', '体育', '教育', '文化', '军事', '娱乐', '时尚'],dtype=object)

上面看到有10个种类,所以我们要做的是10分类

label_mapping = {"汽车": 1, "财经": 2, "科技": 3, "健康": 4, "体育":5, "教育": 6,"文化": 7,"军事": 8,"娱乐": 9,"时尚": 0}
df_train['label'] = df_train['label'].map(label_mapping)
df_train.head()

 

map转换一下后进行测试集和训练集拆分。

from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(df_train['contents_clean'].values, df_train['label'].values, random_state=1)

之后将每个新闻信息转换成字符串形式

words = []
for line_index in range(len(x_train)):
    try:
        words.append(' '.join(x_train[line_index]))
    except:
        print (line_index,word_index)
words[0]      

基于词频,构造词组向量

from sklearn.feature_extraction.text import CountVectorizer

vec = CountVectorizer(analyzer='word', max_features=4000,  lowercase = False)
vec.fit(words)

之后构建贝叶斯分类器

from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(vec.transform(words), y_train)

然后进行测试,不过在测试之前,我们要保证测试集个训练集是一样的,测试集也需要进行字符串的转换

test_words = []
for line_index in range(len(x_test)):
    try:
        #x_train[line_index][word_index] = str(x_train[line_index][word_index])
        test_words.append(' '.join(x_test[line_index]))
    except:
         print (line_index,word_index)
test_words[0]

再进行测试

classifier.score(vec.transform(test_words), y_test)

这里我的结果是

0.7968

最后,我们还可以进行基于TF-IDF进行词频向量的创建

from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer(analyzer='word', max_features=4000,  lowercase = False)
vectorizer.fit(words)
from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(vectorizer.transform(words), y_train)

 

classifier.score(vectorizer.transform(test_words), y_test)

同样进行预测,结果是

0.8088

可以看出TF-IDF结果要好一些。

到此,贝叶斯算法的介绍就到这里了。

  • 28
    点赞
  • 145
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值