畢業設計之 --- 新聞分類系統
簡介
新聞分類課題是在演算法類畢業設計中比較熱門的, 本質上是屬於自然語言分類, 可以使用機器學習演算法去處理, 也可以使用深度學習演算法去處理.
基本步驟如下 :
文字資料採集 --> 選擇訓練演算法(機器學習/深度學習) --> 進行訓練 --> 檢效果.
本文章博主將介紹:
- 從頭開始實踐中文短文字分類
- 運用多種機器學習(深度學習 + 傳統機器學習)方法比較短文字分類處理過程與結果差別
參與及比較演算法
使用下面的演算法來進行文字分類, 並對最後分類準確率進行比較
- CNN 、 CNN + word2vec
- LSTM 、 LSTM + word2vec
- MLP(多層感知機)
- 樸素貝葉斯
- KNN
- SVM
- SVM + word2vec 、SVM + doc2vec
先說結論
- 引入預訓練的 word2vec 模型會給訓練帶來好處,具體來說:(1)間接引入外部訓練資料,防止過擬合;(2)減少需要訓練的引數個數,提高訓練效率
- LSTM 需要訓練的引數個數遠小於 CNN,但訓練時間大於 CNN。CNN 在分類問題的表現上一直很好,無論是影象還是文字;而想讓 LSTM 優勢得到發揮,首先讓訓練資料量得到保證
- 將單詞在 word2vec 中的詞向量加和求平均獲得整個句子的語義向量的方法看似 naive 有時真挺奏效,當然僅限於短句子,長度 100 以內應該問題不大
- 機器學習方法萬千,具體選擇用什麼樣的方法還是要取決於資料集的規模以及問題本身的複雜度,對於複雜程度一般的問題,看似簡單的方法有可能是墜吼地
實現過程
資料爬取
爬蟲這裡不公開提供, 爬取的是各大新聞網站資料, 需要的聯絡博主獲取, 聯絡方式在文章最下方~
資料預處理
將下載的原始資料進行轉碼,然後給文字標類別的標籤,然後製作訓練與測試資料,然後控制文字長度,分詞,去標點符號
哎,坑多,費事,比較麻煩
首先,下載下來是 xml 格式,並且是 GBK (萬惡之源)編碼,需要轉成 UTF8,並整理成 json 方便處理。原始資料長這個樣:
對成功標出來的15個類的新聞,統計一下類別的分佈,結果如下:
分佈比較不均,第 14 類和第 15 類的新聞很少,另外第 8 類和第 11 類一個新聞也沒有
所以最後選了剩下的11個類,每個類抽2000個新聞,按4:1分成訓練與測試,如圖
上一步選出來的訓練新聞長這樣,因為考慮到新聞標題的意義重大,這裡就將新聞標題和新聞內容接到一起,用空格隔開,然後擷取每條新聞的前 100 個字
最後得到以下結果檔案:(1)新聞文字資料,每行 1 條新聞,每條新聞由若干個片語成,詞之間以空格隔開,訓練文字 17600 行,測試文字 4324 行;(2)新聞標籤資料,每行 1 個數字,對應這條新聞所屬的類別編號,訓練標籤 17600行,測試標籤 4324 行
CNN文字分類
深度學習用的 keras 工具,操作簡單易懂,模型上手飛快,居家旅行必備。keras 後端用的 Tensorflow,雖然用什麼都一樣
首先一些先設定一些會用到的引數
MAX_SEQUENCE_LENGTH = 100 # 每條新聞最大長度
EMBEDDING_DIM = 200 # 詞向量空間維度
VALIDATION_SPLIT = 0.16 # 驗證集比例
TEST_SPLIT = 0.2 # 測試集比例
第一步先把訓練與測試資料放在一起提取特徵,使用 keras 的 Tokenizer 來實現,將新聞文件處理成單詞索引序列,單詞與序號之間的對應關係靠單詞的索引表 word_index 來記錄,這裡從所有新聞中提取到 65604 個單詞,比如 [苟,國家,生死] 就變成了 [1024, 666, 233] ;然後將長度不足 100 的新聞用 0 填充(在前端填充),用 keras 的 pad_sequences 實現;最後將標籤處理成 one-hot 向量,比如 6 變成了 [0,0,0,0,0,0,1,0,0,0,0,0,0],用 keras 的 to_categorical 實現
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils import to_categorical
import numpy as np
tokenizer = Tokenizer()
tokenizer.fit_on_texts(all_texts)
sequences = tokenizer.texts_to_sequences(all_texts)
word_index = tokenizer.word_index
print('Found %s unique tokens.' % len(word_index))
data = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)
labels = to_categorical(np.asarray(all_labels))
print('Shape of data tensor:', data.shape)
print('Shape of label tensor:', labels.shape)
再將處理後的新聞資料按 6.4:1.6:2 分為訓練集,驗證集,測試集
p1 = int(len(data)*(1-VALIDATION_SPLIT-TEST_SPLIT))
p2 = int(len(data)*(1-TEST_SPLIT))
x_train = data[:p1]
y_train = labels[:p1]
x_val = data[p1:p2]
y_val = labels[p1:p2]
x_test = data[p2:]
y_test = labels[p2:]
print 'train docs: '+str(len(x_train))
print 'val docs: '+str(len(x_val))
print 'test docs: '+str(len(x_test))
然後就是搭建模型,首先是一個將文字處理成向量的 embedding 層,這樣每個新聞文件被處理成一個 100 x 200 的二維向量,100 是每條新聞的固定長度,每一行的長度為 200 的行向量代表這個單詞在空間中的詞向量。下面通過 1 層卷積層與池化層來縮小向量長度,再加一層 Flatten 層將 2 維向量壓縮到 1 維,最後通過兩層 Dense(全連線層)將向量長度收縮到 12 上,對應新聞分類的 12 個類(其實只有 11 個類,標籤 0 沒有用到)。
from keras.layers import Dense, Input, Flatten, Dropout
from keras.layers import Conv1D, MaxPooling1D, Embedding
from keras.models import Sequential
model = Sequential()
model.add(Embedding(len(word_index) + 1, EMBEDDING_DIM, input_length=MAX_SEQUENCE_LENGTH))
model.add(Dropout(0.2))
model.add(Conv1D(250, 3, padding='valid', activation='relu', strides=1))
model.add(MaxPooling1D(3))
model.add(Flatten())
model.add(Dense(EMBEDDING_DIM, activation='relu'))
model.add(Dense(labels.shape[1], activation='softmax'))
model.summary()
網路模型如下
實驗結果如下
準確度 0.81459521
擁有11個分類的問題達到這個準確度,應該也不錯(易滿足)。並且搜狗給的資料本來也不是很好(甩鍋)。可以看到在訓練集上的準確度達到了 0.88,但是測試集上的準確度只有 0.81,說明還是有些過擬合。另外,整個模型需要訓練的引數接近 1500 萬,其中 1300 萬都是 embedding 層的引數,說明如果利用 word2vec 模型替換 embedding 層,解放這 1300 萬引數,肯定會讓訓練效率得到提高
其他分類方法更新中.......
學長廣告
在這裡為自己打個廣告
學長親自接計算機畢業設計:
有意者q746876041