數據挖掘第三篇 文本分類 文本分類總體上包括8個步驟。數據探索分析 》數據抽取 》文本預處理 》分詞 》去除停用詞 》文本向量化表示 》分類器 》模型評估.重要python庫包括numpy(數組),pandas(用於處理結構化數據),matplotlib(繪製詞雲,便於直觀表示),sklearn(提 ...
數據挖掘第三篇-文本分類
文本分類總體上包括8個步驟。數據探索分析-》數據抽取-》文本預處理-》分詞-》去除停用詞-》文本向量化表示-》分類器-》模型評估.重要python庫包括numpy(數組),pandas(用於處理結構化數據),matplotlib(繪製詞雲,便於直觀表示),sklearn(提供大量分類聚類演算法庫).
1.數據探索分析
(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']
1.1DataFrame中獲取數據的一些方法:
- data.loc[] # 通過字元串索引的方式獲取指定行列數據 例如:
data.loc[0:2,'content'] # 獲取第0,1,2行的content列 的數據,【註意】:0:2獲取的是0,1,2行,這一點和一般的切片不相同
data.loc[[0,2],['content','label']] # 通過列表指定行列
- data.iloc[] # 通過數字索引方式,用法和數組的一模一樣
data['label'] # 獲取label列的數據,結果是一維數組
data[['content','label']] # 結果是 content,label列的所有數據1.2統計不同label出現頻率,繪製餅圖
data['label'].value_counts() # 獲取label這一列數據中各個標記出現次數,結果以series的形式返回
1.2.1繪製餅圖
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()
2.數據抽取
當不同標記的比例不平衡時,需要分層抽樣,例如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可不寫
3.文本預處理
如下圖所示,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次或多次。具體正則表達式的用法網上資源很多,這裡不詳細解釋.
處理完後,標點符號,以及特殊字元都不見了,如下所示:
4.分詞,去除停用詞
第一步先將之前的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]) # 去除停用詞
4.1繪製詞雲
繪製詞雲是文本分類里對詞頻的一個直觀圖像表示,以圖像形式呈現,頻率高的辭彙字體更大,頻率小的,字體小。
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的各種訓練模型進行訓練,測試,模型評估等等。