天天看點

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

1. 問題定義

在這個項目中會采用20Newgroups的資料,這是在網上非常流行的對文本進行分類和聚類的資料集。資料集中的資料分為兩部分,一部分是用來訓練算法模型的資料,一部分是用來評估算法的新資料。網上還提供了3個資料集,這裡采用了20new-bydate這個資料集進行項目研究。這個資料集是按照日期進行排序的,并去掉了部分重複資料和header,共包含18846個文檔。

2.導入資料

這裡使用scikit-learn的loadfiles導入文檔資料,文檔是按照不同的分類分目錄來儲存的,檔案目錄 名稱即所屬類别。

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

在導入文檔資料之前,要導入項目中所需的類庫。

# 導入類庫

from sklearn.datasets import load_files

from sklearn.feature_extraction.text import CountVectorizer

from sklearn.feature_extraction.text import TfidfVectorizer

from sklearn.linear_model import LogisticRegression

from sklearn.naive_bayes import MultinomialNB

from sklearn.neighbors import KNeighborsClassifier

from sklearn.svm import SVC

from sklearn.tree import DecisionTreeClassifier

from sklearn.metrics import classification_report

from sklearn.metrics import accuracy_score

from sklearn.model_selection import cross_val_score

from sklearn.model_selection import KFold

from sklearn.model_selection import GridSearchCV

from sklearn.ensemble import AdaBoostClassifier

from sklearn.ensemble import RandomForestClassifier

from matplotlib import pyplot as plt

import warnings

warnings.filterwarnings('ignore')

利用機器學習對文本進行分類,與對數值特征進行分類最大的差別是,對文本進行分類是要先提取文本特征,提取到的文本特征屬性的個數是巨大的,會有超萬個的特征屬性。

3. 文本特征提取

文本資料屬于非結構化的資料,一般要轉換成結構化的資料才能夠通過機器學習算法進行分類。常見的做法是将文本轉換成“文檔-詞項矩陣”,矩陣中的元素可以使用詞頻或TF-IDF值等。

TF-IDF值是一種用于資訊檢索與資料挖掘的常用權重技術。TF的意思是詞頻(Term Frequency),IDF的意思是逆向檔案頻率(Inverse Document Frequency)。TF-IDF的主要思想是:如果某一個詞或短語在一篇文章中出現的頻率高,并且在其他文章中很少出現,則認為此詞或短語具有很好的類别區分能力,時适合用來分類。TF-IDF實際上是TF*IDF。

IDF的主要思想是:如果包含詞條t的文檔越少,也就是n越小,IDF越大,則說明詞條t具有很好的類别區分能力,如果某一類文檔C中包含詞條t的文檔數為m,而其他類包含t的文檔總數為k,顯然所有包含t的文檔數n = m + k,當m打的時候,n也大,按照IDF公式得到的IDF的值小,這說明該詞條t的類别區分能力不強。但是實際上,如果一個詞條在一個類的文檔中頻繁出現,這說明該詞條能夠很好地代表這個類的文本特征,這樣的詞條應該被賦予較高的權重,并将其作為該類文本的特征詞,以差別于其他類文檔。這就是IDF的不足之處,在一份給定的檔案裡,TF指的是某一個給定的詞語在該檔案中出現的頻率,這是對詞數(Term Count)的歸一化,乙方他偏向長的檔案。IDF是一個詞語普遍重要性的度量,某一特定詞語的IDF,可以由總檔案數目除以包含該詞語的檔案的數目,再将得到的商取對數得到。

在scikit-learn中提供了詞頻和TF-IDF來進行文本特征提取的實作,分别是CountVectorizer和TfidTransformer。下面對訓練資料集分别進行詞頻和TF-IDF的計算。

# 資料準備與了解

# 計算詞頻

count_vect = CountVectorizer(stop_words= 'english',decode_error ='ignore')

X_train_counts = count_vect.fit_transform(dataset_train.data)

# 檢視資料次元

print(X_train_counts.shape)

詞頻統計結果:

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

然後計算TF-IDF:

# 計算TF-IDF

tf_transformer = TfidfVectorizer(stop_words='english',decode_error='ignore')

X_train_counts_tf = tf_transformer.fit_transform(dataset_train.data)

# 檢視資料次元

print(X_train_counts_tf.shape)

TF-IDF的計算結果:

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

這裡通過兩種方法進行了文本特征的提取,并且檢視了資料次元,得到的資料次元還是非常巨大的。

4. 評估算法

通過簡單地檢視資料次元,不能确定那個算法對和這個問題比較有效。下面将采用10折交叉驗證的方式來比較算法的準确度,一遍找到處理問題最有效的兩三種算法,然後進行下一步的處理。

# 設定評估算法的基準

num_folds = 10

seed = 7

scoring = 'accuracy'

接下來将會利用提取到的文本特征TF-IDF來對算法進行審查,審查的算法如下:

線性算法:邏輯回歸(LR)

非線性算法:分類與回歸樹(CART)、支援向量機(SVM)、樸素貝葉斯分類器(MNB)和K近鄰(KNN)。

# 評估算法

# 生成算法模型

models = {}

models['LR'] = LogisticRegression()

models['SVM'] = SVC()

models['CART'] = DecisionTreeClassifier()

models['MNB'] = MultinomialNB()

models['KNN'] = KNeighborsClassifier()

所有的算法使用預設參數,比較算法的準确度和标準方差,以便從中選擇兩三種可以進一步進行研究的算法。

# 比較算法

results = []

for key in models:

kfold = KFold(n_splits= num_folds,random_state= seed)

cv_results = cross_val_score(models[key],X_train_counts_tf,dataset_train.target,cv = kfold,scoring=scoring)

results.append(cv_results)

print('%s :%f(%f)'%(key,cv_results.mean(),cv_results.std()))

執行結果顯示,邏輯回歸(LR)具有最後的準确度,樸素貝葉斯分類器(MNB)和K近鄰也值得進一步研究。

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

接下來看一下算法每次執行結果的分布情況。

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

5.算法調參

通過上面的分析,邏輯回歸(LR)和樸素貝葉斯分類器(MNB)算法值得進一步優化。下面對這兩個算法的參數進行調參,進一步提高算法的準确度。

5.1 邏輯回歸調參

在邏輯回歸中的超參數是C。C是目标的限制函數,C值越小則正則化強度越大。對C進行設定一定數量的值,如果臨界值是最優參數,重複這個步驟,直到找到最優值。

# 調參LR

param_grid = {}

param_grid['C'] = [0.1,5,13,15]

model = LogisticRegression()

kfold = KFold(n_splits=num_folds,random_state=seed)

grid = GridSearchCV(estimator=model,param_grid = param_grid, scoring = scoring,cv=kfold)

grid_result = grid.fit(X=X_train_counts_tf,y=dataset_train.target)

print('最優:%s 使用%s'%(grid_result.best_score_,grid_result.best_params_))

可以看到C的最優參數是15。

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

5.2 樸素貝葉斯分類器調參

通過對邏輯回歸調參,準确度提升到大概0.92,提升還是比較大的。樸素貝葉斯分類器有一個alpha參數,該參數是一個平滑參數,預設值為1.0。我們也可以對這個參數進行調參,以提高算法的準确度。

# 調參 MNB

param_grid ={}

param_grid['alpha'] = [0.001,0.01,0.1,1.5]

model = MultinomialNB()

kfold = KFold(n_splits=num_folds,random_state=seed)

grid = GridSearchCV(estimator= model, param_grid = param_grid, scoring=scoring, cv=kfold)

grid_result = grid.fit(X = X_train_counts_tf, y = dataset_train.target)

print('最優:%s 使用%s'%(grid_result.best_score_,grid_result.best_params_))

同樣,通過多次調整param_grid,得到的樸素貝葉斯分類器的alpha參數的最優值是0.01。

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

通過調參發現,邏輯回歸在C = 15 是具有最好的準确度。接下來進行審查內建算法。

6. 內建算法

除了調參,提高算法準确度的方法是使用內建算法。下面對兩種內建算法進行比較,看看能否進一步提高模型的準确度。

随機森林(RF)

AdaBoost(AB)

# 內建算法

ensembles = {}

ensembles['RF'] = RandomForestClassifier()

ensembles['AB'] = AdaBoostClassifier()

# 比較內建算法

results = []

for key in ensembles:

kfold = KFold(n_splits= num_folds,random_state= seed)

cv_results = cross_val_score(ensembles[key],X_train_counts_tf,dataset_train.target,cv = kfold,scoring = scoring)

results.append(cv_results)

print('%s : %f(%f)'%(key,cv_results.mean(),cv_results.std()))

評估結果:

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

7. 內建算法調參

通過對內建算法的分析,發現随機森林算法具有較高的準确度和非常穩定的資料分布,非常值得進行進一步的研究。下面通過調參對随機森林算法進行優化。随機森林有一個很重要的參數n_estimators,下面對n_estimators進行調參優化,争取找到最優解。

# 調參RF

param_grid = {}

param_grid['n_estimators'] = [10,100,150,200]

model = RandomForestClassifier()

kfold = KFold(n_splits=num_folds,random_state= seed)

grid = GridSearchCV(estimator=model,param_grid = param_grid, scoring = scoring,cv = kfold)

grid_result = grid.fit(X =X_train_counts_tf,y = dataset_train.target)

print('最優:%s 使用%s'%(grid_result.best_score_,grid_result.best_params_))

調參之後的最優結果如下:

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

8. 确定最終模型

通過對算法的比較和調參發現,邏輯回歸算法具有最高的準确度,是以使用邏輯回歸算法生成算法模型。接下來會利用評估資料集對生成的模型進行驗證,以确認模型的準确度。需要注意的是,為了保持資料特征的一緻性,對新資料進行文本特征提取是應進行特征擴充,下面使用之前生成的tf_transformer的transform方法來處理評估資料集。

# 生成模型

model = LogisticRegression(C = 15)

model.fit(X_train_counts_tf,dataset_train.target)

X_test_counts = tf_transformer.transform(dataset_test.data)

predictions = model.predict(X_test_counts)

print(accuracy_score(dataset_test.target, predictions))

print(classification_report(dataset_test.target, predictions))

從結果可以看到,準确度大概達到了85%,與期待的結果比較一緻。執行結果:

python樸素貝葉斯調參_機器學習筆記(4) -- 文本分類執行個體(20Newgroups資料集)...

參考從書:《機器學習Python實踐》 魏貞原