獲取案例鏈接、直播課件、數(shù)據(jù)集在本公眾號(hào)內(nèi)發(fā)送“機(jī)器學(xué)習(xí)”。
本案例旨在用新聞主題分類這一簡(jiǎn)單任務(wù)演示機(jī)器學(xué)習(xí)的一般流程。具體地,我們使用了一個(gè)搜狐新聞數(shù)據(jù)集。使用 Python 的 jieba 分詞工具對(duì)中文新聞進(jìn)行了分詞處理。然后使用 Scikit-learn 工具的 K近鄰算法構(gòu)建 KNN 模型。最后對(duì)新聞分類的效果進(jìn)行了簡(jiǎn)單的分析。
搜狐中文新聞數(shù)據(jù)存放在 train_sample_utf8.csv 和 test_sample_utf8.csv 兩個(gè)文件中,在后面的分析中我們分別當(dāng)做訓(xùn)練集和測(cè)試集來使用。我們首先使用 Pandas
中的 read_csv
函數(shù)讀取。
import pandas as pd
%matplotlib inline
raw_train = pd.read_csv('./input/train_sample_utf8.csv',encoding='utf8')
raw_test = pd.read_csv('./input/test_sample_utf8.csv',encoding='utf8')
查看兩個(gè)文件的前五行數(shù)據(jù)。
raw_train.head(5)
raw_test.head(5)
raw_train.shape
(5521, 3)
raw_test.shape
(3111, 2)
可見,訓(xùn)練集包含 5521 條新聞,測(cè)試集中包含 3111 條新聞。那么,訓(xùn)練集和測(cè)試集中,不同主題的新聞分布如何?我們可以借助 DataFrame
某列的 value_counts
方法完成統(tǒng)計(jì)。然后使用 plot
函數(shù)進(jìn)行可視化顯示。
import matplotlib.pyplot as plt
plt.figure(figsize=(15, 8))
plt.subplot(1, 2, 1)
raw_train['分類'].value_counts().sort_index().plot(kind='barh',title='訓(xùn)練集新聞主題分布')
plt.subplot(1, 2, 2)
raw_test['分類'].value_counts().sort_index().plot(kind='barh',title='測(cè)試集新聞主題分布')
一共包含 12 種主題的新聞,無論是在訓(xùn)練集還是測(cè)試集,各個(gè)主題的新聞分布較均衡。
由于新聞為中文,再進(jìn)一步進(jìn)行處理之前,我們需要先對(duì)新聞內(nèi)容進(jìn)行分詞。簡(jiǎn)單來說,分詞就是將連在一起的新聞內(nèi)容中的詞進(jìn)行分割。這里我們使用 Python 中一個(gè)著名的中文分析器 jieba
完成這項(xiàng)任務(wù)。為了后續(xù)方便,我們封裝一個(gè) news_cut
函數(shù),它接受的輸入為新聞內(nèi)容,輸出為分詞后的結(jié)果。分詞后,詞與詞之間使用空格進(jìn)行分隔。
import jieba
def news_cut(text):
return ' '.join(list(jieba.cut(text)))
#簡(jiǎn)單測(cè)試下分詞效果
test_content = '六月初的一天,來自深圳的中國(guó)旅游團(tuán)游客紛紛拿起相機(jī)拍攝新奇刺激的好萊塢環(huán)球影城主題公園場(chǎng)景。'
print(news_cut(test_content))
現(xiàn)在利用封裝的分詞函數(shù),對(duì)訓(xùn)練集和測(cè)試集中的新聞內(nèi)容進(jìn)行分詞處理,分詞結(jié)果保存到對(duì)應(yīng) DataFrame 對(duì)象的 ”分詞文章“ 一列。這里我們使用了 Pandas
中的 Series
對(duì)象的 map
函數(shù)。它能夠接受一個(gè)函數(shù),對(duì) Series
中的每一個(gè)元素作為該函數(shù)的輸入,然后將函數(shù)的輸出返回。
raw_train['分詞文章'] = raw_train['文章'].map(news_cut)
raw_test['分詞文章'] = raw_test['文章'].map(news_cut)
raw_test.head(5)
#加載停用詞
stop_words = []
file = open('./input/stopwords.txt')
for line in file:
stop_words.append(line.strip())
file.close()
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(stop_words=stop_words)
X_train = vectorizer.fit_transform(raw_train['分詞文章'])
X_test = vectorizer.transform(raw_test['分詞文章'])
使用 sklearn
中 neighbors
模塊的 KNeighborsClassifier
類構(gòu)建一個(gè) KNN 分類器。我們將鄰居數(shù) n_neighbors
設(shè)置為 5 。使用鄰居的標(biāo)簽進(jìn)行投票時(shí),用預(yù)測(cè)樣本與鄰居樣本的距離的倒數(shù)作為權(quán)重。然后使用 fit
方法,在訓(xùn)練集中訓(xùn)練模型。
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5,weights='distance')
knn.fit(X_train, raw_train['分類'])
模型訓(xùn)練完成后,可以使用 predict
方法對(duì)測(cè)試集中的樣本進(jìn)行預(yù)測(cè),得到預(yù)測(cè)標(biāo)簽列表 Y_test
。
Y_test = knn.predict(X_test)
下面使用混淆矩陣來分析模型在測(cè)試樣本上的表現(xiàn)。混淆矩陣從樣本的真實(shí)標(biāo)簽和模型預(yù)測(cè)標(biāo)簽兩個(gè)維度對(duì)測(cè)試集樣本進(jìn)行分組統(tǒng)計(jì),然后以矩陣的形式展示。借助混淆矩陣可以很好地分析模型在每一類樣本上的分類效果。為了更直觀地分析,我們借助 Python 中可視化包 seaborn
提供的 heatmap
函數(shù),將混淆矩陣可視化。
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(9, 7))
## 設(shè)置正常顯示中文
sns.set(font='SimHei')
## 繪制熱力圖
ax = sns.heatmap(confusion_matrix(raw_test['分類'].values,Y_test),linewidths=.5,cmap='Greens',
annot=True, fmt='d',xticklabels=knn.classes_, yticklabels=knn.classes_)
ax.set_ylabel('真實(shí)')
ax.set_xlabel('預(yù)測(cè)')
ax.xaxis.set_label_position('top')
ax.xaxis.tick_top()
ax.set_title('混淆矩陣熱力圖')
這還不是一個(gè)完美的新聞主題分類器,這個(gè)分類器傾向于將主題預(yù)測(cè)為'教育'或'文化'。要獲得更好的效果,我們可能還需要做很多工作,例如更好的文本預(yù)處理和表示,嘗試不同的 K 值的效果,甚至利用其它的機(jī)器學(xué)習(xí)算法等。感興趣的同學(xué)可以自己進(jìn)一步進(jìn)行嘗試。
聯(lián)系客服