有人可以提出关于我多维LSTM实现的改进建议吗?
它非常缓慢,使用了很多内存。
class MultiDimentionalLSTMCell(tf.nn.rnn_cell.RNNCell):
"""
Adapted from TF's BasicLSTMCell to use Layer Normalization.
Note that state_is_tuple is always True.
"""
def __init__(self, num_units, forget_bias=1.0, activation=tf.nn.tanh):
self._num_units = num_units
self._forget_bias = forget_bias
self._activation = activation
@property
def state_size(self):
return tf.nn.rnn_cell.LSTMStateTuple(self._num_units, self._num_units)
@property
def output_size(self):
return self._num_units
def __call__(self, inputs, state, scope=None):
"""Long short-term memory cell (LSTM).
@param: imputs (batch,n)
@param state: the states and hidden unit of the two cells
"""
with tf.variable_scope(scope or type(self).__name__):
c1,c2,h1,h2 = state
# change bias argument to False since LN will add bias via shift
concat = tf.nn.rnn_cell._linear([inputs, h1, h2], 5 * self._num_units, False)
i, j, f1, f2, o = tf.split(1, 5, concat)
# add layer normalization to each gate
#i = ln(i, scope = 'i/')
#j = ln(j, scope = 'j/')
#f1 = ln(f1, scope = 'f1/')
#f2 = ln(f2, scope = 'f2/')
#o = ln(o, scope = 'o/')
new_c = (c1 * tf.nn.sigmoid(f1 + self._forget_bias) +
c2 * tf.nn.sigmoid(f2 + self._forget_bias) + tf.nn.sigmoid(i) *
self._activation(j))
# add layer_normalization in calculation of new hidden state
new_h = self._activation(ln(new_c, scope = 'new_h/')) * tf.nn.sigmoid(o)
new_state = tf.nn.rnn_cell.LSTMStateTuple(new_c, new_h)
return new_h, new_state
def MultidimentionalRNN(rnn_size,input_data,sh,dims=None,scopeN="layer1"):
"""Implements naive multidimentional recurent neural networks
@param rnn_size: the hidden units
@param input_data: the data to process of shape [batch,h,w,chanels]
@param sh: [heigth,width] of the windows
@param dims: dimentions to reverse the input data,eg.
dims=[False,True,True,False] => true means reverse dimention
@param scopeN : the scope
returns [batch,h/sh[0],w/sh[1],chanels*sh[0]*sh[1]] the output of the lstm
"""
with tf.variable_scope("MultiDimentionalLSTMCell-"+scopeN):
cell = MultiDimentionalLSTMCell(rnn_size)
shape = input_data.get_shape().as_list()
# add paddings
#todos:
#y = tf.cond(condition > 0, lambda: tf.matmul(x, W) + b, lambda: tf.matmul(x, W) - b)
if shape[1]%sh[0] != 0:
offset = tf.zeros([shape[0], sh[0]-(shape[1]%sh[0]), shape[2], shape[3]])
input_data = tf.concat(1,[input_data,offset])
shape = input_data.get_shape().as_list()
if shape[2]%sh[1] != 0:
offset = tf.zeros([shape[0], shape[1], sh[1]-(shape[2]%sh[1]), shape[3]])
input_data = tf.concat(2,[input_data,offset])
shape = input_data.get_shape().as_list()
w,h = int(shape[1]/sh[0]),int(shape[2]/sh[1])
features = sh[1]*sh[0]*shape[3]
batch_size = shape[0]
x = tf.reshape(input_data, [batch_size,h,w, features])
if dims is not None:
x = tf.reverse(x, dims)
x = tf.transpose(x, [1,2,0,3])
x = tf.reshape(x, [-1, features])
x = tf.split(0, h*w, x)
states = []
outputs = []
#todo: add seq_len 2D (have to add paddings after)
#use tf.get_variable()
#result = tf.while_loop(condition, body, [x])
with tf.variable_scope("MultiDimentionalRnn-"+scopeN) as scope:
for i,inputs in enumerate(x):
#stateUp = tf.cond(i>=w, lambda: states[i-w], lambda: cell.zero_state(batch_size, tf.float32))
stateUp = states[i-w] if i>=w else cell.zero_state(batch_size, tf.float32)
#stateLast = tf.cond(i%w>0, lambda: states[i-1], lambda: cell.zero_state(batch_size, tf.float32))
stateLast = states[i-1] if i%w>0 else cell.zero_state(batch_size, tf.float32)
currentState = stateUp[0],stateLast[0],stateUp[1],stateLast[1]
out , state = cell(inputs,currentState)
states.append(state)
outputs.append(out)
scope.reuse_variables()
outputs = tf.pack(outputs, axis=0)
y = tf.reshape(outputs, [h,w,batch_size,rnn_size])
y = tf.transpose(y, [2,0,1,3])
if dims is not None:
y = tf.reverse(y, dims)
return y