1. 程式人生 > >機器學習專案實戰----新聞分類任務(一)

機器學習專案實戰----新聞分類任務(一)

一、基礎知識

假設有一份文字資料如下,資料量很大,現在要對整個語料庫進行文字分析,category代表新聞種類,theme代表新聞主題,URL代表新聞連結地址,content代表新聞主題內容

  

停用詞:在content這一列,在資料量很大的情況,很容易發現某些似乎與新聞本身意義不大的詞大量出現,而我們就把這些在語料庫中大量出現但是又沒啥大用的詞叫做停用詞,在資料集連結中包含一份常見的停用詞,如下所示:

  

TF-IDF:用於關鍵詞提取。比如在一篇名叫《中國的蜜蜂養殖》這篇文章中進行詞頻(Term Frequency,縮寫為TF)統計出現次數最多的詞是“的”、“是”、“在”等這一類最常用的詞(停用詞,一般來說是要去掉的),在刪除掉停用詞過後我們發現“中國”、“蜜蜂”、“養殖”這三個詞的出現次數一樣多,那麼這三個詞的重要性是一樣的嗎?一般來說"中國"是很常見的詞,相對而言,"蜜蜂"和"養殖"不那麼常見。這時就需要引入一個叫做逆文件頻率來進行衡量。"逆文件頻率"(Inverse Document Frequency,縮寫為IDF)如果某個詞相比較於整個語料庫來說比較少見,但是它在這篇文章中多次出現,那麼它很可能就反映了這篇文章的特性,那它正是我們所需要的關鍵詞。

計算公式

  

TF-IDF = 詞頻(TF) * 逆文件頻率(IDF)。還是在《中國的蜜蜂養殖》這篇文章中:假定該文長度為1000個詞,"中國"、"蜜蜂"、"養殖"各出現20次,則這三個詞的"詞頻"(TF)都為0.02。搜尋Google發現,包含"的"字的網頁共有250億張,假定這就是中文網頁總數(也就是語料庫)。包含"中國"的網頁共有62.3億張,包含"蜜蜂"的網頁為0.484億張,包含"養殖"的網頁為0.973億張。

  

可以看出蜜蜂和養殖的TF-IDF值比中國這個詞大,那麼這篇文章的關鍵詞重要性依次為蜜蜂、養殖和中國。

文字相似度:假設有如下兩個句子A、B,我們該怎麼判斷這兩個句子的相似度呢

 句子A:我喜歡看電視,不喜歡看電影。
 句子B:我不喜歡看電視,也不喜歡看電影。
先進行分詞來看一下。

 句子A:我/喜歡/看/電視,不/喜歡/看/電影。
 句子B:我/不/喜歡/看/電視,也/不/喜歡/看/電影。
可以得到整個語料庫:我,喜歡,看,電視,電影,不,也。
然後進行詞頻的統計

 句子A:我 1,喜歡 2,看 2,電視 1,電影 1,不 1,也 0。
 句子B:我 1,喜歡 2,看 2,電視 1,電影 1,不 2,也 1。
這樣就可以得出詞頻向量
 句子A:[1, 2, 2, 1, 1, 1, 0]
 句子B:[1, 2, 2, 1, 1, 2, 1]

相似度計算方法:最常用通過餘弦進行計算

  

  

二、任務簡介與資料預處理

現在我們手裡一份新聞資料,資料裡面包含新聞的內容以及新聞的種類等等,我們要做的就是對新聞進行一個分類任務,比如說汽車類時尚類等等。

資料集連結:https://pan.baidu.com/s/1fG_oagJT69bIgCZgasn_Ig 提取碼:yzd0

匯入相關的python庫

import pandas as pd
import jieba  # 如果沒有這個庫可能需要手動安裝

讀取資料集並刪除缺失的資料集(缺失的資料很少,所以可以刪除) 

# read_table()讀取以‘/t’分割的檔案到DataFrame 
# 在實際使用中可以通過對sep引數的控制來對任何文字檔案讀取
df_news = pd.read_table('./data/val.txt',names=['category','theme','URL','content'],encoding='utf-8')
df_news = df_news.dropna() # 刪除缺失資料
df_news.head()

content為新聞的主體內容

  

檢視資料集維度

df_news.shape

得到的結果

(5000, 4)

將新聞內容轉換為list方便進行分詞並檢視第1000條資料內容

content = df_news.content.values.tolist()  # 轉換為list 實際上是二維list
print(content[1000])

內容為:

阿里巴巴集團昨日宣佈,將在集團管理層面設立首席資料官崗位(Chief Data Officer),阿里巴巴B2B公
司CEO陸兆禧將會出任上述職務,向集團CEO馬雲直接彙報。>菹ぃ和6月初的首席風險官職務任命相同,首席資料官亦為阿
裡巴巴集團在完成與雅虎股權談判,推進“one company”目標後,在集團決策層面新增的管理崗位。0⒗錛團昨日表示
,“變成一家真正意義上的資料公司”已是戰略共識。記者劉夏

下面使用python中的jieba庫進行分詞

content_S = []
for line in content:
    # jieba分詞 精確模式。返回一個列表型別,建議使用
    current_segment = jieba.lcut(line)  
    if len(current_segment) > 1 and current_segment != '\r\n':
        content_S.append(current_segment)

檢視第1000條資料分詞後的內容

content_S[1000]

  

轉為pandas支援的DataFrame格式

df_content = pd.DataFrame({'content_S':content_S})   # 轉換為DataFrame
df_content.head()

分完詞後的結果為:

  

可以發現數據裡面包含很多無用的詞彙,所以我們需要對這些資料進行清洗,就是刪除掉裡面包含的停用詞

三、 刪除停用詞

讀取停用詞表

# 讀取停詞表
stopwords = pd.read_csv('./data/stopwords.txt',index_col=False,sep='\t',quoting=3,names=['stopword'],encoding='utf-8')
stopwords.head()

結果為:

  

刪除語料庫中的停用詞,這裡面的all_words是為了後面的詞雲展示。

# 刪除新聞中的停用詞
def drop_stopwords(contents, stopwords):
    contents_clean = [] # 刪除後的新聞
    all_words = []  # 構造詞雲所用的資料
    for line in contents:
        line_clean = []
        for word in line:
            if word in stopwords:
                continue
            line_clean.append(word)
            all_words.append(str(word))
        contents_clean.append(line_clean)
    return contents_clean, all_words


contents = df_content.content_S.values.tolist()
stopwords = stopwords.stopword.values.tolist()
# 得到刪除停用詞後的新聞以及詞雲資料
contents_clean, all_words = drop_stopwords(contents, stopwords)  

# df_content.content_S.isin(stopwords.stopword)
# df_content=df_content[~df_content.content_S.isin(stopwords.stopword)]
# df_content.head()

檢視刪除停用詞後的新聞內容

df_content = pd.DataFrame({'contents_clean':contents_clean})
df_content.head()

從結果可以看出,這次的資料對比上面的資料來說質量提高了很多。

  

檢視一下出現的所有的詞彙,也就是刪除停用詞後的all_words。

df_all_words = pd.DataFrame({'all_words':all_words})
df_all_words.head()

結果為:

  

統計all_words每個詞的詞頻,統計這個詞頻也是為了方便後面的詞雲展示。

import numpy
# 分組統計
words_count = df_all_words.groupby(by=['all_words'])['all_words'].agg({'count':numpy.size})
# 根據count排序
words_count = words_count.reset_index().sort_values(by=['count'],ascending=False)
words_count.head()

結果為:

  

四、詞雲展示

匯入wordcloud庫以及畫圖展示

from wordcloud import WordCloud # 詞雲庫
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib
matplotlib.rcParams['figure.figsize'] = (10.0,5.0)

wordcloud = WordCloud(font_path='./data/simhei.ttf',background_color='white',max_font_size=80)
word_frequence = {x[0]:x[1] for x in words_count.head(100).values} # 這裡只顯示詞頻前100的詞彙
wordcloud = wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud)

視覺化結果為:

  

未完待續。。。

&n