朴素贝叶斯分类-机器学习实战

使用贝叶斯决策理论,计算两个概率进行分类,属于哪一类别的概率大,就认为属于哪一类。实际计算p(c1|x,y)和p(c2|x, y)。

给定由x,y表示的数据点,p(c1|x,y)和p(c2|x, y)这些数据点来自类别c1,c2的概率是多少。

应用贝叶斯准则

p(ci|x,y)=p(x,y|ci)p(ci)p(x,y)p(ci|x,y)=p(x,y|ci)∗p(ci)p(x,y)
以文本分类为例

以w表示一个向量,该向量由文档转换为而成。ci表示距离类别。

p(ci|w⃗ )=p(w⃗ |ci)p(ci)p(w⃗ )p(ci|w→)=p(w→|ci)∗p(ci)p(w→)

使用朴素贝叶斯假设,假设各个属性相互独立。即所有词相互独立,该假设又称作条件独立性假设f。其意味着:
p(w⃗ |ci)=p(w0,w1,...wn|ci)=p(w0|ci)p(w1|ci)...p(wn|ci)p(w→|ci)=p(w0,w1,...wn|ci)=p(w0|ci)∗p(w1|ci)∗...p(wn|ci)

应用上述公式,对每个类计算概率值,然后比较两个概率值的大小,由此判断类别。
  1. 文档转换为词向量
    根据训练集合,构建一个词汇表。根据文档中某个词是否出现在词汇表中,出现设为1,不出现设为0,构建一个词向量,这被称作词集模型(set-of-words model),如果考虑单词出现的次数,出现n次设为n,这种方式称作词袋模型(bag-of-words model)
  2. 构建分类器
    把数据分为训练集和测试集。从数据中随机的取出一部分作为测试集,剩下的作为训练集,称作 留存交叉验证(hold-out cross validation)。
    根据训练集计算平均每个单词在ci条件下出现的概率:统计训练集单词在ci条件下出现的数目,除以所有总的词汇数目。构建概率向量。
  3. 测试分类函数
    输入词向量,词向量与训练集得到的概率向量相乘,即可得到,该词向量的各个单词出现的概率,根据朴素贝叶斯假设,词向量各个单词出现互相独立,从而计算概率,根据概率大小判断其为哪种类别。
from numpy import *
def loadDataSet():
    postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
                 ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
                 ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
                 ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
                 ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
                 ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
    classVec = [0,1,0,1,0,1]    #1表示侮辱类,0表示不属于
    return postingList,classVec #词条切分后的分档和类别标签
# 创建一个词汇列表,不重复
def create_vocab_list(dataSet):
    vocab_set = set()
    for i in dataSet:
       vocab_set=vocab_set|set(i)
    return list(vocab_set)
#词汇表中的词汇,在文档中是否出现。出现设置为1,反之为0;
def words2vec(vocab_set,inputSet):#形参是词汇表和输入文档
    return_vec = [0] * len(vocab_set)
    for word in inputSet:
        if word in vocab_set:
            return_vec[vocab_set.index(word)] += 1
        else:
            print("the word: %s is not in my Vocabulary!" % word)
    return return_vec
#朴素贝叶斯分类器训练函数,返回三个变量
#1侮辱类文档条件下,词向量概论p(w|c1);p(w|c2);侮辱类文档概论p(c1)
def train_NBO(trainMatrix,trainCategory):
    Number_train_docs = len(trainMatrix)#矩阵的行数
    num_words = len(trainMatrix[0]) #矩阵的列数
    pabusive = sum(trainCategory)/Number_train_docs
    p1 = zeros(num_words);p0=zeros(num_words) #用到除法,故使用numpy函数
   # p1 = [0]*num_words;p0=[0]*num_words
   # p1Denom=0; p0Denom=0 #初始化分母项
    p1Denom = 2 ;p0Denom = 2 #
    for i in range(Number_train_docs):
        if trainCategory[i]==1:
            p1 = p1+trainMatrix[i]
            p1Denom = p1Denom + sum(trainMatrix[i])
        else :
            p0 = p0+trainMatrix[i]
            p0Denom = p0Denom +sum(trainMatrix[i])
    p1vect = log(p1/p1Denom)   #p1vect = p1/p1Denop0vect = p0/p0Denom
    p0vect = log(p0/p0Denom)

    return p0vect,p1vect,pabusive

def classifyNBO(vec2Classify,p0Vec,p1Vec,pClass1):
    #同时,采用自然对数进行处理不会有任何损失。ln(a * b) = ln(a) + ln(b)
    p1 = sum(vec2Classify * p1Vec) +log(pClass1)
    p0 = sum(vec2Classify * p0Vec) +log(1-pClass1)
    if p1>p0:
        return 1
    else:
        return 0
#测试函数
def NBO_Test():
    myvocab,classlist = loadDataSet()
    myvocab_list = create_vocab_list(myvocab)
    num_doc = len(myvocab)
    trainMat =[]
    for i in myvocab:
         trainMat.append(words2vec(myvocab_list,i))
    p0V,p1V,pabusive =train_NBO(trainMat,classlist)
    testEntry = ['love', 'my', 'dalmation']  # 正面测试文档
    thisDoc = array(words2vec(myvocab_list, testEntry))  # 词汇表
    classfiy_result = classifyNBO(thisDoc,p0V,p1V,pabusive)
    print("['love', 'my', 'dalmation'] is classified as %d"  %classfiy_result)
    testEntry2 = ['stupid','garbage']
    thisDoc = array(words2vec(myvocab_list, testEntry2))  # 词汇表
    classfiy_result = classifyNBO(thisDoc, p0V, p1V, pabusive)
    print("['stupid','garbage'] is classified as  %d" %classfiy_result)

def textParse(String):
    import re  #引入正则表达式
    list_of_tokens = re.split(r'\W+',String)#r表示原生字符串
    #注意是 \W,w写。因为\w代表单词数字字符  \W代表非单词的字符,应该以此为分隔符。
    return [tok.lower() for tok in list_of_tokens if len(tok)>2 ]
#字符串全部转换成小写 .lower()//.upper()全部转换成大写
# 构建一个新列表的简介方式 [ x for x in list if ...]

def spam_test():
    doc_list =[];class_list=[];full_text=[]
    for i in range(1,26):#从1开始,上边界不取
        # 添加ham邮件
        fo = open('F:\pythonProject\MLIAcode\Ch04\email\ham\%d.txt' %i)
        string = fo.read()#此处报错,邮件有字符不一致
        list = textParse(string)
        doc_list.append(list)
        full_text.extend(list)
        class_list.append(0)
        #添加spam邮件
        fo = open('F:\pythonProject\MLIAcode\Ch04\email\spam\%d.txt' %i)
        string = fo.read()
        list = textParse(string)
        doc_list.append(list)
        full_text.extend(list)
        class_list.append(1)
    vocab_list = create_vocab_list(doc_list)
    #随机拿出10个数据,作为测试集
    test_set = []#测试集
    #test_class =[]
    #training_set = list(range(50)) 训练索引集,转换为列表类。出错,为什么不能强制转化为列表
    training_set = [x for x in range(50)]
    for i in range(10):
        rand_index =int(random.uniform(0,len(training_set)))#不断删除该序列,因此必须不断求长度更新
        #print(rand_index)
        #print(len(training_set))
        test_set.append(training_set[rand_index])
        #test_set.append(words2vec(vocab_list,doc_list[i]))
        #test_class.append(class_list[rand_index])
        del (training_set[rand_index])
    #开始训练。剩下的作为训练集合
    print(training_set)
    train_matrix = [];train_classes=[]
    for doc_index in training_set:
        train_matrix.append(words2vec(vocab_list,doc_list[doc_index]))
        train_classes.append(class_list[doc_index])
    p0v,p1v,p_spam =train_NBO(train_matrix,train_classes)
    print(p_spam)
    #print(len(p0v))
    error_count = 0
    for doc_index in test_set:
        word_vec = words2vec(vocab_list,doc_list[doc_index])
        if classifyNBO(word_vec,p0v,p1v,p_spam) != class_list[doc_index]:
            #print(test_set[i])
            error_count+=1
    print('the error rate is %f' %(error_count/len(test_set)))






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值