我的环境是 ubuntu16.04,cuda10.2,python3.7,tensorflow2.2,阅读 keras 官网这一节时,发现如下奇怪的代码:
import tensorflow as tf
import numpy as np
from tensorflow import keras
class LogisticEndpoint(keras.layers.Layer):
def __init__(self, name=None):
super(LogisticEndpoint, self).__init__(name=name)
self.loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
self.accuracy_fn = keras.metrics.BinaryAccuracy()
def call(self, targets, logits, sample_weights=None):
# Compute the training-time loss value and add it
# to the layer using `self.add_loss()`.
loss = self.loss_fn(targets, logits, sample_weights)
self.add_loss(loss)
# Log accuracy as a metric and add it
# to the layer using `self.add_metric()`.
acc = self.accuracy_fn(targets, logits, sample_weights)
self.add_metric(acc, name="accuracy")
# Return the inference-time prediction tensor (for `.predict()`).
return tf.nn.softmax(logits)
@classmethod
def from_config(cls, config):
return cls(**config)
inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10, name='dense')(inputs)
predictions = LogisticEndpoint(name="predictions")(logits, targets)
model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam")
data = {
"inputs": np.random.random((3, 3)),
"targets": np.random.random((3, 10)),
}
model.fit(data)
我觉得这样的模型的 inputs 似乎有些多余,就想绘制出可视化图确认下,于是加了下面这行代码:
keras.utils.plot_model(model, 'strange.png', show_shapes=True)
提示错误:
“ImportError: Failed to import pydot. You must install pydot and graphviz for
pydotprint
to work.”
于是使用 pip 命令安装这两个库:
$ pip install pydot
$ pip install graphviz
结果还是报错,尝试使用 apt 命令安装:
$ apt install python-pydot python-pydot-ng graphviz
不再报这个错误了。但是另一个错误出现了:
File ".../vis_utils.py", line 143, in model_to_dot
layer_name = layer.name
AttributeError: 'dict' object has no attribute 'name'
查询了下,在 GitHub 上找到了关于这个问题的讨论,似乎有 bug,这个我不关心,我关心的是如何解决问题:出现这种错误应该是某些层没有 name 属性,但是绘制函数认为它有,我们把这些层过滤掉就可以了:
model._layers = [layer for layer in model.layers if not isinstance(layer, dict)]
model.summary()
keras.utils.plot_model(model, 'strange.png', show_shapes=True)
到这里就成功了,可以看出 inputs 果然和我估计的一致。
看看哪些层没有 name 属性,在上述代码之前添加下面这些代码:
for layer in model.layers:
if not isinstance(layer, dict):
print(layer)
得到如下输出:
<tensorflow.python.keras.engine.input_layer.InputLayer object at 0x7fbfe8411ef0>
<tensorflow.python.keras.layers.core.Dense object at 0x7fbf6f671390>
<tensorflow.python.keras.engine.input_layer.InputLayer object at 0x7fbf6f671208>
<__main__.LogisticEndpoint object at 0x7fbf6f671d68>
和估计的差不多。