2017-08-01 3 views
1

J'ai une exigence pour implémenter le calcul avancé de la couche de déconv ​​de la manière du filtre 3D.Comment implémenter la couche deconv dans caffe de la manière du filtre 3D?

Ici, par 'manière de filtre 3D', je veux dire convolution comme le filtre gaussien dans CV. Dans le contraste, le caffe implémente le déconv ​​de la manière gemm + col2im. Je trouve une question similaire here. Le gars a écrit le code selon l'introduction dans tranposed conv.

Image

Il/Elle n'ouvre pas le code source. Donc, je finis mon propre un:

template <typename DataType> int deconv_cpu(
    DataType *src, DataType *dst, DataType *para, DataType *bias, 
    int in_width, int in_height, int in_channel, 
    int out_width, int out_height, int out_channel, 
    int ks, int padding = 0, int step = 1) { // step indicates the stride 

    int col, row, ch_o, ch_i, x, y; 
    int r = (ks - 1)/2; //radius; 

    DataType result; 
    DataType *output; 
    DataType *filter; 
    DataType *input; 

    int sim_width, sim_height, sim_pad, width_border, height_border; 
    sim_width = in_width * step - step + 1; 
    sim_height = in_height * step - step + 1; 
    sim_pad = ks - padding - 1; 
    width_border = sim_pad == 0 ? r : 0; 
    height_border = sim_pad == 0 ? r : 0; 
    for (row = height_border; row < (sim_height - height_border); row++) 
    for (col = width_border; col < (sim_width - width_border); col++) 
    { 
     for (ch_o = 0; ch_o < out_channel; ch_o++) 
     { 
      output = dst + ch_o * out_width * out_height; 
      result = 0; 
      for (ch_i = 0; ch_i < in_channel; ch_i++) 
      { 
       filter = para + ks * ks * (in_channel * ch_o + ch_i); 
       //filter = para + ks*ks * (out_channel * ch_i + ch_o); 
       input = src + ch_i * in_width * in_height; 
       for (x = -r; x <= r; x++) 
       { 
        for (y = -r; y <= r; y++) 
        { 
         if ((row + x) >= 0 && (col + y) >= 0 && (row + x) < sim_height && (col + y) < sim_width) 
         { 
          if ((row + x) % step != 0 || (col + y) % step != 0) continue; 
          result += input[(row + x)/step * in_width + (col + y)/step] * filter[(x + r) * ks + (y + r)]; 
         } 
        } 
       } 
      } 

      if (bias != NULL) result = result + bias[ch_o]; 
      output[(row - height_border) * out_width + (col - width_border)] = result; 
     } 
    } 
    return 0; 
} 

Je compare le résultat avec un de l'caffe:

const caffe::vector<caffe::shared_ptr<caffe::Blob<float> > > blobs = layers[i]->blobs(); 
float *filter = blobs[0]->mutable_cpu_data(); 
float *bias = blobs[1]->mutable_cpu_data(); 

caffe::shared_ptr<caffe::Blob<float> > blob; 
blob = caffe_net->blob_by_name(np.bottom(0)); 
deconv_cpu(blob->mutable_cpu_data(), dst, filter, bias, width1, 
height1, c1, width2, height2, c2, ks, pad, stride); 

blob = caffe_net->blob_by_name(np.top(0)); 
if(compare(dst, blob->mutable_cpu_data()) == 0) printf("match\n"); 
else printf("do not match\n"); 

Cependant, le code ne donne pas le même résultat avec la mise en œuvre du caffe.

Est-ce que quelqu'un sait ce qui ne va pas? Ou des conseils ou des commentaires sur le code?

Répondre

0

Ce problème est finalement corrigé en changeant l'index de filtre: filtre [(r-x) * ks + (r-y)]