我想知道 Tensorflow 卷积层中浮点运算的数量。
当我等待在 TF 2.x 上发布此功能时,我在 TF 1.x 上进行了尝试,结果我不明白是如何计算的,其中一个非常令人印象深刻(检查问题 3)。
我有以下代码:
tf.reset_default_graph()
model = tf.keras.models.Sequential([
InputLayer((32, 32, 1)),
# Conv2D(1, 5, padding='same'),
# Flatten(),
# Dense(1, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
opts = tf.profiler.ProfileOptionBuilder.float_operation()
profile = tf.profiler.profile(tf.get_default_graph(), tf.RunMetadata(), cmd='op', options=opts)
profile.total_float_ops
在这里完成要点:
以下结果的解释是什么?
- 如果我运行上面的代码,只有未
InputLayer
注释的情况下,FLOPS 输出为2
.
Q1:为什么
2
?
- 如果我按如下方式运行代码,则输出为
2050
.
model = tf.keras.models.Sequential([
InputLayer((32, 32, 1)),
Flatten(),
Dense(1, activation='softmax')
])
Q2:为什么
2050?
?我期待着1026
加上1024
那些无法解释的2
。这 1024 个将来自密集层的权重,因为我们有一个神经元是每个输入特征的一个参数,因此,1024
. 再说一遍,为什么要加倍?(反向传播??)
- 最有趣和最重要的一个。如果我按如下方式运行代码,则输出为
2101
.
model = tf.keras.models.Sequential([
InputLayer((32, 32, 1)),
Conv2D(1, 5, padding='same'),
Flatten(),
Dense(1, activation='softmax')
])
Q3:为什么
2101?
?我期待2050 + 1024 x 5
这比 only 更大2101
。卷积层本身应该产生N*N*K*K
whereN=32
和K=5
。考虑到卷积产生相同形状的输入,为什么模型比仅最后一层需要更少的 FLOP?它有什么样的疯狂优化?
[更新]
打印配置文件时,我有这些节点有助于total_float_ops
. 它们中的大多数(见下文)与 相关Initializer
,而不是模型计算本身。
name: "_TFProfRoot"
total_float_ops: 2101
children {
name: "Mul"
float_ops: 1050
total_float_ops: 2101
graph_nodes {
name: "conv2d/kernel/Initializer/random_uniform/mul"
float_ops: 25
total_float_ops: 25
input_shapes {
key: 0
value {
dim {
size: 5
}
dim {
size: 5
}
dim {
size: 1
}
dim {
size: 1
}
}
}
input_shapes {
key: 1
value {
dim {
size: 1
}
}
}
total_definition_count: 1
}
graph_nodes {
name: "dense/kernel/Initializer/random_uniform/mul"
float_ops: 1024
total_float_ops: 1024
input_shapes {
key: 0
value {
dim {
size: 1024
}
dim {
size: 1
}
}
}
input_shapes {
key: 1
value {
dim {
size: 1
}
}
}
total_definition_count: 1
}
graph_nodes {
name: "loss/dense_loss/weighted_loss/Mul"
input_shapes {
key: 0
value {
dim {
size: -1
}
}
}
input_shapes {
key: 1
value {
dim {
size: -1
}
}
}
total_definition_count: 1
}
graph_nodes {
name: "loss/dense_loss/weighted_loss/broadcast_weights"
input_shapes {
key: 0
value {
dim {
size: 1
}
}
}
input_shapes {
key: 1
value {
dim {
size: -1
}
}
}
total_definition_count: 1
}
graph_nodes {
name: "loss/mul"
float_ops: 1
total_float_ops: 1
input_shapes {
key: 0
value {
dim {
size: 1
}
}
}
input_shapes {
key: 1
value {
dim {
size: 1
}
}
}
total_definition_count: 1
}
children {
name: "Add"
float_ops: 1049
total_float_ops: 1051
graph_nodes {
name: "conv2d/kernel/Initializer/random_uniform"
float_ops: 25
total_float_ops: 25
input_shapes {
key: 0
value {
dim {
size: 5
}
dim {
size: 5
}
dim {
size: 1
}
dim {
size: 1
}
}
}
input_shapes {
key: 1
value {
dim {
size: 1
}
}
}
total_definition_count: 1
}
graph_nodes {
name: "dense/kernel/Initializer/random_uniform"
float_ops: 1024
total_float_ops: 1024
input_shapes {
key: 0
value {
dim {
size: 1024
}
dim {
size: 1
}
}
}
input_shapes {
key: 1
value {
dim {
size: 1
}
}
}
total_definition_count: 1
}
children {
name: "Sub"
float_ops: 2
total_float_ops: 2
graph_nodes {
name: "conv2d/kernel/Initializer/random_uniform/sub"
float_ops: 1
total_float_ops: 1
input_shapes {
key: 0
value {
dim {
size: 1
}
}
}
input_shapes {
key: 1
value {
dim {
size: 1
}
}
}
total_definition_count: 1
}
graph_nodes {
name: "dense/kernel/Initializer/random_uniform/sub"
float_ops: 1
total_float_ops: 1
input_shapes {
key: 0
value {
dim {
size: 1
}
}
}
input_shapes {
key: 1
value {
dim {
size: 1
}
}
}
total_definition_count: 1
}
}
}
}