Введение в LSTM
Сериализованные данные означают, что каждый образец связан с его предыдущими образцами, а предыдущие данные имеют отношения порядка со следующими данными. Обработке таких данных посвящена важная ветвь глубокого обучения — рекуррентные нейронные сети. Рекуррентные нейронные сети широко используются в области обработки естественного языка (NLP).Сегодня мы возьмем вас с практического примера, чтобы представить важную улучшенную модель алгоритма рекуррентных нейронных сетей - LSTM. Эта статья не углубляется в принцип LSTM, Если вы хотите узнать больше о LSTM, вы можете обратиться к этой статье[Перевод] Понимание сетей LSTM. Эта статья фокусируется на примере автоматического создания древних стихов и шаг за шагом проведет вас от обработки данных к построению модели, к обучению модели поколения древних стихов и, наконец, к реализации автоматического создания стихов благословения китайского Нового года из древних стихов. .
обработка данных
Мы используем 76748 древних стихов в качестве набора данных, набор данныхссылка для скачивания, форма хранения оригинальных старинных стихов такова:
Мы видим, что оригинальные древние стихи имеют форму текстовых символов, которые не могут быть непосредственно изучены с помощью машинного обучения, поэтому наш первый шаг должен преобразовать текстовую информацию в форму данных.Этот метод преобразования называется встраиванием слов.Мы используем A широко используемый алгоритм встраивания слов - Word2vec кодирует древние стихи. О Word2Vec здесь подробно не рассказывается, если вам интересно, вы можете обратиться к[НЛП] Поймите суть вектора слов Word2vec за секунды. В процессе вложения слов, чтобы избежать слишком большого конечного числа классификаций, вы можете удалить слова, которые появляются реже, например, вы можете удалить слова, которые появляются только один раз. После обучения алгоритма Word2vec будет сгенерирован файл модели, и мы можем использовать этот файл модели для выполнения кодирования вложения слов в тексте древней поэзии.После первого этапа обработки древние стихи и слова были преобразованы в цифровые формы, которые можно смоделировать с помощью машинного обучения.Поскольку мы используем алгоритм LSTM для создания древних стихов, нам также необходимо построить процесс отображения от ввода до вывода. Например: «[Закат на Лонг-Ривер в йенах]» как train_data, а соответствующая метка train_label — «Закат на Лонг-Ривер в йенах]]», то есть «[» -> «Чанг», «Чанг» -> «Река», « Река" -> "падение", "падение" -> "день", "день" -> "круг", "круг" -> "]", "]" -> "]", таким образом, один за другим один по порядку. Это также важная особенность рекуррентных нейронных сетей. Здесь «[» и «]» — это начальный и конечный символы, которые используются для создания маркеров начала и конца древних стихов.
Обобщите этапы обработки данных:
- Прочтите оригинальный текст древней поэзии, сосчитайте все разные слова и используйте алгоритм Word2Vec для соответствующей кодировки;
- Для каждого стихотворения преобразовать каждое слово и пунктуацию в соответствующее число в словаре, чтобы сформировать входные данные train_data нейронной сети;
- Переместите входные данные влево, чтобы сформировать выходную метку train_label;
После обработки данных получаем следующие файлы данных:
- стихотворения_edge_split.txt: исходный файл древней поэзии, упорядоченный по строкам, каждая строка представляет собой стихотворение;
- vectors_poem.bin: модель вектора слов, обученная Word2Vec, начинается с частоты слова и удаляет низкочастотные слова;
- поэма_ids.txt: файл корпуса после сопоставления и обработки в соответствии с отношением ввода-вывода;
- rhyme_words.txt: хранилище рифмованных слов, используемое для создания рифмованных стихотворений;
Вышеупомянутые четыре файла данных были предоставлены в предоставленном исходном коде и помещены в папку данных Код обработки данных см. в файле data_loader.py.Исходная ссылка
Построение модели и обучение
Здесь мы используем двухуровневую структуру LSTM со скрытыми узлами слоя 128 на каждом уровне.Мы используем библиотеку модулей tensorflow.nn для определения слоя сетевой структуры, где RNNcell является базовой единицей для реализации RNN в тензорном потоке.Это абстрактный класс. и используется в практических приложениях.В TensorFlow используются подклассы реализации RNNcell, BasicRNNCell или BasicLSTMCell, BasicGRUCell, если нужно построить многослойную RNN, в TensorFlow можно использовать функцию tf.nn.rnn_cell.MultiRNNCell чтобы сложить RNNCell. Первый слой модельной сети должен встраивать входные данные, что можно понимать как преобразование данных по измерениям.После двух слоев LSTM softMax получает выходную вероятность для полного словаря. Структура модели сети выглядит следующим образом:
Код программы для класса, определяющего сеть, выглядит следующим образом:
class CharRNNLM(object):
def __init__(self, is_training, batch_size, vocab_size, w2v_model,
hidden_size, max_grad_norm, embedding_size, num_layers,
learning_rate, cell_type, dropout=0.0, input_dropout=0.0, infer=False):
self.batch_size = batch_size
self.hidden_size = hidden_size
self.vocab_size = vocab_size
self.max_grad_norm = max_grad_norm
self.num_layers = num_layers
self.embedding_size = embedding_size
self.cell_type = cell_type
self.dropout = dropout
self.input_dropout = input_dropout
self.w2v_model = w2v_model
if embedding_size <= 0:
self.input_size = vocab_size
self.input_dropout = 0.0
else:
self.input_size = embedding_size
# 输入和输入定义
self.input_data = tf.placeholder(tf.int64, [self.batch_size, self.num_unrollings], name='inputs')
self.targets = tf.placeholder(tf.int64, [self.batch_size, self.num_unrollings], name='targets')
# 根据定义选择不同的循环神经网络内核单元
if self.cell_type == 'rnn':
cell_fn = tf.nn.rnn_cell.BasicRNNCell
elif self.cell_type == 'lstm':
cell_fn = tf.nn.rnn_cell.LSTMCell
elif self.cell_type == 'gru':
cell_fn = tf.nn.rnn_cell.GRUCell
params = dict()
if self.cell_type == 'lstm':
params['forget_bias'] = 1.0
cell = cell_fn(self.hidden_size, **params)
cells = [cell]
for i in range(self.num_layers-1):
higher_layer_cell = cell_fn(self.hidden_size, **params)
cells.append(higher_layer_cell)
# 训练时是否进行 Dropout
if is_training and self.dropout > 0:
cells = [tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=1.0-self.dropout) for cell in cells]
# 对lstm层进行堆叠
multi_cell = tf.nn.rnn_cell.MultiRNNCell(cells)
# 定义网络模型初始状态
with tf.name_scope('initial_state'):
self.zero_state = multi_cell.zero_state(self.batch_size, tf.float32)
if self.cell_type == 'rnn' or self.cell_type == 'gru':
self.initial_state = tuple(
[tf.placeholder(tf.float32,
[self.batch_size, multi_cell.state_size[idx]],
'initial_state_'+str(idx+1)) for idx in range(self.num_layers)])
elif self.cell_type == 'lstm':
self.initial_state = tuple(
[tf.nn.rnn_cell.LSTMStateTuple(
tf.placeholder(tf.float32, [self.batch_size, multi_cell.state_size[idx][0]],
'initial_lstm_state_'+str(idx+1)),
tf.placeholder(tf.float32, [self.batch_size, multi_cell.state_size[idx][1]],
'initial_lstm_state_'+str(idx+1)))
for idx in range(self.num_layers)])
# 定义 embedding 层
with tf.name_scope('embedding_layer'):
if embedding_size > 0:
# self.embedding = tf.get_variable('embedding', [self.vocab_size, self.embedding_size])
self.embedding = tf.get_variable("word_embeddings",
initializer=self.w2v_model.vectors.astype(np.float32))
else:
self.embedding = tf.constant(np.eye(self.vocab_size), dtype=tf.float32)
inputs = tf.nn.embedding_lookup(self.embedding, self.input_data)
if is_training and self.input_dropout > 0:
inputs = tf.nn.dropout(inputs, 1-self.input_dropout)
# 创建每个切分通道网络层
with tf.name_scope('slice_inputs'):
sliced_inputs = [tf.squeeze(input_, [1]) for input_ in tf.split(
axis = 1, num_or_size_splits = self.num_unrollings, value = inputs)]
outputs, final_state = tf.nn.static_rnn(
cell = multi_cell,
inputs = sliced_inputs,
initial_state=self.initial_state)
self.final_state = final_state
# 数据变换层,把经过循环神经网络的数据拉伸降维
with tf.name_scope('flatten_outputs'):
flat_outputs = tf.reshape(tf.concat(axis = 1, values = outputs), [-1, hidden_size])
with tf.name_scope('flatten_targets'):
flat_targets = tf.reshape(tf.concat(axis = 1, values = self.targets), [-1])
# 定义 softmax 输出层
with tf.variable_scope('softmax') as sm_vs:
softmax_w = tf.get_variable('softmax_w', [hidden_size, vocab_size])
softmax_b = tf.get_variable('softmax_b', [vocab_size])
self.logits = tf.matmul(flat_outputs, softmax_w) + softmax_b
self.probs = tf.nn.softmax(self.logits)
# 定义 loss 损失函数
with tf.name_scope('loss'):
loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
logits = self.logits, labels = flat_targets)
self.mean_loss = tf.reduce_mean(loss)
# tensorBoard 损失函数可视化
with tf.name_scope('loss_montor'):
count = tf.Variable(1.0, name='count')
sum_mean_loss = tf.Variable(1.0, name='sum_mean_loss')
self.reset_loss_monitor = tf.group(sum_mean_loss.assign(0.0),
count.assign(0.0), name='reset_loss_monitor')
self.update_loss_monitor = tf.group(sum_mean_loss.assign(sum_mean_loss+self.mean_loss),
count.assign(count+1), name='update_loss_monitor')
with tf.control_dependencies([self.update_loss_monitor]):
self.average_loss = sum_mean_loss / count
self.ppl = tf.exp(self.average_loss)
average_loss_summary = tf.summary.scalar(
name = 'average loss', tensor = self.average_loss)
ppl_summary = tf.summary.scalar(
name = 'perplexity', tensor = self.ppl)
self.summaries = tf.summary.merge(
inputs = [average_loss_summary, ppl_summary], name='loss_monitor')
self.global_step = tf.get_variable('global_step', [], initializer=tf.constant_initializer(0.0))
self.learning_rate = tf.placeholder(tf.float32, [], name='learning_rate')
if is_training:
tvars = tf.trainable_variables()
grads, _ = tf.clip_by_global_norm(tf.gradients(self.mean_loss, tvars), self.max_grad_norm)
optimizer = tf.train.AdamOptimizer(self.learning_rate)
self.train_op = optimizer.apply_gradients(zip(grads, tvars), global_step=self.global_step)
Во время обучения вы можете определить значение batch_size и выполнять отсев или нет.Для разнообразия результатов во время обучения символы с вероятностью topK могут выбираться в качестве вывода каждый раз в выходном слое softmax. После обучения вы можете использовать tensorboard для визуализации структуры сети и процесса обучения. Здесь мы рекомендуем онлайн-платформу моделирования искусственного интеллекта.momodel.cn, с полной средой выполнения Python и платформы машинного обучения, а также доступны бесплатные графические процессоры, вы можете попробовать его на этой платформе, когда сможете потренироваться. Код обучающей части и обученной модели см.Ссылка на сайт.
Поэзия поколения
Вызвав предварительно обученную модель, мы можем реализовать приложение древней поэзии, я использую его здесь.Мо платформаРеализована функция автоматического создания тибетских головных стихов и тибетских подстихов, и эффект от операции следующий:
Посмотреть полный код на стороне ПК
Справочная статья:woo woo. Краткое описание.com/afraid/9 9 41 0 на этом… zhuanlan.zhihu.com/p/26306795 GitHub.com/ни ребенок/сломанный…————————————————————————————————————— Мо (URL:momodel.cn) — это платформа моделирования искусственного интеллекта, поддерживающая Python, которая может помочь вам быстро разрабатывать, обучать и развертывать приложения ИИ.