2

問題文MatConvNetはデータとデリバティブのフォーマットが一致しないと言うのはなぜですか?

私は、例のライブラリが付属していますcnn_train機能を使用して、非常に単純な1D例および小規模ネットワークを構築するためにMatConvNetを使用していました。次のように彼らの例に続いて、私は小さなCNNの例を構築しました:

clc;clear;clc;clear; 
%% prepare Data 
M = 32; %batch size 
X_train = zeros(1,1,1,M); % (1 1 1 2) = (1 1 1 M) 
for m=1:M, 
    X_train(:,:,:,m) = m; %training example value 
end 
Y_test = 10*X_train; 
split = ones(1,M); 
split(floor(M*0.75):end) = 2; 
% load image dadabase (imgdb) 
imdb.images.data = X_train; 
imdb.images.label = Y_test; 
imdb.images.set = split; 
%% prepare parameters 
L1=3; 
w1 = randn(1,1,1,L1); %1st layer weights 
w2 = randn(1,1,1,L1); %2nd layer weights 
b1 = randn(1,1,1,L1); %1st layer biases 
b2 = randn(1,1,1,L1); %2nd layer biases 
G1 = ones(1,1,1,L1); % (1 1 1 3) = (1 1 1 L1) BN scale, one per dimension 
B1 = zeros(1,1,1,L1); % (1 1 1 3) = (1 1 1 L1) BN shift, one per dimension 
EPS = 1e-4; 
%% make CNN layers: conv, BN, relu, conv, pdist, l2-loss 
net.layers = {} ; 
net.layers{end+1} = struct('type', 'conv', ... 
          'name', 'conv1', ... 
          'weights', {{w1, b1}}, ... 
          'pad', 0) ; 
net.layers{end+1} = struct('type', 'bnorm', ... 
          'weights', {{G1, B1}}, ... 
          'EPSILON', EPS, ... 
          'learningRate', [1 1 0.05], ... 
          'weightDecay', [0 0]) ;      
net.layers{end+1} = struct('type', 'relu', ... 
          'name', 'relu1') ; 
net.layers{end+1} = struct('type', 'conv', ... 
          'name', 'conv2', ... 
          'weights', {{w2, b2}}, ... 
          'pad', 0) ; 
net.layers{end+1} = struct('type', 'pdist', ... 
          'name', 'averageing1', ... 
          'class', 0, ... 
          'p', 1) ; 
%% add L2-loss     
fwfun = @l2LossForward; 
bwfun = @l2LossBackward; 
net = addCustomLossLayer(net, fwfun, bwfun) ; 
net.layers{end}.class = Y_test; % its the test set 
net = vl_simplenn_tidy(net) ; 
res = vl_simplenn(net, X_train); 
%% prepare train options 
trainOpts.expDir = 'results/' ; %save results/trained cnn 
trainOpts.gpus = [] ; 
trainOpts.batchSize = 2 ; 
trainOpts.learningRate = 0.02 ; 
trainOpts.plotDiagnostics = false ; 
%trainOpts.plotDiagnostics = true ; % Uncomment to plot diagnostics 
trainOpts.numEpochs = 20 ; % number of training epochs 
trainOpts.errorFunction = 'none' ; 
%% CNN TRAIN 
vl_simplenn_display(net) ; 
net = cnn_train(net, imdb, @getBatch, trainOpts) ; 

を私は例を実行するたびに、私はエラーを取得し、the example they providedに応じてこれを作成しました:

Error using vl_nnconv 
DATA and DEROUTPUT do not have compatible formats. 

Error in vl_simplenn (line 397) 
      [res(i).dzdx, dzdw{1}, dzdw{2}] = vl_nnconv(res(i).x, l.weights{1}, 
      l.weights{2}, res(i+1).dzdx) 

Error in cnn_train>process_epoch (line 323) 
    res = vl_simplenn(net, im, dzdy, res, ... 

Error in cnn_train (line 139) 
    [net,stats.train,prof] = process_epoch(opts, getBatch, epoch, train, learningRate, 
    imdb, net) ; 

Error in main_1D_1layer_hard_coded_example (line 64) 
net = cnn_train(net, imdb, @getBatch, trainOpts) ; 

誰かが何が起こっているか知っています?この例は実際にはシンプルなので、私には間違ったことが混乱していると思われます。私はこのを解決するために試した事の


補足SECTION。

私はこれを解決しようとしたことの詳細については、先読みしてください。

私は、エラーの原因となったファイルにその行に行って、私は意味を成していた引数を与えていたことを確認するために、その関数への入力を印刷し、そのすべてが、その点での細かいようです:

case 'conv' 
     size(res(i).x) 
     size(res(i+1).dzdx) 
     size(l.weights{1}) 
     size(l.weights{2}) 
     [res(i).dzdx, dzdw{1}, dzdw{2}] = vl_nnconv(res(i).x, l.weights{1}, l.weights{2}, res(i+1).dzdx) 
    [res(i).dzdx, dzdw{1}, dzdw{2}] = ... 
     vl_nnconv(res(i).x, l.weights{1}, l.weights{2}, res(i+1).dzdx, ... 
     'pad', l.pad, ... 
     'stride', l.stride, ... 
     l.opts{:}, ... 
     cudnn{:}) ; 

プリント:

ans = 

    1  1  3 16 


ans = 

    1  1  3 16 


ans = 

    1  1  1  3 


ans = 

    1  1  1  3 

私は予想どおりです。

私も先に行って、手動でハード誘導体のチェーンネットワークを計算しなければならないものをコード化し、そのファイルが正常に動作するようです:

clc;clear;clc;clear; 
%% prepare Data 
M = 3; 
x = zeros(1,1,1,M); % (1 1 1 2) = (1 1 1 M) 
for m=1:M, 
    x(:,:,:,m) = m; 
end 
Y = 5; 
r=Y; 
%% parameters 
L1 = 3; 
w1 = randn(1,1,1,L1); % (1 1 1 L1) = (1 1 1 3) 
b1 = ones(1,L1); 
w2 = randn(1,1,1,L1); % (1 1 1 L1) = (1 1 1 3) 
b2 = ones(1,L1); 
G1 = ones(1,1,1,L1); % (1 1 1 3) = (1 1 1 L1) BN scale, one per dimension 
B1 = zeros(1,1,1,L1); % (1 1 1 3) = (1 1 1 L1) BN shift, one per dimension 
EPS = 1e-4; 
%% Forward Pass 
z1 = vl_nnconv(x,w1,b1); % (1 1 3 2) = (1 1 L1 M) 
%bn1 = z1; 
bn1 = vl_nnbnorm(z1,G1,B1,'EPSILON',EPS); % (1 1 3 2) = (1 1 L1 M) 
a1 = vl_nnrelu(bn1); % (1 1 3 2) = (1 1 L1 M) 
z2 = vl_nnconv(a1,w2,b2); 
y1 = vl_nnpdist(z2, 0, 1); 
loss_forward = l2LossForward(y1,Y); 
%% 
net.layers = {} ; 
net.layers{end+1} = struct('type', 'conv', ... 
          'name', 'conv1', ... 
          'weights', {{w1, b1}}, ... 
          'pad', 0) ; 
net.layers{end+1} = struct('type', 'bnorm', ... 
          'weights', {{G1, B1}}, ... 
          'EPSILON', EPS, ... 
          'learningRate', [1 1 0.05], ... 
          'weightDecay', [0 0]) ;      
net.layers{end+1} = struct('type', 'relu', ... 
          'name', 'relu1') ; 
net.layers{end+1} = struct('type', 'conv', ... 
          'name', 'conv2', ... 
          'weights', {{w2, b2}}, ... 
          'pad', 0) ; 
net.layers{end+1} = struct('type', 'pdist', ... 
          'name', 'averageing1', ... 
          'class', 0, ... 
          'p', 1) ; 
fwfun = @l2LossForward; 
bwfun = @l2LossBackward; 
net = addCustomLossLayer(net, fwfun, bwfun) ; 
net.layers{end}.class = Y; 
net = vl_simplenn_tidy(net) ; 
res = vl_simplenn(net, x); 
%% 
loss_forward = squeeze(loss_forward) % (1 1) 
loss_res = squeeze(res(end).x) % (1 1) 
%% Backward Pass 
p = 1; 
dldx = l2LossBackward(y1,r,p); 
dy1dx = vl_nnpdist(z2, 0, 1, dldx); 
[dz2dx, dz2dw2] = vl_nnconv(a1, w2, b2, dy1dx); 
da1dx = vl_nnrelu(bn1, dz2dx); 
[dbn1dx,dbn1dG1,dbn1dB1] = vl_nnbnorm(z1,G1,B1,da1dx); 
[dz1dx, dz1dw1] = vl_nnconv(x, w1, b1, dbn1dx); 
%% 
dzdy = 1; 
res = vl_simplenn(net, x, dzdy, res); 
%% 
% func = @(x) proj(p, forward(x, x0)) ; 
% err = checkDerivativeNumerically(f, x, dx) 
% %% 
dz1dx = squeeze(dz1dx) 
dz1dx_vl_simplenn = squeeze(res(1).dzdx) 

私はそのすべてを想定すると思いますので、誘導体は数学に思えますそのファイルは機能します。それはエラーを投げるわけではないので、それが実行されないという事実は私には非常に混乱しています。誰でも何が起こっているのか知っていますか?


私のCNNをロードする方法は、the example fileに基づいており、チュートリアルで提供しています。私はそのファイルの重要な側面の概要を貼り付けます(これはcnn_train関数でうまく動作しますが、私の場合はそうではありません)。

setup() ; 
% setup('useGpu', true); % Uncomment to initialise with a GPU support 
%% Part 3.1: Prepare the data 
% Load a database of blurred images to train from 
imdb = load('data/text_imdb.mat') ; 

%% Part 3.2: Create a network architecture 

net = initializeSmallCNN() ; 
%net = initializeLargeCNN() ; 
% Display network 
vl_simplenn_display(net) ; 

%% Part 3.3: learn the model 
% Add a loss (using a custom layer) 
net = addCustomLossLayer(net, @l2LossForward, @l2LossBackward) ; 

% Train 
trainOpts.expDir = 'data/text-small' ; 
trainOpts.gpus = [] ; 
% Uncomment for GPU training: 
%trainOpts.expDir = 'data/text-small-gpu' ; 
%trainOpts.gpus = [1] ; 
trainOpts.batchSize = 16 ; 
trainOpts.learningRate = 0.02 ; 
trainOpts.plotDiagnostics = false ; 
%trainOpts.plotDiagnostics = true ; % Uncomment to plot diagnostics 
trainOpts.numEpochs = 20 ; 
trainOpts.errorFunction = 'none' ; 

net = cnn_train(net, imdb, @getBatch, trainOpts) ; 
+2

あなたはあまり例のないものを考え出すことができますか?*非* - 最小? –

+0

@AndrasDeak確かに、その複雑さを意味しますか?そのシンプルなネットワークと私はそれを修正しようとしたことのいくつかを提供しています。 – Pinocchio

+0

私はもっと簡単なことを説得するために、この例をもっとコメントしてみました。それが役に立てば幸い。 – Pinocchio

答えて

3

w2のサイズは1x1x3x3である必要があります。

バイアスは、通常、1つのディメンション(または重みの場合は1×1×3×N、対応するバイアスの場合は1×N、Nはフィルタの数)のみを持つため、1×3として与えられ、B1とG1(ここでは1xMであり、Mは前の層のフィルタの数である)。しかしどちらかの方法で動作する可能性があります。

例では、最初の畳み込み後のxのサイズは1x1x3x16です。つまり、各要素の幅と高さがそれぞれ1と3の16個の要素が1つのバッチに含まれていることを意味します。最初の畳み込みは3つのフィルタ(w1の寸法は1x1x1x3です)で行われたためです。

w2は、幅、高さ、深さ1の3つのフィルタを表す1x1x1x3の寸法を持ちます。したがって、フィルタの深さは入力の深さと一致しません。

+0

2つのコメント、1)私はw2 1x1x3x3を作ったが、それでも残念ながら走らなかった。 2)あなたの推論は理にかなっていますが、それでも私が困っているのは、あなたの議論が正しければ、なぜモデルで順調に進むことができるのでしょうか?私が与えたコードに気がついたら、モデルを評価し、実際には私の驚きに応じて 'res = vl_simplenn(net、X_train);という行があります。ディメンションの不一致があった場合、フォワードパスはなぜ実行されますか? まだ分かりませんが、エラー出力からバックパスが問題になっているようです。私はチェックしようとします。 – Pinocchio

+1

私はそれを見逃しているに違いない。それは奇妙だ。たぶん、私はあなた自身のコードを試して、次の数日間に時間があります。 – Wiseful

0

カスタムレイヤーを作成して同じ問題が発生しました。私は最終的にmatconvnetの実装を追跡して、その解決策を見つけました。後で他の人に役立つことを願っています。

要するに、2つのデータが空ではなく、ヌルでなく、同じデバイスタイプ(GPUまたはCPU)と同じデータタイプ(浮動小数点、単一または文字)であることを確認する必要があります。

私の場合、両方のデータに同じ 'gpuArray'と 'single'が必要です。まず、エラー

DATA and FILTERS do not have compatible formats

DATA and BIASES do not have compatible formats

DATA and DEROUTPUT do not have compatible formats

は正確に2つの変数が持っていないことを

======詳細================== を言います互換性のあるフォーマット。 Matconvnetは「互換フォーマット」を意味しますか? これは、ライン269〜278

/* check for GPU/data class consistency */ 


if (hasFilters && ! vl::areCompatible(data, filters)) { 
    vlmxError(VLMXE_IllegalArgument, "DATA and FILTERS do not have compatible formats.") ; 
    } 
    if (hasBiases && ! vl::areCompatible(data, biases)) { 
    vlmxError(VLMXE_IllegalArgument, "DATA and BIASES do not have compatible formats.") ; 
    } 
    if (backMode && ! vl::areCompatible(data, derOutput)) { 
    vlmxError(VLMXE_IllegalArgument, "DATA and DEROUTPUT do not have compatible formats.") ; 
    } 

は、エラーが

ので
inline bool areCompatible(Tensor const & a, Tensor const & b) 
    { 
    return 
    (a.isEmpty() || a.isNull()) || 
    (b.isEmpty() || b.isNull()) || 
    ((a.getDeviceType() == b.getDeviceType()) & (a.getDataType() == b.getDataType())) ; 
    } 

として実装された機能VL :: areCompatibleから来る、vl_nnconv.cuに実装され、基本的に、それは、任意の入力があるかどうかをチェックします空またはヌルで、両方の入力が同じデータ型(double、single、vs char)とデバイスタイプ(GPU、CPU)を持つことを確認します。

/// Type of device: CPU or GPU 
    enum DeviceType { 
    VLDT_CPU = 0, 
    VLDT_GPU 
    } ; 

    /// Type of data (char, float, double, ...) 
    enum DataType { 
    VLDT_Char, 
    VLDT_Float, 
    VLDT_Double 
    } ; 
関連する問題