1. ホーム
  2. neural-network

[解決済み] tf.nn.conv2dはtensorflowで何をするのですか?

2022-05-09 21:14:35

質問

について、tensorflowのドキュメントを見ていました。 tf.nn.conv2d これ . しかし、これが何をするものなのか、何を実現しようとしているのかが理解できないのです。ドキュメントにはこう書いてあります。

#1 : フィルターを形状を持った2次元の行列に平坦化します。

[filter_height * filter_width * in_channels, output_channels] .

さて、これは何をするものなのでしょうか?要素ごとの乗算なのか、それとも単なる行列の乗算なのか?また、ドキュメントに記載されている他の2つのポイントも理解できませんでした。私はそれらを以下に書きました。

# その2:入力テンソルから画像パッチを抽出し、形状の仮想テンソルを形成する。

[batch, out_height, out_width, filter_height * filter_width * in_channels] .

# 3: 各パッチについて、フィルタ行列と画像パッチベクトルを右掛けする。

どなたか、例やコードの一部(非常に助かります)を示して、そこで何が起こっているのか、なぜこのような操作になるのかを説明していただけると本当に助かります。

ほんの一部をコーディングして、操作の形をプリントアウトしてみました。それでも理解できません。

こんな感じでやってみました。

op = tf.shape(tf.nn.conv2d(tf.random_normal([1,10,10,10]), 
              tf.random_normal([2,10,10,10]), 
              strides=[1, 2, 2, 1], padding='SAME'))

with tf.Session() as sess:
    result = sess.run(op)
    print(result)

畳み込みニューラルネットワークについては、断片的に理解しています。私はそれらを研究しました こちら . しかし、tensorflow上の実装は私が期待したものではありません。そこで疑問がわきました。

EDIT : というわけで、もっとシンプルなコードを実装してみました。しかし、何が起こっているのかがわからないのです。つまり、どうしてこのような結果になるのか。どのような処理でこのような出力が出るのか、どなたか教えていただけると非常に助かります。

input = tf.Variable(tf.random_normal([1,2,2,1]))
filter = tf.Variable(tf.random_normal([1,1,1,1]))

op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
init = tf.initialize_all_variables()
with tf.Session() as sess:
    sess.run(init)

    print("input")
    print(input.eval())
    print("filter")
    print(filter.eval())
    print("result")
    result = sess.run(op)
    print(result)

出力

input
[[[[ 1.60314465]
   [-0.55022103]]

  [[ 0.00595062]
   [-0.69889867]]]]
filter
[[[[-0.59594476]]]]
result
[[[[-0.95538563]
   [ 0.32790133]]

  [[-0.00354624]
   [ 0.41650501]]]]

解決方法は?

2次元の畳み込みは、次のような方法で計算されます。 1次元の畳み込み カーネルを入力にスライドさせ、要素ごとの乗算を計算し、それらを合計するのです。しかし、カーネルや入力が配列である代わりに、ここでは行列です。


最も基本的な例では、パディングはなく、stride=1です。ここで、あなたの inputkernel があります。 <イグ

作成したカーネルを使用すると、次のような出力が得られます。 は、次のように計算されます。

  • 14 = 4 * 1 + 3 * 0 + 1 * 1 + 2 * 2 + 1 * 1 + 0 * 0 + 1 * 0 + 2 * 0 + 4 * 1
  • 6 = 3 * 1 + 1 * 0 + 0 * 1 + 1 * 2 + 0 * 1 + 1 * 0 + 2 * 0 + 4 * 0 + 1 * 1
  • 6 = 2 * 1 + 1 * 0 + 0 * 1 + 1 * 2 + 2 * 1 + 4 * 0 + 3 * 0 + 1 * 0 + 0 * 1
  • 12 = 1 * 1 + 0 * 0 + 1 * 1 + 2 * 2 + 4 * 1 + 1 * 0 + 1 * 0 + 0 * 0 + 2 * 1

TFの コンバージョン2D 関数はコンボリューションを一括して計算し、若干異なるフォーマットを使用します。入力は [batch, in_height, in_width, in_channels] カーネルは [filter_height, filter_width, in_channels, out_channels] . ですから、正しいフォーマットでデータを提供する必要があります。

import tensorflow as tf
k = tf.constant([
    [1, 0, 1],
    [2, 1, 0],
    [0, 0, 1]
], dtype=tf.float32, name='k')
i = tf.constant([
    [4, 3, 1, 0],
    [2, 1, 0, 1],
    [1, 2, 4, 1],
    [3, 1, 0, 2]
], dtype=tf.float32, name='i')
kernel = tf.reshape(k, [3, 3, 1, 1], name='kernel')
image  = tf.reshape(i, [1, 4, 4, 1], name='image')

その後、コンボリューションが計算される。

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "VALID"))
# VALID means no padding
with tf.Session() as sess:
   print sess.run(res)

と、手で計算したものと同等になります。


について パディング/ストライドの例は、こちらをご覧ください。 .