一、數據獲取
數據來源於github,文末會附數據來源連結。數據包含微博評論約12萬條,其中正向評論、負向評論各約6萬條。數據有label、review兩個欄位,其中label欄位用於表示評論是否是正向評論,當取值為1時表示正向評論,取值為0時表示負向評論;review欄位用於表示微博評論內容。
二、數據導入與探索
全文運用python作為數據處理、預測的工具。首先利用pandas庫導入數據並觀察一下前五行數據來看一下數據的大致情況:
import pandas as pddata=pd.read_csv(r'C:\Users\zhousiying\Desktop\weibo_senti_100k\weibo_senti_100k\weibo_senti_100k.csv')data.head()所得到的結果如下:
然後看一下數據是否存在空值:
所得結果如下:
label 0review 0dtype: int64
結果表示數據集中不存在空值,因此不需要對空值進行處理。
最後驗證一下正向、負向評論的佔比:
import matplotlib.pyplot as pltfig = plt.figure()data.groupby('label').review.count().plot.bar(ylim=0)plt.show()所得結果如下:
由上述結果知,可驗證正向評論和負向評論數量基本相等,各大約為60000條。
三、數據預處理
首先用jieba庫對評論進行分詞處理,以便下一步對文本進行向量化表示:
import jiebadata['review'] = data['review'].map(lambda x: ' '.join(jieba.cut(x)))然後用sklearn中的TfidfVectorizer函數對文本進行向量化處理:
from sklearn.feature_extraction.text import TfidfVectorizerdef stopwords_list(): with open(r'C:\Users\zhousiying\Desktop\stopword\hit_stopwords.txt',encoding='utf-8') as f: lines = f.readlines() result = [i.strip('\n') for i in lines] return resultstopwords = stopwords_list()X=TfidfVectorizer(token_pattern=r'(?u)\b\w+\b', max_features=100, ngram_range=(1,2), stop_words=stopwords).fit_transform(data['review']).toarray()在TfidfVectorizer函數的參數裡邊,token_pattern函數默認的取值是(?u)\b\w\w+\b,但是這樣會過濾掉單字,因此這裡改成了(?u)\b\w+\b。max_features指的是按語料詞頻排序取前多少個詞,這裡設定的是100,這個參數需要注意的是太小容易造成最後模型的欠擬合,太大的話一方面是可能會造成模型的過擬合,另一方面還會導致內存佔用過大,導致程序的運行速度變慢。stop_words用於指定停用詞,設定好後,函數自動檢測和過濾掉語料中有的停用詞。這裡運用了哈工大的停用詞表,後期可以試一下其它的停用詞表比如百度的停用詞表等,看看經過哪種停用詞表過濾後再使用模型效果會更好。
之後,將得到的tf-idf的特徵矩陣進行歸一化處理。需要說明的是,這裡之所以需要進行歸一化處理,是因為後邊可能要用到logistic回歸模型,若logistic回歸使用梯度下降法求最優解,歸一化有助於其快速收斂,否則模型可能會收斂較慢、甚至不能收斂。
from sklearn.preprocessing import StandardScalerscaler = StandardScaler()X=scaler.fit_transform(X)X=pd.DataFrame(X)Y=data['label']在樣本中隨機選擇十分之九的數據作為訓練集訓練模型,剩餘十分之一作為測試集來檢驗模型的效果。
from sklearn.model_selection import train_test_splitXtrain,Xtest,Ytrain,Ytest=train_test_split(X,Y,test_size=0.1,random_state=20)四、模型訓練
這裡我們把樸素貝葉斯、logistic回歸、隨機森林、GradientBoostingClassifier、xgboost以及lightgbm這五個可以進行二分類的模型作為備選模型。首先看一下這五個模型預測的大致效果和所耗時間(若所耗時間過長,是否選用該模型則需要慎重考慮):
import timefrom sklearn.naive_bayes import GaussianNBfrom sklearn.linear_model import LogisticRegressionfrom sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifierimport xgboost as xgbimport lightgbm as lgbfrom sklearn.model_selection import cross_val_score
model1=GaussianNB()model2=LogisticRegression()model3=RandomForestClassifier()model4=GradientBoostingClassifier()model5=xgb.XGBClassifier()model6=lgb.LGBMClassifier()for model in [model1,model2,model3,model4,model5,model6]: start_time=time.time() score=cross_val_score(model,Xtrain,Ytrain,cv=10,scoring='accuracy').mean() end_time=time.time() time_cost=round(end_time-start_time,2) print('{}模型下的分類準確率為:{},耗時為{}s'.format(model,score,time_cost))得到的結果如下:
從結果可以看出,在五個模型中,GradientBoostingClassifier、xgboost以及lightgbm這三個模型的預測結果較其它模型較高,且所用時長也還可以,因此選擇這三個模型對正向評論、負向評論的分類進行預測。在調參之後,為了加強模型的魯棒性,用投票法對三個模型的預測結果進行結合:
from sklearn.ensemble import VotingClassifiermodel_1=lgb.LGBMClassifier(n_estimators=15)model_2=xgb.XGBClassifier(n_estimators=15,max_depth=5)model_3=GradientBoostingClassifier()eclf = VotingClassifier(estimators=[('lgbc', model_1), ('xgbc', model_2), ('gbc', model_3)], voting='hard')eclf.fit(Xtrain,Ytrain)五、模型檢驗
用測試集的數據對模型效果進行檢驗:
from sklearn.metrics import accuracy_scoreaccuracy=accuracy_score(eclf.predict(Xtest),Ytest)accuracy結果顯示為0.9499958329860821,預測效果總體還可以。
六、總結
剛剛入門,數據集比較友好,導致最後的預測效果還可以。後邊還會繼續學習LSTM、TextCNN、Bert等模型,以及其他數據預處理方法,相信能有更好的預測效果。
附:數據下載連結:
https://github.com/SophonPlus/ChineseNlpCorpus/blob/master/datasets/weibo_senti_100k/intro.ipynb