上一篇文章,我們以微博樹洞為例,講解了怎麼自動爬取單個微博的評論。今天我們就要用上這些資料做一個自殺傾向分類器,這樣的分類器如果應用得當,將可以幫助成千上萬誤入歧途的人們挽回生命。
為了簡化問題,我們將短文字分為兩種類別中的一種,即要麼是正常微博、要麼是自殺傾向微博。這樣,有了上次的微博樹洞,訓練集和測試集就非常好獲得了。由於是短文字二分類問題,可以使用scikit-learn的SVM分類模型。
不過要注意的是,我們的分類器並不能保證分類出來的結果百分百正確,畢竟心理狀態是很難通過文字準確識別出來的,我們只能通過文字,大致判斷其抑鬱情況並加以介入。實際上這是一個寧可錯殺一百,不可放過一個的問題。畢竟放過一個,可能就有一條生命悄然流逝。
本文原始碼: https://github.com/Ckend/suicide-detect-sv... 歡迎一同改進這個專案,在訓練集和模型方面,改進的空間還相當大。如果你訪問不了github,請關注文章最下方公眾號,回覆自殺傾向檢測獲得本專案完整原始碼。
資料集整體上分兩個部分,一部分是訓練集、一部分是測試集。其中,訓練集和測試集中還要分為正常微博短文字和自殺傾向短文字。
將上一篇爬取微博樹洞的文章中得到的資料進行人工篩選後,挑出300條作為訓練集(有點少,其實業界至少也要3000條以上),再根據上次的微博爬蟲隨意爬取10000條微博作為訓練集的正常微博類。另外再分別蒐集自殺傾向微博和普通微博各50條作為測試集。
每條微博按行儲存在txt檔案裡。訓練集中,正常微博命名為normal.txt, 自殺傾向微博命名為die.txt。測試集存放在字尾為_test.txt的檔案中:
此外,接下來我們會使用到一個機器學習工具包叫scikit-learn(sklearn),其打包好了許多機器學習模型和預處理的方法,方便我們構建分類器,在CMD/Terminal輸入以下命令安裝:
pip install -U scikit-learn
如果你還沒有安裝Python,請看這篇文章安裝Python,然後再執行上述命令安裝sklearn.
我們使用一個典型的中文自然語言預處理方法:對文字使用結巴分詞後將其數字化。
由於具有自殺傾向的微博中,其實類似於"死"、"不想活"、"我走了"等這樣的詞語比較常見,因此我們可以用TF-IDF將字串數字化。如果你不瞭解TF-IDF,請看這篇文章: 文字處理之 tf-idf 演算法及其實踐
數字化的部分程式碼如下。
print('(2) doc to var...')
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
# CountVectorizer考慮每種詞彙在該訓練文字中出現的頻率,得到計數矩陣
count_v0= CountVectorizer(analyzer='word',token_pattern='\w{1,}')
counts_all = count_v0.fit_transform(all_text)
count_v1= CountVectorizer(vocabulary=count_v0.vocabulary_)
counts_train = count_v1.fit_transform(train_texts)
print("the shape of train is "+repr(counts_train.shape) )
count_v2 = CountVectorizer(vocabulary=count_v0.vocabulary_)
counts_test = count_v2.fit_transform(test_texts)
print("the shape of test is "+repr(counts_test.shape) )
# 儲存數字化後的詞典
joblib.dump(count_v0.vocabulary_, "model/die_svm_20191110_vocab.m")
counts_all = count_v2.fit_transform(all_text)
print("the shape of all is "+repr(counts_all.shape))
# 將計數矩陣轉換為規格化的tf-idf格式
tfidftransformer = TfidfTransformer()
train_data = tfidftransformer.fit(counts_train).transform(counts_train)
test_data = tfidftransformer.fit(counts_test).transform(counts_test)
all_data = tfidftransformer.fit(counts_all).transform(counts_all)
使用scikit-learn的SVM分類模型,我們能很快滴訓練並構建出一個分類器:
print('(3) SVM...')
from sklearn.svm import SVC
# 使用線性核函式的SVM分類器,並啟用概率估計(分別顯示分到兩個類別的概率如:[0.12983359 0.87016641])
svclf = SVC(kernel = 'linear', probability=True)
# 開始訓練
svclf.fit(x_train,y_train)
# 儲存模型
joblib.dump(svclf, "model/die_svm_20191110.m")
這裡我們忽略了SVM原理的講述,SVM的原理可以參考這篇文章:支援向量機(SVM)——原理篇
測試的時候,我們要分別計算模型對兩個類別的分類精確率和召回率。scikit-learn提供了一個非常好用的函式classification_report來計算它們:
# 測試集進行測試
preds = svclf.predict(x_test)
y_preds = svclf.predict_proba(x_test)
preds = preds.tolist()
for i,pred in enumerate(preds):
# 顯示被分錯的微博
if int(pred) != int(y_test[i]):
try:
print(origin_eval_text[i], ':', test_texts[i], pred, y_test[i], y_preds[i])
except Exception as e:
print(e)
# 分別檢視兩個類別的準確率、召回率和F1值
print(classification_report(y_test, preds))
結果:
對自殺傾向微博的分類精確率為100%,但是查全率不夠,它只找到了50條裡的60%,也就是30條自殺傾向微博。
對於正常微博的分類,其精確率為71%,也就是說有部分正常微博被分類為自殺傾向微博,不過其查全率為100%,也就是不存在不被分類的正常微博。
這是建立在訓練集還不夠多的情況下的結果。我們的自殺傾向微博的資料僅僅才300條,這是遠遠不夠的,如果能增加到3000條,相信結果會改進不少,尤其是對於自殺傾向微博的查全率有很大的幫助。預估最終該模型的精確率和召回率至少能達到95%。
本文原始碼: https://github.com/Ckend/suicide-detect-sv... 歡迎一同改進這個專案。如果你訪問不了github,請關注文章最下方公眾號,回覆自殺傾向檢測獲得本專案完整原始碼。
如果你喜歡今天的Python 教程,請持續關注Python實用寶典,如果對你有幫助,麻煩在下面點一個贊/在看哦有任何問題都可以在下方留言區留言,我們會耐心解答的!