中文郵件分類

按照分類要求的不一樣,文本分類主要能夠分爲二分類,多分類,多標籤分類三大類。html

  • 二分類問題:也是最基礎的分類,顧名思義是將文本歸爲兩種類別,好比將正常郵件郵件劃分問題,垃圾郵件或者正常郵件。一段影評,判斷是好評仍是差評的問題。
  • 多分類問題:是將文本劃分爲多個類別,好比將新聞歸爲政治類,娛樂類,生活類等等。
  • 多標籤分類:是給文本貼上多個不一樣的標籤,好比一部小說能夠同時被劃分爲多個主題,可能既是修仙小說,又是玄幻小說。

文本分類主要有兩種方法:傳統機器學習文本分類算法、深度學習文本分類算法。python

  • 傳統方法:特徵提取(也能夠叫作特徵工程)+ 分類器。就是將文本轉換成固定維度的向量,而後送到分類器中進行分類。
  • 深度學習方法:能夠自動提取特徵,實現端到端的訓練,有較強的特徵表徵能力,因此深度學習進行文本分類的效果每每要好於傳統的方法。

基於SVM的垃圾郵件判斷算法

# 本次咱們用到的數據包含 3 個文件, `ham_data.txt` 文件裏面包含 5000 條正常郵件樣本,`spam_data.txt` 文件裏面包含 5001 個垃圾郵件樣本,`stopwords` 是停用詞表。
wget -nc "http://labfile.oss.aliyuncs.com/courses/1208/ham_data.txt"
wget -nc "http://labfile.oss.aliyuncs.com/courses/1208/spam_data.txt"
wget -nc "http://labfile.oss.aliyuncs.com/courses/1208/stop_word.txt"# 給正常郵件和垃圾郵件貼上標籤,咱們用 `1` 表明正常郵件,`0` 表明垃圾郵件。
path1 = 'ham_data.txt'  # 正常郵件存放地址
path2 = 'spam_data.txt'  # 垃圾郵件地址

# 下面用 utf-8 編碼模式打開正常樣本:
h = open(path1, encoding='utf-8')

# 另外由於咱們準備的數據是每一行一封郵件,這裏咱們要用 `readlines()` 來以行來讀取文本的內容。
h_data = h.readlines()
h_data[0:3]  # 顯示前3封正常郵件

# 同理方式處理垃圾樣本:
s = open(path2, encoding='utf-8')
s_data = s.readlines()
# 讀取以後,咱們的 h_data 數是由 5000 條郵件字符串組成的正常郵件樣本集, s_data 是由 5001 條郵件字符串組成的垃圾郵件樣本集。下面咱們爲將兩個樣本組合起來,並貼上標籤。
# 生成一個 `len(h_data)` 長的的一維全 1 列表:
import numpy as np
h_labels = np.ones(len(h_data)).tolist()  # 生成一個len(h_data)長的的一維全1列表
h_labels[0:10]  # 咱們顯示前10個數據
# 生成一個 `len(s_data)` 長的的一維全 0 列表:
s_labels = np.zeros(len(s_data)).tolist()
s_labels[0:10]  # 咱們顯示前10個數據

# 拼接樣本集和標籤集:
datas = h_data + s_data  # 將正常樣本和垃圾樣本整合到datas當中
labels = h_labels + s_labels
# 這樣咱們獲得一個由全部郵件樣本組合起來的樣本集 `datas`  以及一個標籤集 `labels`。

# 由於咱們沒有事先準備測試集,因此咱們在 10001 個樣本當中,隨機劃出 25% 個樣本和標籤來做爲咱們的測試集,剩下的 75% 做爲樣本集來進行咱們的分類。這裏咱們能夠用到 scikit-learn 工具裏面的 `train_test_split` 類。

# sklearn.model_selection.train_test_split(datas, labels, test_size=0.25, random_state=5 )
# - `datas` : 樣本集
# - `labels`: 標籤集
# - `train_test_split`:劃分到測試集的比例
# - `random_state`:隨機種子,取同一個的隨機種子那麼每次劃分出的測試集是同樣的。
from sklearn.model_selection import train_test_split
train_d, test_d, train_l, test_l = train_test_split(
    datas, labels, test_size=0.25, random_state=5)

# 調用這個函數以後,就能夠獲得:
# - `train_d`:樣本集
# - `test_d`:測試集
# - `train_l`:樣本標籤
# - `test_l`:測試標籤
# 爲了代碼簡潔方便理解,咱們將分詞設計成 `tokenize_words` 函數,供後續直接調用。 import jieba def tokenize_words(corpus): tokenized_words = jieba.cut(corpus) tokenized_words = [token.strip() for token in tokenized_words] return tokenized_words # 去停用詞,首先加載咱們剛剛下載好的停用詞表。這裏也能夠自行在網上下載,編碼格式爲 utf-8,每行一個停用詞。爲了方便調用,咱們將去除停用詞的操做放到 `remove_stopwords` 函數當中。 def remove_stopwords(corpus): # 函數輸入爲樣本集 sw = open('stop_word.txt', encoding='utf-8') # stopwords 停詞表 sw_list = [l.strip() for l in sw] # 去掉文本中的回車符,而後存放到 sw_list 當中 # 調用前面定義好的分詞函數返回到 tokenized_data 當中 tokenized_data = tokenize_words(corpus) # 過濾停用詞,對每一個在 tokenized_data 中的詞 data 進行判斷,若是 data 不在 sw_list 則添加到 filtered_data 當中 filtered_data = [data for data in tokenized_data if data not in sw_list] # 用''將 filtered_data 串起來賦值給 filtered_datas filtered_datas = ''.join(filtered_data) return filtered_datas # 返回去停用詞以後的 datas # 接下來,咱們對分詞結果進行處理。這裏使用 `tqdm` 模塊顯示進度。安裝 `tqdm` 模塊: get_ipython().system('pip install tqdm') from tqdm import tqdm_notebook def preprocessing_datas(datas): preprocessed_datas = [] # 對 datas 當中的每個 data 進行去停用詞操做,並添加到上面剛剛創建的 preprocessed_datas 當中 for data in tqdm_notebook(datas): data = remove_stopwords(data) preprocessed_datas.append(data) return preprocessed_datas # 返回去停用詞以後的新的樣本集 # 而後用上面預處理函數對樣本集進行處理。 pred_train_d = preprocessing_datas(train_d) pred_test_d = preprocessing_datas(test_d) # 經過上面兩步,咱們獲得了分詞事後而且去除停用詞了的樣本集 `pred_train_d` 和 測試集 `pred_test_d`。 # 在進行分詞及去停用詞處理事後,用 TF-IDF 模型特徵來進行特徵提取。 from sklearn.feature_extraction.text import TfidfVectorizer # 定義 TF-IDF 模型訓練器 `vectorizer` 。 vectorizer = TfidfVectorizer( min_df=1, norm='l2', smooth_idf=True, use_idf=True, ngram_range=(1, 1)) # 對預處理事後的 `pred_train_d` 進行特徵提取: tfidf_train_features = vectorizer.fit_transform(pred_train_d) tfidf_train_features # 經過這一步,咱們獲得了 7500 個 5946 維數的向量做爲咱們的訓練特徵集。 # 用訓練集訓練好特徵後的 `vectorizer` 來提取測試集的特徵: # 注意這裏不能用 `vectorizer.fit_transform()` 要用 `vectorizer.transform()`,不然,將會對測試集單獨訓練 TF-IDF 模型,而不是在訓練集的詞數量基礎上作訓練。這樣詞總量跟訓練集不同多,排序也不同,將會致使維數不一樣,最終沒法完成測試。 tfidf_test_features = vectorizer.transform(pred_test_d) tfidf_test_features # 完成以後,咱們獲得 2501 個 5946 維數的向量做爲咱們的測試特徵集。 # 在得到 TF-IDF 特徵以後,咱們能夠調用 `SGDClassifier()` 類來訓練 SVM 分類器。 # sklearn.linear_model.SGDClassifier(loss='hinge') # `SGDClassifier` 是一個多個分類器的組合,當參數 `loss='hinge'` 時是一個支持向量機分類器。 # 加載 SVM 分類器: from sklearn.linear_model import SGDClassifier # 調整 `loss = 'hinge'` : svm = SGDClassifier(loss='hinge') # 而後咱們將以前準備好的樣本集和樣本標籤送進 SVM 分類器進行訓練。 svm.fit(tfidf_train_features, train_l) # 接下來咱們用測試集來測試一下分類器的效果。 predictions = svm.predict(tfidf_test_features) predictions # 爲了直觀顯示分類的結果,咱們用 scikit-learn 庫中的 `accuracy_score` 函數來計算一下分類器的準確率 。 # sklearn.metrics.accuracy_score(test_l, prediction) # 這個函數的做用是爲了計算 `test_l` 中與 `prediction` 相同的比例。即準確率。 # 加載 `metrics` 函數: from sklearn import metrics # 用測試標籤和預測結果 計算分類準確率。`np.round(X,2)` 的做用是 X 四捨五入後保留小數點後2位數字。 accuracy_score = np.round(metrics.accuracy_score(test_l, predictions), 2) accuracy_score # 隨機提取一個樣本查看其預測結果: print('郵件類型:', test_l[20]) print('預測郵件類型:', predictions[20]) print('文本:', test_d[20])
相關文章
相關標籤/搜索