1. 程式人生 > >用Python Scikit-learn 實現機器學習十大演算法--樸素貝葉斯演算法(文末有程式碼)

用Python Scikit-learn 實現機器學習十大演算法--樸素貝葉斯演算法(文末有程式碼)

 

1,前言

很久不發文章,主要是Copy別人的總感覺有些不爽,所以整理些乾貨,希望相互學習吧。不囉嗦,進入主題吧,本文主要時說的為樸素貝葉斯分類演算法。與邏輯迴歸,決策樹一樣,是較為廣泛使用的有監督分類演算法,簡單且易於理解(號稱十大資料探勘演算法中最簡單的演算法)。但其在處理文字分類,郵件分類,拼寫糾錯,中文分詞,統計機器翻譯等自然語言處理範疇較為廣泛使用,或許主要得益於基於概率理論,本文主要為小編從理論理解到實踐的過程記錄。

2,公式推斷

一些貝葉斯定理預習知識:我們知道當事件A和事件B獨立時,P(AB)=P(A)(B),但如果事件不獨立,則P(AB)=P(A)P(B|A)。為兩件事件同時發生時的一般公式,即無論事件A和B是否獨立。當然也可以寫成P(AB)=P(B)P(A|B),表示若要兩件事同事發生,則需要事件B發生後,事件A也要發生。

由上可知,P(A)P(B|A)= P(B)P(A|B)

          推出P(B|A)=

其中P(B)為先驗概率,P(B|A)為B的後驗概率,P(A|B)為A的後驗概率(在這裡也為似然值),P(A)為A的先驗概率(在這也為歸一化常量)。

由上推導可知,其實樸素貝葉斯法就是在貝葉斯定理基礎上,加上特徵條件獨立假設,對特定輸入的X(樣本,包含N個特徵),求出後驗概率最大值時的類標籤Y(如是否為垃圾郵件),理解起來比邏輯迴歸要簡單多,有木有,這也是本演算法優點之一,當然執行起來由於得益於特徵獨立假設,執行速度也更快。


. 引數估計

3,引數估計


由上面推斷出的公式,我們知道其實樸素貝葉斯方法的學習就是對概率P(Y=ck)和P(X(j)=x(j)|Y=ck)的估計。我們可以用極大似然估計法估計上述先驗概率和條件概率。


其中I(x)為指示函式,若括號內成立,則計1,否則為0。李航的課本直接給出了用極大似然(MLE)估計求出的結果,並沒給推導過程,具體推導過程可參考知乎連結http://www.zhihu.com/question/33959624

我們知道,貝葉斯較為常見的問題為0概率問題。為此,需要平滑處理,主要使用拉普拉斯平滑,如下所示:


K是類的個數,Sj是第j維特徵的最大取值。實際上平滑因子λ=0即為最大似然估計,這時會出現提到的0概率問題;而λ=1則避免了0概率問題,這種方法被稱為拉普拉斯平滑。

4,演算法流程


5,樸素貝葉斯演算法優缺點

優點:樸素貝葉斯模型發源於古典數學理論,有著堅實的數學基礎,以及穩定的分類效率

需調參較少,簡單高效,尤其是在文字分類/垃圾文字過濾/情感判別等自然語言處理有廣泛應用。

      在樣本量較少情況下,也能獲得較好效果,計算複雜度較小,即使在多分類問題。

      無論是類別類輸入還是數值型輸入(預設符合正態分佈)都有相應模型可以運用。

缺點:0概率問題,需要平滑處理,通常為拉普拉斯平滑,但加一平滑不一定為效果最好,

      樸素貝葉斯有分佈獨立的假設前提,生活中較少完全獨立,在屬性個數比較多或者屬性之間相關性較大時,NBC模型的分類效率比不上決策樹模型。而在屬性相關性較小時,NBC模型的效能最為良好。

模型注意點:

1, 大家也知道,很多特徵是連續數值型的,一般選擇使用樸素貝葉斯高斯模型。

2, 為避免0概率事件,記得平滑,簡單一點可以用『拉普拉斯平滑』。先處理處理特徵,把相關特徵去掉,

3, 樸素貝葉斯分類器一般可調引數比較少,需集中精力進行資料的預處理等特徵工程工作。

6,Scikit-learn三大樸素貝葉斯模型

Scikit-learn裡面有3種不同型別的樸素貝葉斯(主要摘自寒小陽 的部落格http://blog.csdn.net/han_xiaoyang/article/details/50629608):

1, 高斯分佈型模型:用於classification問題,假定屬性/特徵是服從正態分佈的,一般用在數值型特徵。,

2, 多項式型模型:用於離散值模型裡。比如文字分類問題裡面我們提到過,我們不光看詞語是否在文字中出現,也得看出現的次數。如果總詞數為n,出現詞數為m的話,說起來有點像擲骰子n次出現m次這個詞的場景。

3, 伯努利模型:這種情況下,就如提到的bag ofwords處理方式一樣,最後得到的特徵只有0(沒出現)和1(出現過)。

小編通過實現樸素貝葉斯三種模型以及主要分類演算法,對比發現跟SVM,隨機森林,融合演算法相比,貝葉斯差距明顯,但其時間消耗要遠低於上述演算法,以下為主要演算法主要評估指標)。

 

歡迎關注公眾號二維碼


# -*-coding: utf-8 -*-

importtime

fromsklearn import metrics

fromsklearn.naive_bayes import GaussianNB

fromsklearn.naive_bayes import MultinomialNB

fromsklearn.naive_bayes import BernoulliNB

fromsklearn.neighbors import KNeighborsClassifier

fromsklearn.linear_model import LogisticRegression

fromsklearn.ensemble import RandomForestClassifier

fromsklearn import tree

fromsklearn.ensemble import GradientBoostingClassifier

fromsklearn.svm import SVC

importnumpy as np

importurllib

# urlwith dataset

url ="http://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data"

#download the file

raw_data= urllib.request.urlopen(url)

#load the CSV file as a numpy matrix

dataset= np.loadtxt(raw_data, delimiter=",")

#separate the data from the target attributes

X =dataset[:,0:7]

#X=preprocessing.MinMaxScaler().fit_transform(x)

#print(X)

y =dataset[:,8]

print("\n呼叫scikit的樸素貝葉斯演算法包GaussianNB ")

model= GaussianNB()

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

print("\n呼叫scikit的樸素貝葉斯演算法包MultinomialNB ")

model= MultinomialNB(alpha=1)

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

print("\n呼叫scikit的樸素貝葉斯演算法包BernoulliNB ")

model= BernoulliNB(alpha=1,binarize=0.0)

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

print("\n呼叫scikit的KNeighborsClassifier ")

model= KNeighborsClassifier()

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

print("\n呼叫scikit的LogisticRegression(penalty='l2') ")

model= LogisticRegression(penalty='l2')

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

print("\n呼叫scikit的RandomForestClassifier(n_estimators=8)  ")

model= RandomForestClassifier(n_estimators=8)

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

print("\n呼叫scikit的tree.DecisionTreeClassifier() ")

model= tree.DecisionTreeClassifier()

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

print("\n呼叫scikit的GradientBoostingClassifier(n_estimators=200) ")

model= GradientBoostingClassifier(n_estimators=200) 

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

print("\n呼叫scikit的SVC(kernel='rbf', probability=True) ")

model= SVC(kernel='rbf', probability=True)

start_time= time.time()

model.fit(X,y)

print('training took %fs!' % (time.time() - start_time))

print(model)

expected= y

predicted= model.predict(X)

print(metrics.classification_report(expected,predicted))

print(metrics.confusion_matrix(expected,predicted))

"""

# 預處理程式碼集錦

importpandas as pd

df=pd.DataFrame(dataset)

print(df.head(3))

print(df.describe())##描述性分析

print(df.corr())##各特徵相關性分析

##計算每行每列資料的缺失值個數

defnum_missing(x):

  return sum(x.isnull())

print("Missing values per column:")

print(df.apply(num_missing, axis=0)) #axis=0代表函式應用於每一列

print("\nMissing values per row:")

print(df.apply(num_missing, axis=1).head()) #axis=1代表函式應用於每一行"""