Подробный анализ использования RNN

искусственный интеллект
Подробный анализ использования RNN

Эта статья взята изLoveMIss-Y, адрес блога:blog.CSDN.net/QQ_27825451…Помогает увидеть реальный механизм работы RNN


предисловие: очень просто и удобно использовать текущую основную среду глубокого обучения для реализации рекуррентной нейронной сети, поэтому мы можем много раз забывать, как анализировать нейронную сеть.входить,выводЧто это такое и какое так называемое состояние поддерживается между каждым узлом уровня петли? Эта статья требует базовых знаний рекуррентных нейронных сетей и некоторых базовых теорий, вы можете обратиться к двум моим предыдущим статьям:

blog.CSDN.net/QQ_27825451…

Первоначальная цель написания этой статьи состоит в том, что я прочитал много сообщений в блогах, многие из которых перепечатаны,Есть несколько оригинальных, которые объясняют некоторые основные реализации, но они кажутся двусмысленными и не включают в себя очень подробные места (также очень вероятно, что это написал кто-то другой, и я не могу этого понять)., поэтому я решил написать его сам, в этой статье речь идет только об одном моменте, то есть о циклической нейронной сети每一个cell的输出和它们之间的状态到底是什么样子的,为什么是这个样子, Ввиду ограниченного уровня есть неточности, и надеюсь найдутся большие братья, которые меня поправят.Эта статья основана на tensorflow.

1. Базовая структура RNN

2. Пример для полного понимания проблемы «размерности» вывода и состояния.

(1) Шаг 1: Создайте выборку обучающих данных X

(2) Шаг 2: Создайте структуру рабочего графа

(3) Шаг 3. Постройте график и протестируйте его.

3. Анализ текущих результатов программы

4. Сводка выходного значения RNN и значения состояния

Пять: добавить,

1. Базовая структура RNN

Вы можете увидеть такую ​​структурную схему во многих книгах или блогах, например:

529808-20180725212230112-121431511.png

Конечно, в этом нет ничего плохого, но недостаток в том, что эта картина чрезмерно доработана, слишком абстрактна и непроста для понимания.Что мне делать?Я сделал эскиз на черновике здесь, который мне удобнее понять. :

image.png

Картина не очень хорошая, но раздел описания ниже дает более подробное объяснение.

  • Фактически, вначале я боролся с тем, была ли внутренняя операция конкатенирована напрямую (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 и которыми мы можем поделиться с вами:20180915172427409.gif

20180915172109539.gif

20180917195028940.gif