嵌套在自定义 Keras 层内的 Keras 模型
Keras Model nested inside of Custom Keras Layer
我想构建一个 Keras 模型,它使用类似 SPICE 的数值方法进行前向传播。由于 SPICE 问题无法解析解决,因此我构建了以下 class。 class 非常适合实现预测(数值前向计算)和确定梯度(分析)。
Class:
# "..." notes places where code is ommited for conciseness
class SPICE_solver():
def __init__(self, num_inputs, num_outputs, ...):
...
self.net = build_model_SPICE_solver(num_inputs, num_outputs, ...)
def predict(self, activations, weights, ...):
'''
:param activations: shape: (?, num_inputs)
:param weights: shape: (1, num_inputs, num_outputs)
:return: vout shape: (?, num_outputs)
'''
...
out = np.zeros([activations.shape[0], weights.shape[-1]])
self.net.fit(x=[activations, weights],
y=[out],
epochs=200,
callbacks=[EarlyStoppingByLossVal(monitor='loss', value=self.acc, verbose=0)],
verbose=0,
steps_per_epoch=64)
self.vout = self.net.get_weights()
return self.vout # weights incidate the output of the 'layer'
def gradients(self, activations, weights, ...):
'''
:param activations: shape: (?, num_inputs)
:param weights: shape: (?, num_inputs, num_outputs)
:return: gradient: list of gradients for: activations, weights (w.r.t. vout)
'''
...
outputTensor = self.net.output
listOfVariableTensors = self.net.input
gradients = K.gradients(outputTensor, listOfVariableTensors)
sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
self.grad = sess.run(gradients, feed_dict={self.net.input[0]:activations, self.net.input[1]:weights})
return self.grad
我想使用这个 class 在自定义的更高级别的 Keras 层中完成前向传播 (SPICE_solver.predict) 和反向传播 (SPICE_solver.gradients)。
自定义 Keras 层:
class mac_nonLin_SPICE(Layer):
def __init__(self,
output_dim,
**kwargs):
self.output_dim = output_dim
super(mac_nonLin_SPICE, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=(1, int(input_shape[1]), self.output_dim),
initializer='glorot_uniform',
# constraint='UnitNorm',
trainable=True)
self.slvr = SPICE_solver(int(input_shape[1]), self.output_dim)
super(mac_nonLin_SPICE, self).build(input_shape) # Be sure to call this at the end
def call(self, x):
return self.slvr.predict(x, self.kernel)
# def reutrn gradient():????
# pass
def compute_output_shape(self, input_shape):
return (input_shape[0], self.output_dim)
我在以嵌套方式调用 Keras 模型时遇到很多问题。有没有一种实用的方法可以在自定义 Keras 层中实现这样的对象?
edit:我的直觉告诉我,使用低级 TensorFlow API 重建整个设计是最实用的方法,尽管不方便。仍在寻找一个简单的 Keras 解决方法。
非常感谢任何帮助!
简而言之,我无法使用 Keras 完成此操作。这是我找到的最佳解决方案:
我使用 Tensorflow 低级 API 重新创建了网络并定义了两个损失函数:
- Loss1:前馈路径中的均方误差(换句话说,如果 loss1 高,则 SPICE 解决方案不好)
- 损失 2:均方误差(预测 - training_data)
然后,我将优化器设置为最小化:
Loss = Loss1 + Loss2 * (1 - Gaus(a * Loss1))
其中:
- Gaus() 是高斯函数,归一化为振幅 1
- "a" 是一些因素
这样,Loss2 仅在 Loss1 较小时(当 SPICE 解决方案良好时)最小化。
希望这对某人有所帮助。
我想构建一个 Keras 模型,它使用类似 SPICE 的数值方法进行前向传播。由于 SPICE 问题无法解析解决,因此我构建了以下 class。 class 非常适合实现预测(数值前向计算)和确定梯度(分析)。
Class:
# "..." notes places where code is ommited for conciseness
class SPICE_solver():
def __init__(self, num_inputs, num_outputs, ...):
...
self.net = build_model_SPICE_solver(num_inputs, num_outputs, ...)
def predict(self, activations, weights, ...):
'''
:param activations: shape: (?, num_inputs)
:param weights: shape: (1, num_inputs, num_outputs)
:return: vout shape: (?, num_outputs)
'''
...
out = np.zeros([activations.shape[0], weights.shape[-1]])
self.net.fit(x=[activations, weights],
y=[out],
epochs=200,
callbacks=[EarlyStoppingByLossVal(monitor='loss', value=self.acc, verbose=0)],
verbose=0,
steps_per_epoch=64)
self.vout = self.net.get_weights()
return self.vout # weights incidate the output of the 'layer'
def gradients(self, activations, weights, ...):
'''
:param activations: shape: (?, num_inputs)
:param weights: shape: (?, num_inputs, num_outputs)
:return: gradient: list of gradients for: activations, weights (w.r.t. vout)
'''
...
outputTensor = self.net.output
listOfVariableTensors = self.net.input
gradients = K.gradients(outputTensor, listOfVariableTensors)
sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
self.grad = sess.run(gradients, feed_dict={self.net.input[0]:activations, self.net.input[1]:weights})
return self.grad
我想使用这个 class 在自定义的更高级别的 Keras 层中完成前向传播 (SPICE_solver.predict) 和反向传播 (SPICE_solver.gradients)。
自定义 Keras 层:
class mac_nonLin_SPICE(Layer):
def __init__(self,
output_dim,
**kwargs):
self.output_dim = output_dim
super(mac_nonLin_SPICE, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=(1, int(input_shape[1]), self.output_dim),
initializer='glorot_uniform',
# constraint='UnitNorm',
trainable=True)
self.slvr = SPICE_solver(int(input_shape[1]), self.output_dim)
super(mac_nonLin_SPICE, self).build(input_shape) # Be sure to call this at the end
def call(self, x):
return self.slvr.predict(x, self.kernel)
# def reutrn gradient():????
# pass
def compute_output_shape(self, input_shape):
return (input_shape[0], self.output_dim)
我在以嵌套方式调用 Keras 模型时遇到很多问题。有没有一种实用的方法可以在自定义 Keras 层中实现这样的对象?
edit:我的直觉告诉我,使用低级 TensorFlow API 重建整个设计是最实用的方法,尽管不方便。仍在寻找一个简单的 Keras 解决方法。
非常感谢任何帮助!
简而言之,我无法使用 Keras 完成此操作。这是我找到的最佳解决方案:
我使用 Tensorflow 低级 API 重新创建了网络并定义了两个损失函数:
- Loss1:前馈路径中的均方误差(换句话说,如果 loss1 高,则 SPICE 解决方案不好)
- 损失 2:均方误差(预测 - training_data)
然后,我将优化器设置为最小化: Loss = Loss1 + Loss2 * (1 - Gaus(a * Loss1))
其中:
- Gaus() 是高斯函数,归一化为振幅 1
- "a" 是一些因素
这样,Loss2 仅在 Loss1 较小时(当 SPICE 解决方案良好时)最小化。
希望这对某人有所帮助。