俗话说:若是你手里握了一把锤子🔨,那么你看什么都像钉子。当我手握朴素贝叶斯之锤时,我看掘金文章的归类就像那颗等着被锤的钉子。前端
目前,用户在掘金发文章须要手动选择所发文章的类别。若是利用算法自动判断文章属于哪一类,那么就能够免去此步啦(单就此例而言,用户体验改善甚微,不过改造以后能够更好的进行内容分发)。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 获取个人数据。