Creates an `RNN` specified by RNNCell `cell` and loop function `loop_fn`. **NOTE: This method is still in testing, and the API may change.** This function is a more primitive version of `dynamic_rnn` that provides more direct access to the inputs each iteration. It also provides more cont
(cell, loop_fn,
parallel_iterations=None, swap_memory=False, scope=None)
| 810 | |
| 811 | |
| 812 | def raw_rnn(cell, loop_fn, |
| 813 | parallel_iterations=None, swap_memory=False, scope=None): |
| 814 | """Creates an `RNN` specified by RNNCell `cell` and loop function `loop_fn`. |
| 815 | |
| 816 | **NOTE: This method is still in testing, and the API may change.** |
| 817 | |
| 818 | This function is a more primitive version of `dynamic_rnn` that provides |
| 819 | more direct access to the inputs each iteration. It also provides more |
| 820 | control over when to start and finish reading the sequence, and |
| 821 | what to emit for the output. |
| 822 | |
| 823 | For example, it can be used to implement the dynamic decoder of a seq2seq |
| 824 | model. |
| 825 | |
| 826 | Instead of working with `Tensor` objects, most operations work with |
| 827 | `TensorArray` objects directly. |
| 828 | |
| 829 | The operation of `raw_rnn`, in pseudo-code, is basically the following: |
| 830 | |
| 831 | ```python |
| 832 | time = tf.constant(0, dtype=tf.int32) |
| 833 | (finished, next_input, initial_state, _, loop_state) = loop_fn( |
| 834 | time=time, cell_output=None, cell_state=None, loop_state=None) |
| 835 | emit_ta = TensorArray(dynamic_size=True, dtype=initial_state.dtype) |
| 836 | state = initial_state |
| 837 | while not all(finished): |
| 838 | (output, cell_state) = cell(next_input, state) |
| 839 | (next_finished, next_input, next_state, emit, loop_state) = loop_fn( |
| 840 | time=time + 1, cell_output=output, cell_state=cell_state, |
| 841 | loop_state=loop_state) |
| 842 | # Emit zeros and copy forward state for minibatch entries that are finished. |
| 843 | state = tf.where(finished, state, next_state) |
| 844 | emit = tf.where(finished, tf.zeros_like(emit), emit) |
| 845 | emit_ta = emit_ta.write(time, emit) |
| 846 | # If any new minibatch entries are marked as finished, mark these. |
| 847 | finished = tf.logical_or(finished, next_finished) |
| 848 | time += 1 |
| 849 | return (emit_ta, state, loop_state) |
| 850 | ``` |
| 851 | |
| 852 | with the additional properties that output and state may be (possibly nested) |
| 853 | tuples, as determined by `cell.output_size` and `cell.state_size`, and |
| 854 | as a result the final `state` and `emit_ta` may themselves be tuples. |
| 855 | |
| 856 | A simple implementation of `dynamic_rnn` via `raw_rnn` looks like this: |
| 857 | |
| 858 | ```python |
| 859 | inputs = tf.placeholder(shape=(max_time, batch_size, input_depth), |
| 860 | dtype=tf.float32) |
| 861 | sequence_length = tf.placeholder(shape=(batch_size,), dtype=tf.int32) |
| 862 | inputs_ta = tf.TensorArray(dtype=tf.float32, size=max_time) |
| 863 | inputs_ta = inputs_ta.unstack(inputs) |
| 864 | |
| 865 | cell = tf.contrib.rnn.LSTMCell(num_units) |
| 866 | |
| 867 | def loop_fn(time, cell_output, cell_state, loop_state): |
| 868 | emit_output = cell_output # == None for time == 0 |
| 869 | if cell_output is None: # time == 0 |
nothing calls this directly
no test coverage detected