1. 程式人生 > >Python實現貝葉斯分類器

Python實現貝葉斯分類器

使用樸素貝葉斯分類器,對一片文章進行分類處理

貝葉斯分類器的優缺點:

優點:

  • 速度相對較快,因為針對每個分類的特徵詞不會太多
  • 演算法比較簡單
  • 可以動態的新增訓練資料集合
  • 分類的過程可以檢視

缺點:

  • 無法處理基於特徵組合所產生的變化結果

貝葉斯—文字分類的步驟:

  1. 對中文進行分詞處理 —jieba分詞
  2. 對分開的詞語進行處理,去除重複詞彙,去除標點和單個虛擬詞彙如:你,我,他。。。
  3. 選擇特徵詞,很重要,要總結出符合某一型別的關鍵特徵詞
  4. 對分類器進行訓練,即傳入一些已經分好類的文章,讓分類器可以知道其中的一些特徵詞。
  5. 計算出特徵詞在各個分類中出現的概率。
  6. 為每個特徵詞設定權重值
  7. 計算整篇文件的概率,將每個特徵值的概率相乘,即求出了在某一分類條件下,這篇文章出現的概率P(Document|Category)
  8. 根據P(Document|Category)應用貝葉斯定理求出P(Category|Document)
  9. 判定文章所屬的分類

python程式碼實現

#-*_coding:utf8-*-
import jieba
from sqlite3 import dbapi2 as sqlite


#將傳入文件分詞,並去除重複和不必要的詞彙。
def getwords(doc):
    doc1 = list(jieba.cut(doc))
    words = []
    for s in doc1:
        if(len("".join(s))>1):
            if(s not in words):
                words.append(s)
    return words


class classifier:
    def __init__(self, getfeatures, filename='test1.db'):
        #記錄位於各分類中不同特徵值的數量
        self.fc = {}
        #統計每個分類中的文件數量(即各分類被使用的次數)
        self.cc = {}
        #從即將被歸類的內容項中提取特徵出來
        self.getfeatures = getfeatures
        #連結資料庫
        self.con = sqlite.connect(filename)
        self.con.execute('create table if not exists fc(feature,category,count)')
        self.con.execute('create table if not exists cc(category,count)')


    #增加對特徵/分類組合的計數值
    def incf(self,f,cat):
        count = self.fcount(f,cat)
        if(count==0):
            self.con.execute("insert into fc values ('%s','%s',1)" % (f,cat))
        else:
            self.con.execute("update fc set count=%d where feature='%s' and category='%s'" % (count+1,f,cat))

    #增加對某一分類的技術值
    def incc(self,cat):
        count = self.catcount(cat)
        if(count==0):
            self.con.execute("insert into cc values ('%s',1)" % (cat))
        else:
            self.con.execute("update cc set count=%d where category='%s'" % (count+1,cat))

    #某一特徵出現於某一分類的的次數
    def fcount(self,f,cat):
        res = self.con.execute("select count from fc where feature='%s' and category='%s'" % (f,cat)).fetchone()
        if(res==None):return 0
        else: return float(res[0])

    #某一種分類的內容項數量
    def catcount(self,cat):
        res = self.con.execute("select count from cc where category='%s'" % (cat)).fetchone()
        if(res==None):return 0
        else:return float(res[0])

    #所有內容向的數量
    def totalcount(self):
        res = self.con.execute("select sum(count) from cc").fetchone()
        if(res==None):return 0
        return res[0]

    #所有分類的列表
    def categories(self):
        cur = self.con.execute("select category from cc")
        return [d[0] for d in cur]

    #訓練
    def train(self,item,cat):
        features=self.getfeatures(item)
        #針對該分類為每一個特徵增加計數值
        for f in features:
            self.incf(f,cat)
        #增加針對該分類的計數值
        self.incc(cat)
        #向資料庫提交資料
        self.con.commit()

    #計算概率
    def fprob(self,f,cat):
        if self.catcount(cat)==0: return 0
        #特徵在分類總出現的總次數,除以分類中包含內容項的總數
        return self.fcount(f,cat)/self.catcount(cat)

    #加入概率的權重值
    def weightedprob(self,f,cat,prf,weight=1.0,ap=0.5):
        #計算當前的概率值
        basicprob=prf(f,cat)
        #統計特徵在所有分類中出現的次數
        totals = sum([self.fcount(f,c) for c in self.categories()])
        # print("所有次數:")
        # print(totals)
        #計算加權平均
        bp = ((weight*ap)+(totals*basicprob))/(weight+totals)
        return bp

    #最終的分類方法
    def classify(self,item,default=None):
        probs={}
        #尋找概率最大的分類
        max=0.0
        for cat in self.categories():
            probs[cat] = self.prob(item,cat)
            if probs[cat] > max:
                max = probs[cat]
                best = cat
        return best




#新建一個classifier的子類
class naivebayes(classifier):
    #提取特徵詞,並將所有單詞的概率相乘,以求出整體的概率。P(Document|Category)
    def docprob(self,item,cat):
        features = self.getfeatures(item)
        #將所有的特徵概率相乘
        p=1
        for f in features:p *= self.weightedprob(f,cat,self.fprob)
        return p

    #已知P(Document|Category)應用貝葉斯定理求出P(Category|Document)
    def prob(self,item,cat):
        catprob=self.catcount(cat)/self.totalcount()
        docprob = self.docprob(item,cat)
        return docprob * catprob

呼叫方法:

    import docClass
    cl = docClass.naivebayes(docClass.getwords)
    cl.train('訓練的文章1')
    cl.train('訓練的文章2')
    cl.train('...')
    cl.train('訓練的文章n')
    print(cl.classify('待分類的文章', default='unknow'))

ok,以上的程式碼就實現了貝葉斯的分類器,程式碼中用到了jieba分詞模組,sqlite嵌入式資料庫。