はい、緻密層重み行列の適切な再形成が行われる場合は同じです。
最初に高密度レイヤーを見てみましょう。密集層に20 x 20 x 10
の行列を入力します。最初に平滑化されて4000 x 1
ベクトルを生成します。出力のサイズは64 x 1
です。したがって、必要な重み行列は、4000 x 64
とバイアスパラメータとなります。次にy = w^T * x + b = [4000 x 64]^T * [4000 x 1] + [64 x 1]
は[64 x 1]
ベクターを産生する。したがって、i = [0, 63]
の場合はy[i] = w[i][0]*x[0] + ... + w[i][3999]*x[3999] + b[i]
となります。 b
はバイアスパラメータを示します。
畳み込みにしましょう。サイズ100 x 60 x 10
の入力から5 x 3 x 64
を出力するには、サイズがそれぞれ(20,20)
およびストライド(20,20)
でゼロパディングなしの64個のフィルタが必要です。しかしながら、各20 x 20
フィルタは、深さ全体に沿って延びるローカル接続性を有する、すなわち、ニューロンは、入力の深さに沿って10次元すべてに接続される。畳み込みレイヤのローカル接続に関する詳細については、thisを参照してください。
あなたの畳み込みレイヤは、20 x 20
という受容野を持っています。畳み込み層の各ニューロンは20 x 20 x 10
に接続されます。したがって、合計4000の重み(および1つのバイアスパラメータ)。あなたはそのようなフィルタが64あります。したがって、この層の合計学習可能な重み= 4000 x 64 + 64
です。いくつかの細かい点はここであり
convResult = np.sum(np.sum(np.sum(x*w[:,:,::-1,::-1], axis=-1), axis=-1),axis=-1)
:x
とw
の20 x 20 x 10
ブロックとの間の畳み込み(サイズ= 64 x 20 x 20 x 10
)のように行うことができます。私はw[:,:,::-1,::-1]
でした。なぜなら、theano convolutionはconvolutionカーネルを反転させるからです(そう簡単ではありません!)。誰がフリップし、誰が誰に興味がないのであれば、thisを読んでください。
最後に、密なレイヤーと畳み込みレイヤーは、本質的に同じ操作を行います。彼らは最初に要素ごとに掛け合わせ、4000個の要素のベクトル/行列の2つの集合を集計します。この手順を64回繰り返して64 x 1
ベクターを作製する。したがって、稠密層重み行列を適切に再形成することによって、稠密かつ畳み込み層で正確に同じ結果を達成することが可能である。しかし、結果を一致させるためには、カーネルの反転を注意する必要があります。
以下では、手動で(numpyを使用して)コンボルーションを計算し、Theanoを使用するコードスニペットを示します。
import theano
from theano import tensor as T
import numpy as np
X = T.ftensor4('X')
W = T.ftensor4('W')
out = T.nnet.conv2d(X,W)
f = theano.function([X, W], out, allow_input_downcast=True)
x = np.random.random((1,10,20,20))
w = np.random.random((64,10,20,20))
# convolution using Theano
c1 = np.squeeze(f(x,w)[0])
# convolution using Numpy
c2 = np.sum(np.sum(np.sum(x*w[:,:,::-1,::-1],axis=-1),axis=-1),axis=-1)
# check that both are almost identical
print np.amax(c2 - c1)
私は同じだと思います。私は後で詳しく答えを書くつもりです。 –