1

我想知道 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

在这里完成要点:

https://colab.research.google.com/gist/eduardo4jesus/6721ec992c402bcdc834ab2edbc1b2b4/tf1-flops.ipynb

以下结果的解释是什么?

  1. 如果我运行上面的代码,只有未InputLayer注释的情况下,FLOPS 输出为2.

Q1:为什么2

  1. 如果我按如下方式运行代码,则输出为2050.
model = tf.keras.models.Sequential([
        InputLayer((32, 32, 1)),
        Flatten(),
        Dense(1, activation='softmax')
    ])

Q2:为什么2050??我期待着1026加上1024那些无法解释的2。这 1024 个将来自密集层的权重,因为我们有一个神经元是每个输入特征的一个参数,因此,1024. 再说一遍,为什么要加倍?(反向传播??)

  1. 最有趣和最重要的一个。如果我按如下方式运行代码,则输出为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*KwhereN=32K=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
      }
    }
  }
}
4

1 回答 1

1

我认为这个 API 充其量只是实验性的。

Q1。不知道 2 是从哪里来的。

Q2。正如我们所见,2 与 Input 有关。还剩 2048 个。您的输入大小是 32*32*1,它是 1024 展平的。你的计算是 x W+b,其中 x 是 [1024],对应的 W 是 [1, 1024]。x W 的运算将导致 1024 次乘法和 1024 次加法。偏置添加似乎被忽略了,因为否则它应该会导致总共 2051 个操作:2+1024+1024+1。

Q3。我将您的过滤器大小更改为 3 并得到 21 次失败,这太荒谬了。CPU/GPU 执行器的数字没有改变。我的结论是卷积层不会产生可信的数字。

tf.keras.models.Sequential([
        InputLayer((32, 32, 1)),
        Conv2D(1, 3, padding='same'),
        Flatten(),
    ]) # => 21 ops



tf.keras.models.Sequential([
    InputLayer((32, 32, 1)),
    Conv2D(32, 3, padding='same'),
    Conv2D(1, 3, padding='same'),
    Flatten(),
]) # => 1.09K ops
于 2019-12-24T00:43:36.913 回答