文本分類整體上包括8個步驟。數據探索分析-》數據抽取-》文本預處理-》分詞-》去除停用詞-》文本向量化表示-》分類器-》模型評估.重要python庫包括numpy(數組),pandas(用於處理結構化數據),matplotlib(繪製詞雲,便於直觀表示),sklearn(提供大量分類聚類算法庫).python
(1)獲取大量未通過處理的文檔,且標記好文檔所屬類型。
(2)給各個文檔分配惟一的Id,並將以前用文字標記的分類類別用離散數字代替。例如 分類標記爲[‘正常短信’,‘垃圾短信’],將其離散表示爲[0,1].
(3)將Id,文檔內容,標記 做爲列,樣本個數做爲行,將這些文檔讀入一個數組中。形式爲:[ [Id1,content1,label1], ...,[Id_n,content_n,label_n] ]
代碼示例:
import pandas as pd
data = pd.read_csv(csv文件名,header=None) # 讀入csv文件,不讀入列名
data.columns = ['Id','Content','Label']正則表達式
data['label'] # 獲取label列的數據,結果是一維數組
data[['content','label']] # 結果是 content,label列的全部數據算法
data['label'].value_counts() # 獲取label這一列數據中各個標記出現次數,結果以series的形式返回windows
num=data['label'].value_counts()
import matplotlib.pyplot as plt
plt.figure(figsize=(3,3)) # 將畫布設置爲3*3的正方形
plt.pie(num,labels=['正常','垃圾']) # 繪製餅圖,num是一個series ,series是一個帶索引的數組,和字典使用相似。
plt.show()數組
當不一樣標記的比例不平衡時,須要分層抽樣,例如0標記出現72000次,而1標記出現8000次,則此時會產生模型偷懶問題。
data_normal = data.loc[data['label']==1].sample(1000,random_state=123) #在label爲1的全部數據裏挑選1000個隨機樣本
data_bad = data.loc[data['label']==0].sample(1000,random_state=123) #在label爲0的全部數據裏挑選1000個隨機樣本
data_new = pd.contat([data_normal,data_bad],axis=0) # 默認行拼接,因此axis可不寫app
以下圖所示,content一項中包含了xxx,以及一些特殊編碼字符,以及逗號句號等等的標點符號,這些東西都是無心義字符,須要刪除掉
刪除這些特殊非中文字符,須要用到正則表達式,正則表達式是爬蟲中必不可少的一個知識點,是一個條件表達式,用這個構造的條件表達式所指定的規則在一個指定字符串中檢索匹配出符合規則的句子。
import re
afterDeleteSpecialWord=data_new['content'].apply(lambda x:re.sub('[^\u4E00-\u9FD5]+','',string))
這裏的apply表示對這個series數組中的每個元素(即文檔的內容字符串)都執行這個匿名函數x,string是傳進來的參數,re.sub 表示 將前面指定的正則表達式'[^\u4E00-\u9FD5]+'所匹配的字符串(即非中文特殊字符)用''代替。這裏的正則表達式'[^\u4E00-\u9FD5]+':
[]是一個原子列表,^表示非,\u4E00-\u9FD5中文字符的正則表示,前面加上^則表示非中文字符,[]+表示這個原子列表中的字符能夠匹配1次或屢次。具體正則表達式的用法網上資源不少,這裏不詳細解釋.
處理完後,標點符號,以及特殊字符都不見了,以下所示:
dom
第一步先將以前的content中的內容進行分詞,分詞後content列的元素是一個列表,好比以前的content列中的元素'我來到北京清華大學計算機學院',執行分詞後結果爲:['我','來到','北京','清華大學','計算機','學院']
第二步是去除停用詞,首先加載停用詞文件,裏面存儲了N個停用詞,而後對第一步中的分詞結果進行去除存在於停用詞列表中的詞.
代碼以下:
import jieba # 分詞庫
with open('stopList.txt','r') as f:
stop=f.read() # 獲取的結果是一個大的字符串,其中換行符之類的特殊字符也存在於其中
stop = stop.split() # 按照空格,換行符進行分割,獲取停用詞列表
stop = [' ']+stop # 因爲以前的stop裏沒有空格,而空格是停用詞,因此從新加回空格
jieba.load_userdic(path) # 加載指定路徑path裏的用戶自定義詞典
after_segement = afterDeleteSpecialWord.apply(jieba.lcut) # 進行分詞
data_after = after_segement.apply(lambda x:[i for i in x if i not in stop]) # 去除停用詞機器學習
繪製詞雲是文本分類裏對詞頻的一個直觀圖像表示,以圖像形式呈現,頻率高的詞彙字體更大,頻率小的,字體小。
import matplotlib.pyplot as plt # 畫圖工具
from wordcloud import WordCloud # 詞雲工具庫
import itertools # 將二維數據壓縮爲一維數據
pic = plt.imread(picturePath) # 這裏picturePath爲具體圖片所在路徑,這裏沒有指定.這行代碼是加載畫板的一個背景圖片
'''
wc = WordCloud(font_path=r'C:\Windows\Fonts\字體名稱',background_color='white',mask=pic) # 生成一個詞雲對象 ,windows系統中的字體存放在c盤Windows文件夾下的Fonts文件夾中。由於這裏統計的都是中文,因此不要選英文字體,而是選擇中文字體,右鍵,屬性,如圖,爲具體的字體名稱 '''
num = pd.Series(list(itertools.chain(*list(data_after)))).value_counts() # 統計詞頻
wc.fit_words(num) # 將統計好的詞頻放進去
plt.imshow(wc)
plt.show()
函數
文本向量化表示的含義爲:因爲咱們目前獲得的是一個分詞結果,是中文,而計算機不能直接將中文做爲分類的輸入數據,必須將其用數字來表示,那麼如何將一個文檔用一個數字化的向量表示呢,這就是文本向量化。
經常使用的向量化表示有詞袋模型,詞頻,TF-IDF,以及考慮上下文的詞嵌入。
詞袋模型是指,一個文檔中出現了的詞則該詞置1,詞庫中其餘詞置0,而不考慮出現次數的多少。一個文檔則能夠表示成一個N維的0,1向量,N的大小取決於詞庫的大小。
詞頻:在詞袋模型的基礎上,考慮出現詞的次數,而不是隻要出現了就是1。
TF-IDF:考慮一個詞的詞頻以及逆文檔頻率,逆文檔頻率是指該詞在全部文檔裏的稀有程度,該詞在全部文檔裏出現的文檔數越少,則該詞越稀有,區分度就越高,逆文檔頻率就越高,逆文檔頻率=log(全部文檔數/(出現該詞的文檔數+1)),而TF-IDF則=TF*IDF。
在sklearn 中的feature_extraction.text包中有CountVectorizer,TfidfVectorizer直接能夠作文本向量化工做,一個是根據詞頻,一個是TF-IDF。
tmp = data_after.apply(lambda x:' '.join(x)) # 因爲谷歌開發的向量化工具僅支持按空格統計,因此以前的列表存放的單詞須要轉換成一個以空格分隔開的一個大字符串。
cv=CountVectorizer().fit(tmp) # 加載字典,以及須要向量化的文本數據
vector_data = cv.transform(tmp) # 向量化,結果是一個迭代器
vector_array = vector_data.toarray() # 將迭代器轉爲數組工具
接下來的步驟和通常機器學習分類問題是如出一轍的,很少作介紹。已經獲得結構化數據vector_array,以及相應的標籤label,能夠用sklearn的各類訓練模型進行訓練,測試,模型評估等等。