предисловие
Сверточная нейронная сеть (CNN) добилась больших успехов в области обработки изображений.Его структура свертки и объединения может очень хорошо извлекать информацию изображений, в то время как в области НЛП больше используется рекуррентная нейронная сеть (RNN), RNN и их различные варианты лучше обрабатывают контекст из-за их возможностей памяти. Но многие аспекты области NLP достигли отличных результатов с использованием CNN, таких как такие задачи, как семантический анализ, поиск запросов и классификация текста. В этом посте рассматривается, как использовать CNN для классификации текста.
Структура модели
Структуру модели можно увидеть послойно на рисунке ниже, который состоит в общей сложности из 4 частей, включая входной слой, слой свертки, слой объединения и полностью связанный слой.
входной слой
Крайняя левая часть рисунка — это входной слой, в общем случае входной слой — это матрица, соответствующая предложению. Как правило, горячие векторы не используются для представления слов, но используются k-мерные распределенные векторы слов. Затем для предложения длины n формируется матрица размера n×k.
Следовательно, можно установить— i-е слово предложения, представляющее собой k-мерный вектор. Тогда предложение,возначает конкатенацию.
Кроме того, по влиянию на вектор слова его можно разделить на два режима: статический и нестатический. Статический режим означает, что я напрямую использую вектор слов, выпущенный третьей стороной, или вектор слов, который я сам обучил для инициализации матрицы, и это не влияет на обратное распространение ошибки во время каждого процесса обучения, не изменяет вектор слов и вектор слова на протяжении всего тренировочного процесса. Нестатический режим отличается.После того, как вектор слов также используется для инициализации матрицы, в каждом последующем процессе обучения вектор слов будет точно настроен в соответствии с обратным распространением ошибки, и вектор слов будет обновляться на протяжении всего обучения. процесс.
сверточный слой
Вторая часть рисунка — это слой свертки, который используется для извлечения признаков предложений. В основном через ядро свертки размером h × k w скользит сверху вниз во входном слое для выполнения операции свертки и получения карты признаков посредством операции свертки. Столбец карты признаков равен 1, а поведение равно (n-h+1), т.е.,в.
Красный прямоугольник на входном слое на рисунке выше — это ядро свертки операции свертки, Видно, что оно имеет размерность 2 × k и становится элементом карты объектов после операции. Кроме того, h также может быть установлено равным 3, и ядро свертки становится размером 3 × k, как показано в желтой рамке на рисунке. Одно и то же измерение может иметь несколько ядер свертки с разными параметрами, поэтому в итоге можно получить несколько карт признаков в каждом измерении.
Каково значение операции свертки? Видно, что он фактически извлекает признаки соседних слов разной длины в соответствии с размером h, что на самом деле может соответствовать языковой модели n-грамм.
объединяющий слой
Третья часть на рисунке — это слой пула, Функция слоя пула состоит в дальнейшем извлечении функций и извлечении наиболее важных функций. Здесь используется операция max-over-time pooling, то есть максимальное значение в карте признаков берется как самый важный признак, то есть. Таким образом, в конце концов, после объединения каждой карты признаков получается одномерный вектор.Принятие максимального значения в качестве признака также решает проблему разной длины предложений.Хотя короткие предложения будут заполнены 0, эта проблема устраняется принимает максимальное значение. .
Предыдущие несколько карт объектов получаются с помощью нескольких различных операций ядра свертки в слое свертки, а затем после обработки слоем объединения получаются несколько одномерных векторов.
полносвязный слой
Последняя часть рисунка — полносвязный слой, который получает вероятность каждой классификации с помощью классификатора softmax. Выходные данные предыдущего слоя пула полностью связаны со слоем softmax, который определяет классификацию.
предотвратить переоснащение
Чтобы предотвратить переобучение, в предпоследнем слое во время обучения используется метод отсева, который случайным образом удаляет некоторые узлы скрытого слоя, чтобы он не работал. Конкретный метод может заключаться в том, чтобы установить некоторые узлы в 0, когда сеть передает вперед, например, на предпоследнем уровне,, здесь мы предполагаем, что у нас есть m ядер свертки. После прохождения отсева,,вИ 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»
Добро пожаловать, чтобы следовать: