为了学习张量流,我执行了这个tensorflow官方mnist脚本(cnn_mnist.py)并显示了带有张量板的图形。
以下是代码的一部分。 该网络包含两个转换层和两个密集层。
conv1 = tf.layers.conv2d(inputs=input_layer,filters=32,kernel_size=[5, 5],
padding="same",activation=tf.nn.relu)
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
conv2 = tf.layers.conv2d(inputs=pool1,filters=64,kernel_size=[5, 5],
padding="same",activation=tf.nn.relu)
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])
dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
dropout = tf.layers.dropout(
inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)
logits = tf.layers.dense(inputs=dropout, units=10)
然而,查看由张量板生成的图形,有三个转换层和三个密集层。
我没想到会生成conv2d_1
和dense_1
。
为什么生成了conv2d_1
和dense_1
?
答案 0 :(得分:1)
这是一个很好的问题,因为它为# php garbage collection for file-based sessions on debian is done via
# cronjob but roundcubemail uses mysql as storage during runtime which is
# not cleaned up by the cronjob. So reenable the default php gc method
php_admin_value session.gc_probability 1
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/(roundcubemail|webmail)
RewriteRule ^[a-zA-Z0-9]{16}/(.*) /%1/$1 [PT,L]
</ifModule>
<ifModule mod_authz_core.c>
Require all granted
</ifModule>
<ifModule !mod_authz_core.c>
Order Allow,Deny
Allow from All
</ifModule>
包装器的内部结构提供了一些启示。我们进行两个实验:
tf.layers
参数向图层添加显式名称,然后重新运行。这与你的图形相同,但我扩展并放大到logits密集层。请注意,name
包含图层变量(内核和偏差),dense_1
包含ops(矩阵乘法和加法)。
这意味着仍然是一层,但两个命名范围 - dense_2
和dense_1
。这是因为这是第二个密集层,第一个已使用命名范围dense_2
。变量创建与实际层逻辑分离 - 有dense
和build
方法, - 它们都尝试获取范围的唯一名称。这导致call
和dense_1
分别保留变量和操作。
现在让我们将dense_2
添加到同一层并再次运行:
name='logits'
你可以看到仍然有2个变量和2个操作,但是该层设法获取范围的一个唯一名称(logits = tf.layers.dense(inputs=dropout, units=10, name='logits')
)并将所有内容放入其中。
这是一个很好的例子,为什么张量流中的显式命名是有益的,无论它是关于张量直接还是更高层次。当模型使用有意义的名称而不是自动生成的名称时,会产生更少的混淆。
答案 1 :(得分:0)
它们只是tf.layers.conv2d
中发生的变量创建和其他隐藏操作,而不仅仅是卷积操作本身(tf.nn.conv2d
)和激活(同样适用于密集层)。只有2个卷积发生:正如您所看到的,如果您按照图表中的数据操作,它永远不会通过conv2D_1
或dense_1
,只是这些操作的结果(基本上是所需的变量)对于卷积运算本身也作为输入给出。我实际上更惊讶的是没有看到同样出现在conv_2d上的东西,但我真的不担心!