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

算法原理

朴素贝叶斯算法是一个典型的统计学习方法,主要理论基础就是一个贝叶斯公式,贝叶斯公式的基本定义如下:

 

朴素贝叶斯分类器的表示形式:

 

 

当特征为为x时,计算所有类别的条件概率,选取条件概率最大的类别作为待分类的类别。由于上公式的分母对每个类别都是一样的,因此计算时可以不考虑分母,即

 

 

朴素贝叶斯的朴素体现在其对各个条件的独立性假设上,加上独立假设后,大大减少了参数假设空间。

实验过程 垃圾邮件分类


1.创建词典,词典长度为不重复的总单词数
def creteVocabList(dataSet):
    vocabList = set([]) #建立一个空集合
    for data in dataSet:
        vocabList = vocabList | set(data) #词典对每一行求并集
    return list(vocabList)

    
2.将文本转化为向量,测试集和训练集都需要这一步

##词集模型将输入的文本转化为词向量,建立一个和词典长度相同的向量,在该文本出现的词设为1,没出现的设为0
def setofWords2Vec(vocabList,inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if(word in vocabList):
            returnVec[vocabList.index(word)] = 1   #查找一个列表中某一元素的索引
    return returnVec

#词袋模型,与词集模型类似,但是出现不是置为1,而是该词出现的次数。
def bagofWords2Vec(vocabList,inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if(word in vocabList):
            returnVec[vocabList.index(word)] += 1   #查找一个列表中某一元素的索引
    return returnVec

3.对训练集进行训练
#训练算法,此算法是针对二分类,输入是两个array数组,返回的p0vect,p1vect也是数组


def trainNB0(trainMatrix,trainCategory):
    cal = len(trainCategory)
    row = len(trainMatrix[0])
    P1 = sum(trainCategory)/float(len(trainMatrix))
    Cal0 = ones(row);Cal1 = ones(row)  #原为Cal0 = zeros(row);Cal1 = zeros(row)
    Total0Word = 2.0 #原为Total0Word = 0.0
    Total1Word = 2.0  #原为Total0Word = 0.0
    for i in range(cal):
        if(trainCategory[i]==1):
            Cal1 += trainMatrix[i]
            Total1Word += sum(trainMatrix[i])
        else:
            Cal0 += trainMatrix[i]
            Total0Word += sum(trainMatrix[i])

    #下面是对一个数组/一个实数,对每个元素做除法
    P1vect = log(Cal1/Total1Word)  #原为P1vect = Cal1/Total1Word
    P0vect = log(Cal0/Total0Word)   #原为P1vect = Cal0/Total0Word
    return P1,P0vect,P1vect

    
4.分类器
#根据现实情况修改分类器,上述分类器存在问题有p(w0|1)*P(w1|1)...若有一个值为0则概率为0,因此将各个单词出现次数初始化为1,分母初始化为2.
#经过上面的修改,由于相乘的数都太小容易发生下溢出,对乘数取对数处理
#下面是分类器的使用
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):

    p1 = sum(vec2Classify*p1Vec)+log(pClass1)
    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
    if p1>p0:
        return 1
    else:
        return 0

        
5.上述分类器在邮件分类中的使用
    先读取文件,将文件分成一个一个单词
    采用正则表达式,将一个字符串读成包涵长度大于3单词的列表

def textParse(bigString):
    listofTokens = re.split(r"\W+",bigString)
    return(tok.lower() for tok in listofTokens if len(tok)>2)

    接下来进行分类
def spamTest():
    docList = [];classList = [];
    #读取数据和标签,开始都读入到训练集中,后来再分割为训练集和测试集
    for i in range(1,26):
        wordList = textParse(open('email/spam/%d.txt'%i).read())
        wordList = list(wordList) #这里返回的是可迭代对象?将他转为列表,开始按照书中写的错误率特别高
        docList.append(wordList)
        #fullText.extend(listwordList)
        classList.append(1)
        wordList = textParse(open('email/ham/%d.txt' % i).read())
        wordList = list(wordList)
        docList.append(wordList)
        #fullText.extend(wordList)
        classList.append(0)
    #创建词典
    vocabList = Bayes1.creteVocabList(docList)
    #print(vocabList)
    #列表记录索引,便于分割
    trainingSet = list(range(50));testSet = []
    #划分测试集
    for i in range(10
        #随机选取0-len..中的整数,这个的作用和书中的int(random.uniform(0,len..))作用一样,uniform返回的不是整数
        randIndex = random.randint(0,len(trainingSet))
        #print(randIndex)
        testSet.append(trainingSet[randIndex])
        del(trainingSet[randIndex])
    #将训练集转化为向量
    trainMat = [];trainClass = []
    for docIndex in trainingSet:
        trainMat.append(Bayes1.bagofWords2Vec(vocabList,docList[docIndex]))
        trainClass.append(classList[docIndex])
    #对训练进行训练
    p1,p0V,p1V = Bayes1.trainNB0(array(trainMat),array(trainClass))
    #下面是测试,并计算错误率
    errorCount = 0
    for docIndex in testSet:
        print(docList[docIndex])
        wordVector = Bayes1.bagofWords2Vec(vocabList,docList[docIndex])
        if Bayes1.classifyNB(array(wordVector),p0V,p1V,p1)!=classList[docIndex]:
            errorCount += 1
            #print("classification error", docList[docIndex])
    print("error rate is:",float(errorCount)/len(testSet))

 

 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值