• Home
  • About
    • Dr.Zee Blog photo

      Dr.Zee Blog

      Xiangyu Zhang;PHD student;Reinforcement learning, intelligent wireless communication

    • Learn More
    • Email
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

keras.backends中function函数详解

20 May 2019

Reading time ~1 minute

Keras是一个模型级库,为开发深度学习模型提供高级构建块。 它不处理低级操作,如张量积,卷积等本身。 相反,它依赖于专门的,优化良好的张量操纵库来实现,作为Keras的“后端引擎”。 Keras不是选择单个张量库并将Keras的实现与该库绑定,而是以模块化方式处理问题,并且可以将几个不同的后端引擎无缝插入到Keras中。

keras 的backends

keras的官方解释

Keras是一个模型级库,为开发深度学习模型提供高级构建块。 它不处理低级操作,如张量积,卷积等本身。 相反,它依赖于专门的,优化良好的张量操纵库来实现,作为Keras的“后端引擎”。 Keras不是选择单个张量库并将Keras的实现与该库绑定,而是以模块化方式处理问题,并且可以将几个不同的后端引擎无缝插入到Keras中。

自我理解:

找了一些文章都是感觉理解上,这是一个选择backends(TensorFlow、 Theano、 CNTK ) 的地方。但是看了该类下面的各个函数之后,发现实际并不是那么简单。backends中包含了许多已有的方法是对整个建立好的图网络进行处理。例如:update、clear_session。 backends中的计算函数大多数都是处理一个tensor。

function 函数

官方解释

keras.backend.function(inputs, outputs, updates=None)

Instantiates a Keras function. Arguments inputs: List of placeholder tensors. outputs: List of output tensors. updates: List of update ops. **kwargs: Passed to tf.Session.run. Returns

具体说明

其实官方没有给出比较好的解释,但是仔细观察一下源代码 注意:

  • 为简单起见,已经删除了不必要的部分 留下了大部分重要的部分
  • 同时只保留基础功能
class Function(object):

    with ops.control_dependencies(self.outputs):
      updates_ops = []
      for update in updates:
        if isinstance(update, tuple):
          p, new_p = update
          updates_ops.append(state_ops.assign(p, new_p))
        else:
          # assumed already an op
          updates_ops.append(update)
      self.updates_op = control_flow_ops.group(*updates_ops)
    self.name = name
    self.session_kwargs = session_kwargs

  def __call__(self, inputs):
    feed_dict = {}
    for tensor, value in zip(self.inputs, inputs):
      if is_sparse(tensor):
        sparse_coo = value.tocoo()
        indices = np.concatenate((np.expand_dims(sparse_coo.row, 1),
                                  np.expand_dims(sparse_coo.col, 1)), 1)
        value = (indices, sparse_coo.data, sparse_coo.shape)
      feed_dict[tensor] = value
    session = get_session()
    updated = session.run(
        self.outputs + [self.updates_op],
        feed_dict=feed_dict,
        **self.session_kwargs)
    return updated[:len(self.outputs)]

def function(inputs, outputs, updates=None, **kwargs):
  return Function(inputs, outputs, updates=updates, **kwargs)

可以看出来 当我们调用 function函数的时候, function函数最后输出了一个类。这个类在初始化的时候,创建了一个计算图。 也就是 在首先定义function的时候,输入进去的 input 是 List of placeholder tensors 是创建当前网络的输入。 outputs 是List of output tensors. 创建了当前网络的输出。 updates 是 List of update ops. 更新网络的方式。 即 tf中的 session。 当创建好这个图的时候。 可以得到一个定义好的 图网络。 然后我们就可以利用输入然后去计算输出、更新这个图网络。

应用

  • 直接利用现有网络,提取其中的感兴趣层,并输出出来。 例如: 把序贯网络的前三层提取出来。
    from keras import backend as K
    get_3rd_layer_output = K.function([model.layers[0].input],
                                    [model.layers[3].output])
    layer_output = get_3rd_layer_output([x])[0]
    

    注意 此处没有利用update op 所以输出结果之后,就不会再进行反向传播,优化其网络。

  • 直接利用现有网络,提取其中的感兴趣层,并利用自定义误差来训练它出来。
    from keras import backend as K
    optimizer = Adam(lr=.001, clipnorm=1.)
    get_3rd_layer_output = K.function([model.layers[0].input]+ [K.learning_phase()],
                                [model.layers[3].output],updates=optimizer.get_gradients(params=training,
                                                                    loss=loss))
    layer_output = get_3rd_layer_output([x])[0]
    

    其中update 是用来更新的 ,loss 是自定义误差,但是请注意,这个地方的loss 一定是 与参数params 有关系的 否则会报错。

  • 建立多关联网络。 例如强化学习DDPG中, actor的输出是 critic的输入,而critic的输出是 actor训练误差

首先建立 关联

        combined_inputs = []
        critic_inputs = []
        for i in self.critic.input:
            if i == self.critic_action_input:
                combined_inputs.append([])
            else:
                combined_inputs.append(i)
                critic_inputs.append(i)
        combined_inputs[self.critic_action_input_idx] = self.actor(critic_inputs)

        combined_output = self.critic(combined_inputs)

然后定义更新loss 注意这里的更新变量是combine_output 也就是critic的输出Q值

updates = actor_optimizer.get_updates(
            params=self.actor.trainable_weights, loss=-K.mean(combined_output))

定义函数

            self.actor_train_fn = K.function(critic_inputs + [K.learning_phase()],
                                             [self.actor(critic_inputs)], updates=updates)

调用函数并训练 虽然这里没有输入 loss 但是整个网络的结构 就已经在图中保存 ,所以这个地方是可以直接利用之前的critic的输出的。

action_values = self.actor_train_fn(inputs)[0]
​```


keras Share Tweet +1