02-NLP-02-朴素贝叶斯与应用
Posted josie-chen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了02-NLP-02-朴素贝叶斯与应用相关的知识,希望对你有一定的参考价值。
朴素贝叶斯与应用
贝叶斯理论简单回顾
在我们有一大堆样本(包含特征和类别)的时候,我们非常容易通过统计得到 p(特征|类别)p(特征|类别).
大家又都很熟悉下述公式:
p(x)p(y|x)=p(y)p(x|y)p(x)p(y|x)=p(y)p(x|y)
所以做一个小小的变换
p(特征)p(类别|特征)=p(类别)p(特征|类别)p(特征)p(类别|特征)=p(类别)p(特征|类别)
p(类别|特征)=p(类别)p(特征|类别)p(特征)p(类别|特征)=p(类别)p(特征|类别)p(特征)
独立假设
看起来很简单,但实际上,你的特征可能是很多维的
p(features|class)=p(f0,f1,…,fn|c)p(features|class)=p(f0,f1,…,fn|c)
就算是2个维度吧,可以简单写成
p(f0,f1|c)=p(f1|c,f0)p(f0|c)p(f0,f1|c)=p(f1|c,f0)p(f0|c)
这时候我们加一个特别牛逼的假设:特征之间是独立的。这样就得到了
p(f0,f1|c)=p(f1|c)p(f0|c)p(f0,f1|c)=p(f1|c)p(f0|c)
其实也就是:
p(f0,f1,…,fn|c)=Πnip(fi|c)p(f0,f1,…,fn|c)=Πinp(fi|c)
贝叶斯分类器
OK,回到机器学习,其实我们就是对每个类别计算一个概率p(ci)p(ci),然后再计算所有特征的条件概率p(fj|ci)p(fj|ci),那么分类的时候我们就是依据贝叶斯找一个最可能的类别:
p(classi|f0,f1,…,fn)=p(classi)p(f0,f1,…,fn)Πnjp(fj|ci)p(classi|f0,f1,…,fn)=p(classi)p(f0,f1,…,fn)Πjnp(fj|ci)
文本分类问题
下面我们来看一个文本分类问题,经典的新闻主题分类,用朴素贝叶斯怎么做。
In [2]:
#coding: utf-8
import os
import time
import random
import jieba #处理中文
#import nltk #处理英文
import sklearn
from sklearn.naive_bayes import MultinomialNB
import numpy as np
import pylab as pl
import matplotlib.pyplot as plt
In [4]:
#粗暴的词去重
def make_word_set(words_file):
words_set = set()
with open(words_file, ‘r‘) as fp:
for line in fp.readlines():
word = line.strip().decode("utf-8")
if len(word)>0 and word not in words_set: # 去重
words_set.add(word)
return words_set
In [5]:
# 文本处理,也就是样本生成过程
def text_processing(folder_path, test_size=0.2):
folder_list = os.listdir(folder_path)
data_list = []
class_list = []
# 遍历文件夹
for folder in folder_list:
new_folder_path = os.path.join(folder_path, folder)
files = os.listdir(new_folder_path)
# 读取文件
j = 1
for file in files:
if j > 100: # 怕内存爆掉,只取100个样本文件,你可以注释掉取完
break
with open(os.path.join(new_folder_path, file), ‘r‘) as fp:
raw = fp.read()
## 是的,随处可见的jieba中文分词
jieba.enable_parallel(4) # 开启并行分词模式,参数为并行进程数,不支持windows
word_cut = jieba.cut(raw, cut_all=False) # 精确模式,返回的结构是一个可迭代的genertor
word_list = list(word_cut) # genertor转化为list,每个词unicode格式
jieba.disable_parallel() # 关闭并行分词模式
data_list.append(word_list) #训练集list
class_list.append(folder.decode(‘utf-8‘)) #类别
j += 1
## 粗暴地划分训练集和测试集
data_class_list = zip(data_list, class_list)
random.shuffle(data_class_list)
index = int(len(data_class_list)*test_size)+1
train_list = data_class_list[index:]
test_list = data_class_list[:index]
train_data_list, train_class_list = zip(*train_list)
test_data_list, test_class_list = zip(*test_list)
#其实可以用sklearn自带的部分做
#train_data_list, test_data_list, train_class_list, test_class_list = sklearn.cross_validation.train_test_split(data_list, class_list, test_size=test_size)
# 统计词频放入all_words_dict
all_words_dict = {}
for word_list in train_data_list:
for word in word_list:
if all_words_dict.has_key(word):
all_words_dict[word] += 1
else:
all_words_dict[word] = 1
# key函数利用词频进行降序排序
all_words_tuple_list = sorted(