2016-06-14 10 views
5

以下、このペーパーのAlex GravesのアルゴリズムACTをエミュレートするように設計されたTensorflow RNNセルの実装を示します。http://arxiv.org/abs/1603.08983while_loopのコンテキストでTensorArraysを使用して値を累積します

via rnn.rnn(静的なsequence_lengthパラメータで、rnnが動的に展開されるように、私は20の固定バッチサイズを使用しています)、ACTStepを呼び出して、サイズの出力を再帰的に呼び出しますRNNセルの隠れた次元が200であり、バッチサイズが1である(1,200)。

Tensorflowのwhileループを使用して、累積停止確率が十分に高くなるまで繰り返します。これらのすべては合理的にスムーズに機能しますが、最終的なセル出力/状態として重み付けされた組み合わせを作成するために必要な、whileループ内の状態、確率および出力の蓄積に問題があります。

私は以下のように単純なリストを使ってみましたが、出力が同じフレームにないのでグラフがコンパイルされたときに失敗します(control_flow_opsのswitch関数を使用してテンソルをそれらが必要とされるポイント、すなわち、値を返す直前のadd_n関数?)。私もTensorArray構造体を使用しようとしましたが、形状情報を破壊して手動で置き換えるように見えるため、この使い方が難しいと感じています。私はTensorArraysに関する多くのドキュメンテーションを見つけることができませんでした。おそらく彼らがそうであるように、主に内部TFの使用のために想像していました。

ACTStepによって生成された変数を正しく蓄積する方法についてのアドバイスをいただければ幸いです。

class ACTCell(RNNCell): 
"""An RNN cell implementing Graves' Adaptive Computation time algorithm""" 
def __init__(self, num_units, cell, epsilon, max_computation): 

    self.one_minus_eps = tf.constant(1.0 - epsilon) 
    self._num_units = num_units 
    self.cell = cell 
    self.N = tf.constant(max_computation) 
@property 
def input_size(self): 
    return self._num_units 
@property 
def output_size(self): 
    return self._num_units 
@property 
def state_size(self): 
    return self._num_units 

def __call__(self, inputs, state, scope=None): 

    with vs.variable_scope(scope or type(self).__name__): 

     # define within cell constants/ counters used to control while loop 
     prob = tf.get_variable("prob", [], tf.float32,tf.constant_initializer(0.0)) 
     counter = tf.get_variable("counter", [],tf.float32,tf.constant_initializer(0.0)) 
     tf.assign(prob,0.0) 
     tf.assign(counter, 0.0) 

     # the predicate for stopping the while loop. Tensorflow demands that we have 
     # all of the variables used in the while loop in the predicate. 
     pred = lambda prob,counter,state,input,\ 
         acc_state,acc_output,acc_probs:\ 
      tf.logical_and(tf.less(prob,self.one_minus_eps), tf.less(counter,self.N)) 

     acc_probs = [] 
     acc_outputs = [] 
     acc_states = [] 


     _,iterations,_,_,acc_states,acc_output,acc_probs = \ 
     control_flow_ops.while_loop(pred, 
     self.ACTStep, 
     [prob,counter,state,input,acc_states,acc_outputs,acc_probs]) 

    # TODO:fix last part of this, need to use the remainder. 
    # TODO: find a way to accumulate the regulariser 

    # here we take a weighted combination of the states and outputs 
    # to use as the actual output and state which is passed to the next timestep. 

    next_state = tf.add_n([tf.mul(x,y) for x,y in zip(acc_probs,acc_states)]) 
    output = tf.add_n([tf.mul(x,y) for x,y in zip(acc_probs,acc_outputs)]) 


    return output, next_state 

def ACTStep(self,prob,counter,state,input, acc_states,acc_outputs,acc_probs): 

    output, new_state = rnn.rnn(self.cell, [input], state, scope=type(self.cell).__name__) 

    prob_w = tf.get_variable("prob_w", [self.cell.input_size,1]) 
    prob_b = tf.get_variable("prob_b", [1]) 
    p = tf.nn.sigmoid(tf.matmul(prob_w,new_state) + prob_b) 

    acc_states.append(new_state) 
    acc_outputs.append(output) 
    acc_probs.append(p) 

    return [tf.add(prob,p),tf.add(counter,1.0),new_state, input,acc_states,acc_outputs,acc_probs] 

答えて

3

これは完全な解決策ではなく、セルを改善する方法に関するコメントです。

あなたACTStep機能で、オフを開始するには、[input]で定義された(1時間ステップのためrnn.rnnを呼び出す。あなたは、単一のタイムステップをやっている場合は、それが実際のself.cellコール機能、おそらく簡単な使用に、より効率的である。あなた」あなたはTensorArraysを使用して試してみましたことを述べたtensorflowにrnncell wrappers

を使用し、これと同じメカニズムを参照してくださいでしょう。あなたが適切tensorarraysをパックし、解凍しましたか?ここでは、model.py下tensorarraysがパックされ、適切に展開されていますrepoです。

control_flow_opsに関数があれば、すべてのテンソルを累積する必要があります。あなたが探していると思う。tf.control_dependencies

control_dependiciesですべての出力テンソル演算をリストすることができ、その点までのすべてのテンソルを計算するにはテンソルフローが必要になります。

また、counter変数が訓練可能であるようです。あなたはこれが事実であると確信していますか?あなたのカウンターにプラス1を加えているなら、おそらく正しい結果が得られません。他方では、最終的に熟考コスト関数のためにそれを差別化するために意図的にそれを訓練可能に保つことができました。

また、私は剰余関数がスクリプトであるべきと考えている:

class ACTCell(RNNCell): 
    """An RNN cell implementing Graves' Adaptive Computation time algorithm 
    Notes: https://www.evernote.com/shard/s189/sh/fd165646-b630-48b7-844c-86ad2f07fcda/c9ab960af967ef847097f21d94b0bff7 

    """ 
    def __init__(self, num_units, cell, max_computation = 5.0, epsilon = 0.01): 

     self.one_minus_eps = tf.constant(1.0 - epsilon) #episolon is 0.01 as found in the paper 
     self._num_units = num_units 
     self.cell = cell 
     self.N = tf.constant(max_computation) 

    @property 
    def input_size(self): 
     return self._num_units 
    @property 
    def output_size(self): 
     return self._num_units 
    @property 
    def state_size(self): 
     return self._num_units 

    def __call__(self, inputs, state, scope=None): 

     with vs.variable_scope(scope or type(self).__name__): 

      # define within cell constants/ counters used to control while loop 
      prob = tf.constant(0.0, shape = [batch_size]) 
      counter = tf.constant(0.0, shape = [batch_size]) 

      # the predicate for stopping the while loop. Tensorflow demands that we have 
      # all of the variables used in the while loop in the predicate. 
      pred = lambda prob,counter,state,input,acc_states,acc_output,acc_probs:\ 
       tf.logical_and(tf.less(prob,self.one_minus_eps), tf.less(counter,self.N)) 

      acc_probs, acc_outputs, acc_states = [], [], [] 

      _,iterations,_,_,acc_states,acc_output,acc_probs = \ 
      control_flow_ops.while_loop(
      pred, 
      self.ACTStep, #looks like he purposely makes the while loop here 
      [prob, counter, state, input, acc_states, acc_outputs, acc_probs]) 

     '''mean-field updates for states and outputs''' 
     next_state = tf.add_n([x*y for x,y in zip(acc_probs,acc_states)]) 
     output = tf.add_n([x*y for x,y in zip(acc_probs,acc_outputs)]) 

     remainder = 1.0 - tf.add_n(acc_probs[:-1]) #you take the last off to avoid a negative ponder cost #the problem here is we need to take the sum of all the remainders 
     tf.add_to_collection("ACT_remainder", remainder) #if this doesnt work then you can do self.list based upon timesteps 
     tf.add_to_collection("ACT_iterations", iterations) 
     return output, next_state 

    def ACTStep(self,prob, counter, state, input, acc_states, acc_outputs, acc_probs): 

     '''run rnn once''' 
     output, new_state = rnn.rnn(self.cell, [input], state, scope=type(self.cell).__name__) 

     prob_w = tf.get_variable("prob_w", [self.cell.input_size,1]) 
     prob_b = tf.get_variable("prob_b", [1]) 
     halting_probability = tf.nn.sigmoid(tf.matmul(prob_w,new_state) + prob_b) 


     acc_states.append(new_state) 
     acc_outputs.append(output) 
     acc_probs.append(halting_probability) 

     return [p + prob, counter + 1.0, new_state, input,acc_states,acc_outputs,acc_probs] 


    def PonderCostFunction(self, time_penalty = 0.01): 
     ''' 
     note: ponder is completely different than probability and ponder = roe 

     the ponder cost function prohibits the rnn from cycling endlessly on each timestep when not much is needed 
     ''' 
     n_iterations = tf.get_collection_ref("ACT_iterations") 
     remainder = tf.get_collection_ref("ACT_remainder") 
     return tf.reduce_sum(n_iterations + remainder) #completely different from probability 

これは私がしていることを実現するための複雑な紙です。ここ

remainder = 1.0 - tf.add_n(acc_probs[:-1]) 
#note that there is a -1 in the list as you do not want to grab the last probability 

はあなたのコードの私のバージョンが編集されて自分で働いている。私はTensorflowでそれを行うためにあなたと協力しても構いません。興味があればSkypeのLeavesBreatheに私を追加してください。そこから行くことができます。

関連する問題