Эта статья взята изLoveMIss-Y, адрес блога:blog.CSDN.net/QQ_27825451…Помогает увидеть реальный механизм работы RNN
предисловие: очень просто и удобно использовать текущую основную среду глубокого обучения для реализации рекуррентной нейронной сети, поэтому мы можем много раз забывать, как анализировать нейронную сеть.входить,выводЧто это такое и какое так называемое состояние поддерживается между каждым узлом уровня петли? Эта статья требует базовых знаний рекуррентных нейронных сетей и некоторых базовых теорий, вы можете обратиться к двум моим предыдущим статьям:
Первоначальная цель написания этой статьи состоит в том, что я прочитал много сообщений в блогах, многие из которых перепечатаны,Есть несколько оригинальных, которые объясняют некоторые основные реализации, но они кажутся двусмысленными и не включают в себя очень подробные места (также очень вероятно, что это написал кто-то другой, и я не могу этого понять)., поэтому я решил написать его сам, в этой статье речь идет только об одном моменте, то есть о циклической нейронной сети每一个cell的输出和它们之间的状态到底是什么样子的
,为什么是这个样子
, Ввиду ограниченного уровня есть неточности, и надеюсь найдутся большие братья, которые меня поправят.Эта статья основана на tensorflow.
1. Базовая структура RNN
2. Пример для полного понимания проблемы «размерности» вывода и состояния.
(1) Шаг 1: Создайте выборку обучающих данных X
(2) Шаг 2: Создайте структуру рабочего графа
(3) Шаг 3. Постройте график и протестируйте его.
3. Анализ текущих результатов программы
4. Сводка выходного значения RNN и значения состояния
Пять: добавить,
1. Базовая структура RNN
Вы можете увидеть такую структурную схему во многих книгах или блогах, например:
Конечно, в этом нет ничего плохого, но недостаток в том, что эта картина чрезмерно доработана, слишком абстрактна и непроста для понимания.Что мне делать?Я сделал эскиз на черновике здесь, который мне удобнее понять. :
Картина не очень хорошая, но раздел описания ниже дает более подробное объяснение.
- Фактически, вначале я боролся с тем, была ли внутренняя операция конкатенирована напрямую (mul(concat(input, state), W)+b) или после матричной операции (input * Wi + state * Ws) Вышеупомянутый процесс уже может объяснить мой вопрос, очевидно, что это последний, а также есть открытие, что количество единиц в состоянии и скрытом слое совпадает.
- На рисунке хорошо видны данные batch_size.После ввода rnn для расчета получен результат
[batch_size,max_length,vocab_size]
Результат последовательности и[batch_size,vocab_size]
Статус результат
2. Пример для полного понимания проблемы «размерности» вывода и состояния.
В этой статье используется структура tensorflow, версией которой является функция dynamic_rnn() в tensorflow 1.9. Зачем использовать эту функцию? В предыдущей статье уже подробно объяснялось.
(1) Шаг 1: Создайте выборку обучающих данных X
import tensorflow as tf
import numpy as np
import pprint
train_X = np.array([
[[0, 1, 2], [9, 8, 7],[3,6,8]],
[[3, 4, 5], [1, 3, 5],[6,2,9]],
[[6, 7, 8], [6, 5, 4],[1,7,4]],
[[9, 0, 1], [3, 7, 4],[5,8,2]],
])
'''
样本数据为(samples,timesteps,features)的形式,
其中samples=4,timesteps=3,features=3
'''
(2) Шаг 2: Создайте структуру рабочего графа
#创建一个容纳训练数据的placeholder
X=tf.placeholder(tf.float32,shape=[None,3,3])
# tensorflow处理变长时间序列的处理方式,首先每一个循环的cell里面有5个神经元
basic_cell=tf.nn.rnn_cell.BasicRNNCell(num_units=5)
#使用dynamic_rnn创建一个动态计算的RNN
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
(3) Шаг 3. Постройте график и протестируйте его.
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
outputs_val, states_val = sess.run(
[outputs, states], feed_dict={X:train_X})
pprint.pprint(outputs_val) #打印输出值和状态值
pprint.pprint(states_val)
print('==============================================')
print(np.shape(outputs_val)) 查看输出值和状态的维度
print(np.shape(states_val))
print('++++++++++++++++++++++++++++++++++++++++++++++++')
print(basic_cell.state_size)
print(basic_cell.output_size)
3. Анализ текущих результатов программы
Результат работы программы следующий:
array([
[[-0.6108298 , 0.0596378 , -0.37820065, 0.3211917 ,0.56089014],
[-0.99999994, 0.9993362 , 0.9778955 , 0.5386584 ,-0.9203638],
[-0.9997577 , 0.9915552 , -0.9343918 , -0.24285667,0.63978183]],
[[-0.9990114 , 0.9177295 , -0.06776464, 0.6655134 ,0.4589014 ],
[-0.98075587, 0.53816617, -0.05612217, -0.24713938,0.48741972],
[-0.99997896, -0.47020257, 0.9985639 , 0.99964374,0.99789286]],
[[-0.999998 , 0.9958609 , 0.2563717 , 0.85442424,0.34319228],
[-0.9999506 , 0.9972327 , 0.8965514 , -0.5725894 ,-0.9418285],
[-0.98404294, 0.99636745, -0.99936426, -0.98879707,-0.83194304]],
[[-0.99995047, 0.92161566, 0.9999575 , 0.9958721 ,-0.23263188],
[-0.99924177, 0.9996709 , -0.97150767, -0.9945894 ,-0.991192 ],
[-0.99982065, 0.99869967, -0.8663484 , -0.98502225,-0.98442185]]], dtype=float32)
array([[-0.9997577 , 0.9915552 , -0.9343918 , -0.24285667, 0.63978183],
[-0.99997896, -0.47020257, 0.9985639 , 0.99964374, 0.99789286],
[-0.98404294, 0.99636745, -0.99936426, -0.98879707, -0.83194304],
[-0.99982065, 0.99869967, -0.8663484 , -0.98502225, -0.98442185]],
dtype=float32)
==============================================
(4, 3, 5)
(4, 5)
++++++++++++++++++++++++++++++++++++++++++++++++
5
5
С помощью вышеуказанного теста мы обнаружили, что:
Размерность выходного значения Y равна (4,3,5). Почему? Приведенная выше рукописная диаграмма уже объяснила;
Размерность значения состояния S равна (4, 5), что также было объяснено выше,
Теоретически Y и S должны быть одинаковыми, но определение этого состояния в тензорном потоке состоит в том, что выход выше последнего временного шага равен S. Из приведенных выше результатов также видно, что последний выход каждого выходного вектора y A равен равно S и обозначается следующим образом:
array([
[[-0.6108298 , 0.0596378 , -0.37820065, 0.3211917 ,0.56089014],
[-0.99999994, 0.9993362 , 0.9778955 , 0.5386584 ,-0.9203638],
[-0.9997577 , 0.9915552 , -0.9343918 , -0.24285667,0.63978183]],
[[-0.9990114 , 0.9177295 , -0.06776464, 0.6655134 ,0.4589014 ],
[-0.98075587, 0.53816617, -0.05612217, -0.24713938,0.48741972],
[-0.99997896, -0.47020257, 0.9985639 , 0.99964374,0.99789286]],
[[-0.999998 , 0.9958609 , 0.2563717 , 0.85442424,0.34319228],
[-0.9999506 , 0.9972327 , 0.8965514 , -0.5725894 ,-0.9418285],
[-0.98404294, 0.99636745, -0.99936426, -0.98879707,-0.83194304]],
[[-0.99995047, 0.92161566, 0.9999575 , 0.9958721 ,-0.23263188],
[-0.99924177, 0.9996709 , -0.97150767, -0.9945894 ,-0.991192 ],
[-0.99982065, 0.99869967, -0.8663484 , -0.98502225,-0.98442185]]], dtype=float32)
array([[-0.9997577 , 0.9915552 , -0.9343918 , -0.24285667, 0.63978183],
[-0.99997896, -0.47020257, 0.9985639 , 0.99964374, 0.99789286],
[-0.98404294, 0.99636745, -0.99936426, -0.98879707, -0.83194304],
[-0.99982065, 0.99869967, -0.8663484 , -0.98502225, -0.98442185]],
dtype=float32)
В-четвертых, сводка RNN
Резюме этой статьи основано на dynamic_rnn тензорного потока, но это существенное отражение процесса работы RNN, который является универсальным.
Заключение Резюме:
(1)Выходное измерение RNN, размерность output_Y (выборки, временные шаги, число_единиц)
(2)Размерность состояния RNN, размерность output_S (выборки, число_единиц)
Обратите внимание, что output_S и output_Y по сути одинаковы, за исключением того, что состояние в середине искусственной RNN передается между ячейками RNN, а выхода нет, поэтому оно считается не выходным значением, а состоянием выше последний временной шаг используется в качестве выходного состояния.
Дополнение: Взгляните на определение dynamic_rnn
tf.nn.dynamic_rnn(
cell,
inputs,
sequence_length=None,
initial_state=None,
dtype=None,
parallel_iterations=None,
swap_memory=False,
time_major=False,
scope=None
)
'''
Defined in tensorflow/python/ops/rnn.py.
See the guide: Neural Network > Recurrent Neural Networks
Creates a recurrent neural network specified by RNNCell cell.
Performs fully dynamic unrolling of inputs.
'''
#Example:
#=====================================================================
'''
使用用例,可以进行参考
'''
# create a BasicRNNCell
rnn_cell = tf.nn.rnn_cell.BasicRNNCell(hidden_size)
# 'outputs' is a tensor of shape [batch_size, max_time, cell_state_size]
# defining initial state
initial_state = rnn_cell.zero_state(batch_size, dtype=tf.float32)
# 'state' is a tensor of shape [batch_size, cell_state_size]
outputs, state = tf.nn.dynamic_rnn(rnn_cell, input_data,
initial_state=initial_state,
dtype=tf.float32)
#======================================================================
'''
使用用例,可以进行参考
'''
# create 2 LSTMCells
rnn_layers = [tf.nn.rnn_cell.LSTMCell(size) for size in [128, 256]]
# create a RNN cell composed sequentially of a number of RNNCells
multi_rnn_cell = tf.nn.rnn_cell.MultiRNNCell(rnn_layers)
# 'outputs' is a tensor of shape [batch_size, max_time, 256]
# 'state' is a N-tuple where N is the number of LSTMCells containing a
# tf.contrib.rnn.LSTMStateTuple for each cell
outputs, state = tf.nn.dynamic_rnn(cell=multi_rnn_cell,
inputs=data,
dtype=tf.float32)
Объяснение параметра:
- cell: объект экземпляра, созданный классом RNNCell.
-
inputs: Это вход сети RNN, еслиtime_major == False(это значение по умолчанию), форма входных данных должна быть:
atch_size, max_time, features]
но еслиtime_major == True, форма входов должна быть:[max_time, batch_size,features]
Примечание: max_time здесь эквивалентно предыдущим временным шагам, но зачем здесь использовать max_time? Поскольку наши последовательности иногда имеют переменную длину, здесь указана максимальная длина последовательности, а о том, как поступать с последовательностями неопределенной длины, мы поговорим позже, поэтому для общности здесь используется max_time. Особенности здесь иногда представлены глубиной, что означает особенности. - sequence_length: Это необязательный параметр, который специально используется для работы с последовательностями переменной длины, которые будут подробно объяснены позже, но не будут объясняться здесь.
-
time_major: Этот параметр определяет форму входов и выходов.Если True, входы и выходы
[max_time, batch_size, depth]
, Если False, входные входы и выходные выходы[batch_size, max_time, depth]
. Следует отметить, что значение по умолчанию False может больше соответствовать нашим привычкам, но при использовании True эффективность работы выше, а почему я уже объяснял в статье выше, так как временные шаги соответствуют фронту . static_rnn, это реализовано в соответствии с процессом работы RNN, и не требует транспонирования и других операций.Если временные шаги находятся посередине, это соответствует dynamic_rnn.Это требует некоторых операций транспонирования, поэтому эффективность относительно низкая
возвращаемое значение:
-
outputs: The RNN output Tensor.
-
Если time_major == False (по умолчанию), это будет форма Tensor: [batch_size, max_time, cell.output_size]. Это случай по умолчанию.
-
If time_major == True, this will be a Tensor shaped: [max_time, batch_size, cell.output_size].
-
-
state: То же, что и выше.
Пять: добавить,
Вот несколько динамических диаграмм, которые хорошо знакомы с RNN и которыми мы можем поделиться с вами: