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]
```