NLP—比較各分類器在影評分類任務上的性能

題目:比較分類器在影評分類任務上的性能。

訓練集:1500,測試集:500。
1、Naive Bayes(樸素貝葉斯)有三個常用模型:高斯、多項式、伯努利;
2、KNN選擇K(最好是交叉驗證);
3、SVM選擇核函數。
4、決策樹分類器
5、最大熵分類器
要求:在原理部分,對每種模型要簡述原理,調整的每個參數要說明意義。最後部分簡單概括,各分類器在影評分類任務上的性能。

【方法原理】

1、樸素貝葉斯模型:選擇具有最高後驗概率作爲確定類別的指標。
2、KNN模型:如果待測樣本在特徵空間中的k個最鄰近樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別,並擁有這個類別上樣本的特徵。實現確定近鄰數,一般爲奇數;根據事先確定的距離度量公式(歐式距離),計算待分類數據點和所有已分類樣本點之間的距離,並計算出最近的k個樣本點;統計哥哥樣本點中,各個類別的數量,數量最多的樣本類型,即爲待分類數據的類型。當樣本數量不平衡時,一個類的樣本數量很大,而其他樣本數量很少時,很有可能導致,當輸入一個未知樣本時,該樣本的K個鄰居中大數量類樣本佔多數;可以通過爲距離設置權值來改進,與該樣本距離大的權值小,與該樣本距離小的權值大。
3、SVM:支持向量機是一種迴歸和支持向量機算法,通過調節核函數參數的設置,可將數據集映射到多維平面上,對其細粒度化,從而使它的特徵從二維變成多維,將在二維上線性不可分的問題轉化爲在多維上線性可分的問題,最後再尋找一個最優切割平面(相當於在決策樹基礎上再尋找一個最優解),因此svm的分類效果是優於大多數的機器學習分類方法的。
1)線性核函數:主要用於線性可分的情況,我們可以看到特徵空間到輸入空間的維度是一樣的,其參數少速度快,對於線性可分數據,其分類效果很理想,因此我們通常首先嚐試用線性核函數來做分類,看看效果如何,如果不行再換別的。
2)多項式核函數可以實現將低維的輸入空間映射到高緯的特徵空間,但是多項式核函數的參數多,當多項式的階數比較高的時候,核矩陣的元素值將趨於無窮大或者無窮小,計算複雜度會大到無法計算。
3)高斯徑向基函數是一種局部性強的核函數,其可以將一個樣本映射到一個更高維的空間內,該核函數是應用最廣的一個,無論大樣本還是小樣本都有比較好的性能,而且其相對於多項式核函數參數要少,因此大多數情況下在不知道用什麼核函數的時候,優先使用高斯核函數。
  採用sigmoid核函數,支持向量機實現的就是一種多層神經網絡。
在選擇核函數時,吳恩達在課上提到過幾種方法:
如果特徵的數量大到和樣本數量差不多,則選用LR或者線性核的SVM;
如果特徵的數量小,樣本的數量正常,則選用SVM+高斯核函數;
如果特徵的數量小,而樣本的數量很大,則需要手工添加一些特徵從而變成第一種情況。
附帶sklearn.svm.SVC參數說明
C:C-SVC的懲罰參數C,默認值是1.0
C越大,相當於懲罰鬆弛變量,希望鬆弛變量接近0,即對誤分類的懲罰增大,趨向於對訓練集全分對的情況,這樣對訓練集測試時準確率很高,但泛化能力弱。C值小,對誤分類的懲罰減小,允許容錯,將他們當成噪聲點,泛化能力較強。
kernel :核函數,默認是rbf,可以是‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’
  0 – 線性:u’v
   1 – 多項式:(gamma*u’v + coef0)^degree
  2 – RBF函數:exp(-gamma|u-v|^2)
  3 –sigmoid:tanh(gamma
u’v + coef0)
degree :多項式poly函數的維度,默認是3,選擇其他核函數時會被忽略。
gamma : ‘rbf’,‘poly’ 和‘sigmoid’的核函數參數。默認是’auto’,則會選擇1/n_features
coef0 :核函數的常數項。對於‘poly’和 ‘sigmoid’有用。
probability :是否採用概率估計?.默認爲False
shrinking :是否採用shrinking heuristic方法,默認爲true
tol :停止訓練的誤差值大小,默認爲1e-3
cache_size :核函數cache緩存大小,默認爲200
class_weight :類別的權重,字典形式傳遞。設置第幾類的參數C爲weight
C(C-SVC中的C)
verbose :允許冗餘輸出?
max_iter :最大迭代次數。-1爲無限制。
decision_function_shape :‘ovo’, ‘ovr’ or None, default=None3
random_state :數據洗牌時的種子值,int值
主要調節的參數有:C、kernel、degree、gamma、coef0

4、決策樹是一種樹形結構,爲人們提供決策依據,決策樹可以用來回答yes和no問題,它通過樹形結構將各種情況組合都表示出來,每個分支表示一次選擇(選擇yes還是no),直到所有選擇都進行完畢,最終給出正確答案。構造樹的基本想法是隨着樹深度的增加,節點的熵迅速地降低。熵降低的速度越快越好(即信息增益越大越好)。
建樹方法簡單表述爲:求出每一個屬性的信息增益,最大的爲根結點,以此類推,繼續構造決策樹。系統的信息熵降爲0時,就沒有必要再往下構造決策樹了,此時葉子節點都是純的–這是理想情況。最壞的情況下,決策樹的高度爲屬性(決策變量)的個數,葉子節點不純(這意味着我們要以一定的概率來作出決策,一般採用多數表決的方式確定此葉子節點)。

5、最大熵原理認爲,學習概率模型時,在所有可能的概率模型(分佈)中,熵最大的模型是最好的模型。如果有約束條件,最大熵原理也可以表述爲在滿足約束條件的模型集合中選取熵最大的模型。最大熵模型做的事就是假設分類模型是一個條件概率分佈P(Y|X),然後利用最大熵原理選擇最好的分類模型。
最大熵模型在分類方法中算是比較優的模型,但是由於它的約束函數數目一般來說會隨着樣本量的增大而增大,導致樣本量很大的時候,對偶函數的優化求解過程非常慢。優點是可以靈活設置約束條件,通過約束條件的多少可以調節模型對未知數據的適應度和對已知數據的擬合度。缺點是約束函數數量和樣本數目有關,導致迭代過程計算量巨大,實際應用比較難。

【結果】

1、Naive Bayes
在這裏插入圖片描述
2、KNN
求出不同K值時的準確率,最後選擇最好的k值,輸出其準確率。
在這裏插入圖片描述
在這裏插入圖片描述
3、SVM
首先判斷四個核函數最好的是linear,然後使用linear求出向量機模型的準確率。
在這裏插入圖片描述

4、決策樹
在這裏插入圖片描述
5、最大熵
在這裏插入圖片描述

【代碼】

Nave Bayes

import nltk
from nltk.corpus import movie_reviews
from nltk.corpus import stopwords
import random
import numpy as np
from sklearn.naive_bayes import GaussianNB
from sklearn.naive_bayes import MultinomialNB
from sklearn.naive_bayes import BernoulliNB

documents=[(list(movie_reviews.words(fileid)),category)for category in movie_reviews.categories()for fileid in movie_reviews.fileids(category)]
random.shuffle(documents)
all_words = nltk.FreqDist(w.lower()for w in movie_reviews.words())      #建立全部影評的詞頻表
all_words = all_words.most_common(2000)     #詞頻表按頻率排序
stop_words=stopwords.words('english')	#去停止詞

word_features  =[w for (w,f) in all_words if w not in stop_words]

features = np.zeros([len(documents),len(word_features)],dtype=float)
for n in range(len(documents)):
        document_words = set(documents[n][0])
        for  m in range(len(word_features)):
                if word_features[m] in document_words:
                        features[n,m] = 1 # 文件-詞集矩陣

target=[c for (d,c) in documents]
train_set=features[:1500,:]
target_train=target[:1500]
test_set=features[1500:,:]
target_test=target[1500:]

#高斯
gauNB = GaussianNB()
gauNB.fit(train_set,target_train)
pred = gauNB.predict(test_set)
print("高斯模型準確率:%s"%str(sum([1 for n in range(len(target_test)) if pred[n]==target_test[n] ])/len(target_test)))
#多項式
mulNB = MultinomialNB()
mulNB.fit(train_set,target_train)
pred = mulNB.predict(test_set)
print("多項式模型準確率:%s"%str(sum([1 for n in range(len(target_test)) if pred[n]==target_test[n] ])/len(target_test)))   
#伯努利
berNB = BernoulliNB()
berNB.fit(train_set,target_train)
pred = berNB.predict(test_set)
print("伯努利模型準確率:%s"%str(sum([1 for n in range(len(target_test)) if pred[n]==target_test[n] ])/len(target_test)))

KNN

documents = [(list(movie_reviews.words(fileid)), category) for category in movie_reviews.categories() for fileid in movie_reviews.fileids(category)]  #轉化爲詞列表的影評,與標籤,組成二元組
import random
random.shuffle(documents)	

all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
all_words=all_words.most_common(2000)	#詞頻表按頻率排序
from nltk.corpus import stopwords
stop_words=stopwords.words('english')	#去停止詞

word_features  =[w for (w,f) in all_words if w not in stop_words]

import numpy as np
features = np.zeros([len(documents),len(word_features)],dtype=float)
for n in range(len(documents)):
        document_words = set(documents[n][0])
        for  m in range(len(word_features)):
                if word_features[m] in document_words:
                        features[n,m] = 1 # 文件-詞集矩陣

target=[c for (d,c) in documents]
train_set=features[:1500,:]
target_train=target[:1500]
test_set=features[1500:,:]
target_test=target[1500:]

#交叉驗證
from sklearn.model_selection import cross_val_score
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
X =[3,5,7,9,11,13,15,17,19,21,23,25,27,29,31]
k_scores = []

for k in X:
        knnclf = KNeighborsClassifier(n_neighbors=k)
        scores = cross_val_score(knnclf,train_set,target_train,cv=10)
        k_scores.append(scores.mean())
print(k_scores)
plt.plot(X, k_scores)
plt.xlabel('K Value in KNN')
plt.ylabel('Cross-Validation Mean Accuracy')
plt.show()
#使用效果最好的k值進行預測
knnclf = KNeighborsClassifier(n_neighbors=31)#default with k=5  
knnclf.fit(train_set,target_train)  
pred = knnclf.predict(test_set)
print(sum([1 for n in range(len(target_test)) if pred[n]==target_test[n] ])/len(target_test))

SVM

import nltk
from nltk.corpus import movie_reviews
documents = [(list(movie_reviews.words(fileid)), category) for category in movie_reviews.categories() for fileid in movie_reviews.fileids(category)]  #轉化爲詞列表的影評,與標籤,組成二元組
import random
random.shuffle(documents)	
print(documents[:200])

all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
all_words=all_words.most_common(2000)	#詞頻表按頻率排序,高頻2000詞

from nltk.corpus import stopwords
stop_words=stopwords.words('english')	#停止詞 stopwords
import string
punct = set(string.punctuation)                 # punctuation marks
word_features  =[w for (w,f) in all_words if w not in stop_words and w not in punct]

import numpy as np
features = np.zeros([len(documents),len(word_features)],dtype=float)
for n in range(len(documents)):
        document_words = set(documents[n][0])
        for  m in range(len(word_features)):
                if word_features[m] in document_words:
                        features[n,m] = 1 # 文件-詞集矩陣

target=[c for (d,c) in documents]
train_set=features[:1500,:]
target_train=target[:1500]
test_set=features[1500:,:]
target_test=target[1500:]
print(test_set)
print(target_test)

##
###選擇分類效果最好的核函數
##from sklearn.model_selection import GridSearchCV
##from sklearn.svm import SVC
##tuned_parameters = [{'kernel': ['rbf','poly','linear','sigmoid']}]
##svm_clf = GridSearchCV(SVC(gamma='auto'), tuned_parameters, cv=10)
##svm_clf.fit(train_set,target_train)
##print("The best parameters are %s : %0.2f" % (svm_clf.best_params_,svm_clf.best_score_))
##
###基於上一步選出的最好的核函數爲線形
##svc= SVC(kernel = 'linear')
##svc.fit(train_set,target_train)
##pred = svc.predict(test_set)
##print("支持向量機準確率:"+str(sum([1 for n in range(len(target_test)) if pred[n]==target_test[n] ])/len(target_test)))

決策樹

import nltk
from nltk.corpus import movie_reviews
documents = [(list(movie_reviews.words(fileid)), category) for category in movie_reviews.categories() for fileid in movie_reviews.fileids(category)]  #轉化爲詞列表的影評,與標籤,組成二元組
import random
random.shuffle(documents)	

all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
all_words=all_words.most_common(2000)	#詞頻表按頻率排序
from nltk.corpus import stopwords
stop_words=stopwords.words('english')	#去停止詞

word_features  =[w for (w,f) in all_words if w not in stop_words]

#建立特徵提取器,標定該影評中是否有特徵詞
def document_features(document):
    document_words = set(document)
    features = {}
    for word in word_features:
        features['contains(%s)'%word]=(word in document_words)
    return features
#建立特徵集
featuresets = [(document_features(d),c) for (d,c) in documents]
train_set,test_set = featuresets[:1500],featuresets[1500:]

from nltk.classify import DecisionTreeClassifier
dt_classifier = DecisionTreeClassifier.train(train_set, binary=True, entropy_cutoff=0.8, depth_cutoff=50, support_cutoff=30)
##Entropy_cutoff:當子集的熵大於該值時,會被進一步分解。因此,如果該值過大,子集中的標籤分佈很不均勻就已經停止了決策。
##Depth_cutoff:該值控制樹的深度,它與訓練時間成正比,與精度成反比。
##Support_cutoff:控制用於分解子集的標籤集的數量,當少於該值時,被認爲訓練一個特徵的樣本數量不足。


print("決策樹精確度:%s"%nltk.classify.accuracy(dt_classifier, test_set))

最大熵

import nltk
from nltk.corpus import movie_reviews
documents = [(list(movie_reviews.words(fileid)), category) for category in movie_reviews.categories() for fileid in movie_reviews.fileids(category)]  #轉化爲詞列表的影評,與標籤,組成二元組
import random
random.shuffle(documents)	

all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
all_words=all_words.most_common(2000)	#詞頻表按頻率排序
from nltk.corpus import stopwords
stop_words=stopwords.words('english')	#去停止詞

word_features  =[w for (w,f) in all_words if w not in stop_words]

#建立特徵提取器,標定該影評中是否有特徵詞
def document_features(document):
    document_words = set(document)
    features = {}
    for word in word_features:
        features['contains(%s)'%word]=(word in document_words)
    return features
#建立特徵集
featuresets = [(document_features(d),c) for (d,c) in documents]
train_set,test_set = featuresets[:1500],featuresets[1500:]

from nltk.classify import MaxentClassifier
me_classifier = MaxentClassifier.train(train_set, algorithm='iis', trace=0, max_iter=1, min_lldelta=0.5)
print('最大熵分類器精度:%s'%nltk.classify.accuracy(me_classifier, test_set))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章