机器学习之三:朴素贝叶斯算法

本文为作者学习朴素贝叶斯算法后的整理笔记,仅供学习使用!

一、概述

  贝叶斯算法是一系列分类算法的总称,这类算法均是以贝叶斯定理为基础,所以将之统称为贝叶斯分类。而朴素贝叶斯(Naive Bayesian)是其中应用最为广泛的分类算法之一。

  朴素贝叶斯分类器是基于一个简单的假定:给定目标值时属性之间相互条件独立。

二、核心思想

  用p1(x, y)表示数据点(x, y)输入类别1的概率,用p2(x, y)表示数据点(x, y)属于类别2的概率,

    a、如果p1(x, y) > p2(x, y), 那么类别为1

    b、如果p2(x, y) > p1(x, y), 那么类别为2

  也就是说,我们会选择高概率对应的类别,即选择具有最高概率的决策。

三、优缺点

(1)优点

      在数据较少的情况下仍然有效,可以处理多类别问题。

(2)缺点

      对于输入数据的准备方式较为敏感

  综上,适用的数据类型:标称型数据

四、贝叶斯准则(公式)

                                                                            

五、方法步骤

# ##################################################
#           使用朴素贝叶斯对电子邮件进行分类
# 步骤:
# 1、收集数据:提供文本文件
# 2、准备数据:将文本文件解析成词条向量
# 3、分析数据:检查词条确保解析的正确性
# 4、训练算法:使用trainNBO()函数
# 5、测试算法:使用classifyNB()函数,并且构建一个新的测试函数来计算文档集的错误率
# 6、使用算法:构建一个完整的程序对一组文件进行分类,将错分的文档输出到屏幕上
# ##################################################

六、使用朴素贝叶斯进行垃圾邮件过滤

(1)收集数据

# 步骤一: 收集数据:提供文本文件
def create_dataset(file_name):
    # file_name = "email/ham/6.txt"
    try:
        email_text = open(file_name).read()
    except:
        email_text = open(file_name, encoding="utf-8").read()
    return email_text

(2)准备数据(数据预处理)

# 步骤二: 准备数据:将文本文件解析成词条向量
import re
def text_parse(big_string):
    list_of_tokens = re.split("\\W*", big_string)
    return [tok.lower() for tok in list_of_tokens if len(tok) > 2]

(3)分析数据

def set_of_word2vec(vocab_list, input_set):
    return_vec = [0] * len(vocab_list)
    for word in input_set:
        if word in vocab_list:
            return_vec[vocab_list.index(word)] = 1
        else:
            print("the word: %s is not in my Vocabulary!" % word)
    return return_vec

def bag_of_word2vec(vocab_list, input_set):
    return_vec = [0] * len(vocab_list)
    for word in input_set:
        if word in vocab_list:
            return_vec[vocab_list.index(word)] += 1
    return return_vec

(4)训练算法

# 用朴素贝叶斯分类器训练函数
def trainNBO(train_matrix, train_category):
    num_of_train_docs = len(train_matrix)
    num_of_words = len(train_matrix[0])
    pAbusive = sum(train_category) / float(num_of_train_docs)
    # #########################################################
    # p0Num = zeros(num_of_words)
    #   不同zeros的原因是:
    #       利用贝叶斯分类器对文档进行分类时,要计算多个概率的乘积以获得文档属于某个类别的概率,即计算p(a | l) * p(b | l) * p(c | l)
    #       如果其中某一个概率为0, 那么最后的乘积也为0,为降低这种影响,将所有的词的出现次数初始化为1,分母初始化为2
    # #########################################################
    p0Num = ones(num_of_words)
    p1Num = ones(num_of_words)
    p0Denom = 2.0
    p1Denom = 2.0
    for i in range(num_of_train_docs):
        if train_category[i] == 1:
            p1Num += train_matrix[i]
            p1Denom += sum(train_matrix[i])
        else:
            p0Num += train_matrix[i]
            p0Denom += sum(train_matrix[i])
    # #########################################################
    # p1Vect = p1Num / p1Denom
    # 下溢出问题:
    #       由于太多很小的数相乘造成的。当计算乘积p(w0|Ci)p(w1|Ci)...p(wn|Ci)时,由于大部分因子都非常小,
    #       导致最后相乘的结果四舍五入会得到0,所以程序会下溢出或者得到不正确的答案
    # #########################################################
    p1Vect = -log(p1Num / p1Denom)
    p0Vect = -log(p0Num / p0Denom)
    return p1Vect, p0Vect,pAbusive

(5)测试算法

# 步骤五: 测试算法:使用classifyNB()函数,并且构建一个新的测试函数来计算文档集的错误率(使用朴素贝叶斯进行交叉验证)
def read_file(index, list_of_doc, full_text, list_of_class, flag):
    if flag == 1:
        file_name = "email/spam/%d.txt" % index
    else:
        file_name = "email/ham/%d.txt" % index
    dataset = create_dataset(file_name)
    list_of_word = text_parse(dataset)
    list_of_doc.append(list_of_word)
    full_text.extend(list_of_word)
    list_of_class.append(flag)


import random
from numpy import * 
def spam_test():
    list_of_doc = []
    list_of_class = []
    full_text = []

    for i in range(1, 26):
        read_file(i, list_of_doc, full_text, list_of_class, 1)
        read_file(i, list_of_doc, full_text, list_of_class, 0)
    list_of_vocab = create_vocab_list(list_of_doc)
    training_set = list(range(50))
    test_set = []
    for i in range(10):
        randIndex = int(random.uniform(0, len(training_set)))
        test_set.append(training_set[randIndex])
        del training_set[randIndex] 
    training_matrix = []
    training_classes = []
    for doc_index in training_set:
        training_matrix.append(nb.set_of_word2vec(list_of_vocab, list_of_doc[doc_index]))
        training_classes.append(list_of_class[doc_index])
    p0V,p1V, pSpam = trainNBO(training_matrix, training_classes)
    error_count = 0
    for docIndex in test_set:
        word_vector = set_of_word2vec(list_of_vocab, list_of_doc[docIndex])
        if nb.classifyNB(array(word_vector), p0V, p1V, pSpam) != list_of_class[docIndex]:
            error_count += 1
    print("the error rate is : ", float(error_count) / len(test_set))

猜你喜欢

转载自blog.csdn.net/u011585024/article/details/82861251
今日推荐