Сверточные нейронные сети для классификации текста

искусственный интеллект Нейронные сети NLP Java
Сверточные нейронные сети для классификации текста

предисловие

Сверточная нейронная сеть (CNN) добилась больших успехов в области обработки изображений.Его структура свертки и объединения может очень хорошо извлекать информацию изображений, в то время как в области НЛП больше используется рекуррентная нейронная сеть (RNN), RNN и их различные варианты лучше обрабатывают контекст из-за их возможностей памяти. Но многие аспекты области NLP достигли отличных результатов с использованием CNN, таких как такие задачи, как семантический анализ, поиск запросов и классификация текста. В этом посте рассматривается, как использовать CNN для классификации текста.

Структура модели

Структуру модели можно увидеть послойно на рисунке ниже, который состоит в общей сложности из 4 частей, включая входной слой, слой свертки, слой объединения и полностью связанный слой.

这里写图片描述

входной слой

Крайняя левая часть рисунка — это входной слой, в общем случае входной слой — это матрица, соответствующая предложению. Как правило, горячие векторы не используются для представления слов, но используются k-мерные распределенные векторы слов. Затем для предложения длины n формируется матрица размера n×k.

Следовательно, можно установитьx_i— i-е слово предложения, представляющее собой k-мерный вектор. Тогда предложениеx_{1:n}=x_1 \bigoplus x_2 \bigoplus ...\bigoplus x_n\bigoplusозначает конкатенацию.

Кроме того, по влиянию на вектор слова его можно разделить на два режима: статический и нестатический. Статический режим означает, что я напрямую использую вектор слов, выпущенный третьей стороной, или вектор слов, который я сам обучил для инициализации матрицы, и это не влияет на обратное распространение ошибки во время каждого процесса обучения, не изменяет вектор слов и вектор слова на протяжении всего тренировочного процесса. Нестатический режим отличается.После того, как вектор слов также используется для инициализации матрицы, в каждом последующем процессе обучения вектор слов будет точно настроен в соответствии с обратным распространением ошибки, и вектор слов будет обновляться на протяжении всего обучения. процесс.

сверточный слой

Вторая часть рисунка — это слой свертки, который используется для извлечения признаков предложений. В основном через ядро ​​​​свертки размером h × k w скользит сверху вниз во входном слое для выполнения операции свертки и получения карты признаков посредством операции свертки. Столбец карты признаков равен 1, а поведение равно (n-h+1), т.е.c=(c_1,c_2,...c_{n-h+1})c_i=f(w \cdot x_{i:i+h-1}+b).

Красный прямоугольник на входном слое на рисунке выше — это ядро ​​​​свертки операции свертки, Видно, что оно имеет размерность 2 × k и становится элементом карты объектов после операции. Кроме того, h также может быть установлено равным 3, и ядро ​​свертки становится размером 3 × k, как показано в желтой рамке на рисунке. Одно и то же измерение может иметь несколько ядер свертки с разными параметрами, поэтому в итоге можно получить несколько карт признаков в каждом измерении.

Каково значение операции свертки? Видно, что он фактически извлекает признаки соседних слов разной длины в соответствии с размером h, что на самом деле может соответствовать языковой модели n-грамм.

объединяющий слой

Третья часть на рисунке — это слой пула, Функция слоя пула состоит в дальнейшем извлечении функций и извлечении наиболее важных функций. Здесь используется операция max-over-time pooling, то есть максимальное значение в карте признаков берется как самый важный признак, то есть\widehat{c} = max\{c\}. Таким образом, в конце концов, после объединения каждой карты признаков получается одномерный вектор.Принятие максимального значения в качестве признака также решает проблему разной длины предложений.Хотя короткие предложения будут заполнены 0, эта проблема устраняется принимает максимальное значение. .

Предыдущие несколько карт объектов получаются с помощью нескольких различных операций ядра свертки в слое свертки, а затем после обработки слоем объединения получаются несколько одномерных векторов.

полносвязный слой

Последняя часть рисунка — полносвязный слой, который получает вероятность каждой классификации с помощью классификатора softmax. Выходные данные предыдущего слоя пула полностью связаны со слоем softmax, который определяет классификацию.

предотвратить переоснащение

Чтобы предотвратить переобучение, в предпоследнем слое во время обучения используется метод отсева, который случайным образом удаляет некоторые узлы скрытого слоя, чтобы он не работал. Конкретный метод может заключаться в том, чтобы установить некоторые узлы в 0, когда сеть передает вперед, например, на предпоследнем уровне,z=[\widehat{c}_1,\widehat{c}_2...,\widehat{c}_m], здесь мы предполагаем, что у нас есть m ядер свертки. После прохождения отсева,y=w\cdot(z\circ r)+b\circИ r реализует функцию маски, то есть r является вектором того же размера, что и z, и его значение случайное 0 или 1, а узел, соответствующий 0, является отброшенным узлом.

В то же время регуляризация L2 также может использоваться в полносвязном слое для ограничения весового вектора w.

Основной код реализации

Построить график

Во-первых, создайте необходимые заполнители и константы, где заполнители включают заполнители ввода, заполнители меток, заполнители исключения и константы регулярных потерь L2.

train_inputs = tf.placeholder(tf.int32, [None, sequence_length])
train_labels = tf.placeholder(tf.float32, [None, classes_num])
keep_prob = tf.placeholder(tf.float32)
l2_loss = tf.constant(0.0)

Затем нам понадобится слой встраивания для встраивания словаря в указанное пространство измерений, размерность задается embedding_size. В то же время размер_словаря — это размер словаря, чтобы все слова можно было сопоставить с указанным пространством измерений. Встраивание слоя черезtf.nn.embedding_lookupВы можете найти вектор пространства слов, соответствующий вводу, вот небольшое объяснениеembedding_lookupОперация, он получит вектор слова, соответствующий каждому элементу входных данных из словаря.Если входные данные двумерные, после этой операции он станет трехмерным, потому что слово было представлено размерным вектором embedding_size. Кроме того, поскольку вызывается операция свертки, здесь результат расширяется на одно измерение.

with tf.device('/cpu:0'):
    embeddings = tf.Variable(tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
    embed = tf.nn.embedding_lookup(embeddings, train_inputs)
    conv_inputs = tf.expand_dims(embed, -1)

Затем начните выполнять операцию свертки и операцию объединения. Поскольку мы определим несколько ядер свертки, а каждая высота имеет несколько ядер свертки, мы получим много разных карт признаков, а затем выполним операции объединения по максимальному времени на этих картах признаков и, наконец, получим пул Преобразованный признак.

features_pooled = []
for filter_height, filter_num in zip(filters_height, filter_num_per_height):
    conv_filter = tf.Variable(tf.truncated_normal([filter_height, embedding_size, 1, filter_num], stddev=0.1))
    conv = tf.nn.conv2d(conv_inputs, conv_filter, strides=[1, 1, 1, 1], padding="VALID")
    bias = tf.Variable(tf.constant(0.1, shape=[filter_num]))
    feature_map = tf.nn.relu(tf.nn.bias_add(conv, bias))
    feature_pooled = tf.nn.max_pool(feature_map, ksize=[1, sequence_length - filter_height + 1, 1, 1],
                                        strides=[1, 1, 1, 1],
                                        padding='VALID')
    features_pooled.append(feature_pooled)

Теперь сеть остается с полностью подключенным слоем, в котором выполняется операция отсева для временного отключения некоторых узлов, а затем выполняется линейный расчет для получения оценки для получения прогноза.

filter_num_total = sum(filter_num_per_height)
features_pooled_flat = tf.reshape(tf.concat(features_pooled, 3), [-1, filter_num_total])
features_pooled_flat_drop = tf.nn.dropout(features_pooled_flat, keep_prob)
W = tf.get_variable("W", shape=[filter_num_total, classes_num], initializer=tf.contrib.layers.xavier_initializer())
b = tf.Variable(tf.constant(0.1, shape=[classes_num]))
scores = tf.nn.xw_plus_b(features_pooled_flat_drop, W, b)

Наконец, вычисляются потери, одна из которых — обычная потеря L2, а другая — потеря перекрестной энтропии, и общая потеря получается через две. и рассчитать точность.

l2_loss += tf.nn.l2_loss(W)
l2_loss += tf.nn.l2_loss(b)
losses = tf.nn.softmax_cross_entropy_with_logits(logits=scores, labels=train_labels)
loss = tf.reduce_mean(losses) + l2_lambda * l2_loss
predictions = tf.argmax(scores, 1)
correct_predictions = tf.equal(predictions, tf.argmax(train_labels, 1))
accuracy = tf.reduce_mean(tf.cast(correct_predictions, "float"))

github

Полный код прикреплен на github.

https://github.com/sea-boat/nlp_lab/tree/master/cnn_text_classify

reference

Convolutional Neural Networks for Sentence Classification

------------- Рекомендуем прочитать ------------

Резюме моей статьи за 2017 год — машинное обучение

Краткое изложение моих статей за 2017 год — Java и промежуточное ПО

Резюме моих статей 2017 года — глубокое обучение

Краткое изложение моих статей за 2017 год — исходный код JDK

Резюме моей статьи за 2017 год — обработка естественного языка

Резюме моих статей 2017 года — Java Concurrency

------------------рекламное время----------------

Планета знаний: путешествие по океану

Меню официальной учетной записи было разделено на «распределенное», «машинное обучение», «глубокое обучение», «НЛП», «глубина Java», «ядро параллелизма Java», «исходный код JDK», «ядро Tomcat», и т.д. Там может быть один стиль, чтобы удовлетворить ваш аппетит.

Зачем писать «Анализ проектирования ядра Tomcat»

Добро пожаловать, чтобы следовать:

这里写图片描述