Аннотация: в этой статье подробно объясняется реализация классических алгоритмов классификации текста с глубоким обучением в Keras, включая LSTM, BiLSTM, BiLSTM+Attention и CNN, TextCNN.
Эта статья опубликована в сообществе HUAWEI CLOUD.«Keras Глубокое изучение китайского текста, классификация десяти тысяч слов, сводка (CNN, TextCNN, BiLSTM, Внимание)», Автор: истмаунт.
1. Обзор классификации текстов
Классификация текстов предназначена для автоматической классификации и маркировки текстовых наборов в соответствии с определенной системой или стандартом классификации и относится к автоматической классификации, основанной на системе классификации. Классификацию текстов можно проследить до 1950-х годов, когда классификация текстов в основном осуществлялась экспертами, определяющими правила; в 1980-х появились экспертные системы, созданные инженерией знаний; в 1990-х — с помощью методов машинного обучения, путем искусственной инженерии признаков. и модель классификации мелкого слоя для классификации текста.В настоящее время для классификации текстов в основном используются векторы слов и глубокие нейронные сети.
Г-н Ню Яфэн резюмировал традиционный процесс классификации текстов, как показано на рисунке ниже. В традиционной классификации текстов в основном большинство методов машинного обучения применяются в области классификации текстов. в основном включает:
-
Naive Bayes
-
KNN
-
SVM
-
Методы класса коллекции
-
максимальная энтропия
-
Нейронные сети
Основной процесс классификации текста с использованием фреймворка Keras выглядит следующим образом:
Шаг 1: Предварительная обработка текста, сегментация слов->удаление стоп-слов->статистический выбор первых n слов в качестве характерных слов
Шаг 2. Создайте идентификаторы для каждого функционального слова.
Шаг 3. Преобразование текста в последовательность идентификаторов и отступ слева
Шаг 4: Перетасовка тренировочного набора
Шаг 5: Embedded Layer преобразует слова в векторы слов.
Шаг 6: Добавьте модель и постройте структуру нейронной сети
Шаг 7: Обучите модель
Шаг 8: Получите точность, отзыв, значение F1
Обратите внимание, что если вы используете TFIDF вместо векторов слов для представления документа, вы можете напрямую сгенерировать матрицу TFIDF и ввести ее в модель после сегментации слов.
Методы классификации текста глубокого обучения включают в себя:
-
Сверточная нейронная сеть (TextCNN)
-
Рекуррентная нейронная сеть (TextRNN)
-
TextRNN+Attention
-
TextRCNN(TextRNN+CNN)
-
BiLSTM+Attention
-
передача обучения
Рекомендую статью Ню Яфэна:
- Классификация текстов на основе word2vec и CNN: обзор и практика
2. Предварительная обработка данных и сегментация слов
Эта статья в основном основана на коде, а предыдущие статьи и последующие статьи о принципах алгоритмов будут дополняться. Набор данных показан ниже:
- Обучающий набор: news_dataset_train.csv
Игровая тема (10000), Спортивная тема (10000), Культурная тема (10000), Финансовая тема (10000)
- тестовый набор: news_dataset_test.csv
Игровая тема (5000), спортивная тема (5000), культурная тема (5000), финансовая тема (5000)
- набор проверки: news_dataset_val.csv
Игровая тема (5000), спортивная тема (5000), культурная тема (5000), финансовая тема (5000)
Во-первых, необходимо выполнить предварительную обработку сегментации китайских слов, и для реализации требуется библиотека Jieba. код показывает, как показано ниже:
-
data_preprocess.py
-- coding:utf-8 --
By:Eastmount CSDN 2021-03-19
import csv import pandas as pd import numpy as np import jieba import jieba.analyse
#Добавить пользовательский словарь и отключить словарь jieba.load_userdict("user_dict.txt") stop_list = pd.read_csv('stop_words.txt', двигатель = 'питон', кодировка = 'utf-8', разделитель="\n", имена=['t'])['t'].tolist()
#------------------------------------------------- ---------------------- Функция сегментации слов #Jieba защита txt_cut (юзи): вернуть [w вместо w в jieba.lcut(juzi), если w нет в стоп_листе]
#------------------------------------------------- ---------------------- #Прочитанный файл сегментации китайских слов def fenci (имя файла, результат): #Запишите результат сегментации слова fw = open (результат, "w", новая строка = '', кодировка = 'gb18030') писатель = csv.writer (fw)
writer.writerow(['label','cutword'])#使用csv.DictReader读取文件中的信息 labels = [] contents = [] with open(filename, "r", encoding="UTF-8") as f: reader = csv.DictReader(f) for row in reader: #数据元素获取 labels.append(row['label']) content = row['content'] #中文分词 seglist = txt_cut(content) #空格拼接 output = ' '.join(list(seglist)) contents.append(output) #文件写入 tlist = [] tlist.append(row['label']) tlist.append(output) writer.writerow(tlist) print(labels[:5]) print(contents[:5]) fw.close()
#------------------------------------------------- ---------------------- #основная функция еслиname == 'main': fenci("news_dataset_train.csv", "news_dataset_train_fc.csv") fenci("news_dataset_test.csv", "news_dataset_test_fc.csv") fenci("news_dataset_val.csv", "news_dataset_val_fc.csv")
Результат работы показан на следующем рисунке:
Затем мы пытаемся просто просмотреть распределение данных по длине и визуализировать метки.
-
data_show.py
-- coding: utf-8 --
""" Created on 2021-03-19 @author: xiuzhang Eastmount CSDN """ import pandas as pd import numpy as np from sklearn import metrics import matplotlib.pyplot as plt import seaborn as sns
#-----------------------------------------------------Первый шаг чтения данных---- - -------------------------------
Чтение тестового набора данных
train_df = pd.read_csv("news_dataset_train_fc.csv") val_df = pd.read_csv("news_dataset_val_fc.csv") test_df = pd.read_csv("news_dataset_test_fc.csv") print(train_df.head())
Решить проблему китайского дисплея
plt.rcParams['font.sans-serif'] = ['KaiTi'] #Укажите шрифт SimHei по умолчанию полужирный plt.rcParams['axes.unicode_minus'] = False #Решение сохранить изображение является отрицательным знаком'
Посмотрите, какие метки есть в обучающем наборе
plt.figure() sns.countplot(train_df.label) plt.xlabel('Label',size = 10) plt.xticks(size = 10) plt.show()
Проанализируйте распределение количества фраз в обучающей выборке
печать (train_df.cutwordnum.describe()) plt.figure() plt.hist (train_df.cutwordnum, бункеры = 100) plt.xlabel("длина фразы", размер = 12) plt.ylabel("Частота", размер = 12) plt.title("обучающий набор данных") plt.show()
Результат показан на рисунке ниже.В следующей статье мы расскажем, как нарисовать красивую диаграмму на бумаге.
Обратите внимание, что если сообщается об ошибке «UnicodeDecodeError: кодек 'utf-8' не может декодировать байт 0xce в позиции 17: недопустимый байт продолжения», вам необходимо сохранить файл CSV в формате UTF-8, как показано на следующем рисунке. .
3. Классификация китайских текстов CNN
1. Принцип введения
Сверточные нейронные сети (CNN) — это класс нейронных сетей с прямой связью с глубокой структурой, который включает сверточные вычисления и является одним из типичных алгоритмов глубокого обучения. Обычно он используется в таких областях, как распознавание изображений и распознавание речи, и может давать лучшие результаты, а также может использоваться в анализе видео, машинном переводе, обработке естественного языка, открытии лекарств и других областях. Знаменитый AlphaGo позволяет компьютерам понимать язык Go на основе сверточных нейронных сетей.
-
Свертка относится не к обработке каждого пикселя, а к обработке области изображения.Этот метод усиливает непрерывность изображения и видит график вместо точки, что также углубляет понимание изображения нейронной сетью.
-
Обычно сверточная нейронная сеть проходит через процесс «изображение->свертка->удержание->свертка->удержание->результат передается в двухслойный полносвязный нейронный слой->классификатор» и, наконец, реализует Обработка классификации CNN.
2. Реализация кода
Код CNN для Keras для реализации классификации текста выглядит следующим образом:
-
Keras_CNN_cnews.py
-- coding: utf-8 --
""" Created on 2021-03-19 @author: xiuzhang Eastmount CSDN CNN Model """ import os import time import pickle import pandas as pd import numpy as np from sklearn import metrics import matplotlib.pyplot as plt import seaborn as sns import tensorflow as tf from sklearn.preprocessing import LabelEncoder,OneHotEncoder from keras.models import Model from keras.layers import LSTM, Activation, Dense, Dropout, Input, Embedding from keras.layers import Convolution1D, MaxPool1D, Flatten from keras.preprocessing.text import Tokenizer from keras.preprocessing import sequence from keras.callbacks import EarlyStopping from keras.models import load_model from keras.models import Sequential
Обработка GPU. Читатели могут комментировать эту часть кода, если они используют CPU.
Укажите верхний предел видеопамяти, используемой в каждом процессе GPU.0,9 означает, что 90% ресурсов GPU могут использоваться для обучения.
os.environ["CUDA_DEVICES_ORDER"] = "PCI_BUS_IS" os.environ["CUDA_VISIBLE_DEVICES"] = "0" gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
start = time.clock()
#---------------------------- Первый шаг чтения данных---------------- -------------
Чтение тестового набора данных
train_df = pd.read_csv("news_dataset_train_fc.csv") val_df = pd.read_csv("news_dataset_val_fc.csv") test_df = pd.read_csv("news_dataset_test_fc.csv") print(train_df.head())
Решить проблему китайского дисплея
plt.rcParams['font.sans-serif'] = ['KaiTi'] #Укажите шрифт SimHei по умолчанию полужирный plt.rcParams['axes.unicode_minus'] = False #Решение сохранить изображение является отрицательным знаком'
#----------------------------------------------------Второй этап кодирования OneHotEncoder() ---- ------------ ----
Кодировать данные метки набора данных
train_y = train_df.label val_y = val_df.label test_y = test_df.label print("Label:") print(train_y[:10])
le = LabelEncoder() train_y = le.fit_transform(train_y).reshape(-1,1) val_y = le.transform(val_y).reshape(-1,1) test_y = le.transform(test_y).reshape(-1,1) print("LabelEncoder") print(train_y[:10]) print(len(train_y))
Горячее кодирование данных метки набора данных
ohe = OneHotEncoder() train_y = ohe.fit_transform(train_y).toarray() val_y = ohe.transform(val_y).toarray() test_y = ohe.transform(test_y).toarray() print("OneHotEncoder:") print(train_y[:10])
#-----------------------Третий шаг использует Tokenizer для кодирования фразы ---------------- --- макс_слов = 6000 max_len = 600 tok = Tokenizer(num_words=max_words) # Максимальное количество слов 6000 печать (train_df.cutword [: 5]) печать (тип (train_df.cutword))
Предотвратить обработку числовых строк в корпусе
train_content = [str(a) for a in train_df.cutword.tolist()] val_content = [str(a) for a in val_df.cutword.tolist()] test_content = [str(a) for a in test_df.cutword.tolist()] tok.fit_on_texts(train_content) print(tok)
#Когда объект Tokenizer создан, используйте функцию fit_on_texts() для идентификации каждого слова #tok.fit_on_texts(train_df.cutword)
Сохраните обученный токенизатор и импортируйте
with open('tok.pickle', 'wb') as handle: #saving pickle.dump(tok, handle, protocol=pickle.HIGHEST_PROTOCOL) with open('tok.pickle', 'rb') as handle: #loading tok = pickle.load(handle)
Используйте свойство word_index для просмотра кодировки, соответствующей каждому слову.
Используйте свойство word_counts, чтобы просмотреть частоту, соответствующую каждому слову.
for ii,iterm in enumerate(tok.word_index.items()): if ii < 10: print(iterm) else: break print("===================")
for ii,iterm in enumerate(tok.word_counts.items()): if ii < 10: print(iterm) else: break#----------------------------Четвертый шаг — преобразовать данные в последовательность----------- ----- --------------
Используйте sequence.pad_sequences(), чтобы настроить каждую последовательность на одинаковую длину.
После кодирования каждого слова каждое слово в каждом новостном предложении может быть представлено соответствующим кодом, то есть каждая новость может быть преобразована в вектор
train_seq = tok.texts_to_sequences(train_content) val_seq = tok.texts_to_sequences(val_content) test_seq = tok.texts_to_sequences(test_content)
Настройте каждую последовательность на одинаковую длину
train_seq_mat = sequence.pad_sequences (train_seq, maxlen = max_len) val_seq_mat = sequence.pad_sequences (val_seq, maxlen = max_len) test_seq_mat = sequence.pad_sequences (test_seq, maxlen = max_len) print("Последовательность преобразования данных") печать (train_seq_mat.shape) печать (val_seq_mat.shape) печать (test_seq_mat.shape) печать (train_seq_mat [: 2])
#-------------------------------Шаг 5 Построить модель CNN------------- --------------
Категория 4
num_labels = 4 inputs = Input(name='inputs',shape=[max_len], dtype='float64')
Вложения слов используют предварительно обученные векторы слов
layer = Embedding(max_words+1, 128, input_length=max_len, trainable=False)(inputs)
Сверточный слой и слой пула (размер окна слова составляет 3 128 ядер)
cnn = Convolution1D(128, 3, padding='same', strides = 1, activation='relu')(layer) cnn = MaxPool1D(pool_size=4)(cnn)
Dropout предотвращает переоснащение
flat = Flatten()(cnn) drop = Dropout(0.3)(flat)
полносвязный слой
main_output = Dense(num_labels, activation='softmax')(drop) model = Model(inputs=inputs, outputs=main_output)
Функция оптимизации Индекс оценки
model.summary() model.compile(loss="categorical_crossentropy", optimizer='adam', # RMSprop() metrics=["accuracy"])
#------------------------------- Шаг 6 Обучение модели и прогнозирование ------------ - ---------------
Сначала настройте тренировку, затем настройте тестовую проверку.
флаг = "поезд" если флаг == "поезд": print("Обучение модели") ## обучение модели прекращает обучение, когда val-loss больше не улучшается 0,0001 model_fit = model.fit (train_seq_mat, train_y, batch_size = 128, эпохи = 10, validation_data=(val_seq_mat,val_y), обратные вызовы = [Ранняя остановка (монитор = 'val_loss', min_delta = 0,0001)]
) ## сохранить модель модель.сохранить('моя_модель.h5')
del model # удаляет существующую модель ## расчет времени прошедшее = (время.часы() - начало) print("Использовано время:", истекло) печать (model_fit.history)еще: print("Предсказание модели") ## Импорт обученной модели модель = load_model('my_model.h5') ## делать прогнозы на тестовом наборе test_pre = model.predict (test_seq_mat) ## Оценить эффект предсказания и вычислить матрицу путаницы confm = metrics.confusion_matrix (np.argmax (test_y, ось = 1), np.argmax (test_pre, ось = 1)) печать (конфм)
## 混淆矩阵可视化 Labname = ["体育", "文化", "财经", "游戏"] print(metrics.classification_report(np.argmax(test_y,axis=1),np.argmax(test_pre,axis=1))) plt.figure(figsize=(8,8)) sns.heatmap(confm.T, square=True, annot=True, fmt='d', cbar=False, linewidths=.6, cmap="YlGnBu") plt.xlabel('True label',size = 14) plt.ylabel('Predicted label', size = 14) plt.xticks(np.arange(4)+0.5, Labname, size = 12) plt.yticks(np.arange(4)+0.5, Labname, size = 12) plt.savefig('result.png') plt.show() #----------------------------------第七 验证算法-------------------------- ## 使用tok对验证数据集重新预处理,并使用训练好的模型进行预测 val_seq = tok.texts_to_sequences(val_df.cutword) ## 将每个序列调整为相同的长度 val_seq_mat = sequence.pad_sequences(val_seq,maxlen=max_len) ## 对验证集进行预测 val_pre = model.predict(val_seq_mat) print(metrics.classification_report(np.argmax(val_y,axis=1),np.argmax(val_pre,axis=1))) ## 计算时间 elapsed = (time.clock() - start) print("Time used:", elapsed)
Работа графического процессора показана на рисунке ниже. Обратите внимание, что если ваш компьютер является версией ЦП, вам нужно только закомментировать первую часть приведенного выше кода, а более поздняя часть LSTM использует библиотечную функцию, соответствующую графическому процессору.
Модель выходных данных обучения показана на следующем рисунке:
Результат обучения следующий:
模型训练
Train on 40000 samples, validate on 20000 samples
Epoch 1/10
40000/40000 [==============================] - 15s 371us/step - loss: 1.1798 - acc: 0.4772 - val_loss: 0.9878 - val_acc: 0.5977
Epoch 2/10
40000/40000 [==============================] - 4s 93us/step - loss: 0.8681 - acc: 0.6612 - val_loss: 0.8167 - val_acc: 0.6746
Epoch 3/10
40000/40000 [==============================] - 4s 92us/step - loss: 0.7268 - acc: 0.7245 - val_loss: 0.7084 - val_acc: 0.7330
Epoch 4/10
40000/40000 [==============================] - 4s 93us/step - loss: 0.6369 - acc: 0.7643 - val_loss: 0.6462 - val_acc: 0.7617
Epoch 5/10
40000/40000 [==============================] - 4s 96us/step - loss: 0.5670 - acc: 0.7957 - val_loss: 0.5895 - val_acc: 0.7867
Epoch 6/10
40000/40000 [==============================] - 4s 92us/step - loss: 0.5074 - acc: 0.8226 - val_loss: 0.5530 - val_acc: 0.8018
Epoch 7/10
40000/40000 [==============================] - 4s 93us/step - loss: 0.4638 - acc: 0.8388 - val_loss: 0.5105 - val_acc: 0.8185
Epoch 8/10
40000/40000 [==============================] - 4s 93us/step - loss: 0.4241 - acc: 0.8545 - val_loss: 0.4836 - val_acc: 0.8304
Epoch 9/10
40000/40000 [==============================] - 4s 92us/step - loss: 0.3900 - acc: 0.8692 - val_loss: 0.4599 - val_acc: 0.8403
Epoch 10/10
40000/40000 [==============================] - 4s 93us/step - loss: 0.3657 - acc: 0.8761 - val_loss: 0.4472 - val_acc: 0.8457
Time used: 52.203992899999996
Результаты прогнозирования и проверки следующие:
[[3928 472 264 336]
[ 115 4529 121 235]
[ 151 340 4279 230]
[ 145 593 195 4067]]
precision recall f1-score support
0 0.91 0.79 0.84 5000
1 0.76 0.91 0.83 5000
2 0.88 0.86 0.87 5000
3 0.84 0.81 0.82 5000
avg / total 0.85 0.84 0.84 20000
precision recall f1-score support
0 0.90 0.77 0.83 5000
1 0.78 0.92 0.84 5000
2 0.88 0.85 0.86 5000
3 0.84 0.85 0.85 5000
avg / total 0.85 0.85 0.85 20000
4. Классификация китайского текста TextCNN
1. Принцип введения
TextCNN — это алгоритм классификации текста с использованием сверточных нейронных сетей, предложенный Юн Кимом в статье «Сверточные нейронные сети для классификации предложений» в 2014 году.
Основная идея сверточной нейронной сети состоит в том, чтобы захватить локальные функции, Для текста локальные функции представляют собой скользящие окна, состоящие из нескольких слов, похожие на N-граммы. Преимущество сверточных нейронных сетей заключается в том, что они могут автоматически комбинировать и фильтровать признаки N-грамм для получения семантической информации на разных уровнях абстракции. На рисунке ниже представлена архитектура модели сверточной нейронной сети, используемой для классификации текста в статье.
Еще одна классическая статья TextCNN — «Анализ чувствительности (и практическое руководство) сверточных нейронных сетей для классификации предложений», результаты моделирования которого показаны на рисунке ниже. Описание структуры TextCNN, используемое в основном для задач классификации текста, подробно объясняет, как архитектура TextCNN и матрица векторов слов являются сверточными.
Предположим, у нас есть несколько предложений, которые необходимо классифицировать. Каждое слово в предложении состоит из n-мерных векторов слов, то есть размер входной матрицы равен m*n, где m — длина предложения. CNN необходимо выполнить операцию свертки над входными выборками.Для текстовых данных фильтр больше не скользит горизонтально, а только движется вниз, что чем-то похоже на локальную корреляцию между N-граммами при извлечении слов.
На рисунке показаны три стратегии размера шага, а именно 2, 3 и 4, и каждый размер шага имеет два фильтра (количество фильтров в реальном обучении будет большим). Примените разные фильтры к разным окнам слов и, наконец, получите 6 свернутых векторов. Затем выполните операцию максимального объединения для каждого вектора и соедините каждое значение объединения и, наконец, получите представление признаков предложения, передайте вектор предложения классификатору для классификации и, наконец, завершите весь процесс классификации текста.
Наконец, я искренне рекомендую следующие введения о TextCNN, особенно Азия-Ли из CSDN. Мне очень нравятся его статьи. Это действительно здорово!
-
«Сверточные нейронные сети для классификации предложений 2014»
-
Анализ чувствительности (и практическое руководство) сверточных нейронных сетей для классификации предложений
2. Реализация кода
Код TextCNN для Keras для реализации классификации текста выглядит следующим образом:
-
Keras_TextCNN_cnews.py
-- coding: utf-8 --
""" Created on 2021-03-19 @author: xiuzhang Eastmount CSDN TextCNN Model """ import os import time import pickle import pandas as pd import numpy as np from sklearn import metrics import matplotlib.pyplot as plt import seaborn as sns import tensorflow as tf from sklearn.preprocessing import LabelEncoder,OneHotEncoder from keras.models import Model from keras.layers import LSTM, Activation, Dense, Dropout, Input, Embedding from keras.layers import Convolution1D, MaxPool1D, Flatten from keras.preprocessing.text import Tokenizer from keras.preprocessing import sequence from keras.callbacks import EarlyStopping from keras.models import load_model from keras.models import Sequential from keras.layers.merge import concatenate
Обработка GPU. Читатели могут комментировать эту часть кода, если они используют CPU.
Укажите верхний предел видеопамяти, используемой в каждом процессе GPU.0,9 означает, что 90% ресурсов GPU могут использоваться для обучения.
os.environ["CUDA_DEVICES_ORDER"] = "PCI_BUS_IS" os.environ["CUDA_VISIBLE_DEVICES"] = "0" gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
start = time.clock()
#---------------------------- Первый шаг чтения данных---------------- -------------
Чтение тестового набора данных
train_df = pd.read_csv("news_dataset_train_fc.csv") val_df = pd.read_csv("news_dataset_val_fc.csv") test_df = pd.read_csv("news_dataset_test_fc.csv")
Решить проблему китайского дисплея
plt.rcParams['font.sans-serif'] = ['KaiTi'] #Укажите шрифт SimHei по умолчанию полужирный plt.rcParams['axes.unicode_minus'] = False #Решение сохранить изображение является отрицательным знаком'
#----------------------------------------------------Второй этап кодирования OneHotEncoder() ---- ------------ ----
Кодировать данные метки набора данных
train_y = train_df.label val_y = val_df.label test_y = test_df.label print("Label:") print(train_y[:10])
le = LabelEncoder() train_y = le.fit_transform(train_y).reshape(-1,1) val_y = le.transform(val_y).reshape(-1,1) test_y = le.transform(test_y).reshape(-1,1) print("LabelEncoder") print(train_y[:10]) print(len(train_y))
Горячее кодирование данных метки набора данных
ohe = OneHotEncoder() train_y = ohe.fit_transform(train_y).toarray() val_y = ohe.transform(val_y).toarray() test_y = ohe.transform(test_y).toarray() print("OneHotEncoder:") print(train_y[:10])
#-----------------------Третий шаг использует Tokenizer для кодирования фразы ---------------- --- макс_слов = 6000 max_len = 600 tok = Tokenizer(num_words=max_words) # Максимальное количество слов 6000 печать (train_df.cutword [: 5]) печать (тип (train_df.cutword))
Предотвратить обработку числовых строк в корпусе
train_content = [str(a) for a in train_df.cutword.tolist()] val_content = [str(a) for a in val_df.cutword.tolist()] test_content = [str(a) for a in test_df.cutword.tolist()] tok.fit_on_texts(train_content) print(tok)
Сохраните обученный токенизатор и импортируйте
with open('tok.pickle', 'wb') as handle: #saving pickle.dump(tok, handle, protocol=pickle.HIGHEST_PROTOCOL) with open('tok.pickle', 'rb') as handle: #loading tok = pickle.load(handle)
#----------------------------Четвертый шаг — преобразовать данные в последовательность----------- ----- -------------- train_seq = tok.texts_to_sequences(train_content) val_seq = tok.texts_to_sequences(val_content) test_seq = tok.texts_to_sequences(test_content)
Настройте каждую последовательность на одинаковую длину
train_seq_mat = sequence.pad_sequences (train_seq, maxlen = max_len) val_seq_mat = sequence.pad_sequences (val_seq, maxlen = max_len) test_seq_mat = sequence.pad_sequences (test_seq, maxlen = max_len) print("Последовательность преобразования данных") печать (train_seq_mat.shape) печать (val_seq_mat.shape) печать (test_seq_mat.shape) печать (train_seq_mat [: 2])
#-------------------------------Шаг 5 Создайте модель TextCNN------------- --------------
Категория 4
num_labels = 4 inputs = Input(name='inputs',shape=[max_len], dtype='float64')
Вложения слов используют предварительно обученные векторы слов
layer = Embedding(max_words+1, 256, input_length=max_len, trainable=False)(inputs)
Размер окна слова 3,4,5
cnn1 = Convolution1D(256, 3, padding='same', strides = 1, activation='relu')(layer) cnn1 = MaxPool1D(pool_size=4)(cnn1) cnn2 = Convolution1D(256, 4, padding='same', strides = 1, activation='relu')(layer) cnn2 = MaxPool1D(pool_size=4)(cnn2) cnn3 = Convolution1D(256, 5, padding='same', strides = 1, activation='relu')(layer) cnn3 = MaxPool1D(pool_size=4)(cnn3)
Объедините выходные векторы трех моделей
cnn = concatenate([cnn1,cnn2,cnn3], axis=-1) flat = Flatten()(cnn) drop = Dropout(0.2)(flat) main_output = Dense(num_labels, activation='softmax')(drop) model = Model(inputs=inputs, outputs=main_output) model.summary() model.compile(loss="categorical_crossentropy", optimizer='adam', # RMSprop() metrics=["accuracy"])
#------------------------------- Шаг 6 Обучение модели и прогнозирование ------------ - ---------------
Сначала настройте тренировку, затем настройте тестовую проверку.
флаг = "поезд" если флаг == "поезд": print("Обучение модели") ## обучение модели прекращает обучение, когда val-loss больше не улучшается 0,0001 model_fit = model.fit (train_seq_mat, train_y, batch_size = 128, эпохи = 10, validation_data=(val_seq_mat,val_y), обратные вызовы = [Ранняя остановка (монитор = 'val_loss', min_delta = 0,0001)]
) model.save('my_model.h5')
del model elapsed = (time.clock() - start) print("Time used:", elapsed) print(model_fit.history)еще: print("Предсказание модели") ## Импорт обученной модели модель = load_model('my_model.h5') ## делать прогнозы на тестовом наборе test_pre = model.predict (test_seq_mat) ## Оценить эффект предсказания и вычислить матрицу путаницы confm = metrics.confusion_matrix (np.argmax (test_y, ось = 1), np.argmax (test_pre, ось = 1)) печать (конфм)
## 混淆矩阵可视化 Labname = ["体育", "文化", "财经", "游戏"] print(metrics.classification_report(np.argmax(test_y,axis=1),np.argmax(test_pre,axis=1))) plt.figure(figsize=(8,8)) sns.heatmap(confm.T, square=True, annot=True, fmt='d', cbar=False, linewidths=.6, cmap="YlGnBu") plt.xlabel('True label',size = 14) plt.ylabel('Predicted label', size = 14) plt.xticks(np.arange(4)+0.5, Labname, size = 12) plt.yticks(np.arange(4)+0.5, Labname, size = 12) plt.savefig('result.png') plt.show() #----------------------------------第七 验证算法-------------------------- ## 使用tok对验证数据集重新预处理,并使用训练好的模型进行预测 val_seq = tok.texts_to_sequences(val_df.cutword) ## 将每个序列调整为相同的长度 val_seq_mat = sequence.pad_sequences(val_seq,maxlen=max_len) ## 对验证集进行预测 val_pre = model.predict(val_seq_mat) print(metrics.classification_report(np.argmax(val_y,axis=1),np.argmax(val_pre,axis=1))) elapsed = (time.clock() - start) print("Time used:", elapsed)
Обученная модель выглядит так:
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
inputs (InputLayer) (None, 600) 0
__________________________________________________________________________________________________
embedding_1 (Embedding) (None, 600, 256) 1536256 inputs[0][0]
__________________________________________________________________________________________________
conv1d_1 (Conv1D) (None, 600, 256) 196864 embedding_1[0][0]
__________________________________________________________________________________________________
conv1d_2 (Conv1D) (None, 600, 256) 262400 embedding_1[0][0]
__________________________________________________________________________________________________
conv1d_3 (Conv1D) (None, 600, 256) 327936 embedding_1[0][0]
__________________________________________________________________________________________________
max_pooling1d_1 (MaxPooling1D) (None, 150, 256) 0 conv1d_1[0][0]
__________________________________________________________________________________________________
max_pooling1d_2 (MaxPooling1D) (None, 150, 256) 0 conv1d_2[0][0]
__________________________________________________________________________________________________
max_pooling1d_3 (MaxPooling1D) (None, 150, 256) 0 conv1d_3[0][0]
__________________________________________________________________________________________________
concatenate_1 (Concatenate) (None, 150, 768) 0 max_pooling1d_1[0][0]
max_pooling1d_2[0][0]
max_pooling1d_3[0][0]
__________________________________________________________________________________________________
flatten_1 (Flatten) (None, 115200) 0 concatenate_1[0][0]
__________________________________________________________________________________________________
dropout_1 (Dropout) (None, 115200) 0 flatten_1[0][0]
__________________________________________________________________________________________________
dense_1 (Dense) (None, 4) 460804 dropout_1[0][0]
==================================================================================================
Total params: 2,784,260
Trainable params: 1,248,004
Non-trainable params: 1,536,256
__________________________________________________________________________________________________
Прогнозируемые результаты следующие:
[[4448 238 182 132]
[ 151 4572 124 153]
[ 185 176 4545 94]
[ 181 394 207 4218]]
precision recall f1-score support
0 0.90 0.89 0.89 5000
1 0.85 0.91 0.88 5000
2 0.90 0.91 0.90 5000
3 0.92 0.84 0.88 5000
avg / total 0.89 0.89 0.89 20000
precision recall f1-score support
0 0.90 0.88 0.89 5000
1 0.86 0.93 0.89 5000
2 0.91 0.89 0.90 5000
3 0.92 0.88 0.90 5000
avg / total 0.90 0.90 0.90 20000
5. Классификация китайского текста LSTM
1. Принцип введения
Долгосрочная сеть (LSTM) — это особый тип RNN (рекуррентная нейронная сеть), который может изучать информацию о долгосрочных зависимостях. LSTM был предложен Хохрайтером и Шмидхубером (1997), а недавно улучшен и продвинут Алексом Грейвсом. Во многих задачах LSTM добились значительных успехов и широко используются.
Из-за проблемы исчезновения градиента в RNN люди улучшили скрытую структуру позиции индекса последовательности t и использовали некоторые уловки, чтобы усложнить скрытую структуру, чтобы избежать проблемы исчезновения градиента.Таким специальным RNN является наш LSTM. Полное название LSTM — Long Short-Term Memory. Благодаря особенностям своего дизайна LSTM очень подходит для моделирования данных временных рядов, таких как текстовые данные. Структура LSTM выглядит следующим образом:
LSTM избегают долгосрочных зависимостей благодаря преднамеренному дизайну. Запоминание долгосрочной информации на практике является поведением LSTM по умолчанию, а не очень дорогой возможностью. LSTM внесла некоторые улучшения в обычный RNN, LSTM RNN имеет еще три контроллера, а именно:
-
входной контроллер
-
выходной контроллер
-
забыть контроллер
Слева больше основных линий, таких как основной сюжет фильма, а исходная система RNN стала подсюжетом, а все три контроллера находятся на подстроке.
-
Контроллер ввода (запись ворота): Установите ворота при вводе ввода. Функция ворот состоит в том, чтобы решить, следует ли записывать этот ввод в нашу память. Он эквивалентен параметру и также может быть обучен. Этот параметр используется для управления тем, запоминать ли эту точку в настоящее время.
-
Контроллер вывода (считывающий вентиль): В воротах выходного положения решите, следует ли читать текущую память.
-
Забудьте контроллер (забудьте ворота): Обработайте забытый контроллер местоположения и решите, следует ли забыть предыдущую память.
Принцип работы LSTM таков: если содержимое ветки очень важно для конечного результата, контроллер ввода запишет содержимое ветки в содержимое основной строки в соответствии с его важностью, а затем проанализирует его; содержимое ветки меняет наше предыдущее мышление, затем забываем, что контроллер забудет некоторый основной контент, а затем пропорционально заменит новый контент, поэтому обновление основного контента зависит от ввода и забудет управление; окончательный вывод будет основан на основной контент и контент ветвей. Наша RNN хорошо контролируется этими тремя воротами, и на основе этих механизмов управления LSTM является хорошим лекарством от задержки памяти, что приводит к лучшим результатам.
2. Реализация кода
Код LSTM для Keras для реализации классификации текста выглядит следующим образом:
-
Keras_LSTM_cnews.py
""" Created on 2021-03-19 @author: xiuzhang Eastmount CSDN LSTM Model """ import os import time import pickle import pandas as pd import numpy as np from sklearn import metrics import matplotlib.pyplot as plt import seaborn as sns import tensorflow as tf from sklearn.preprocessing import LabelEncoder,OneHotEncoder from keras.models import Model from keras.layers import LSTM, Activation, Dense, Dropout, Input, Embedding from keras.layers import Convolution1D, MaxPool1D, Flatten from keras.preprocessing.text import Tokenizer from keras.preprocessing import sequence from keras.callbacks import EarlyStopping from keras.models import load_model from keras.models import Sequential
#GPU ускорение CuDNNLSTM быстрее, чем LSTM импорт из keras.layers CuDNNLSTM, CuDNNGRU
Обработка GPU. Читатели могут комментировать эту часть кода, если они используют CPU.
Укажите верхний предел видеопамяти, используемой в каждом процессе GPU.0,9 означает, что 90% ресурсов GPU могут использоваться для обучения.
os.environ["CUDA_DEVICES_ORDER"] = "PCI_BUS_IS" os.environ["CUDA_VISIBLE_DEVICES"] = "0" gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
start = time.clock()
#---------------------------- Первый шаг чтения данных---------------- -------------
Чтение тестового набора данных
train_df = pd.read_csv("news_dataset_train_fc.csv") val_df = pd.read_csv("news_dataset_val_fc.csv") test_df = pd.read_csv("news_dataset_test_fc.csv") print(train_df.head())
Решить проблему китайского дисплея
plt.rcParams['font.sans-serif'] = ['KaiTi'] #Укажите шрифт SimHei по умолчанию полужирный plt.rcParams['axes.unicode_minus'] = False #Решение сохранить изображение является отрицательным знаком'
#----------------------------------------------------Второй этап кодирования OneHotEncoder() ---- ------------ ----
Кодировать данные метки набора данных
train_y = train_df.label val_y = val_df.label test_y = test_df.label print("Label:") print(train_y[:10])
le = LabelEncoder() train_y = le.fit_transform(train_y).reshape(-1,1) val_y = le.transform(val_y).reshape(-1,1) test_y = le.transform(test_y).reshape(-1,1) print("LabelEncoder") print(train_y[:10]) print(len(train_y))
Горячее кодирование данных метки набора данных
ohe = OneHotEncoder() train_y = ohe.fit_transform(train_y).toarray() val_y = ohe.transform(val_y).toarray() test_y = ohe.transform(test_y).toarray() print("OneHotEncoder:") print(train_y[:10])
#-----------------------Третий шаг использует Tokenizer для кодирования фразы ---------------- --- макс_слов = 6000 max_len = 600 tok = Tokenizer(num_words=max_words) # Максимальное количество слов 6000 печать (train_df.cutword [: 5]) печать (тип (train_df.cutword))
Предотвратить обработку числовых строк в корпусе
train_content = [str(a) for a in train_df.cutword.tolist()] val_content = [str(a) for a in val_df.cutword.tolist()] test_content = [str(a) for a in test_df.cutword.tolist()] tok.fit_on_texts(train_content) print(tok)
Сохраните обученный токенизатор и импортируйте
with open('tok.pickle', 'wb') as handle: #saving pickle.dump(tok, handle, protocol=pickle.HIGHEST_PROTOCOL) with open('tok.pickle', 'rb') as handle: #loading tok = pickle.load(handle)
#----------------------------Четвертый шаг — преобразовать данные в последовательность----------- ----- -------------- train_seq = tok.texts_to_sequences(train_content) val_seq = tok.texts_to_sequences(val_content) test_seq = tok.texts_to_sequences(test_content)
Настройте каждую последовательность на одинаковую длину
train_seq_mat = sequence.pad_sequences (train_seq, maxlen = max_len) val_seq_mat = sequence.pad_sequences (val_seq, maxlen = max_len) test_seq_mat = sequence.pad_sequences (test_seq, maxlen = max_len) print("Последовательность преобразования данных") печать (train_seq_mat.shape) печать (val_seq_mat.shape) печать (test_seq_mat.shape) печать (train_seq_mat [: 2])
#------------------------------- Шаг 5 Создайте модель LSTM ------------ --------------
Определите модель LSTM
inputs = Input(name='inputs',shape=[max_len],dtype='float64')
Встраивание (размер словаря, размер пакета, длина каждой новости)
layer = Embedding(max_words+1, 128, input_length=max_len)(inputs) #layer = LSTM(128)(layer) layer = CuDNNLSTM(128)(layer)
layer = Dense(128, activation="relu", name="FC1")(layer) layer = Dropout(0.1)(layer) layer = Dense(4, activation="softmax", name="FC2")(layer) model = Model(inputs=inputs, outputs=layer) model.summary() model.compile(loss="categorical_crossentropy", optimizer='adam', # RMSprop() metrics=["accuracy"])
#------------------------------- Шаг 6 Обучение модели и прогнозирование ------------ - ---------------
Сначала настройте тренировку, затем настройте тестовую проверку.
флаг = "поезд" если флаг == "поезд": print("Обучение модели") ## обучение модели прекращает обучение, когда val-loss больше не улучшается 0,0001 model_fit = model.fit (train_seq_mat, train_y, batch_size = 128, эпохи = 10, validation_data=(val_seq_mat,val_y), обратные вызовы = [Ранняя остановка (монитор = 'val_loss', min_delta = 0,0001)]
) model.save('my_model.h5')
del model elapsed = (time.clock() - start) print("Time used:", elapsed) print(model_fit.history)еще: print("Предсказание модели") ## Импорт обученной модели модель = load_model('my_model.h5') ## делать прогнозы на тестовом наборе test_pre = model.predict (test_seq_mat) ## Оценить эффект предсказания и вычислить матрицу путаницы confm = metrics.confusion_matrix (np.argmax (test_y, ось = 1), np.argmax (test_pre, ось = 1)) печать (конфм)
## 混淆矩阵可视化 Labname = ["体育", "文化", "财经", "游戏"] print(metrics.classification_report(np.argmax(test_y,axis=1),np.argmax(test_pre,axis=1))) plt.figure(figsize=(8,8)) sns.heatmap(confm.T, square=True, annot=True, fmt='d', cbar=False, linewidths=.6, cmap="YlGnBu") plt.xlabel('True label',size = 14) plt.ylabel('Predicted label', size = 14) plt.xticks(np.arange(4)+0.8, Labname, size = 12) plt.yticks(np.arange(4)+0.4, Labname, size = 12) plt.savefig('result.png') plt.show() #----------------------------------第七 验证算法-------------------------- ## 使用tok对验证数据集重新预处理,并使用训练好的模型进行预测 val_seq = tok.texts_to_sequences(val_df.cutword) ## 将每个序列调整为相同的长度 val_seq_mat = sequence.pad_sequences(val_seq,maxlen=max_len) ## 对验证集进行预测 val_pre = model.predict(val_seq_mat) print(metrics.classification_report(np.argmax(val_y,axis=1),np.argmax(val_pre,axis=1))) elapsed = (time.clock() - start) print("Time used:", elapsed)
Модель вывода обучения выглядит следующим образом:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
inputs (InputLayer) (None, 600) 0
_________________________________________________________________
embedding_1 (Embedding) (None, 600, 128) 768128
_________________________________________________________________
cu_dnnlstm_1 (CuDNNLSTM) (None, 128) 132096
_________________________________________________________________
FC1 (Dense) (None, 128) 16512
_________________________________________________________________
dropout_1 (Dropout) (None, 128) 0
_________________________________________________________________
FC2 (Dense) (None, 4) 516
=================================================================
Total params: 917,252
Trainable params: 917,252
Non-trainable params: 0
Прогнозируемые результаты следующие:
[[4539 153 188 120]
[ 47 4628 181 144]
[ 113 133 4697 57]
[ 101 292 157 4450]]
precision recall f1-score support
0 0.95 0.91 0.93 5000
1 0.89 0.93 0.91 5000
2 0.90 0.94 0.92 5000
3 0.93 0.89 0.91 5000
avg / total 0.92 0.92 0.92 20000
precision recall f1-score support
0 0.96 0.89 0.92 5000
1 0.89 0.94 0.92 5000
2 0.90 0.93 0.92 5000
3 0.94 0.92 0.93 5000
avg / total 0.92 0.92 0.92 20000
6. Классификация китайского текста BiLSTM
1. Принцип введения
BiLSTM — это аббревиатура двунаправленной долговременной кратковременной памяти, которая состоит из прямого LSTM и обратного LSTM. И он, и LSTM часто используются для моделирования контекстной информации в задачах обработки естественного языка. Прямой LSTM объединяется с обратным LSTM для формирования BiLSTM. Например, мы кодируем фразу «Я люблю Китай», а модель показана на рисунке.
Также существует проблема из-за моделирования предложений с помощью LSTM: он не может кодировать информацию сзади вперед. В более мелкозернистой классификации, такой как задача с пятью категориями сильно положительного, слабо положительного, нейтрального, слабо отрицательного и сильно отрицательного, необходимо обратить внимание на взаимодействие между эмоциональными словами, словами степени и отрицательными словами. . Например, «Этот ресторан не такой грязный, он не так хорош, как соседний.» «Нет» здесь является модификацией степени «грязности», и BiLSTM может лучше фиксировать двунаправленные семантические зависимости.
- Справочная статья:zhuanlan.zhihu.com/p/47802053
2. Реализация кода
Код BiLSTM для Keras для реализации классификации текста выглядит следующим образом:
-
Keras_BiLSTM_cnews.py
""" Created on 2021-03-19 @author: xiuzhang Eastmount CSDN BiLSTM Model """ import os import time import pickle import pandas as pd import numpy as np from sklearn import metrics import matplotlib.pyplot as plt import seaborn as sns import tensorflow as tf from sklearn.preprocessing import LabelEncoder,OneHotEncoder from keras.models import Model from keras.layers import LSTM, Activation, Dense, Dropout, Input, Embedding from keras.layers import Convolution1D, MaxPool1D, Flatten from keras.preprocessing.text import Tokenizer from keras.preprocessing import sequence from keras.callbacks import EarlyStopping from keras.models import load_model from keras.models import Sequential
#GPU ускорение CuDNNLSTM быстрее, чем LSTM импорт из keras.layers CuDNNLSTM, CuDNNGRU из keras.layers импорт двунаправленный
Обработка GPU. Читатели могут комментировать эту часть кода, если они используют CPU.
Укажите верхний предел видеопамяти, используемой в каждом процессе GPU.0,9 означает, что 90% ресурсов GPU могут использоваться для обучения.
os.environ["CUDA_DEVICES_ORDER"] = "PCI_BUS_IS" os.environ["CUDA_VISIBLE_DEVICES"] = "0" gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
start = time.clock()
#---------------------------- Первый шаг чтения данных---------------- -------------
Чтение тестового набора данных
train_df = pd.read_csv("news_dataset_train_fc.csv") val_df = pd.read_csv("news_dataset_val_fc.csv") test_df = pd.read_csv("news_dataset_test_fc.csv") print(train_df.head())
Решить проблему китайского дисплея
plt.rcParams['font.sans-serif'] = ['KaiTi'] #Укажите шрифт SimHei по умолчанию полужирный plt.rcParams['axes.unicode_minus'] = False #Решение сохранить изображение является отрицательным знаком'
#----------------------------------------------------Второй этап кодирования OneHotEncoder() ---- ------------ ----
Кодировать данные метки набора данных
train_y = train_df.label val_y = val_df.label test_y = test_df.label print("Label:") print(train_y[:10])
le = LabelEncoder() train_y = le.fit_transform(train_y).reshape(-1,1) val_y = le.transform(val_y).reshape(-1,1) test_y = le.transform(test_y).reshape(-1,1) print("LabelEncoder") print(train_y[:10]) print(len(train_y))
Горячее кодирование данных метки набора данных
ohe = OneHotEncoder() train_y = ohe.fit_transform(train_y).toarray() val_y = ohe.transform(val_y).toarray() test_y = ohe.transform(test_y).toarray() print("OneHotEncoder:") print(train_y[:10])
#-----------------------Третий шаг использует Tokenizer для кодирования фразы ---------------- --- макс_слов = 6000 max_len = 600 tok = Tokenizer(num_words=max_words) # Максимальное количество слов 6000 печать (train_df.cutword [: 5]) печать (тип (train_df.cutword))
Предотвратить обработку числовых строк в корпусе
train_content = [str(a) for a in train_df.cutword.tolist()] val_content = [str(a) for a in val_df.cutword.tolist()] test_content = [str(a) for a in test_df.cutword.tolist()] tok.fit_on_texts(train_content) print(tok)
Сохраните обученный токенизатор и импортируйте
with open('tok.pickle', 'wb') as handle: #saving pickle.dump(tok, handle, protocol=pickle.HIGHEST_PROTOCOL) with open('tok.pickle', 'rb') as handle: #loading tok = pickle.load(handle)
#----------------------------Четвертый шаг — преобразовать данные в последовательность----------- ----- -------------- train_seq = tok.texts_to_sequences(train_content) val_seq = tok.texts_to_sequences(val_content) test_seq = tok.texts_to_sequences(test_content)
Настройте каждую последовательность на одинаковую длину
train_seq_mat = sequence.pad_sequences (train_seq, maxlen = max_len) val_seq_mat = sequence.pad_sequences (val_seq, maxlen = max_len) test_seq_mat = sequence.pad_sequences (test_seq, maxlen = max_len) print("Последовательность преобразования данных") печать (train_seq_mat.shape) печать (val_seq_mat.shape) печать (test_seq_mat.shape) печать (train_seq_mat [: 2])
#-------------------------------Шаг 5 Создайте модель BiLSTM------------- -------------- число_меток = 4 модель = Последовательный() model.add(Встраивание(max_words+1, 128, input_length=max_len)) model.add (двунаправленный (CuDNNLSTM (128))) model.add (плотный (128, активация = 'relu')) model.add (Выпадение (0,3)) model.add (Dense (num_labels, активация = 'softmax')) модель.резюме() model.compile(потеря="categorical_crossentropy", оптимизатор='адам', # RMSprop() метрики=["точность"])
#------------------------------- Шаг 6 Обучение модели и прогнозирование ------------ - ---------------
Сначала настройте тренировку, затем настройте тестовую проверку.
флаг = "поезд" если флаг == "поезд": print("Обучение модели") ## обучение модели прекращает обучение, когда val-loss больше не улучшается 0,0001 model_fit = model.fit (train_seq_mat, train_y, batch_size = 128, эпохи = 10, validation_data=(val_seq_mat,val_y), обратные вызовы = [Ранняя остановка (монитор = 'val_loss', min_delta = 0,0001)]
) model.save('my_model.h5')
del model elapsed = (time.clock() - start) print("Time used:", elapsed) print(model_fit.history)еще: print("Предсказание модели") ## Импорт обученной модели модель = load_model('my_model.h5') ## делать прогнозы на тестовом наборе test_pre = model.predict (test_seq_mat) ## Оценить эффект предсказания и вычислить матрицу путаницы confm = metrics.confusion_matrix (np.argmax (test_y, ось = 1), np.argmax (test_pre, ось = 1)) печать (конфм)
## 混淆矩阵可视化 Labname = ["体育", "文化", "财经", "游戏"] print(metrics.classification_report(np.argmax(test_y,axis=1),np.argmax(test_pre,axis=1))) plt.figure(figsize=(8,8)) sns.heatmap(confm.T, square=True, annot=True, fmt='d', cbar=False, linewidths=.6, cmap="YlGnBu") plt.xlabel('True label',size = 14) plt.ylabel('Predicted label', size = 14) plt.xticks(np.arange(4)+0.5, Labname, size = 12) plt.yticks(np.arange(4)+0.5, Labname, size = 12) plt.savefig('result.png') plt.show() #----------------------------------第七 验证算法-------------------------- ## 使用tok对验证数据集重新预处理,并使用训练好的模型进行预测 val_seq = tok.texts_to_sequences(val_df.cutword) ## 将每个序列调整为相同的长度 val_seq_mat = sequence.pad_sequences(val_seq,maxlen=max_len) ## 对验证集进行预测 val_pre = model.predict(val_seq_mat) print(metrics.classification_report(np.argmax(val_y,axis=1),np.argmax(val_pre,axis=1))) elapsed = (time.clock() - start) print("Time used:", elapsed)
Модель выходных данных обучения показана ниже, и время GPU по-прежнему очень быстрое.
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_1 (Embedding) (None, 600, 128) 768128
_________________________________________________________________
bidirectional_1 (Bidirection (None, 256) 264192
_________________________________________________________________
dense_1 (Dense) (None, 128) 32896
_________________________________________________________________
dropout_1 (Dropout) (None, 128) 0
_________________________________________________________________
dense_2 (Dense) (None, 4) 516
=================================================================
Total params: 1,065,732
Trainable params: 1,065,732
Non-trainable params: 0
Train on 40000 samples, validate on 20000 samples
Epoch 1/10
40000/40000 [==============================] - 23s 587us/step - loss: 0.5825 - acc: 0.8038 - val_loss: 0.2321 - val_acc: 0.9246
Epoch 2/10
40000/40000 [==============================] - 21s 521us/step - loss: 0.1433 - acc: 0.9542 - val_loss: 0.2422 - val_acc: 0.9228
Time used: 52.763230400000005
Прогнозируемые результаты показаны на следующем рисунке:
[[4593 143 113 151]
[ 81 4679 60 180]
[ 110 199 4590 101]
[ 73 254 82 4591]]
precision recall f1-score support
0 0.95 0.92 0.93 5000
1 0.89 0.94 0.91 5000
2 0.95 0.92 0.93 5000
3 0.91 0.92 0.92 5000
avg / total 0.92 0.92 0.92 20000
precision recall f1-score support
0 0.94 0.90 0.92 5000
1 0.89 0.95 0.92 5000
2 0.95 0.90 0.93 5000
3 0.91 0.94 0.93 5000
avg / total 0.92 0.92 0.92 20000
7. Классификация китайских текстов BiLSTM+Attention
1. Принцип введения
Механизм «Внимание» — это метод решения проблем, предложенный путем имитации человеческого внимания, проще говоря, заключается в быстром отсеивании ценной информации из большого объема информации. Он в основном используется для решения проблемы, заключающейся в том, что трудно получить окончательное и разумное векторное представление, когда входная последовательность модели LSTM / RNN длинная.Метод состоит в том, чтобы сохранить промежуточные результаты LSTM, изучить его с помощью нового модель и связать ее с выходом, тем самым достигнув цели фильтрации информации.
Что такое внимание?
Сначала кратко опишите, что такое механизм внимания. Я полагаю, что изучающие НЛП не будут сильно незнакомы с этим механизмом, он описан в статье«Внимание — это все, что вам нужно»В задаче машинного перевода это помогло глубокой модели значительно повысить производительность и вывести лучшую модель на тот момент. Конечно, в дополнение к механизму внимания модель также использует множество полезных приемов, помогающих повысить производительность модели. Но нельзя отрицать, что ядром этой модели является внимание.
Механизм внимания также известен как механизм внимания. Как следует из названия, это технология, которая позволяет модели сосредоточиться на важной информации и полностью изучить и усвоить ее. Это не полная модель, а технология, которая может воздействовать на любая модель последовательности.
Почему внимание?
Зачем вводить механизм внимания. Например, в модели seq2seq для текстовой последовательности мы обычно используем какой-то механизм для кодирования последовательности и кодируем ее в вектор фиксированной длины посредством уменьшения размерности, который используется для ввода в следующий полносвязный слой. Как правило, мы будем использовать такие модели, как CNN или RNN (включая GRU или LSTM), для кодирования данных последовательности, а затем использовать различные пулы или напрямую брать скрытое состояние последнего t времени для RNN в качестве векторного вывода предложения.
Но тут будет проблема:Обычные методы кодирования не могут отразить степень внимания к различным морфемам в последовательности предложений. В естественном языке разные части предложения имеют разное значение и важность, как, например, в приведенном выше примере: Я ненавижу этот фильм. Очевидно, что больше внимания следует уделить слову ненависть. Конечно, CNN и RNN могут кодировать эту информацию, но эта возможность кодирования также ограничена.Для более длинных текстов эффект модели не будет слишком улучшен.
- Ссылки и рекомендуемые статьи:zhuanlan.zhihu.com/p/46313756
Внимание имеет широкий спектр приложений, включая текст и изображения.
-
Текст: применяется к моделям seq2seq, наиболее распространенным применением является перевод.
-
Изображение: извлечение изображения в сверточных нейронных сетях
-
голос
На рисунке ниже представлена более классическая модель BiLSTM+Attention, которая также является моделью, которую нам нужно построить дальше.
2. Реализация кода
Код BiLSTM+Attention для Keras для реализации классификации текста выглядит следующим образом:
-
Keras_Attention_BiLSTM_cnews.py
""" Created on 2021-03-19 @author: xiuzhang Eastmount CSDN BiLSTM+Attention Model """ import os import time import pickle import pandas as pd import numpy as np from sklearn import metrics import matplotlib.pyplot as plt import seaborn as sns import tensorflow as tf from sklearn.preprocessing import LabelEncoder,OneHotEncoder from keras.models import Model from keras.layers import LSTM, Activation, Dense, Dropout, Input, Embedding from keras.layers import Convolution1D, MaxPool1D, Flatten from keras.preprocessing.text import Tokenizer from keras.preprocessing import sequence from keras.callbacks import EarlyStopping from keras.models import load_model from keras.models import Sequential
#GPU ускорение CuDNNLSTM быстрее, чем LSTM импорт из keras.layers CuDNNLSTM, CuDNNGRU из keras.layers импорт двунаправленный
Обработка GPU. Читатели могут комментировать эту часть кода, если они используют CPU.
Укажите верхний предел видеопамяти, используемой в каждом процессе GPU.0,9 означает, что 90% ресурсов GPU могут использоваться для обучения.
os.environ["CUDA_DEVICES_ORDER"] = "PCI_BUS_IS" os.environ["CUDA_VISIBLE_DEVICES"] = "0" gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
start = time.clock()
#---------------------------- Первый шаг чтения данных---------------- -------------
Чтение тестового набора данных
train_df = pd.read_csv("news_dataset_train_fc.csv") val_df = pd.read_csv("news_dataset_val_fc.csv") test_df = pd.read_csv("news_dataset_test_fc.csv") print(train_df.head())
Решить проблему китайского дисплея
plt.rcParams['font.sans-serif'] = ['KaiTi'] #Укажите шрифт SimHei по умолчанию полужирный plt.rcParams['axes.unicode_minus'] = False #Решение сохранить изображение является отрицательным знаком'
#----------------------------------------------------Второй этап кодирования OneHotEncoder() ---- ------------ ----
Кодировать данные метки набора данных
train_y = train_df.label val_y = val_df.label test_y = test_df.label print("Label:") print(train_y[:10])
le = LabelEncoder() train_y = le.fit_transform(train_y).reshape(-1,1) val_y = le.transform(val_y).reshape(-1,1) test_y = le.transform(test_y).reshape(-1,1) print("LabelEncoder") print(train_y[:10]) print(len(train_y))
Горячее кодирование данных метки набора данных
ohe = OneHotEncoder() train_y = ohe.fit_transform(train_y).toarray() val_y = ohe.transform(val_y).toarray() test_y = ohe.transform(test_y).toarray() print("OneHotEncoder:") print(train_y[:10])
#-----------------------Третий шаг использует Tokenizer для кодирования фразы ---------------- --- макс_слов = 6000 max_len = 600 tok = Tokenizer(num_words=max_words) # Максимальное количество слов 6000 печать (train_df.cutword [: 5]) печать (тип (train_df.cutword))
Предотвратить обработку числовых строк в корпусе
train_content = [str(a) for a in train_df.cutword.tolist()] val_content = [str(a) for a in val_df.cutword.tolist()] test_content = [str(a) for a in test_df.cutword.tolist()] tok.fit_on_texts(train_content) print(tok)
Сохраните обученный токенизатор и импортируйте
with open('tok.pickle', 'wb') as handle: #saving pickle.dump(tok, handle, protocol=pickle.HIGHEST_PROTOCOL) with open('tok.pickle', 'rb') as handle: #loading tok = pickle.load(handle)
#----------------------------Четвертый шаг — преобразовать данные в последовательность----------- ----- -------------- train_seq = tok.texts_to_sequences(train_content) val_seq = tok.texts_to_sequences(val_content) test_seq = tok.texts_to_sequences(test_content)
Настройте каждую последовательность на одинаковую длину
train_seq_mat = sequence.pad_sequences (train_seq, maxlen = max_len) val_seq_mat = sequence.pad_sequences (val_seq, maxlen = max_len) test_seq_mat = sequence.pad_sequences (test_seq, maxlen = max_len) print("Последовательность преобразования данных") печать (train_seq_mat.shape) печать (val_seq_mat.shape) печать (test_seq_mat.shape) печать (train_seq_mat [: 2])
#---------------------------- Пятый шаг - установить механизм внимания ------------ ---- ------ """ Поскольку в Keras нет готового слоя Attention, который можно было бы использовать напрямую, нам нужно самим создать новую функцию слоя. Пользовательские функции Keras в основном разделены на четыре части, а именно: init: инициализировать некоторые необходимые параметры bulid: как конкретно определить вес вызов: основная часть, определяет, как работает вектор Compute_output_shape: определяет размер вывода этого слоя. рекомендуемая статья:blog.CSDN.net/Мастер Хуан Хао/… zhuanlan.zhihu.com/p/29201491 """
Hierarchical Model with Attention
from keras import initializers from keras import constraints from keras import activations from keras import regularizers from keras import backend as K from keras.engine.topology import Layer
K.clear_session()
class AttentionLayer(Layer): def init(self, attention_size=None, **kwargs): self.attention_size = attention_size super(AttentionLayer, self).init(**kwargs)
def get_config(self): config = super().get_config() config['attention_size'] = self.attention_size return config def build(self, input_shape): assert len(input_shape) == 3 self.time_steps = input_shape[1] hidden_size = input_shape[2] if self.attention_size is None: self.attention_size = hidden_size self.W = self.add_weight(name='att_weight', shape=(hidden_size, self.attention_size), initializer='uniform', trainable=True) self.b = self.add_weight(name='att_bias', shape=(self.attention_size,), initializer='uniform', trainable=True) self.V = self.add_weight(name='att_var', shape=(self.attention_size,), initializer='uniform', trainable=True) super(AttentionLayer, self).build(input_shape) def call(self, inputs): self.V = K.reshape(self.V, (-1, 1)) H = K.tanh(K.dot(inputs, self.W) + self.b) score = K.softmax(K.dot(H, self.V), axis=1) outputs = K.sum(score * inputs, axis=1) return outputs def compute_output_shape(self, input_shape): return input_shape[0], input_shape[2]
#------------------------------- Шестой шаг строит модель BiLSTM------------ - --------------
Определение модели BiLSTM
BiLSTM+Attention
число_меток = 4 входы = ввод (имя = 'входы', форма = [max_len], dtype = 'float64') слой = вложение (max_words + 1, 256, input_length = max_len) (входы) #lstm = двунаправленный (LSTM (100, отсев = 0,2, recurrent_dropout = 0,1, return_sequences = True)) (уровень) bilstm = Bidirectional(CuDNNLSTM(128, return_sequences=True))(layer) #Параметр сохраняет размерность 3 слой = плотный (128, активация = 'relu') (bilstm) слой = отсев (0,2) (слой)
механизм внимания
attention = AttentionLayer(attention_size=50)(layer) output = Dense(num_labels, activation='softmax')(attention) model = Model(inputs=inputs, outputs=output) model.summary() model.compile(loss="categorical_crossentropy", optimizer='adam', # RMSprop() metrics=["accuracy"])
#----------------------------------------------------------- Шаг 7 Обучение модели и предсказание ------------- ---------------
Сначала настройте тренировку, затем настройте тестовую проверку.
флаг = "тест" если флаг == "поезд": print("Обучение модели") ## обучение модели прекращает обучение, когда val-loss больше не улучшается 0,0001 model_fit = model.fit (train_seq_mat, train_y, batch_size = 128, эпохи = 10, validation_data=(val_seq_mat,val_y), обратные вызовы = [Ранняя остановка (монитор = 'val_loss', min_delta = 0,0001)]
) ## сохранить модель модель.сохранить('моя_модель.h5')
del model # удаляет существующую модель ## расчет времени прошедшее = (время.часы() - начало) print("Использовано время:", истекло) печать (model_fit.history)еще: print("Предсказание модели") ## Импорт обученной модели модель = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer(50)}, compile=False) ## делать прогнозы на тестовом наборе test_pre = model.predict (test_seq_mat) ## Оценить эффект предсказания и вычислить матрицу путаницы confm = metrics.confusion_matrix (np.argmax (test_y, ось = 1), np.argmax (test_pre, ось = 1)) печать (конфм)
## 混淆矩阵可视化 Labname = ["体育", "文化", "财经", "游戏"] print(metrics.classification_report(np.argmax(test_y,axis=1),np.argmax(test_pre,axis=1))) plt.figure(figsize=(8,8)) sns.heatmap(confm.T, square=True, annot=True, fmt='d', cbar=False, linewidths=.6, cmap="YlGnBu") plt.xlabel('True label',size = 14) plt.ylabel('Predicted label', size = 14) plt.xticks(np.arange(4)+0.5, Labname, size = 12) plt.yticks(np.arange(4)+0.5, Labname, size = 12) plt.savefig('result.png') plt.show() #----------------------------------第七 验证算法-------------------------- ## 使用tok对验证数据集重新预处理,并使用训练好的模型进行预测 val_seq = tok.texts_to_sequences(val_df.cutword) ## 将每个序列调整为相同的长度 val_seq_mat = sequence.pad_sequences(val_seq,maxlen=max_len) ## 对验证集进行预测 val_pre = model.predict(val_seq_mat) print(metrics.classification_report(np.argmax(val_y,axis=1),np.argmax(val_pre,axis=1))) ## 计算时间 elapsed = (time.clock() - start) print("Time used:", elapsed)
Модель вывода обучения выглядит следующим образом:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
inputs (InputLayer) (None, 600) 0
_________________________________________________________________
embedding_1 (Embedding) (None, 600, 256) 1536256
_________________________________________________________________
bidirectional_1 (Bidirection (None, 600, 256) 395264
_________________________________________________________________
dense_1 (Dense) (None, 600, 128) 32896
_________________________________________________________________
dropout_1 (Dropout) (None, 600, 128) 0
_________________________________________________________________
attention_layer_1 (Attention (None, 128) 6500
_________________________________________________________________
dense_2 (Dense) (None, 4) 516
=================================================================
Total params: 1,971,432
Trainable params: 1,971,432
Non-trainable params: 0
Прогнозируемые результаты показаны на следующем рисунке:
[[4625 138 100 137]
[ 63 4692 77 168]
[ 129 190 4589 92]
[ 82 299 78 4541]]
precision recall f1-score support
0 0.94 0.93 0.93 5000
1 0.88 0.94 0.91 5000
2 0.95 0.92 0.93 5000
3 0.92 0.91 0.91 5000
avg / total 0.92 0.92 0.92 20000
precision recall f1-score support
0 0.95 0.91 0.93 5000
1 0.88 0.95 0.91 5000
2 0.95 0.90 0.92 5000
3 0.92 0.93 0.93 5000
avg / total 0.92 0.92 0.92 20000
Нажмите «Подписаться», чтобы впервые узнать о новых технологиях HUAWEI CLOUD~