我想知道在下面的代码中,两个堆叠单元的权重是否被共享:
cell = rnn_cell.GRUCell(hidden_dim)stacked_cell = tf.nn.rnn_cell.MultiRNNCell([cell] * 2)
如果它们没有被共享,如何强制在任何RNN中共享权重?
注意:我更可能希望在嵌套的输入到输出连接的RNN配置中共享权重,其中第一层被克隆多次以用于第二层的每个输入(例如,句子,其中第一层代表字母,第二层代表通过迭代第一层的输出收集的单词)
回答:
你可以通过执行以下脚本来看到权重没有被共享:
import tensorflow as tfwith tf.variable_scope("scope1") as vs: cell = tf.nn.rnn_cell.GRUCell(10) stacked_cell = tf.nn.rnn_cell.MultiRNNCell([cell] * 2) stacked_cell(tf.Variable(np.zeros((100, 100), dtype=np.float32), name="moo"), tf.Variable(np.zeros((100, 100), dtype=np.float32), "bla")) # 仅检索LSTM变量。 vars = [v.name for v in tf.all_variables() if v.name.startswith(vs.name)] print vars
你会看到除了虚拟变量外,它返回了两组GRU权重:带有”Cell1″的和带有”Cell0″的。
为了使它们共享,你可以实现一个自己的单元类,该类继承自GRUCell
,并通过始终使用相同的变量作用域来始终重用权重:
import tensorflow as tfclass SharedGRUCell(tf.nn.rnn_cell.GRUCell): def __init__(self, num_units, input_size=None, activation=tf.nn.tanh): tf.nn.rnn_cell.GRUCell.__init__(self, num_units, input_size, activation) self.my_scope = None def __call__(self, a, b): if self.my_scope == None: self.my_scope = tf.get_variable_scope() else: self.my_scope.reuse_variables() return tf.nn.rnn_cell.GRUCell.__call__(self, a, b, self.my_scope)with tf.variable_scope("scope2") as vs: cell = SharedGRUCell(10) stacked_cell = tf.nn.rnn_cell.MultiRNNCell([cell] * 2) stacked_cell(tf.Variable(np.zeros((20, 10), dtype=np.float32), name="moo"), tf.Variable(np.zeros((20, 10), dtype=np.float32), "bla")) # 仅检索LSTM变量。 vars = [v.name for v in tf.all_variables() if v.name.startswith(vs.name)] print vars
这样,两者之间的GRUCells变量就被共享了。请注意,你需要小心处理形状,因为同一个单元需要同时处理原始输入和自身的输出。