背景
我的问题基于Geron的动手机器学习第12章:定制模型中的示例。
本示例的目的是创建一个定制的神经网络模型。该模型有5个Dense
隐藏层。自定义部分是我们reconstruction
在输出之前添加一个图层。重建层的目的是重建输入。然后,我们求出差值reconstruction-inputs
,得到MSE,然后将此值应用于损失函数。这应该是一个正规化步骤。
最低(应为)工作示例
以下代码几乎直接来自教科书,但无效。
import numpy as np
num_training=10;
num_dim=2;
X = np.random.random((10,2))
y = np.random.random(10)
import tensorflow as tf
import tensorflow.keras as keras
class ReconstructingRegressor(keras.models.Model):
def __init__(self, output_dim, **kwargs):
super().__init__(**kwargs)
self.hidden = [keras.layers.Dense(30, activation="selu",
kernel_initializer="lecun_normal")
for _ in range(5)]
self.out = keras.layers.Dense(output_dim)
def build(self, batch_input_shape):
n_inputs = batch_input_shape[-1]
self.reconstruct = keras.layers.Dense(n_inputs)
super().build(batch_input_shape)
def call(self, inputs, training=None):
Z = inputs
for layer in self.hidden:
Z = layer(Z)
reconstruction = self.reconstruct(Z)
recon_loss = tf.reduce_mean(tf.square(reconstruction - inputs))
self.add_loss(0.05 * recon_loss)
return self.out(Z)
model = ReconstructingRegressor(1)
model.compile(loss="mse", optimizer="nadam")
history = model.fit(X, y, epochs=2)
错误信息
但是,在调用时出现以下错误model.fit()
:
---------------------------------------------------------------------------
InaccessibleTensorError Traceback (most recent call last)
<ipython-input-10-b7211d3022fa> in <module>
34 model = ReconstructingRegressor(1)
35 model.compile(loss="mse", optimizer="nadam")
---> 36 history = model.fit(X, y, epochs=2)
并且,在错误消息的末尾:
InaccessibleTensorError:无法在此处访问张量'Tensor(“ mul:0”,shape =(),dtype = float32)':它是在另一个函数或代码块中定义的。使用返回值,显式的Python局部变量或TensorFlow集合来访问它。定义于:FuncGraph(name = build_graph,id = 140602287140624); 可从以下网址访问:FuncGraph(name = train_function,id = 140602287108640)。
故障排除
如果我注释掉计算损失的代码,即
#recon_loss = tf.reduce_mean(tf.square(reconstruction - inputs))
#self.add_loss(0.05 * recon_loss)
在中call
,但我将其他所有内容保持不变,则收到以下警告
警告:tensorflow:最小化损耗时,变量['dense / kernel:0','dense / bias:0']不存在渐变。
不确定是否相关。
我不确定100%,但是我认为问题是由于您添加通孔self.add_loss
所涉及的损耗是指在计算主损耗时未使用的层,并且可能在主图中进行了优化。因此,当您要访问它们时,就无法访问张量。
我认为最简单的方法是稍微改写网络:
training
参数model.call
来使用重建层。model.train_step
仍然能够使用fit
。(请参阅指南:自定义Model.fit中发生的事情)。使用的training
参数model.call
,我们设置为reconstruct
仅在训练期间使用该图层,并使网络返回机器人进行预测和重构。但是,当我们要进行预测时,仅返回预测。
覆盖train_step
只是在这里仍然可以使用fit
,而不必从头开始编写训练循环。test_step
在这种情况下,我们不需要重写,因为用例相当简单。
import tensorflow as tf
import tensorflow.keras as keras
import numpy as np
num_training = 10
num_dim = 2
X = np.random.random((10, 2)).astype(np.float32)
y = np.random.random((10,)).astype(np.float32)
class ReconstructingRegressor(keras.models.Model):
def __init__(self, output_dim, **kwargs):
super().__init__(**kwargs)
self.hidden = [
keras.layers.Dense(
30,
activation="selu",
kernel_initializer="lecun_normal",
name=f"hidden_{idx}",
)
for idx in range(5)
]
self.out = keras.layers.Dense(output_dim, name="output")
def build(self, batch_input_shape):
n_inputs = batch_input_shape[-1]
self.reconstruct = keras.layers.Dense(n_inputs, name="reconstruct")
super().build(batch_input_shape)
@staticmethod
def reconstruction_loss(reconstruction, inputs, rate=0.05):
return tf.reduce_mean(tf.square(reconstruction - inputs)) * rate
def train_step(self, data):
x, y = data
with tf.GradientTape() as tape:
y_pred, recon = self(x, training=True)
loss = self.compiled_loss(y, y_pred)
loss += self.reconstruction_loss(recon, x)
gradients = tape.gradient(loss, self.trainable_variables)
# Update weights
self.optimizer.apply_gradients(zip(gradients, self.trainable_variables))
# Update metrics (includes the metric that tracks the loss)
self.compiled_metrics.update_state(y, y_pred)
# Return a dict mapping metric names to current value
return {m.name: m.result() for m in self.metrics}
def call(self, inputs, training=None):
Z = inputs
for layer in self.hidden:
Z = layer(Z)
if training:
return self.out(Z), self.reconstruct(Z)
return self.out(Z)
model = ReconstructingRegressor(1)
model.compile(optimizer="nadam", loss="mse")
history = model.fit(X, y, epochs=10)
history = model.evaluate(X, y)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句