樸素貝葉斯Naïve Bayes分類演算法在Hadoop上的實現
Naïve Bayes是一個簡單有效的分類演算法,已經得到廣泛使用。本文討論了海量資料(TB級)下Naïve Bayes演算法的實現方法,並給出了Hadoop上的實現方案。
2. Naïve Bayes演算法介紹
樸素貝葉斯分類器基於一個簡單的假定: 在給定目標值時屬性值之間相互獨立, 即特徵對於給定類的影響獨立於其它特徵。利用該假設,文件d 屬於類c 的概率可以表示為:
3. Naïve Bayes演算法在Hadoop上實現
分兩個階段進行,首先是訓練獲取分類器,然後是預測。
(1) 訓練
訓練階段要計算兩種概率:[1] 每種類別的先驗概率 [2] 每個term(單詞)在每個類別中得條件概率。
[1] 計算類別的先驗概率
由一個Hadoop Job實現,虛擬碼如下:
該作業主要統計了每種類別文件的總數目,具體概率的計算放在了後面。假設該作業計算得到的資料彙總在了檔案dict1.txt中。
[2] 計算term的條件概率
由一個Hadoop job實現,虛擬碼如下:
其中,c表示種類,w表示word,該作業只統計了每個<c,w>對出現的總次數,具體條件概率計算放在了後面。假設該作業得到的資料彙總在檔案dict2.txt中。
(2) 預測
預測時,需要把檔案dict1.txt和dict2.txt作為字典載入到記憶體中,一般而言,dict1.txt很小,而dict2.txt很大,如種類數是100,term總數為10000,0000,則dict2需要儲存的記錄總數為100*10000 0000=10^10。為了解決該問題,提出以下解決方案:
(1)將種類分片儲存到多個檔案中。比如,共有100個種類,每10個種類為一組存放到10個字典中(即:某個字典只儲存與某10個種類相關的<c,w>對,這個可以通過將同一種類的<c,w>將給相同reduce task處理做到),分批計算。
(2)dict2.txt中實際上存放的是一個稀疏矩陣,稀疏矩陣很適合用HashTable儲存,在C++中,很容易想到STL map,實際上,這種方案非常浪費記憶體。STL map是紅黑樹,每個節點的資料結構如下:
1 2 3 4 5 6 7 8 9 |
struct
node {
T*
data; //
key +value=4+4=8
bool
color, //ignore
struct
node *father, *left, *right;
}
|
每個節點大約需要8+4*3=20個位元組。為了改進該方案,採用vector+二分查詢的方案:
首先,將<c,w>對壓縮到一個unsigned int中,如,高7位表示種類(事先對種類進行編號,能表示2^7=128個種類),低25位表示term編號(最大可有33554432個term);
1 2 3 4 5 |
unsigned
int
FormatToCombinedNumber(unsigned int
high, unsigned int
low) {
return
((high & 0x7f) << 24) + (low & 0xffffff);
}
|
然後,將(<c,w>, 次數)儲存到vector中,並事先按照<c,w>(實際上是一個unsigned int)排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
vector<KeyValue>
term_prb;
class
KeyValue {
public :
void
Set(unsigned int
|