在本文中,咱們將看到如何開發具備多個輸出的文本分類模型。咱們將開發一個文本分類模型,該模型可分析文本註釋並預測與該註釋關聯的多個標籤。多標籤分類問題其實是多個輸出模型的子集。在本文結尾,您將可以對數據執行多標籤文本分類。網絡
數據集包含來自Wikipedia對話頁編輯的評論。 評論能夠屬於全部這些類別,也能夠屬於這些類別的子集,這使其成爲多標籤分類問題。dom
將CSV文件下載到您的本地目錄中。我已將文件重命名爲「 toxic_comments.csv」。 ide
如今,咱們導入所需的庫並將數據集加載到咱們的應用程序中。如下腳本導入所需的庫:函數
fromnumpyimportarrayfromkeras.preprocessing.textimportone_hotfromkeras.preprocessing.sequenceimportpad_sequencesfromkeras.modelsimportSequentialfromkeras.layers.coreimportActivation, Dropout, Densefromkeras.layersimportFlatten, LSTMfromkeras.layersimportGlobalMaxPooling1Dfromkeras.modelsimportModelfromkeras.layers.embeddingsimportEmbeddingfromsklearn.model_selectionimporttrain_test_splitfromkeras.preprocessing.textimportTokenizerfromkeras.layersimportInputfromkeras.layers.mergeimportConcatenateimportpandasaspdimportnumpyasnpimportreimportmatplotlib.pyplotasplt
post
如今,將數據集加載到內存中:性能
toxic_comments = pd.read_csv("/content/drive/My Drive/Colab Datasets/toxic_comments.csv")
學習
如下腳本顯示數據集的形狀,並顯示數據集的標題:測試
print(toxic_comments.shape) toxic_comments.head()
this
輸出:編碼
(159571,8)
數據集包含159571條記錄和8列。數據集的標題以下所示:
讓咱們刪除全部記錄中任何行包含空值或空字符串的記錄。
filter = toxic_comments["comment_text"] !=""toxic_comments = toxic_comments[filter] toxic_comments = toxic_comments.dropna()
該comment_text
列包含文本註釋。
print(toxic_comments["comment_text"][168])
輸出:
You should be fired, you're a moronic wimp who is too lazy todoresearch. It makes me sick that peoplelikeyou existinthis world.
讓咱們看一下與此註釋相關的標籤:
print("Toxic:"+ str(toxic_comments["toxic"][168])) print("Severe_toxic:"+ str(toxic_comments["severe_toxic"][168])) print("Obscene:"+ str(toxic_comments["obscene"][168])) print("Threat:"+ str(toxic_comments["threat"][168])) print("Insult:"+ str(toxic_comments["insult"][168])) print("Identity_hate:"+ str(toxic_comments["identity_hate"][168]))
輸出:
Toxic:1Severe_toxic:0Obscene:0Threat:0Insult:1Identity_hate:0
,咱們將首先過濾全部標籤或輸出列。
toxic_comments_labels = toxic_comments[["toxic","severe_toxic","obscene","threat","insult","identity_hate"]] toxic_comments_labels.head()
輸出:
使用toxic_comments_labels
數據框,咱們將繪製條形圖,以顯示不一樣標籤的總註釋數。
輸出:
您能夠看到,「有毒」評論的出現頻率最高,其次分別是 「侮辱」。
建立多標籤分類模型的方法有兩種:使用單個密集輸出層和多個密集輸出層。
在第一種方法中,咱們能夠使用具備六個輸出的單個密集層,並具備S型激活函數和二進制交叉熵損失函數。
在第二種方法中,咱們將爲每一個標籤建立一個密集輸出層。
具備單輸出層的多標籤文本分類模型
在本節中,咱們將建立具備單個輸出層的多標籤文本分類模型。
在下一步中,咱們將建立輸入和輸出集。輸入是來自該comment_text
列的註釋。
這裏咱們不須要執行任何一鍵編碼,由於咱們的輸出標籤已是一鍵編碼矢量的形式。
下一步,咱們將數據分爲訓練集和測試集:咱們須要將文本輸入轉換爲嵌入式向量。
咱們將使用GloVe詞嵌入將文本輸入轉換爲數字輸入。
如下腳本建立模型。咱們的模型將具備一個輸入層,一個嵌入層,一個具備128個神經元的LSTM層和一個具備6個神經元的輸出層,由於咱們在輸出中有6個標籤。
LSTM_Layer_1 = LSTM(128)(embedding_layer) dense_layer_1 = Dense(6, activation='sigmoid')(LSTM_Layer_1) model = Model()
讓咱們打印模型摘要:
print(model.summary())
輸出:
**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**Layer (type) Output Shape Param # =================================================================input_1 (InputLayer) (None, 200) 0**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**embedding_1 (Embedding) (None, 200, 100) 14824300**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**lstm_1 (LSTM) (None, 128) 117248**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**dense_1 (Dense) (None, 6) 774 =================================================================Total params: 14,942,322 Trainable params: 118,022 Non-trainable params: 14,824,300
如下腳本打印了咱們的神經網絡的體系結構:
plot_model(model, to_file='model_plot4a.png', show_shapes=True, show_layer_names=True)
輸出:
從上圖能夠看到,輸出層僅包含1個具備6個神經元的密集層。如今讓咱們訓練模型:
能夠用更多的時間訓練模型,看看結果是好是壞。
結果以下:
rainon102124samples,validateon25532samplesEpoch1/5102124/102124[==============================]-245s2ms/step-loss:0.1437-acc:0.9634-val_loss:0.1361-val_acc:0.9631Epoch2/5102124/102124[==============================]-245s2ms/step-loss:0.0763-acc:0.9753-val_loss:0.0621-val_acc:0.9788Epoch3/5102124/102124[==============================]-243s2ms/step-loss:0.0588-acc:0.9800-val_loss:0.0578-val_acc:0.9802Epoch4/5102124/102124[==============================]-246s2ms/step-loss:0.0559-acc:0.9807-val_loss:0.0571-val_acc:0.9801Epoch5/5102124/102124[==============================]-245s2ms/step-loss:0.0528-acc:0.9813-val_loss:0.0554-val_acc:0.9807
如今讓咱們在測試集中評估模型:
print("Test Score:", score[0]) print("Test Accuracy:", score[1])
輸出:
31915/31915[==============================] - 108s 3ms/stepTestScore: 0.054090796736467786TestAccuracy: 0.9810642735274182
咱們的模型實現了約98%的精度 。
最後,咱們將繪製訓練和測試集的損失和準確性值,以查看咱們的模型是否過擬合。
plt.title('model loss') plt.ylabel('loss') plt.xlabel('epoch') plt.legend(['train','test'], loc='upper left') plt.show()
輸出:
您能夠看到模型在驗證集上沒有過擬合。
具備多個輸出層的多標籤文本分類模型
在本節中,咱們將建立一個多標籤文本分類模型,其中每一個輸出標籤將具備一個 輸出密集層。讓咱們首先定義預處理功能:
defpreprocess_text(sen):_# Remove punctuations and numbers__# Single character removal__# Removing multiple spaces_sentence = re.sub(r'\s+',' ', sentence)returnsentence
第二步是爲模型建立輸入和輸出。該模型的輸入將是文本註釋,而輸出將是六個標籤。如下腳本建立輸入層和組合的輸出層:
y = toxic_comments[["toxic","severe_toxic","obscene","threat","insult","identity_hate"]]
讓咱們將數據分爲訓練集和測試集:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
該y
變量包含6個標籤的組合輸出。可是,咱們要爲每一個標籤建立單獨的輸出層。咱們將建立6個變量,這些變量存儲來自訓練數據的各個標籤,還有6個變量,分別存儲測試數據的各個標籤值。
下一步是將文本輸入轉換爲嵌入的向量。
X_train = pad_sequences(X_train, padding='post', maxlen=maxlen) X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)
咱們將再次使用GloVe詞嵌入:
embedding_matrix = zeros((vocab_size,100))
咱們的模型將具備一層輸入層,一層嵌入層,而後一層具備128個神經元的LSTM層。LSTM層的輸出將用做6個密集輸出層的輸入。每一個輸出層將具備1個具備S型激活功能的神經元。
如下腳本建立咱們的模型:
model = Model()
如下腳本打印模型的摘要:
print(model.summary())
輸出:
**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____Layer (type) Output Shape Param # Connected to ==================================================================================================input_1 (InputLayer) (None, 200) 0**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____embedding__1 (Embedding) (None, 200, 100) 14824300 input__1[0][0]**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____lstm__1 (LSTM) (None, 128) 117248 embedding__1[0][0]**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____dense__1 (Dense) (None, 1) 129 lstm__1[0][0]**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____dense__2 (Dense) (None, 1) 129 lstm__1[0][0]**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____dense__3 (Dense) (None, 1) 129 lstm__1[0][0]**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____dense__4 (Dense) (None, 1) 129 lstm__1[0][0]**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____dense__5 (Dense) (None, 1) 129 lstm__1[0][0]**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**_____dense_6 (Dense) (None, 1) 129 lstm_1[0][0] ==================================================================================================Total params: 14,942,322 Trainable params: 118,022 Non-trainable params: 14,824,300
如下腳本顯示了咱們模型的體系結構:
plot_model(model, to_file='model_plot4b.png', show_shapes=True, show_layer_names=True)
輸出:
您能夠看到咱們有6個不一樣的輸出層。上圖清楚地說明了咱們在上一節中建立的具備單個輸入層的模型與具備多個輸出層的模型之間的區別。
如今讓咱們訓練模型:
history = model.fit(x=X_train, y=[y1_train, y2_train, y3_train, y4_train, y5_train, y6_train], batch_size=8192, epochs=5, verbose=1, validation_split=0.2)
每一個時期的結果以下所示:
輸出:
Trainon102124samples,validateon25532samplesEpoch1/5102124/102124[==============================]-24s239us/step-loss:3.5116-dense_1_loss:0.6017-dense_2_loss:0.5806-dense_3_loss:0.6150-dense_4_loss:0.5585-dense_5_loss:0.5828-dense_6_loss:0.5730-dense_1_acc:0.9029-dense_2_acc:0.9842-dense_3_acc:0.9444-dense_4_acc:0.9934-dense_5_acc:0.9508-dense_6_acc:0.9870-val_loss:1.0369-val_dense_1_loss:0.3290-val_dense_2_loss:0.0983-val_dense_3_loss:0.2571-val_dense_4_loss:0.0595-val_dense_5_loss:0.1972-val_dense_6_loss:0.0959-val_dense_1_acc:0.9037-val_dense_2_acc:0.9901-val_dense_3_acc:0.9469-val_dense_4_acc:0.9966-val_dense_5_acc:0.9509-val_dense_6_acc:0.9901Epoch2/5102124/102124[==============================]-20s197us/step-loss:0.9084-dense_1_loss:0.3324-dense_2_loss:0.0679-dense_3_loss:0.2172-dense_4_loss:0.0338-dense_5_loss:0.1983-dense_6_loss:0.0589-dense_1_acc:0.9043-dense_2_acc:0.9899-dense_3_acc:0.9474-dense_4_acc:0.9968-dense_5_acc:0.9510-dense_6_acc:0.9915-val_loss:0.8616-val_dense_1_loss:0.3164-val_dense_2_loss:0.0555-val_dense_3_loss:0.2127-val_dense_4_loss:0.0235-val_dense_5_loss:0.1981-val_dense_6_loss:0.0554-val_dense_1_acc:0.9038-val_dense_2_acc:0.9900-val_dense_3_acc:0.9469-val_dense_4_acc:0.9965-val_dense_5_acc:0.9509-val_dense_6_acc:0.9900Epoch3/5102124/102124[==============================]-20s199us/step-loss:0.8513-dense_1_loss:0.3179-dense_2_loss:0.0566-dense_3_loss:0.2103-dense_4_loss:0.0216-dense_5_loss:0.1960-dense_6_loss:0.0490-dense_1_acc:0.9043-dense_2_acc:0.9899-dense_3_acc:0.9474-dense_4_acc:0.9968-dense_5_acc:0.9510-dense_6_acc:0.9915-val_loss:0.8552-val_dense_1_loss:0.3158-val_dense_2_loss:0.0566-val_dense_3_loss:0.2074-val_dense_4_loss:0.0225-val_dense_5_loss:0.1960-val_dense_6_loss:0.0568-val_dense_1_acc:0.9038-val_dense_2_acc:0.9900-val_dense_3_acc:0.9469-val_dense_4_acc:0.9965-val_dense_5_acc:0.9509-val_dense_6_acc:0.9900Epoch4/5102124/102124[==============================]-20s198us/step-loss:0.8442-dense_1_loss:0.3153-dense_2_loss:0.0570-dense_3_loss:0.2061-dense_4_loss:0.0213-dense_5_loss:0.1952-dense_6_loss:0.0493-dense_1_acc:0.9043-dense_2_acc:0.9899-dense_3_acc:0.9474-dense_4_acc:0.9968-dense_5_acc:0.9510-dense_6_acc:0.9915-val_loss:0.8527-val_dense_1_loss:0.3156-val_dense_2_loss:0.0558-val_dense_3_loss:0.2074-val_dense_4_loss:0.0226-val_dense_5_loss:0.1951-val_dense_6_loss:0.0561-val_dense_1_acc:0.9038-val_dense_2_acc:0.9900-val_dense_3_acc:0.9469-val_dense_4_acc:0.9965-val_dense_5_acc:0.9509-val_dense_6_acc:0.9900Epoch5/5102124/102124[==============================]-20s197us/step-loss:0.8410-dense_1_loss:0.3146-dense_2_loss:0.0561-dense_3_loss:0.2055-dense_4_loss:0.0213-dense_5_loss:0.1948-dense_6_loss:0.0486-dense_1_acc:0.9043-dense_2_acc:0.9899-dense_3_acc:0.9474-dense_4_acc:0.9968-dense_5_acc:0.9510-dense_6_acc:0.9915-val_loss:0.8501-val_dense_1_loss:0.3153-val_dense_2_loss:0.0553-val_dense_3_loss:0.2069-val_dense_4_loss:0.0226-val_dense_5_loss:0.1948-val_dense_6_loss:0.0553-val_dense_1_acc:0.9038-val_dense_2_acc:0.9900-val_dense_3_acc:0.9469-val_dense_4_acc:0.9965-val_dense_5_acc:0.9509-val_dense_6_acc:0.9900
對於每一個時期,咱們在輸出中的全部6個密集層都有 精度 。
如今讓咱們評估模型在測試集上的性能:
print("Test Score:", score[0]) print("Test Accuracy:", score[1])
輸出:
31915/31915[==============================] - 111s 3ms/stepTestScore: 0.8471985269747015TestAccuracy: 0.31425264998511726
經過多個輸出層在 只能達到31%的精度。
如下腳本繪製了第一密集層的訓練和驗證集的損失和準確值。
plt.title('model loss') plt.ylabel('loss') plt.xlabel('epoch') plt.legend(['train','test'], loc='upper left') plt.show()
輸出:
從輸出中能夠看到,在第一個時期以後,測試(驗證)的準確性並未收斂。
多標籤文本分類是最多見的文本分類問題之一。在本文中,咱們研究了兩種用於多標籤文本分類的深度學習方法。在第一種方法中,咱們使用具備多個神經元的單個密集輸出層,其中每一個神經元表明一個標籤。
在第二種方法中,咱們爲每一個帶有一個神經元的標籤建立單獨的密集層。結果代表,在咱們的狀況下,具備多個神經元的單個輸出層比多個輸出層的效果更好。