私は、tf.layersがよりサポートされており、将来性のあるオプションであるように見えるため、tf-slimのconv2dの使用からtf.layers.conv2dの使用に使用しているネットワークを変換しようとしています。関数のシグネチャはかなり似ていますが、2つの間にアルゴリズム的に異なるものがありますか?予想とは異なる出力テンソル次元を取得しています。
x = tf.layers.conv2d(inputs=x,
filters=256,
kernel_size=[3,3],
trainable=True)
これとは対照的に:
x = slim.conv2d(x, 256, 3)
予想とは異なる出力テンソル次元を取得しています。
これは、tf.layers.conv2dが有効なパディングを使用するのに対し、デフォルトでは、slim.conv2dは同じパディングを使用するという事実によるものです。
まったく同じ動作を再現する場合は、正しい実装を次に示します。
x = tf.layers.conv2d(x, 256, 3, padding='same')
tf.slim
パッケージの説明 は、違いにもう少し光を当てます。具体的には、「レイヤー」の下を見ると、次のことがわかります。
レイヤー
TensorFlowの一連の操作は非常に広範囲ですが、ニューラルネットワークの開発者は通常、「レイヤー」、「損失」、「メトリック」、「ネットワーク」などの高レベルの概念の観点からモデルを考えます。畳み込み層、完全に接続された層、BatchNorm層などの層は、単一のTensorFlow操作よりも抽象的であり、通常はいくつかの操作が含まれます。さらに、より基本的な操作とは異なり、レイヤーには通常(常にではないが)変数(調整可能なパラメーター)が関連付けられています。たとえば、ニューラルネットワークの畳み込み層は、いくつかの低レベルの操作で構成されています。
- 重み変数とバイアス変数の作成
- 前のレイヤーからの入力で重みを畳み込む
- 畳み込みの結果にバイアスを追加します。
- アクティベーション機能の適用。
単純なTensorFlowコードのみを使用すると、これはかなり面倒です。
input = ... with tf.name_scope('conv1_1') as scope: kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 128], dtype=tf.float32, stddev=1e-1), name='weights') conv = tf.nn.conv2d(input, kernel, [1, 1, 1, 1], padding='SAME') biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32), trainable=True, name='biases') bias = tf.nn.bias_add(conv, biases) conv1 = tf.nn.relu(bias, name=scope)
このコードを繰り返し複製する必要性を軽減するために、TF-Slimは、ニューラルネットワーク層のより抽象的なレベルで定義された多くの便利な操作を提供します。たとえば、上記のコードを対応するTF-Slimコードの呼び出しと比較します。
input = ... net = slim.conv2d(input, 128, [3, 3], scope='conv1_1')
要するに、slim
演算子はTensorFlowのすべての核心の詳細を心配する必要がないように、いくつかのきちんとした抽象化を行います。ただし、これはまだ活発に開発されているようですので、今後の開発で積極的に使用する前に、もう少し詳しく説明します。