TensorFlow deconvolution (Deconv) Implementation principle + handwritten Python code to achieve deconvolution (DECONV)

Source: Internet
Author: User

The previous article has introduced the implementation of convolution, this article we learn the deconvolution principle, again, after understanding the deconvolution principle, in the back hand-written Python code to implement the deconvolution. 1 Inverse convolution principle

The deconvolution principle does not work well with text descriptions, where the deconvolution process is described directly in a simple example.

Suppose the input is as follows:

[[1,0,1],
 [0,2,1],
 [1,1,0]]

The deconvolution volume kernel is as follows:

[[1, 0, 1],
 [-1, 1, 0],
 [0,-1, 0]]

Now the deconvolution is done by stride=2, which changes the size from the original 3*3 to 6*6. Then in the TensorFlow framework, the process of deconvolution is as follows (different frames may not be the same step in cropping):


In fact, through this diagram I have drawn, the principle has been made clear. The general step is to fill 0, and then convolution, convolution process with the previous article is consistent. The final step also needs to be trimmed. Well, the principle is finished, (#^.^#) ... 2 Code Implementation

In the previous article we only aimed at the output channel number of 1 for code implementation, in this article, deconvolution, we set the output channel to multiple, so that more in line with the actual scene.

Define input and convolution cores first:

input_data=[[[1,0,1], [0,2,1], [1,1,0]], [[2,0,2],

               [0,1,0], [1,0,0]], [[1,1,1], [2,2,0], [1,1,1]],
[[1,1,2], [1,0,1], [0,2,2]]] weights_data=[[[[1, 0, 1], [-1, 1, 0], [0,-1, 0]], [[-1,
                0, 1], [0, 0, 1], [1, 1, 1]], [[0, 1, 1], [2, 0, 1],

              [1, 2, 1]], [[1, 1, 1], [0, 2, 1], [1, 0, 1]],
                [[[1, 0, 2], [-2, 1, 1], [1,-1, 0]], [[-1, 0, 1], [-1, 2, 1], [1, 1, 1]], [[0, 0, 0], [2, 2, 1], [1,-1, 1 ]], [[2, 1, 1], [0,-1, 1], [1, 1, 1]]]]
 

The input and convolution cores defined above are followed by the following operation as shown in the diagram below:

As you can see, the deconvolution and convolution are basically the same, but the difference is that the deconvolution requires a filling process and needs to be cropped at the last step. The specific implementation code is as follows:

#根据输入map ([h,w]) and convolution cores ([k,k]), compute feature map import NumPy as NP def COMPUTE_CONV (Fm,kernel) after convolution: [H,w]=fm.shape [K,_] =kernel.shape r=int (K/2) #定义边界填充0后的map Padding_fm=np.zeros ([h+2,w+2],np.float32) #保存计算结果 Rs=np.zeros ( [H,w],np.float32) #将输入在指定该区域赋值, that is, after 4 boundaries, the remaining area PADDING_FM[1:H+1,1:W+1]=FM #对每个点为中心的区域遍历 for I in range (1,
            H+1): For J in Range (1,w+1): #取出当前点为中心的k *k area roi=padding_fm[i-r:i+r+1,j-r:j+r+1] #计算当前点的卷积, multiply the k*k by Rs[i-1][j-1]=np.sum (Roi*kernel) return RS #填充0 def fill_zeros (input): [C,h
            , W]=input.shape Rs=np.zeros ([c,h*2+1,w*2+1],np.float32) for I in Range (c): for J in Range (h): for k in Range (W): Rs[i,2*j+1,2*k+1]=input[i,j,k] return rs def my_deconv (input,weights): #wei Ghts Shape=[out_c,in_c,h,w] [out_c,in_c,h,w]=weights.shape out_h=h*2 out_w=w*2 rs=[] for I in range (out_c): W=weighTs[i] Tmp=np.zeros ([Out_h,out_w],np.float32) for J in Range (In_c): Conv=compute_conv (INPUT[J),  W[J]) #注意裁剪, last row and last column remove Tmp=tmp+conv[0:out_h,0:out_w] rs.append (TMP) return RS def Main (): Input=np.asarray (Input_data,np.float32) input= Fill_zeros (input) Weights=np.asarray (WEIGHTS_DATA,NP . float32) Deconv=my_deconv (input,weights) print (Np.asarray (deconv)) if __name__== ' __main__ ': Main ()

Calculate the convolution code, consistent with the previous article. The code looks directly at the annotation and no longer explains it. The results of the operation are as follows:

[[  4.   3.   6.   2.   7.   3.]
  [  4.   3.   3.   2.   7.   5.]
  [  8.   6.   8.   5.   2.]
  [  3.   2.   7.   2.   3.   3.]
  [  5.   5.  One-   3.   9.   3.]
  [  2.   1.   4.   5.   4.   4.]]

 [[  4.   1.   7.   0.   7.   2.]
  [  5.   6.   0.   1.   8.   5.]
  [  8.   0.   8.  -2.   2.]
  [  3.   3.   9.   8.   1.   0.]
  [  3.   0.   0.   2.]
  [  3.   5.   3.   1.   3.   0.]]]

To verify the correctness of the implemented code, we use the TensorFlow conv2d_transpose function to perform the same input and convolution cores to see if the results are consistent. The validation code is as follows:

Import TensorFlow as TF import NumPy as NP def tf_conv2d_transpose (input,weights): #input_shape =[n,height,width,chann El] Input_shape = Input.get_shape (). As_list () #weights Shape=[height,width,out_c,in_c] Weights_shape=weights.g Et_shape (). As_list () output_shape=[input_shape[0], input_shape[1]*2, Input_shape[2]*2, weights_shape[2]] Print ("Output_shape:", Output_shape) Deconv=tf.nn.conv2d_transpose (Input,weights,output_shape=output_shape, strides =[1, 2, 2, 1], padding= ' SAME ') return Deconv def main (): Weights_np=np.asarray (Weights_data,np.float32) #将输入 Each convolution nucleus rotates 180°weights_np=np.rot90 (weights_np,2, (2,3)) Const_input = Tf.constant (Input_data, Tf.float32) const _weights = Tf.constant (weights_np, tf.float32) input = tf. Variable (const_input,name= "input") #[c,h,w]------>[h,w,c] Input=tf.transpose (input,perm= (1,2,0)) #[h,w,c]-- ---->[n,h,w,c] Input=tf.expand_dims (input,0) #weights shape=[out_c,iN_C,H,W] weights = tf. Variable (const_weights,name= "weights") #[out_c,in_c,h,w]------>[h,w,out_c,in_c] weights=tf.transpose (weights, Perm= (2,3,0,1)) #执行tensorflow的反卷积 deconv=tf_conv2d_transpose (input,weights) Init=tf.global_variables_initia Lizer () sess=tf. Session () Sess.run (init) deconv_val = Sess.run (deconv) hwc=deconv_val[0] Print (HWC) if __name__== ' __ 
 Main__ ': Main ()

In the code above, there are a few points to note: Each convolution kernel needs to rotate 180°, and then into the Tf.nn.conv2d_transpose function, because the tf.nn.conv2d_transpose inside will rotate 180 °, so advance rotation, and then after the internal rotation, This ensures that the convolution core is aligned with the data in the convolution core we are using. The shape of the input we define is [c,h,w] needs to be converted to [n,h,w,c] used by the TensorFlow. The convolution kernel shape we define is [out_c,in_c,h,w] and needs to be converted to the [H,w,out_c,in_c] used in the TensorFlow deconvolution.

After executing the above code, the execution results are as follows:

[[  4.   3.   6.   2.   7.   3.]
 [  4.   3.   3.   2.   7.   5.]
 [  8.   6.   8.   5.   2.]
 [  3.   2.   7.   2.   3.   3.]
 [  5.   5.  One-   3.   9.   3.]
 [  2.   1.   4.   5.   4.   4.]]
[[  4.   1.   7.   0.   7.   2.]
 [  5.   6.   0.   1.   8.   5.]
 [  8.   0.   8.  -2.   2.]
 [  3.   3.   9.   8.   1.   0.]
 [  3.   0.   0.   2.]
 [  3.   5.   3.   1.   3.   0.]]

The comparison results show that the data is consistent and that the deconvolution code of the previously handwritten Python implementation is correct.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.