[Python人工智能] 二十.基于Keras+RNN的文本分類vs基于傳統(tǒng)機器學習的文本分類(Python人工智能需要學什么)

      網(wǎng)友投稿 702 2025-04-03

      代碼-:https://github.com/eastmountyxz/AI-for-TensorFlow

      代碼-:https://github.com/eastmountyxz/AI-for-Keras

      博客-:https://github.com/eastmountyxz/CSDNBlog-AI-for-Python

      文章目錄

      一.RNN文本分類

      1.RNN

      2.文本分類

      二.基于傳統(tǒng)機器學習貝葉斯算法的文本分類

      1.MultinomialNB+TFIDF文本分類

      2.GaussianNB+Word2Vec文本分類

      三.Keras實現(xiàn)RNN文本分類

      1.IMDB數(shù)據(jù)集和序列預處理

      2.詞嵌入模型訓練

      3.RNN文本分類

      四.RNN實現(xiàn)中文數(shù)據(jù)集的文本分類

      1.RNN+Word2Vector文本分類

      2.LSTM+Word2Vec文本分類

      3.LSTM+TFIDF文本分類

      4.機器學習和深度學習對比分析

      五.總結

      華為云社區(qū)前文賞析:

      [Python人工智能] 一.TensorFlow2.0環(huán)境搭建及神經(jīng)網(wǎng)絡入門

      [Python人工智能] 二.TensorFlow基礎及一元直線預測案例

      [Python人工智能] 三.TensorFlow基礎之Session、變量、傳入值和激勵函數(shù)

      [Python人工智能] 四.TensorFlow創(chuàng)建回歸神經(jīng)網(wǎng)絡及Optimizer優(yōu)化器

      [Python人工智能] 五.Tensorboard可視化基本用法及繪制整個神經(jīng)網(wǎng)絡

      [Python人工智能] 六.TensorFlow實現(xiàn)分類學習及MNIST手寫體識別案例

      [Python人工智能] 七.什么是過擬合及dropout解決神經(jīng)網(wǎng)絡中的過擬合問題

      [Python人工智能] 八.卷積神經(jīng)網(wǎng)絡CNN原理詳解及TensorFlow編寫CNN

      [Python人工智能] 九.gensim詞向量Word2Vec安裝及《慶余年》中文短文本相似度計算

      [Python人工智能] 十.Tensorflow+Opencv實現(xiàn)CNN自定義圖像分類及與KNN圖像分類對比

      [Python人工智能] 十一.Tensorflow如何保存神經(jīng)網(wǎng)絡參數(shù)

      [Python人工智能] 十二.循環(huán)神經(jīng)網(wǎng)絡RNN和LSTM原理詳解及TensorFlow編寫RNN分類案例

      [Python人工智能] 十三.如何評價神經(jīng)網(wǎng)絡、loss曲線圖繪制、圖像分類案例的F值計算

      [Python人工智能] 十四.循環(huán)神經(jīng)網(wǎng)絡LSTM RNN回歸案例之sin曲線預測 丨【百變AI秀】

      [Python人工智能] 十五.無監(jiān)督學習Autoencoder原理及聚類可視化案例詳解

      [Python人工智能] 十六.Keras環(huán)境搭建、入門基礎及回歸神經(jīng)網(wǎng)絡案例

      [Python人工智能] 十七.Keras搭建分類神經(jīng)網(wǎng)絡及MNIST數(shù)字圖像案例分析

      [Python人工智能] 十八.Keras搭建卷積神經(jīng)網(wǎng)絡及CNN原理詳解

      [Python人工智能] 十九.Keras搭建循環(huán)神經(jīng)網(wǎng)絡分類案例及RNN原理詳解

      [Python人工智能] 二十.基于Keras+RNN的文本分類vs基于傳統(tǒng)機器學習的文本分類

      補充一張深度學習的思維導圖。

      一.RNN文本分類

      1.RNN

      循環(huán)神經(jīng)網(wǎng)絡英文是Recurrent Neural Networks,簡稱RNN。RNN的本質概念是利用時序信息,在傳統(tǒng)神經(jīng)網(wǎng)絡中,假設所有的輸入(以及輸出)都各自獨立。但是,對于很多任務而言,這非常局限。舉個例子,假如你想根據(jù)一句沒說完的話,預測下一個單詞,最好的辦法就是聯(lián)系上下文的信息。而RNN(循環(huán)神經(jīng)網(wǎng)絡)之所以是“循環(huán)”,是因為它們對序列的每個元素執(zhí)行相同的任務,而每次的結果都獨立于之前的計算。

      假設有一組數(shù)據(jù)data0、data1、data2、data3,使用同一個神經(jīng)網(wǎng)絡預測它們,得到對應的結果。如果數(shù)據(jù)之間是有關系的,比如做菜下料的前后步驟,英文單詞的順序,如何讓數(shù)據(jù)之間的關聯(lián)也被神經(jīng)網(wǎng)絡學習呢?這就要用到——RNN。

      比如存在ABCD數(shù)字,需要預測下一個數(shù)字E,會根據(jù)前面ABCD順序進行預測,這就稱為記憶。預測之前,需要回顧以前的記憶有哪些,再加上這一步新的記憶點,最終輸出output,循環(huán)神經(jīng)網(wǎng)絡(RNN)就利用了這樣的原理。

      首先,讓我們想想人類是怎么分析事物之間的關聯(lián)或順序的。人類通常記住之前發(fā)生的事情,從而幫助我們后續(xù)的行為判斷,那么是否能讓計算機也記住之前發(fā)生的事情呢?

      在分析data0時,我們把分析結果存入記憶Memory中,然后當分析data1時,神經(jīng)網(wǎng)絡(NN)會產(chǎn)生新的記憶,但此時新的記憶和老的記憶沒有關聯(lián),如上圖所示。在RNN中,我們會簡單的把老記憶調用過來分析新記憶,如果繼續(xù)分析更多的數(shù)據(jù)時,NN就會把之前的記憶全部累積起來。

      下面是一個典型的RNN結果模型,按照時間點t-1、t、t+1,每個時刻有不同的x,每次計算會考慮上一步的state和這一步的x(t),再輸出y值。在該數(shù)學形式中,每次RNN運行完之后都會產(chǎn)生s(t),當RNN要分析x(t+1)時,此刻的y(t+1)是由s(t)和s(t+1)共同創(chuàng)造的,s(t)可看作上一步的記憶。多個神經(jīng)網(wǎng)絡NN的累積就轉換成了循環(huán)神經(jīng)網(wǎng)絡,其簡化圖如下圖的左邊所示。例如,如果序列中的句子有5個單詞,那么,橫向展開網(wǎng)絡后將有五層神經(jīng)網(wǎng)絡,一層對應一個單詞。

      總之,只要你的數(shù)據(jù)是有順序的,就可以使用RNN,比如人類說話的順序,電話號碼的順序,圖像像素排列的順序,ABC字母的順序等。RNN常用于自然語言處理、機器翻譯、語音識別、圖像識別等領域。

      2.文本分類

      文本分類旨在對文本集按照一定的分類體系或標準進行自動分類標記,屬于一種基于分類體系的自動分類。文本分類最早可以追溯到上世紀50年代,那時主要通過專家定義規(guī)則來進行文本分類;80年代出現(xiàn)了利用知識工程建立的專家系統(tǒng);90年代開始借助于機器學習方法,通過人工特征工程和淺層分類模型來進行文本分類。現(xiàn)在多采用詞向量以及深度神經(jīng)網(wǎng)絡來進行文本分類。

      牛亞峰老師將傳統(tǒng)的文本分類流程歸納如下圖所示。在傳統(tǒng)的文本分類中,基本上大部分機器學習方法都在文本分類領域有所應用。主要包括:

      Naive Bayes

      KNN

      SVM

      集合類方法

      最大熵

      神經(jīng)網(wǎng)絡

      利用Keras框架進行文本分類的基本流程如下:

      步驟 1:文本的預處理,分詞->去除停用詞->統(tǒng)計選擇top n的詞做為特征詞

      步驟 2:為每個特征詞生成ID

      步驟 3:將文本轉化成ID序列,并將左側補齊

      步驟 4:訓練集shuffle

      步驟 5:Embedding Layer 將詞轉化為詞向量

      步驟 6:添加模型,構建神經(jīng)網(wǎng)絡結構

      步驟 7:訓練模型

      步驟 8:得到準確率、召回率、F1值

      注意,如果使用TFIDF而非詞向量進行文檔表示,則直接分詞去停后生成TFIDF矩陣后輸入模型。本文將采用詞向量、TFIDF兩種方式進行實驗。

      深度學習文本分類方法包括:

      卷積神經(jīng)網(wǎng)絡(TextCNN)

      循環(huán)神經(jīng)網(wǎng)絡(TextRNN)

      TextRNN+Attention

      TextRCNN(TextRNN+CNN)

      推薦牛亞峰老師的文章:基于 word2vec 和 CNN 的文本分類 :綜述 & 實踐

      二.基于傳統(tǒng)機器學習貝葉斯算法的文本分類

      1.MultinomialNB+TFIDF文本分類

      數(shù)據(jù)集采用基基偉老師的自定義文本,共21行數(shù)據(jù),包括2類(小米手機、小米粥)。其基本流程是:

      獲取數(shù)據(jù)集data和target

      [Python人工智能] 二十.基于Keras+RNN的文本分類vs基于傳統(tǒng)機器學習的文本分類(python人工智能需要學什么)

      調用Jieba庫實現(xiàn)中文分詞

      計算TF-IDF值,將詞頻矩陣轉換為TF-IDF向量矩陣

      調用機器學習算法進行訓練和預測

      實驗評估及可視化分析

      完整代碼如下:

      # -*- coding: utf-8 -*- """ Created on Sat Mar 28 22:10:20 2020 @author: Eastmount CSDN """ from jieba import lcut #--------------------------------載入數(shù)據(jù)及預處理------------------------------- data = [ [0, '小米粥是以小米作為主要食材熬制而成的粥,口味清淡,清香味,具有簡單易制,健胃消食的特點'], [0, '煮粥時一定要先燒開水然后放入洗凈后的小米'], [0, '蛋白質及氨基酸、脂肪、維生素、礦物質'], [0, '小米是傳統(tǒng)健康食品,可單獨燜飯和熬粥'], [0, '蘋果,是水果中的一種'], [0, '粥的營養(yǎng)價值很高,富含礦物質和維生素,含鈣量豐富,有助于代謝掉體內多余鹽分'], [0, '雞蛋有很高的營養(yǎng)價值,是優(yōu)質蛋白質、B族維生素的良好來源,還能提供脂肪、維生素和礦物質'], [0, '這家超市的蘋果都非常新鮮'], [0, '在北方小米是主要食物之一,很多地區(qū)有晚餐吃小米粥的習俗'], [0, '小米營養(yǎng)價值高,營養(yǎng)全面均衡 ,主要含有碳水化合物'], [0, '蛋白質及氨基酸、脂肪、維生素、鹽分'], [1, '小米、三星、華為,作為安卓三大手機旗艦'], [1, '別再管小米華為了!魅族手機再曝光:這次真的完美了'], [1, '蘋果手機或將重陷2016年困境,但這次它無法再大幅提價了'], [1, '三星想要繼續(xù)壓制華為,僅憑A70還不夠'], [1, '三星手機屏占比將再創(chuàng)新高,超華為及蘋果旗艦'], [1, '華為P30、三星A70爆賣,斬獲蘇寧最佳手機營銷獎'], [1, '雷軍,用一張圖告訴你:小米和三星的差距在哪里'], [1, '小米米聊APP官方Linux版上線,適配深度系統(tǒng)'], [1, '三星剛剛更新了自家的可穿戴設備APP'], [1, '華為、小米跨界并不可怕,可怕的打不破內心的“天花板”'], ] #中文分析 X, Y = [' '.join(lcut(i[1])) for i in data], [i[0] for i in data] print(X) print(Y) #['煮粥 時 一定 要 先燒 開水 然后 放入 洗凈 后 的 小米', ...] #--------------------------------------計算詞頻------------------------------------ from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer #將文本中的詞語轉換為詞頻矩陣 vectorizer = CountVectorizer() #計算個詞語出現(xiàn)的次數(shù) X_data = vectorizer.fit_transform(X) print(X_data) #獲取詞袋中所有文本關鍵詞 word = vectorizer.get_feature_names() print('【查看單詞】') for w in word: print(w, end = " ") else: print("\n") #詞頻矩陣 print(X_data.toarray()) #將詞頻矩陣X統(tǒng)計成TF-IDF值 transformer = TfidfTransformer() tfidf = transformer.fit_transform(X_data) #查看數(shù)據(jù)結構 tfidf[i][j]表示i類文本中的tf-idf權重 weight = tfidf.toarray() print(weight) #--------------------------------------數(shù)據(jù)分析------------------------------------ from sklearn.naive_bayes import MultinomialNB from sklearn.metrics import classification_report from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(weight, Y) print(len(X_train), len(X_test)) print(len(y_train), len(y_test)) print(X_train) #調用MultinomialNB分類器 clf = MultinomialNB().fit(X_train, y_train) pre = clf.predict(X_test) print("預測結果:", pre) print("真實結果:", y_test) print(classification_report(y_test, pre)) #--------------------------------------可視化分析------------------------------------ #降維繪制圖形 from sklearn.decomposition import PCA import matplotlib.pyplot as plt pca = PCA(n_components=2) newData = pca.fit_transform(weight) print(newData) L1 = [n[0] for n in newData] L2 = [n[1] for n in newData] plt.scatter(L1, L2, c=Y, s=200) plt.show()

      輸出結果如下所示:

      6個預測數(shù)據(jù)的accuracy ===> 0.67

      ['小米粥 是 以 小米 作為 主要 食材 熬 制而成 的 粥 , 口味 清淡 , 清香味 , 具有 簡單 易制 , 健胃 消食 的 特點', '煮粥 時 一定 要 先燒 開水 然后 放入 洗凈 后 的 小米', '蛋白質 及 氨基酸 、 脂肪 、 維生素 、 礦物質', ... '三星 剛剛 更新 了 自家 的 可 穿戴 設備 APP', '華為 、 小米 跨界 并 不 可怕 , 可怕 的 打 不破 內心 的 “ 天花板 ”'] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 【查看單詞】 2016 app linux p30 一定 一張 一種 三星 健康 ... 雷軍 食品 食材 食物 魅族 雞蛋 [[0 0 0 ... 0 0 0] [0 0 0 ... 0 0 0] [0 0 0 ... 0 0 0] ... [0 0 1 ... 0 0 0] [0 0 1 ... 0 0 0] [0 0 0 ... 0 0 0]] 15 6 15 6 [[0. 0. 0. ... 0. 0. 0. ] [0. 0. 0. ... 0. 0. 0.32161043] [0. 0. 0. ... 0. 0. 0. ] ... [0. 0.31077094 0. ... 0. 0. 0. ] [0. 0. 0. ... 0. 0. 0. ] [0.35882035 0. 0. ... 0. 0. 0. ]] 預測結果: [0 1 0 1 1 1] 真實結果: [0, 0, 0, 0, 1, 1] precision recall f1-score support 0 1.00 0.50 0.67 4 1 0.50 1.00 0.67 2 accuracy 0.67 6 macro avg 0.75 0.75 0.67 6 weighted avg 0.83 0.67 0.67 6

      繪制圖形如下圖所示:

      2.GaussianNB+Word2Vec文本分類

      該方法與前面不同之處是采用Word2Vec進行詞向量計算,將每行數(shù)據(jù)集分詞,并計算每個特征詞的詞向量,接著轉換為詞向量矩陣,比如15行數(shù)據(jù),每行數(shù)據(jù)40個特征詞,每個特征詞用20維度的詞向量表示,即(15, 40, 20)。同時,由于詞向量存在負數(shù),所以需要使用GaussianNB算法替代MultinomialNB算法。

      sentences:傳入的數(shù)據(jù)集序列(list of lists of tokens),默認值為None

      size:詞向量維數(shù),默認值為100

      window:同句中當前詞和預測詞的最大距離,默認值為5

      min_count:最低詞頻過濾,默認值為5

      workers:線程數(shù),默認值為3

      sg:模型參數(shù),其值為0表示CBOW,值為1表示skip-gram,默認值為0

      hs:模型參數(shù),其值為0表示負例采樣,值為1表示層次softmax,默認值為0

      negative:負例樣本數(shù),默認值為5

      ns_exponent:用于形成負例樣本的指數(shù),默認值為0.75

      cbow_mean:上下文詞向量參數(shù),其值為0表示上下文詞向量求和值,值為1表示上下文詞向量平均值,默認值為1

      alpha:初始學習率,默認值為0.025

      min_alpha:最小學習率,默認值為0.0001

      完整代碼如下:

      # -*- coding: utf-8 -*- """ Created on Sat Mar 28 22:10:20 2020 @author: Eastmount CSDN """ from jieba import lcut from numpy import zeros from gensim.models import Word2Vec from sklearn.model_selection import train_test_split from tensorflow.python.keras.preprocessing.sequence import pad_sequences max_features = 20 #詞向量維度 maxlen = 40 #序列最大長度 #--------------------------------載入數(shù)據(jù)及預處理------------------------------- data = [ [0, '小米粥是以小米作為主要食材熬制而成的粥,口味清淡,清香味,具有簡單易制,健胃消食的特點'], [0, '煮粥時一定要先燒開水然后放入洗凈后的小米'], [0, '蛋白質及氨基酸、脂肪、維生素、礦物質'], [0, '小米是傳統(tǒng)健康食品,可單獨燜飯和熬粥'], [0, '蘋果,是水果中的一種'], [0, '粥的營養(yǎng)價值很高,富含礦物質和維生素,含鈣量豐富,有助于代謝掉體內多余鹽分'], [0, '雞蛋有很高的營養(yǎng)價值,是優(yōu)質蛋白質、B族維生素的良好來源,還能提供脂肪、維生素和礦物質'], [0, '這家超市的蘋果都非常新鮮'], [0, '在北方小米是主要食物之一,很多地區(qū)有晚餐吃小米粥的習俗'], [0, '小米營養(yǎng)價值高,營養(yǎng)全面均衡 ,主要含有碳水化合物'], [0, '蛋白質及氨基酸、脂肪、維生素、鹽分'], [1, '小米、三星、華為,作為安卓三大手機旗艦'], [1, '別再管小米華為了!魅族手機再曝光:這次真的完美了'], [1, '蘋果手機或將重陷2016年困境,但這次它無法再大幅提價了'], [1, '三星想要繼續(xù)壓制華為,僅憑A70還不夠'], [1, '三星手機屏占比將再創(chuàng)新高,超華為及蘋果旗艦'], [1, '華為P30、三星A70爆賣,斬獲蘇寧最佳手機營銷獎'], [1, '雷軍,用一張圖告訴你:小米和三星的差距在哪里'], [1, '小米米聊APP官方Linux版上線,適配深度系統(tǒng)'], [1, '三星剛剛更新了自家的可穿戴設備APP'], [1, '華為、小米跨界并不可怕,可怕的打不破內心的“天花板”'], ] #中文分析 X, Y = [lcut(i[1]) for i in data], [i[0] for i in data] #劃分訓練集和預測集 X_train, X_test, y_train, y_test = train_test_split(X, Y) #print(X_train) print(len(X_train), len(X_test)) print(len(y_train), len(y_test)) """['三星', '剛剛', '更新', '了', '自家', '的', '可', '穿戴', '設備', 'APP']""" #--------------------------------Word2Vec詞向量------------------------------- word2vec = Word2Vec(X_train, size=max_features, min_count=1) #最大特征 最低過濾頻次1 print(word2vec) #映射特征詞 w2i = {w:i for i, w in enumerate(word2vec.wv.index2word)} print("【顯示詞語】") print(word2vec.wv.index2word) print(w2i) """['小米', '三星', '是', '維生素', '蛋白質', '及', 'APP', '氨基酸',...""" """{',': 0, '的': 1, '小米': 2, '、': 3, '華為': 4, ....}""" #詞向量計算 vectors = word2vec.wv.vectors print("【詞向量矩陣】") print(vectors.shape) print(vectors) #自定義函數(shù)-獲取詞向量 def w2v(w): i = w2i.get(w) return vectors[i] if i else zeros(max_features) #自定義函數(shù)-序列預處理 def pad(ls_of_words): a = [[w2v(i) for i in x] for x in ls_of_words] a = pad_sequences(a, maxlen, dtype='float') return a #序列化處理 轉換為詞向量 X_train, X_test = pad(X_train), pad(X_test) print(X_train.shape) print(X_test.shape) """(15, 40, 20) 15個樣本 40個特征 每個特征用20詞向量表示""" #拉直形狀 (15, 40, 20)=>(15, 40*20) (6, 40, 20)=>(6, 40*20) X_train = X_train.reshape(len(y_train), maxlen*max_features) X_test = X_test.reshape(len(y_test), maxlen*max_features) print(X_train.shape) print(X_test.shape) #--------------------------------建模與訓練------------------------------- from sklearn.naive_bayes import GaussianNB from sklearn.metrics import classification_report from sklearn.model_selection import train_test_split #調用GaussianNB分類器 clf = GaussianNB().fit(X_train, y_train) pre = clf.predict(X_test) print("預測結果:", pre) print("真實結果:", y_test) print(classification_report(y_test, pre))

      輸出結果如下所示:

      6個預測數(shù)據(jù)的accuracy ===> 0.83

      15 6 15 6 Word2Vec(vocab=126, size=20, alpha=0.025) 【顯示詞語】 [',', '、', '小米', '的', '華為', '手機', '蘋果', '維生素', 'APP', '官方', 'Linux', ... '安卓三大', '旗艦'] {',': 0, '、': 1, '小米': 2, '的': 3, '華為': 4, '手機': 5, '蘋果': 6, ..., '安卓三大': 124, '旗艦': 125} 【詞向量矩陣】 (126, 20) [[ 0.02041552 -0.00929706 -0.00743623 ... -0.00246041 -0.00825108 0.02341811] [-0.00256093 -0.01301112 -0.00697959 ... -0.00449076 -0.00551124 -0.00240511] [ 0.01535473 0.01690796 -0.00262145 ... -0.01624218 0.00871249 -0.01159615] ... [ 0.00631155 0.00369085 -0.00382834 ... 0.02468265 0.00945442 -0.0155745 ] [-0.01198495 0.01711261 0.01097644 ... 0.01003117 0.01074963 0.01960118] [ 0.00450704 -0.01114052 0.0186879 ... 0.00804681 0.01060277 0.01836049]] (15, 40, 20) (6, 40, 20) (15, 800) (6, 800) 預測結果: [1 1 1 0 1 0] 真實結果: [0, 1, 1, 0, 1, 0] precision recall f1-score support 0 1.00 0.67 0.80 3 1 0.75 1.00 0.86 3 accuracy 0.83 6 macro avg 0.88 0.83 0.83 6 weighted avg 0.88 0.83 0.83 6

      三.Keras實現(xiàn)RNN文本分類

      1.IMDB數(shù)據(jù)集和序列預處理

      (1) IMDB數(shù)據(jù)集

      Keras框架為我們提供了一些常用的內置數(shù)據(jù)集。比如,圖像識別領域的手寫識別MNIST數(shù)據(jù)集、文本分類領域的電影影評imdb數(shù)據(jù)集等等。這些數(shù)據(jù)庫可以用一條代碼就可以調用:

      (trainX, trainY), (testX, testY) = imdb.load_data(path=“imdb.npz”, num_words=max_features)

      這些數(shù)據(jù)集是通過https://s3.amazonaws.com進行下載的,但有時該網(wǎng)站不能使用,需要下載數(shù)據(jù)至本地,再進行調用分析。Keras數(shù)據(jù)集百度云鏈接:

      https://pan.baidu.com/s/1aZRp0uMkNj2QEWYstaNsKQ,提取碼: 3a2u

      該數(shù)據(jù)集是互聯(lián)網(wǎng)電影資料庫(Internet Movie Database,簡稱IMDb),它是一個關于電影演員、電影、電視節(jié)目、電視明星和電影制作的在線數(shù)據(jù)庫。

      imdb.npz文件中數(shù)據(jù)和格式如下:

      [list([1, 14, 22, 16, 43, 530, 973, 1622, 1385, 65, 458, 4468, 66, 3941, 4, 173, 36, 256, 5, 25, 100, 43, 838, 112, 50, 670, 2, 9, 35, 480, 284, 5, 150, 4, 172, ...]) list([1, 194, 1153, 194, 8255, 78, 228, 5, 6, 1463, 4369, 5012, 134, 26, 4, 715, 8, 118, 1634, 14, 394, 20, 13, 119, 954, 189, 102, 5, 207, 110, 3103, 21, 14, 69, ...]) list([1, 14, 47, 8, 30, 31, 7, 4, 249, 108, 7, 4, 5974, 54, 61, 369, 13, 71, 149, 14, 22, 112, 4, 2401, 311, 12, 16, 3711, 33, 75, 43, 1829, 296, 4, 86, 320, 35, ...]) ... list([1, 11, 6, 230, 245, 6401, 9, 6, 1225, 446, 2, 45, 2174, 84, 8322, 4007, 21, 4, 912, 84, 14532, 325, 725, 134, 15271, 1715, 84, 5, 36, 28, 57, 1099, 21, 8, 140, ...]) list([1, 1446, 7079, 69, 72, 3305, 13, 610, 930, 8, 12, 582, 23, 5, 16, 484, 685, 54, 349, 11, 4120, 2959, 45, 58, 1466, 13, 197, 12, 16, 43, 23, 2, 5, 62, 30, 145, ...]) list([1, 17, 6, 194, 337, 7, 4, 204, 22, 45, 254, 8, 106, 14, 123, 4, 12815, 270, 14437, 5, 16923, 12255, 732, 2098, 101, 405, 39, 14, 1034, 4, 1310, 9, 115, 50, 305, ...])] train sequences

      每個list是一個句子,句子中每個數(shù)字表示單詞的編號。那么,怎么獲取編號對應的單詞?此時需要使用imdb_word_index.json文件,其文件格式如下:

      {"fawn": 34701, "tsukino": 52006,..., "paget": 18509, "expands": 20597}

      共有88584個單詞,采用key-value格式存放,key代表單詞,value代表(單詞)編號。詞頻(單詞在語料中出現(xiàn)次數(shù))越高編號越小,例如, “the:1”出現(xiàn)次數(shù)最高,編號為1。

      (2) 序列預處理

      在進行深度學習向量轉換過程中,通常需要使用pad_sequences()序列填充。其基本用法如下:

      keras.preprocessing.sequence.pad_sequences( sequences, maxlen=None, dtype='int32', padding='pre', truncating='pre', value=0. )

      參數(shù)含義如下:

      sequences:浮點數(shù)或整數(shù)構成的兩層嵌套列表

      maxlen:None或整數(shù),為序列的最大長度。大于此長度的序列將被截短,小于此長度的序列將在后部填0

      dtype:返回的numpy array的數(shù)據(jù)類型

      padding:pre或post,確定當需要補0時,在序列的起始還是結尾補0

      truncating:pre或post,確定當需要截斷序列時,從起始還是結尾截斷

      value:浮點數(shù),此值將在填充時代替默認的填充值0

      返回值是個2維張量,長度為maxlen

      基本用法如下所示:

      from keras.preprocessing.sequence import pad_sequences print(pad_sequences([[1, 2, 3], [1]], maxlen=2)) """[[2 3] [0 1]]""" print(pad_sequences([[1, 2, 3], [1]], maxlen=3, value=9)) """[[1 2 3] [9 9 1]]""" print(pad_sequences([[2,3,4]], maxlen=10)) """[[0 0 0 0 0 0 0 2 3 4]]""" print(pad_sequences([[1,2,3,4,5],[6,7]], maxlen=10)) """[[0 0 0 0 0 1 2 3 4 5] [0 0 0 0 0 0 0 0 6 7]]""" print(pad_sequences([[1, 2, 3], [1]], maxlen=2, padding='post')) """結束位置補: [[2 3] [1 0]]""" print(pad_sequences([[1, 2, 3], [1]], maxlen=4, truncating='post')) """起始位置補: [[0 1 2 3] [0 0 0 1]]"""

      在自然語言中一般和分詞器一起使用。

      >>> tokenizer.texts_to_sequences(["下 雨 我 加班"]) [[4, 5, 6, 7]] >>> keras.preprocessing.sequence.pad_sequences(tokenizer.texts_to_sequences(["下 雨 我 加班"]), maxlen=20) array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7]],dtype=int32)

      2.詞嵌入模型訓練

      此時我們將通過詞嵌入模型進行訓練,具體流程包括:

      導入IMDB數(shù)據(jù)集

      數(shù)據(jù)集轉換為序列

      創(chuàng)建Embedding詞嵌入模型

      神經(jīng)網(wǎng)絡訓練

      完整代碼如下:

      # -*- coding: utf-8 -*- """ Created on Sat Mar 28 17:08:28 2020 @author: Eastmount CSDN """ from keras.datasets import imdb #Movie Database from keras.preprocessing import sequence from keras.models import Sequential from keras.layers import Dense, Flatten, Embedding #-----------------------------------定義參數(shù)----------------------------------- max_features = 20000 #按詞頻大小取樣本前20000個詞 input_dim = max_features #詞庫大小 必須>=max_features maxlen = 80 #句子最大長度 batch_size = 128 #batch數(shù)量 output_dim = 40 #詞向量維度 epochs = 2 #訓練批次 #--------------------------------載入數(shù)據(jù)及預處理------------------------------- #數(shù)據(jù)獲取 (trainX, trainY), (testX, testY) = imdb.load_data(path="imdb.npz", num_words=max_features) print(trainX.shape, trainY.shape) #(25000,) (25000,) print(testX.shape, testY.shape) #(25000,) (25000,) #序列截斷或補齊為等長 trainX = sequence.pad_sequences(trainX, maxlen=maxlen) testX = sequence.pad_sequences(testX, maxlen=maxlen) print('trainX shape:', trainX.shape) print('testX shape:', testX.shape) #------------------------------------創(chuàng)建模型------------------------------------ model = Sequential() #詞嵌入:詞庫大小、詞向量維度、固定序列長度 model.add(Embedding(input_dim, output_dim, input_length=maxlen)) #平坦化: maxlen*output_dim model.add(Flatten()) #輸出層: 2分類 model.add(Dense(units=1, activation='sigmoid')) #RMSprop優(yōu)化器 二元交叉熵損失 model.compile('rmsprop', 'binary_crossentropy', ['acc']) #訓練 model.fit(trainX, trainY, batch_size, epochs) #模型可視化 model.summary()

      輸出結果如下所示:

      (25000,) (25000,) (25000,) (25000,) trainX shape: (25000, 80) testX shape: (25000, 80) Epoch 1/2 25000/25000 [==============================] - 2s 98us/step - loss: 0.6111 - acc: 0.6956 Epoch 2/2 25000/25000 [==============================] - 2s 69us/step - loss: 0.3578 - acc: 0.8549 Model: "sequential_2" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= embedding_2 (Embedding) (None, 80, 40) 800000 _________________________________________________________________ flatten_2 (Flatten) (None, 3200) 0 _________________________________________________________________ dense_2 (Dense) (None, 1) 3201 ================================================================= Total params: 803,201 Trainable params: 803,201 Non-trainable params: 0 _________________________________________________________________

      顯示矩陣如下圖所示:

      3.RNN文本分類

      RNN對IMDB電影數(shù)據(jù)集進行文本分類的完整代碼如下所示:

      # -*- coding: utf-8 -*- """ Created on Sat Mar 28 17:08:28 2020 @author: Eastmount CSDN """ from keras.datasets import imdb #Movie Database from keras.preprocessing import sequence from keras.models import Sequential from keras.layers import Dense, Flatten, Embedding from keras.layers import SimpleRNN #-----------------------------------定義參數(shù)----------------------------------- max_features = 20000 #按詞頻大小取樣本前20000個詞 input_dim = max_features #詞庫大小 必須>=max_features maxlen = 40 #句子最大長度 batch_size = 128 #batch數(shù)量 output_dim = 40 #詞向量維度 epochs = 3 #訓練批次 units = 32 #RNN神經(jīng)元數(shù)量 #--------------------------------載入數(shù)據(jù)及預處理------------------------------- #數(shù)據(jù)獲取 (trainX, trainY), (testX, testY) = imdb.load_data(path="imdb.npz", num_words=max_features) print(trainX.shape, trainY.shape) #(25000,) (25000,) print(testX.shape, testY.shape) #(25000,) (25000,) #序列截斷或補齊為等長 trainX = sequence.pad_sequences(trainX, maxlen=maxlen) testX = sequence.pad_sequences(testX, maxlen=maxlen) print('trainX shape:', trainX.shape) print('testX shape:', testX.shape) #-----------------------------------創(chuàng)建RNN模型----------------------------------- model = Sequential() #詞嵌入 詞庫大小、詞向量維度、固定序列長度 model.add(Embedding(input_dim, output_dim, input_length=maxlen)) #RNN Cell model.add(SimpleRNN(units, return_sequences=True)) #返回序列全部結果 model.add(SimpleRNN(units, return_sequences=False)) #返回序列最尾結果 #輸出層 2分類 model.add(Dense(units=1, activation='sigmoid')) #模型可視化 model.summary() #-----------------------------------建模與訓練----------------------------------- #激活神經(jīng)網(wǎng)絡 model.compile(optimizer = 'rmsprop', #RMSprop優(yōu)化器 loss = 'binary_crossentropy', #二元交叉熵損失 metrics = ['accuracy'] #計算誤差或準確率 ) #訓練 history = model.fit(trainX, trainY, batch_size=batch_size, epochs=epochs, verbose=2, validation_split=.1 #取10%樣本作驗證 ) #-----------------------------------預測與可視化----------------------------------- import matplotlib.pyplot as plt accuracy = history.history['accuracy'] val_accuracy = history.history['val_accuracy'] plt.plot(range(epochs), accuracy) plt.plot(range(epochs), val_accuracy) plt.show()

      輸出結果如下所示,三個Epoch訓練。

      訓練數(shù)據(jù)的accuracy ===> 0.9075

      評估數(shù)據(jù)的val_accuracy ===> 0.7844

      Epoch可以用下圖進行形象的表示。

      (25000,) (25000,) (25000,) (25000,) trainX shape: (25000, 40) testX shape: (25000, 40) Model: "sequential_2" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= embedding_2 (Embedding) (None, 40, 40) 800000 _________________________________________________________________ simple_rnn_3 (SimpleRNN) (None, 40, 32) 2336 _________________________________________________________________ simple_rnn_4 (SimpleRNN) (None, 32) 2080 _________________________________________________________________ dense_2 (Dense) (None, 1) 33 ================================================================= Total params: 804,449 Trainable params: 804,449 Non-trainable params: 0 _________________________________________________________________ Train on 22500 samples, validate on 2500 samples Epoch 1/3 - 11s - loss: 0.5741 - accuracy: 0.6735 - val_loss: 0.4462 - val_accuracy: 0.7876 Epoch 2/3 - 14s - loss: 0.3572 - accuracy: 0.8430 - val_loss: 0.4928 - val_accuracy: 0.7616 Epoch 3/3 - 12s - loss: 0.2329 - accuracy: 0.9075 - val_loss: 0.5050 - val_accuracy: 0.7844

      繪制的accuracy和val_accuracy曲線如下圖所示:

      loss: 0.2329 - accuracy: 0.9075 - val_loss: 0.5050 - val_accuracy: 0.7844

      四.RNN實現(xiàn)中文數(shù)據(jù)集的文本分類

      1.RNN+Word2Vector文本分類

      第一步,導入文本數(shù)據(jù)集并轉換為詞向量。

      data = [ [0, '小米粥是以小米作為主要食材熬制而成的粥,口味清淡,清香味,具有簡單易制,健胃消食的特點'], [0, '煮粥時一定要先燒開水然后放入洗凈后的小米'], [0, '蛋白質及氨基酸、脂肪、維生素、礦物質'], [0, '小米是傳統(tǒng)健康食品,可單獨燜飯和熬粥'], [0, '蘋果,是水果中的一種'], [0, '粥的營養(yǎng)價值很高,富含礦物質和維生素,含鈣量豐富,有助于代謝掉體內多余鹽分'], [0, '雞蛋有很高的營養(yǎng)價值,是優(yōu)質蛋白質、B族維生素的良好來源,還能提供脂肪、維生素和礦物質'], [0, '這家超市的蘋果都非常新鮮'], [0, '在北方小米是主要食物之一,很多地區(qū)有晚餐吃小米粥的習俗'], [0, '小米營養(yǎng)價值高,營養(yǎng)全面均衡 ,主要含有碳水化合物'], [0, '蛋白質及氨基酸、脂肪、維生素、鹽分'], [1, '小米、三星、華為,作為安卓三大手機旗艦'], [1, '別再管小米華為了!魅族手機再曝光:這次真的完美了'], [1, '蘋果手機或將重陷2016年困境,但這次它無法再大幅提價了'], [1, '三星想要繼續(xù)壓制華為,僅憑A70還不夠'], [1, '三星手機屏占比將再創(chuàng)新高,超華為及蘋果旗艦'], [1, '華為P30、三星A70爆賣,斬獲蘇寧最佳手機營銷獎'], [1, '雷軍,用一張圖告訴你:小米和三星的差距在哪里'], [1, '小米米聊APP官方Linux版上線,適配深度系統(tǒng)'], [1, '三星剛剛更新了自家的可穿戴設備APP'], [1, '華為、小米跨界并不可怕,可怕的打不破內心的“天花板”'], ] #中文分析 X, Y = [lcut(i[1]) for i in data], [i[0] for i in data] #劃分訓練集和預測集 X_train, X_test, y_train, y_test = train_test_split(X, Y) #print(X_train) print(len(X_train), len(X_test)) print(len(y_train), len(y_test)) """['三星', '剛剛', '更新', '了', '自家', '的', '可', '穿戴', '設備', 'APP']""" #--------------------------------Word2Vec詞向量------------------------------- word2vec = Word2Vec(X_train, size=max_features, min_count=1) #最大特征 最低過濾頻次1 print(word2vec) #映射特征詞 w2i = {w:i for i, w in enumerate(word2vec.wv.index2word)} print("【顯示詞語】") print(word2vec.wv.index2word) print(w2i) """['小米', '三星', '是', '維生素', '蛋白質', '及', 'APP', '氨基酸',...""" """{',': 0, '的': 1, '小米': 2, '、': 3, '華為': 4, ....}""" #詞向量計算 vectors = word2vec.wv.vectors print("【詞向量矩陣】") print(vectors.shape) print(vectors) #自定義函數(shù)-獲取詞向量 def w2v(w): i = w2i.get(w) return vectors[i] if i else zeros(max_features) #自定義函數(shù)-序列預處理 def pad(ls_of_words): a = [[w2v(i) for i in x] for x in ls_of_words] a = pad_sequences(a, maxlen, dtype='float') return a #序列化處理 轉換為詞向量 X_train, X_test = pad(X_train), pad(X_test)

      此時輸出結果如下所示:

      15 6 15 6 Word2Vec(vocab=120, size=20, alpha=0.025) 【顯示詞語】 [',', '的', '、', '小米', '三星', '是', '維生素', '蛋白質', '及', '脂肪', '華為', '蘋果', '可', 'APP', '氨基酸', '在', '手機', '旗艦', '礦物質', '主要', '有', '小米粥', '作為', '剛剛', '更新', '設備', ...] {',': 0, '的': 1, '、': 2, '小米': 3, '三星': 4, '是': 5, '維生素': 6, '蛋白質': 7, '及': 8, '脂肪': 9, '和': 10, '華為': 11, '蘋果': 12, '可': 13, 'APP': 14, '氨基酸': 15, ...} 【詞向量矩陣】 (120, 20) [[ 0.00219526 0.00936278 0.00390177 ... -0.00422463 0.01543128 0.02481441] [ 0.02346811 -0.01520025 -0.00563479 ... -0.01656673 -0.02222313 0.00438196] [-0.02253242 -0.01633896 -0.02209039 ... 0.01301584 -0.01016752 0.01147605] ... [ 0.01793107 0.01912305 -0.01780855 ... -0.00109831 0.02460653 -0.00023512] [-0.00599797 0.02155897 -0.01874896 ... 0.00149929 0.00200266 0.00988515] [ 0.0050361 -0.00848463 -0.0235001 ... 0.01531716 -0.02348576 0.01051775]]

      第二步,建立RNN神經(jīng)網(wǎng)絡結構,使用Bi-GRU模型,并進行訓練與預測。

      #--------------------------------建模與訓練------------------------------- model = Sequential() #雙向RNN model.add(Bidirectional(GRU(units), input_shape=(maxlen, max_features))) #輸出層 2分類 model.add(Dense(units=1, activation='sigmoid')) #模型可視化 model.summary() #激活神經(jīng)網(wǎng)絡 model.compile(optimizer = 'rmsprop', #RMSprop優(yōu)化器 loss = 'binary_crossentropy', #二元交叉熵損失 metrics = ['acc'] #計算誤差或準確率 ) #訓練 history = model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, verbose=verbose, validation_data=(X_test, y_test)) #----------------------------------預測與可視化------------------------------ #預測 score = model.evaluate(X_test, y_test, batch_size=batch_size) print('test loss:', score[0]) print('test accuracy:', score[1]) #可視化 acc = history.history['acc'] val_acc = history.history['val_acc'] # 設置類標 plt.xlabel("Iterations") plt.ylabel("Accuracy") #繪圖 plt.plot(range(epochs), acc, "bo-", linewidth=2, markersize=12, label="accuracy") plt.plot(range(epochs), val_acc, "gs-", linewidth=2, markersize=12, label="val_accuracy") plt.legend(loc="upper left") plt.title("RNN-Word2vec") plt.show()

      輸出結果如下圖所示,發(fā)現(xiàn)accuracy和val_accuracy值非常不理想。怎么解決呢?

      神經(jīng)網(wǎng)絡模型和Epoch訓練結果如下圖所示:

      test loss: 0.7160684466362

      test accuracy: 0.33333334

      這里補充一個知識點——EarlyStopping。

      EarlyStopping是Callbacks的一種,callbacks用于指定在每個epoch開始和結束的時候進行哪種特定操作。Callbacks中有一些設置好的接口,可以直接使用,如acc、val_acc、loss和val_loss等。EarlyStopping則是用于提前停止訓練的callbacks,可以達到當訓練集上的loss不在減小(即減小的程度小于某個閾值)的時候停止繼續(xù)訓練。上面程序中,當我們loss不在減小時就可以調用Callbacks停止訓練。

      推薦文章:[深度學習] keras的EarlyStopping使用與技巧 - zwqjoy

      最后給出該部分的完整代碼:

      # -*- coding: utf-8 -*- """ Created on Sat Mar 28 22:10:20 2020 @author: Eastmount CSDN """ from jieba import lcut from numpy import zeros import matplotlib.pyplot as plt from gensim.models import Word2Vec from sklearn.model_selection import train_test_split from tensorflow.python.keras.preprocessing.sequence import pad_sequences from tensorflow.python.keras.models import Sequential from tensorflow.python.keras.layers import Dense, GRU, Bidirectional from tensorflow.python.keras.callbacks import EarlyStopping #-----------------------------------定義參數(shù)---------------------------------- max_features = 20 #詞向量維度 units = 30 #RNN神經(jīng)元數(shù)量 maxlen = 40 #序列最大長度 epochs = 9 #訓練最大輪數(shù) batch_size = 12 #每批數(shù)據(jù)量大小 verbose = 1 #訓練過程展示 patience = 1 #沒有進步的訓練輪數(shù) callbacks = [EarlyStopping('val_acc', patience=patience)] #--------------------------------載入數(shù)據(jù)及預處理------------------------------- data = [ [0, '小米粥是以小米作為主要食材熬制而成的粥,口味清淡,清香味,具有簡單易制,健胃消食的特點'], [0, '煮粥時一定要先燒開水然后放入洗凈后的小米'], [0, '蛋白質及氨基酸、脂肪、維生素、礦物質'], [0, '小米是傳統(tǒng)健康食品,可單獨燜飯和熬粥'], [0, '蘋果,是水果中的一種'], [0, '粥的營養(yǎng)價值很高,富含礦物質和維生素,含鈣量豐富,有助于代謝掉體內多余鹽分'], [0, '雞蛋有很高的營養(yǎng)價值,是優(yōu)質蛋白質、B族維生素的良好來源,還能提供脂肪、維生素和礦物質'], [0, '這家超市的蘋果都非常新鮮'], [0, '在北方小米是主要食物之一,很多地區(qū)有晚餐吃小米粥的習俗'], [0, '小米營養(yǎng)價值高,營養(yǎng)全面均衡 ,主要含有碳水化合物'], [0, '蛋白質及氨基酸、脂肪、維生素、鹽分'], [1, '小米、三星、華為,作為安卓三大手機旗艦'], [1, '別再管小米華為了!魅族手機再曝光:這次真的完美了'], [1, '蘋果手機或將重陷2016年困境,但這次它無法再大幅提價了'], [1, '三星想要繼續(xù)壓制華為,僅憑A70還不夠'], [1, '三星手機屏占比將再創(chuàng)新高,超華為及蘋果旗艦'], [1, '華為P30、三星A70爆賣,斬獲蘇寧最佳手機營銷獎'], [1, '雷軍,用一張圖告訴你:小米和三星的差距在哪里'], [1, '小米米聊APP官方Linux版上線,適配深度系統(tǒng)'], [1, '三星剛剛更新了自家的可穿戴設備APP'], [1, '華為、小米跨界并不可怕,可怕的打不破內心的“天花板”'], ] #中文分析 X, Y = [lcut(i[1]) for i in data], [i[0] for i in data] #劃分訓練集和預測集 X_train, X_test, y_train, y_test = train_test_split(X, Y) #print(X_train) print(len(X_train), len(X_test)) print(len(y_train), len(y_test)) """['三星', '剛剛', '更新', '了', '自家', '的', '可', '穿戴', '設備', 'APP']""" #--------------------------------Word2Vec詞向量------------------------------- word2vec = Word2Vec(X_train, size=max_features, min_count=1) #最大特征 最低過濾頻次1 print(word2vec) #映射特征詞 w2i = {w:i for i, w in enumerate(word2vec.wv.index2word)} print("【顯示詞語】") print(word2vec.wv.index2word) print(w2i) """['小米', '三星', '是', '維生素', '蛋白質', '及', 'APP', '氨基酸',...""" """{',': 0, '的': 1, '小米': 2, '、': 3, '華為': 4, ....}""" #詞向量計算 vectors = word2vec.wv.vectors print("【詞向量矩陣】") print(vectors.shape) print(vectors) #自定義函數(shù)-獲取詞向量 def w2v(w): i = w2i.get(w) return vectors[i] if i else zeros(max_features) #自定義函數(shù)-序列預處理 def pad(ls_of_words): a = [[w2v(i) for i in x] for x in ls_of_words] a = pad_sequences(a, maxlen, dtype='float') return a #序列化處理 轉換為詞向量 X_train, X_test = pad(X_train), pad(X_test) #--------------------------------建模與訓練------------------------------- model = Sequential() #雙向RNN model.add(Bidirectional(GRU(units), input_shape=(maxlen, max_features))) #輸出層 2分類 model.add(Dense(units=1, activation='sigmoid')) #模型可視化 model.summary() #激活神經(jīng)網(wǎng)絡 model.compile(optimizer = 'rmsprop', #RMSprop優(yōu)化器 loss = 'binary_crossentropy', #二元交叉熵損失 metrics = ['acc'] #計算誤差或準確率 ) #訓練 history = model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, verbose=verbose, validation_data=(X_test, y_test)) #----------------------------------預測與可視化------------------------------ #預測 score = model.evaluate(X_test, y_test, batch_size=batch_size) print('test loss:', score[0]) print('test accuracy:', score[1]) #可視化 acc = history.history['acc'] val_acc = history.history['val_acc'] # 設置類標 plt.xlabel("Iterations") plt.ylabel("Accuracy") #繪圖 plt.plot(range(epochs), acc, "bo-", linewidth=2, markersize=12, label="accuracy") plt.plot(range(epochs), val_acc, "gs-", linewidth=2, markersize=12, label="val_accuracy") plt.legend(loc="upper left") plt.title("RNN-Word2vec") plt.show()

      2.LSTM+Word2Vec文本分類

      接著我們使用LSTM和Word2Vec進行文本分類。整個神經(jīng)網(wǎng)絡的結構很簡單,第一層是嵌入層,將文本中的單詞轉化為向量;之后經(jīng)過一層LSTM層,使用LSTM中最后一個時刻的隱藏狀態(tài);再接一個全連接層,即可完成整個網(wǎng)絡的構造。

      注意矩陣形狀的變換。

      X_train = X_train.reshape(len(y_train), maxlen*max_features)

      X_test = X_test.reshape(len(y_test), maxlen*max_features)

      完整代碼如下所示:

      # -*- coding: utf-8 -*- """ Created on Sat Mar 28 22:10:20 2020 @author: Eastmount CSDN """ from jieba import lcut from numpy import zeros import matplotlib.pyplot as plt from gensim.models import Word2Vec from sklearn.model_selection import train_test_split from tensorflow.python.keras.preprocessing.sequence import pad_sequences from tensorflow.python.keras.models import Sequential from tensorflow.python.keras.layers import Dense, LSTM, GRU, Embedding from tensorflow.python.keras.callbacks import EarlyStopping #-----------------------------------定義參數(shù)---------------------------------- max_features = 20 #詞向量維度 units = 30 #RNN神經(jīng)元數(shù)量 maxlen = 40 #序列最大長度 epochs = 9 #訓練最大輪數(shù) batch_size = 12 #每批數(shù)據(jù)量大小 verbose = 1 #訓練過程展示 patience = 1 #沒有進步的訓練輪數(shù) callbacks = [EarlyStopping('val_acc', patience=patience)] #--------------------------------載入數(shù)據(jù)及預處理------------------------------- data = [ [0, '小米粥是以小米作為主要食材熬制而成的粥,口味清淡,清香味,具有簡單易制,健胃消食的特點'], [0, '煮粥時一定要先燒開水然后放入洗凈后的小米'], [0, '蛋白質及氨基酸、脂肪、維生素、礦物質'], [0, '小米是傳統(tǒng)健康食品,可單獨燜飯和熬粥'], [0, '蘋果,是水果中的一種'], [0, '粥的營養(yǎng)價值很高,富含礦物質和維生素,含鈣量豐富,有助于代謝掉體內多余鹽分'], [0, '雞蛋有很高的營養(yǎng)價值,是優(yōu)質蛋白質、B族維生素的良好來源,還能提供脂肪、維生素和礦物質'], [0, '這家超市的蘋果都非常新鮮'], [0, '在北方小米是主要食物之一,很多地區(qū)有晚餐吃小米粥的習俗'], [0, '小米營養(yǎng)價值高,營養(yǎng)全面均衡 ,主要含有碳水化合物'], [0, '蛋白質及氨基酸、脂肪、維生素、鹽分'], [1, '小米、三星、華為,作為安卓三大手機旗艦'], [1, '別再管小米華為了!魅族手機再曝光:這次真的完美了'], [1, '蘋果手機或將重陷2016年困境,但這次它無法再大幅提價了'], [1, '三星想要繼續(xù)壓制華為,僅憑A70還不夠'], [1, '三星手機屏占比將再創(chuàng)新高,超華為及蘋果旗艦'], [1, '華為P30、三星A70爆賣,斬獲蘇寧最佳手機營銷獎'], [1, '雷軍,用一張圖告訴你:小米和三星的差距在哪里'], [1, '小米米聊APP官方Linux版上線,適配深度系統(tǒng)'], [1, '三星剛剛更新了自家的可穿戴設備APP'], [1, '華為、小米跨界并不可怕,可怕的打不破內心的“天花板”'], ] #中文分析 X, Y = [lcut(i[1]) for i in data], [i[0] for i in data] #劃分訓練集和預測集 X_train, X_test, y_train, y_test = train_test_split(X, Y) #print(X_train) print(len(X_train), len(X_test)) print(len(y_train), len(y_test)) """['三星', '剛剛', '更新', '了', '自家', '的', '可', '穿戴', '設備', 'APP']""" #--------------------------------Word2Vec詞向量------------------------------- word2vec = Word2Vec(X_train, size=max_features, min_count=1) #最大特征 最低過濾頻次1 print(word2vec) #映射特征詞 w2i = {w:i for i, w in enumerate(word2vec.wv.index2word)} print("【顯示詞語】") print(word2vec.wv.index2word) print(w2i) """['小米', '三星', '是', '維生素', '蛋白質', '及', 'APP', '氨基酸',...""" """{',': 0, '的': 1, '小米': 2, '、': 3, '華為': 4, ....}""" #詞向量計算 vectors = word2vec.wv.vectors print("【詞向量矩陣】") print(vectors.shape) print(vectors) #自定義函數(shù)-獲取詞向量 def w2v(w): i = w2i.get(w) return vectors[i] if i else zeros(max_features) #自定義函數(shù)-序列預處理 def pad(ls_of_words): a = [[w2v(i) for i in x] for x in ls_of_words] a = pad_sequences(a, maxlen, dtype='float') return a #序列化處理 轉換為詞向量 X_train, X_test = pad(X_train), pad(X_test) print(X_train.shape) print(X_test.shape) """(15, 40, 20) 15個樣本 40個特征 每個特征用20詞向量表示""" #拉直形狀 (15, 40, 20)=>(15, 40*20) (6, 40, 20)=>(6, 40*20) X_train = X_train.reshape(len(y_train), maxlen*max_features) X_test = X_test.reshape(len(y_test), maxlen*max_features) #--------------------------------建模與訓練------------------------------- model = Sequential() #構建Embedding層 128代表Embedding層的向量維度 model.add(Embedding(max_features, 128)) #構建LSTM層 model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2)) #構建全連接層 #注意上面構建LSTM層時只會得到最后一個節(jié)點的輸出,如果需要輸出每個時間點的結果需將return_sequences=True model.add(Dense(units=1, activation='sigmoid')) #模型可視化 model.summary() #激活神經(jīng)網(wǎng)絡 model.compile(optimizer = 'rmsprop', #RMSprop優(yōu)化器 loss = 'binary_crossentropy', #二元交叉熵損失 metrics = ['acc'] #計算誤差或準確率 ) #訓練 history = model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, verbose=verbose, validation_data=(X_test, y_test)) #----------------------------------預測與可視化------------------------------ #預測 score = model.evaluate(X_test, y_test, batch_size=batch_size) print('test loss:', score[0]) print('test accuracy:', score[1]) #可視化 acc = history.history['acc'] val_acc = history.history['val_acc'] # 設置類標 plt.xlabel("Iterations") plt.ylabel("Accuracy") #繪圖 plt.plot(range(epochs), acc, "bo-", linewidth=2, markersize=12, label="accuracy") plt.plot(range(epochs), val_acc, "gs-", linewidth=2, markersize=12, label="val_accuracy") plt.legend(loc="upper left") plt.title("LSTM-Word2vec") plt.show()

      輸出結果如下所示,仍然不理想。

      test loss: 0.712007462978363

      test accuracy: 0.33333334

      Model: "sequential_22" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= embedding_8 (Embedding) (None, None, 128) 2560 _________________________________________________________________ lstm_8 (LSTM) (None, 128) 131584 _________________________________________________________________ dense_21 (Dense) (None, 1) 129 ================================================================= Total params: 134,273 Trainable params: 134,273 Non-trainable params: 0 _________________________________________________________________ Train on 15 samples, validate on 6 samples Epoch 1/9 15/15 [==============================] - 8s 552ms/sample - loss: 0.6971 - acc: 0.5333 - val_loss: 0.6911 - val_acc: 0.6667 Epoch 2/9 15/15 [==============================] - 5s 304ms/sample - loss: 0.6910 - acc: 0.7333 - val_loss: 0.7111 - val_acc: 0.3333 Epoch 3/9 15/15 [==============================] - 3s 208ms/sample - loss: 0.7014 - acc: 0.4667 - val_loss: 0.7392 - val_acc: 0.3333 Epoch 4/9 15/15 [==============================] - 4s 261ms/sample - loss: 0.6890 - acc: 0.5333 - val_loss: 0.7471 - val_acc: 0.3333 Epoch 5/9 15/15 [==============================] - 4s 248ms/sample - loss: 0.6912 - acc: 0.5333 - val_loss: 0.7221 - val_acc: 0.3333 Epoch 6/9 15/15 [==============================] - 3s 210ms/sample - loss: 0.6857 - acc: 0.5333 - val_loss: 0.7143 - val_acc: 0.3333 Epoch 7/9 15/15 [==============================] - 3s 187ms/sample - loss: 0.6906 - acc: 0.5333 - val_loss: 0.7346 - val_acc: 0.3333 Epoch 8/9 15/15 [==============================] - 3s 185ms/sample - loss: 0.7066 - acc: 0.5333 - val_loss: 0.7578 - val_acc: 0.3333 Epoch 9/9 15/15 [==============================] - 4s 235ms/sample - loss: 0.7197 - acc: 0.5333 - val_loss: 0.7120 - val_acc: 0.3333 6/6 [==============================] - 0s 43ms/sample - loss: 0.7120 - acc: 0.3333 test loss: 0.712007462978363 test accuracy: 0.33333334

      對應的圖形如下所示。

      3.LSTM+TFIDF文本分類

      同時,補充LSTM+TFIDF文本分類代碼。

      # -*- coding: utf-8 -*- """ Created on Sat Mar 28 22:10:20 2020 @author: Eastmount CSDN """ from jieba import lcut from numpy import zeros import matplotlib.pyplot as plt from gensim.models import Word2Vec from sklearn.model_selection import train_test_split from tensorflow.python.keras.preprocessing.sequence import pad_sequences from tensorflow.python.keras.models import Sequential from tensorflow.python.keras.layers import Dense, LSTM, GRU, Embedding from tensorflow.python.keras.callbacks import EarlyStopping #-----------------------------------定義參數(shù)---------------------------------- max_features = 20 #詞向量維度 units = 30 #RNN神經(jīng)元數(shù)量 maxlen = 40 #序列最大長度 epochs = 9 #訓練最大輪數(shù) batch_size = 12 #每批數(shù)據(jù)量大小 verbose = 1 #訓練過程展示 patience = 1 #沒有進步的訓練輪數(shù) callbacks = [EarlyStopping('val_acc', patience=patience)] #--------------------------------載入數(shù)據(jù)及預處理------------------------------- data = [ [0, '小米粥是以小米作為主要食材熬制而成的粥,口味清淡,清香味,具有簡單易制,健胃消食的特點'], [0, '煮粥時一定要先燒開水然后放入洗凈后的小米'], [0, '蛋白質及氨基酸、脂肪、維生素、礦物質'], [0, '小米是傳統(tǒng)健康食品,可單獨燜飯和熬粥'], [0, '蘋果,是水果中的一種'], [0, '粥的營養(yǎng)價值很高,富含礦物質和維生素,含鈣量豐富,有助于代謝掉體內多余鹽分'], [0, '雞蛋有很高的營養(yǎng)價值,是優(yōu)質蛋白質、B族維生素的良好來源,還能提供脂肪、維生素和礦物質'], [0, '這家超市的蘋果都非常新鮮'], [0, '在北方小米是主要食物之一,很多地區(qū)有晚餐吃小米粥的習俗'], [0, '小米營養(yǎng)價值高,營養(yǎng)全面均衡 ,主要含有碳水化合物'], [0, '蛋白質及氨基酸、脂肪、維生素、鹽分'], [1, '小米、三星、華為,作為安卓三大手機旗艦'], [1, '別再管小米華為了!魅族手機再曝光:這次真的完美了'], [1, '蘋果手機或將重陷2016年困境,但這次它無法再大幅提價了'], [1, '三星想要繼續(xù)壓制華為,僅憑A70還不夠'], [1, '三星手機屏占比將再創(chuàng)新高,超華為及蘋果旗艦'], [1, '華為P30、三星A70爆賣,斬獲蘇寧最佳手機營銷獎'], [1, '雷軍,用一張圖告訴你:小米和三星的差距在哪里'], [1, '小米米聊APP官方Linux版上線,適配深度系統(tǒng)'], [1, '三星剛剛更新了自家的可穿戴設備APP'], [1, '華為、小米跨界并不可怕,可怕的打不破內心的“天花板”'], ] #中文分詞 X, Y = [' '.join(lcut(i[1])) for i in data], [i[0] for i in data] print(X) print(Y) #['煮粥 時 一定 要 先燒 開水 然后 放入 洗凈 后 的 小米', ...] #--------------------------------------計算詞頻------------------------------------ from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer #將文本中的詞語轉換為詞頻矩陣 vectorizer = CountVectorizer() #計算個詞語出現(xiàn)的次數(shù) X_data = vectorizer.fit_transform(X) print(X_data) #獲取詞袋中所有文本關鍵詞 word = vectorizer.get_feature_names() print('【查看單詞】') for w in word: print(w, end = " ") else: print("\n") #詞頻矩陣 print(X_data.toarray()) #將詞頻矩陣X統(tǒng)計成TF-IDF值 transformer = TfidfTransformer() tfidf = transformer.fit_transform(X_data) #查看數(shù)據(jù)結構 tfidf[i][j]表示i類文本中的tf-idf權重 weight = tfidf.toarray() print(weight) #數(shù)據(jù)集劃分 X_train, X_test, y_train, y_test = train_test_split(weight, Y) print(X_train.shape, X_test.shape) print(len(y_train), len(y_test)) #(15, 117) (6, 117) 15 6 #--------------------------------建模與訓練------------------------------- model = Sequential() #構建Embedding層 128代表Embedding層的向量維度 model.add(Embedding(max_features, 128)) #構建LSTM層 model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2)) #構建全連接層 #注意上面構建LSTM層時只會得到最后一個節(jié)點的輸出,如果需要輸出每個時間點的結果需將return_sequences=True model.add(Dense(units=1, activation='sigmoid')) #模型可視化 model.summary() #激活神經(jīng)網(wǎng)絡 model.compile(optimizer = 'rmsprop', #RMSprop優(yōu)化器 loss = 'binary_crossentropy', #二元交叉熵損失 metrics = ['acc'] #計算誤差或準確率 ) #訓練 history = model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, verbose=verbose, validation_data=(X_test, y_test)) #----------------------------------預測與可視化------------------------------ #預測 score = model.evaluate(X_test, y_test, batch_size=batch_size) print('test loss:', score[0]) print('test accuracy:', score[1]) #可視化 acc = history.history['acc'] val_acc = history.history['val_acc'] # 設置類標 plt.xlabel("Iterations") plt.ylabel("Accuracy") #繪圖 plt.plot(range(epochs), acc, "bo-", linewidth=2, markersize=12, label="accuracy") plt.plot(range(epochs), val_acc, "gs-", linewidth=2, markersize=12, label="val_accuracy") plt.legend(loc="upper left") plt.title("LSTM-TFIDF") plt.show()

      輸出結果如下所示:

      test loss: 0.7694947719573975

      test accuracy: 0.33333334

      Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= embedding_1 (Embedding) (None, None, 128) 2560 _________________________________________________________________ lstm_1 (LSTM) (None, 128) 131584 _________________________________________________________________ dense_1 (Dense) (None, 1) 129 ================================================================= Total params: 134,273 Trainable params: 134,273 Non-trainable params: 0 _________________________________________________________________ Train on 15 samples, validate on 6 samples Epoch 1/9 15/15 [==============================] - 2s 148ms/sample - loss: 0.6898 - acc: 0.5333 - val_loss: 0.7640 - val_acc: 0.3333 Epoch 2/9 15/15 [==============================] - 1s 48ms/sample - loss: 0.6779 - acc: 0.6000 - val_loss: 0.7773 - val_acc: 0.3333 Epoch 3/9 15/15 [==============================] - 1s 36ms/sample - loss: 0.6769 - acc: 0.6000 - val_loss: 0.7986 - val_acc: 0.3333 Epoch 4/9 15/15 [==============================] - 1s 47ms/sample - loss: 0.6722 - acc: 0.6000 - val_loss: 0.8097 - val_acc: 0.3333 Epoch 5/9 15/15 [==============================] - 1s 42ms/sample - loss: 0.7021 - acc: 0.6000 - val_loss: 0.7680 - val_acc: 0.3333 Epoch 6/9 15/15 [==============================] - 1s 36ms/sample - loss: 0.6890 - acc: 0.6000 - val_loss: 0.8147 - val_acc: 0.3333 Epoch 7/9 15/15 [==============================] - 1s 37ms/sample - loss: 0.6906 - acc: 0.6000 - val_loss: 0.8599 - val_acc: 0.3333 Epoch 8/9 15/15 [==============================] - 1s 43ms/sample - loss: 0.6819 - acc: 0.6000 - val_loss: 0.8303 - val_acc: 0.3333 Epoch 9/9 15/15 [==============================] - 1s 40ms/sample - loss: 0.6884 - acc: 0.6000 - val_loss: 0.7695 - val_acc: 0.3333 6/6 [==============================] - 0s 7ms/sample - loss: 0.7695 - acc: 0.3333 test loss: 0.7694947719573975 test accuracy: 0.33333334

      對應圖形如下:

      4.機器學習和深度學習對比分析

      最終結果我們進行簡單對比,發(fā)現(xiàn)機器學習比深度學習好,這是為什么呢?我們又能做哪些提升呢?

      MultinomialNB+TFIDF:test accuracy = 0.67

      GaussianNB+Word2Vec:test accuracy = 0.83

      RNN+Word2Vector:test accuracy = 0.33333334

      LSTM+Word2Vec:test accuracy = 0.33333334

      LSTM+TFIDF:test accuracy = 0.33333334

      一是?數(shù)據(jù)集預處理的原因,上述代碼沒有進行停用詞過濾,大量標點符號和停用詞影響了文本分類效果。同時詞向量的維度設置也需要進行調試。

      二是?數(shù)據(jù)集大小的原因。數(shù)據(jù)量少的情況下,推薦使用CNN,RNN的過擬合會讓你欲哭無淚。如果數(shù)據(jù)量多,也許RNN效果會更好。如果為了創(chuàng)新,RLSTM和RCNN等都是近幾年不錯的選擇。但如果僅僅是為了應用,用普通的機器學習方法已經(jīng)足夠優(yōu)秀了(特別是新聞數(shù)據(jù)集),如果考慮上時間成本,貝葉斯無疑才是真正的最好選擇。

      三是?CNN和RNN適用性不同。CNN擅長空間特征的學習和捕獲,RNN擅長時序特征的捕獲。從結構來講,RNN更勝一籌。主流的NLP問題,比如翻譯、生成文本,seq2seq(倆獨立RNN)的引入突破了很多之前的benchmark。Attention的引入是為了解決長句問題,其本質就是外掛了額外的一個softmax去學詞和詞的映射關系,有點像外掛存儲,其根源來自一篇名為“neural turing machine”的paper。

      四是?不同的數(shù)據(jù)集適應不同的方法,各種方法各有所長。有的情感分析GRU好于CNN,而新聞分類、文本分類競賽CNN可能會有優(yōu)勢。CNN具有速度優(yōu)勢,基本比較大的數(shù)據(jù)上CNN能加大參數(shù),擬合更多種類的local phrase frequency,獲得更好的效果。如果你是想做系統(tǒng),兩個算法又各有所長,就是ensemble登場的時候了。

      五是?在文本情感分類領域,GRU是要好于CNN,并且隨著句子長度的增長,GRU的這一優(yōu)勢會進一步放大。當句子的情感分類是由整個句子決定的時候,GRU會更容易分類正確, 當句子的情感分類是由幾個局部的key-phrases決定的時候,CNN會更容易分類正確。

      參考及推薦文章:請問對于中文長文本分類,是CNN效果好,還是RNN效果好?- 知乎

      五.總結

      寫道這里,這篇文章就結束了。希望對您有所幫助,同時文章中不足或錯誤的地方,歡迎讀者提出。這些實驗都是我在做論文研究或項目評價常見的一些問題,希望讀者帶著這些問題,結合自己的需求進行深入的思考,更希望大家能學以致用。

      總之,本文通過Keras實現(xiàn)了一個RNN文本分類學習的案例,并詳細介紹了循環(huán)神經(jīng)網(wǎng)絡原理知識及與機器學習對比。最后,作為人工智能的菜鳥,我希望自己能不斷進步并深入,后續(xù)將它應用于圖像識別、網(wǎng)絡安全、對抗樣本等領域,指導大家撰寫簡單的學術論文,一起加油!

      感恩能與大家在華為云遇見!

      希望能與大家一起在華為云社區(qū)共同成長。原文地址:https://blog.csdn.net/Eastmount/article/details/105165164

      (By:娜璋之家 Eastmount 2021-11-09 夜于武漢)

      參考文獻:

      [1]?Keras的imdb和MNIST數(shù)據(jù)集無法下載問題解決 - 摸金青年v

      [2]?官網(wǎng)實例詳解4.42(imdb.py)-keras學習筆記四 - wyx100

      [3]?Keras文本分類 - 強推基基偉老師文章

      [4]?TextCNN文本分類(keras實現(xiàn))- 強推Asia-Lee老師的文章

      [5]?Keras之文本分類實現(xiàn) - 強推知乎王奕磊老師的文章

      [6 ]自然語言處理入門(二)–Keras實現(xiàn)BiLSTM+Attention新聞標題文本分類 - ilivecode

      [7]?用深度學習(CNN RNN Attention)解決大規(guī)模文本分類問題 - 綜述和實踐 - 知乎清凇

      [8]?基于 word2vec 和 CNN 的文本分類 :綜述 & 實踐 - 牛亞峰serena

      [9]?https://github.com/keras-team/keras

      [10]?[深度學習] keras的EarlyStopping使用與技巧 - zwqjoy

      [11]?深度學習為什么會出現(xiàn)validation accuracy大于train accuracy的現(xiàn)象?- ICOZ

      [12]?Keras實現(xiàn)CNN文本分類 - vivian_ll

      [13]?Keras文本分類實戰(zhàn)(上)- weixin_34351321

      [14]?請問對于中文長文本分類,是CNN效果好,還是RNN效果好?- 知乎

      Keras 深度學習 神經(jīng)網(wǎng)絡

      版權聲明:本文內容由網(wǎng)絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網(wǎng)絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內刪除侵權內容。

      上一篇:wps表格怎樣計算人的年齡(wps里面如何計算年齡)
      下一篇:wps文字中怎樣繪制表格(wps如何繪制表格)
      相關文章
      久久精品亚洲综合一品| 亚洲国产成人精品电影| 亚洲乱码一区二区三区在线观看| 亚洲啪啪免费视频| 亚洲国产成人久久综合碰| 在线观看亚洲网站| 亚洲中文字幕久久精品无码A | 亚洲第一中文字幕| 亚洲成av人在线视| 亚洲AV日韩AV永久无码绿巨人| 亚洲av无码潮喷在线观看 | 久久亚洲国产成人精品无码区| 国产成人精品久久亚洲高清不卡| 亚洲AV无码国产剧情| 亚洲免费网站观看视频| 久久久久亚洲国产| 亚洲欧美日韩中文字幕一区二区三区 | 亚洲成aⅴ人片在线影院八| 国产精品亚洲成在人线| 国产aⅴ无码专区亚洲av麻豆| 77777亚洲午夜久久多人| 国产亚洲人成网站观看| 国产亚洲精品a在线观看app| 国产亚洲成人久久| 久久亚洲精品视频| 久久亚洲AV无码精品色午夜| 亚洲精品国产专区91在线| 亚洲成a人片77777群色| 中日韩亚洲人成无码网站| 亚洲狠狠婷婷综合久久| 亚洲heyzo专区无码综合| 亚洲国产精品丝袜在线观看| 亚洲大码熟女在线观看| 亚洲AV永久无码天堂影院| 亚洲一区二区三区在线播放 | 日韩亚洲人成在线综合| 亚洲日韩涩涩成人午夜私人影院| 国产自偷亚洲精品页65页| 亚洲精品免费在线观看| 亚洲av乱码一区二区三区香蕉| 亚洲啪啪免费视频|