俗話說:若是你手裏握了一把錘子🔨,那麼你看什麼都像釘子。當我手握樸素貝葉斯之錘時,我看掘金文章的歸類就像那顆等着被錘的釘子。前端
目前,用戶在掘金髮文章須要手動選擇所發文章的類別。若是利用算法自動判斷文章屬於哪一類,那麼就能夠免去此步啦(單就此例而言,用戶體驗改善甚微,不過改造以後能夠更好的進行內容分發)。git
抓了掘金前端類目下的文章標題 192 條,後端類目下的文章標題 969 條,人工智能類目下的文章 692 條。沒作任何優化的樸素貝葉斯訓練完的模型分類準確率爲 0.79。github
能夠看到樸素貝葉斯在技術文章分類方面是很好的算法,僅利用不到2000條標題就能夠作到 0.8 的 正確率,若是再添上文章內容,我猜能夠作到準確率 0.9 以上。算法
直接用採集器新建採集任務,好比八爪魚、后羿之類的。將採集到的文章數據保存到本地。我用的是后羿採集器,每一個類別一個採集任務,將抓到的數據保存爲 Excel。後端
TF—IDF 中 TF 是詞頻,指的是詞 a 在待分類文檔中出現的次數與待分類文檔總詞數之比。IDF 是逆文件頻率,指的是在總的文檔集合中包含了指定的詞 a 的文檔佔比。bash
TF*IDF 就等於 TF-IDF 了。微信
好比文章 A 的標題裏共8個詞,出現了一次前端,而我抓取的1000條標題裏有800條包含前端。那麼 TF-IDF 就等於 1/8 * lg(1000/800)。測試
利用 TF-IDF 能夠選出對單條標題重要,可是在全部標題中出現頻率低的詞。而這種詞,正式區分文章類別的關鍵。優化
因此,計算 TF-IDF 的第一步是分詞,用 jieba 分詞來作:ui
import jieba
def cut_words(title):
""" 對文本進行切詞 :param title: 文章標題 :return: 以空格爲間隔的詞語列表 """
# title 是 DataFrame 格式,強制轉換爲 string
title = str(title)
text_with_space = ''
text_cutted = jieba.cut(text)
for i in text_cutted:
text_with_space += i + ' '
return text_with_space
複製代碼
TF—IDF 直接利用 sklearn 自帶的 TfidfVectorizer 就能夠計算。
from sklearn.feature_extraction.text import TfidfVectorizer
# stop_words:中止詞
# x_train: 分詞後的文本列表訓練集
# x_test:分詞後的文本列表測試集
tf = TfidfVectorizer(stop_words=stop_words, max_df=0.5)
train_features = tf.fit_transform(x_train)
test_features = tf.transform(x_test)
複製代碼
代碼中的 stop_words 是一個文本文件,裏面保存了好比 的、我、等這些在中文中常見的鏈接詞。由於這些詞很廣泛並且對文本分類沒有幫助,全部在實際計算 TF-IDF 的時候就不算這些詞了。
from sklearn.naive_bayes import MultinomialNB
# alpha:平滑係數
clf = MultinomialNB(alpha=0.001).fit(train_features, y_train)
predicted_labels=clf.predict(test_features)
複製代碼
predicted_labels 就是我利用文本分類模型預測的文章分類。 與實際值作對比:
from sklearn import metrics
metrics.accuracy_score(y_test, predicted_labels)
# output: 0.7931034482758621
複製代碼
掘金髮展到如今,無數做者已經間接提供了大量準確標記的數據了。利用更多數據進行訓練,選擇合適的中止詞詞庫並對文章標題進行一些必要的預處理,對一些關鍵詞——好比前端、JavaScript、Android、Java 等增長權重,分類正確率到97%也何嘗不可。
完整的代碼能夠點這裏。
想本身試試又懶得抓數據的同窗能夠關注個人微信公衆號「數據科學與技術」(read_csv)回覆 0720 獲取個人數據。