學習與分類算法
先從訓練數據中計算先驗概率和條件概率,然後對於給定的實例計算最大的條件概率,輸出該條件對應的類別。形式化的描述如下:
貝葉斯估計
最大似然估計有個隱患,假設訓練數據中沒有出現某種參數和類別的組合怎麼辦?此時估計的概率值爲0,但是這不代表真實數據中就沒有這樣的組合。解決辦法是採用貝葉斯估計
1、條件概率的貝葉斯估計:
其中,Sj表示xj可能取值的種數。分子和分母分別比最大似然估計多了一點東西,其意義是在隨機變量每個取值的頻數上加一個常量。當此常量取0時,就是最大似然估計,當此常量取1時,稱爲拉普拉斯平滑。
2、先驗概率的貝葉斯估計:
貝葉斯情感極性分析器
這裏分析一個基於貝葉斯文本分類器實現的簡單情感極性分析器。
調用實例:
- # -*-coding:utf-8 -*-
- #Filename: Bayes.py
- # Author:hankcs
- # Date:2015/2/6 22:25
- from math import log, exp
-
-
- class LaplaceEstimate(object):
- """
- 拉普拉斯平滑處理的貝葉斯估計
- """
-
- def __init__(self):
- self.d = {} # [詞-詞頻]的map
- self.total = 0.0 # 全部詞的詞頻
- self.none = 1 # 當一個詞不存在的時候,它的詞頻(等於0+1)
-
- def exists(self, key):
- return key in self.d
-
- def getsum(self):
- return self.total
-
- def get(self, key):
- if not self.exists(key):
- return False, self.none
- return True, self.d[key]
-
- def getprob(self, key):
- """
- 估計先驗概率
- :param key: 詞
- :return: 概率
- """
- return float(self.get(key)[1]) / self.total
-
- def samples(self):
- """
- 獲取全部樣本
- :return:
- """
- return self.d.keys()
-
- def add(self, key, value):
- self.total += value
- if not self.exists(key):
- self.d[key] = 1
- self.total += 1
- self.d[key] += value
-
-
- class Bayes(object):
- def __init__(self):
- self.d = {} # [標籤, 概率] map
- self.total = 0 # 全部詞頻
-
-
- def train(self, data):
- for d in data: # d是[[詞鏈表], 標籤]
- c = d[1] # c是分類
- if c not in self.d:
- self.d[c] =LaplaceEstimate() # d[c]是概率統計工具
- for word in d[0]:
- self.d[c].add(word, 1) # 統計詞頻
- self.total = sum(map(lambda x: self.d[x].getsum(), self.d.keys()))
-
- def classify(self, x):
- tmp = {}
- for c in self.d: # 分類
- tmp[c] = log(self.d[c].getsum()) - log(self.total) # P(Y=ck)
- for word in x:
- tmp[c] += log(self.d[c].getprob(word)) # P(Xj=xj | Y=ck)
- ret, prob = 0, 0
- for c in self.d:
- now = 0
- try:
- for otherc in self.d:
- now += exp(tmp[otherc] - tmp[c]) # 將對數還原爲1/p
- now = 1 / now
- except OverflowError:
- now = 0
- if now > prob:
- ret, prob = c, now
- return (ret, prob)
-
-
- class Sentiment(object):
- def __init__(self):
- self.classifier = Bayes()
-
- def segment(self, sent):
- words = sent.split(' ')
- return words
-
- def train(self,neg_docs, pos_docs):
- data = []
- for sent in neg_docs:
- data.append([self.segment(sent), u'neg'])
- for sent in pos_docs:
- data.append([self.segment(sent), u'pos'])
- self.classifier.train(data)
-
- def classify(self, sent):
-
- return self.classifier.classify(self.segment(sent))
-
- s =Sentiment()
- s.train([u'糟糕', u'好 差勁'], [u'優秀', u'很 好']) # 空格分詞
-
- print s.classify(u"好 優秀")
|
輸出
- (u'pos', 0.6666666666666665)
|
說明“好優秀”這句話具有正能量的概率是66%,雖然“好”這個詞語也存在於負極性的語句中,但是分類器還是準確地區分了它。
上面的貝葉斯分類器使用了拉布拉斯平滑處理策略,在進行條件概率的時候,不是連乘,而是取對數相加,最後逐差取指數,這個過程會發生歸一化,得出一個概率出來。
原文作者:hankcs
原文地址:http://www.hankcs.com/ml/naive-bayesian-method.html