淘先锋技术网

首页 1 2 3 4 5 6 7

学习来源: 深度学习理论和实战
上篇文章中,我们卷积神经网络中一些基础概念做了一次理解,知道了什么叫卷积,什么叫池化,什么叫卷积神经网络。这篇文章的主要内容是卷积和池化用tensorflow的具体实现。
使用版本介绍:
tensorflow : 1.15
python : 3

卷积

卷积在tensorflow中的API 是,tf.nn.conv2d()。
参数如下图所示:
tf_converlution
参数解释如下:
第一个参数:input,即输入数据,通常是一个(batch,h,w,channels)的4维向量:

  • batch: 一次输入的图片数量
  • h: 表示图片的高度
  • w: 表示图片的宽度
  • channels: 表示图片的通道数量,例如一张rpg图片的channels为3

第二个参数:filter,即卷积核,也是由一个(k_h,k_w,in,out)的4维向量:

  • k_h: 卷积核的高度
  • w_h: 卷积核的宽度
  • in: 通道数量,一般图片通道数量相同
  • out: 即卷积核个数

第三个参数:strides,即移动步长,也是由一个(1,s_h,s_w,1)的4维向量:

  • s_h: 在高度上移动的步长
  • s_w: 在宽度上移动的步长
  • 关于s_h,s_w参数的位置其实和data_format有关,data_format有两种形式:’“NHWC” 和“NCHW”,如果是前者,则strdes表示为(1,s_h,s_w,1),如果是后者,则strides 表示为(1,1,s_h,s_w)

第四个参数:padding,即输出是否会补零策略

  • 如果padding=“SAME”,tensorflow会对输出自动补零,保证输入和输出维度相同;
  • 如果padding=“VALID”,tensorflow 就不会自动补零。
    其他参数默认即可,感兴趣的同学可以自己探索。

卷积代码实现

# 导入相关模块
import tensorflow as tf 
import urllib.request
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
%matplotlib inline 
#导入图片
cat_url = 'https://image.ibb.co/iFGs0x/kitty.png'
cat = Image.open(urllib.request.urlopen(cat_url)).convert('L')
cat = np.array(im,dtype='float32')

# 可视化图片
plt.imshow(cat.astype('uint8'),cmap='gray')

source_cat

查看图片维度
print (cat.shape[0])
print (cat.shape[1])

h_w

# 将图片矩阵转化为tensor
cat = tf.constant(cat.reshape((1,cat.shape[0],cat.shape[1],1)),name='input')

# 定义一个卷积核
sobel_kernel = np.array([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]],dtype=np.float32)
sobel_kernel = tf.constant(sobel_kernel,shape=(3,3,1,1))
#调用tensorflow 卷积API
# padding='SAME' 的卷积
edge1 = tf.nn.conv2d(cat,sobel_kernel,[1,1,1,1],'SAME',name='same_conv')
# padding='VALID'的卷积
edge2 = tf.nn.conv2d(cat,sobel_kernel,[1,1,1,1],'VALID',name='valid_conv')
#激活tensorflow
sess = tf.InteractiveSession()

edge1_np = sess.run(edge1)
edge2_np = sess.run(edge2)
# padding = 'SAME'下的图片
plt.imshow(np.squeeze(edge1_np),cmap='gray')
plt.title('shape={}'.format(edge1_np.shape))

con_same

# padding="VALID"
plt.imshow(np.squeeze(edge2_np),cmap='gray')
plt.title('shape={}'.format(edge2_np.shape))

conv_valid
通过对比两种方式,我们发现了什么?我们padding为SAME的输出维度和输入图片维度是相同的。

池化

tensorflow 也已经封装了池化层的API ,在这里我们只讨论最大化池化层API: tf.nn.max_pool().
参数如下图所示:
max_pool
具体解释:
value: 即输入,是一个四维tensor(batch,h,w,channels).
ksize: 池化核大小,是一个四维tensor(1,k_h,k_w,1),和卷积相同含义.
strides: 同卷积strides含义.
padding: 同卷积padding含义.

池化代码实现

# padding='SAME'
small_im1 = tf.nn.max_pool(cat,[1,2,2,1],[1,2,2,1],'SAME',name='same_max_pool')
# padding = "VALID"
small_im2 = tf.nn.max_pool(cat,[1,2,2,1],[1,2,2,1],'VALID',name = 'valid_max_pool')
# 激活tensor
small_im1_np,small_im2_np = sess.run([small_im1,small_im2])
#画图 padding='SAME'
plt.imshow(np.squeeze(small_im1_np),cmap='gray')
plt.title('shape={}'.format(small_im1_np.shape))

pool_max

# 画图 padding='VALID'
plt.imshow(np.squeeze(small_im2_np),cmap='gray')
plt.title('shape={}'.format(small_im2_np.shape))

valid_pool
发现池化层中的补零策略,对输出结果的维度并没有影响。

总结,通过卷积和池化实现,我们发现,池化在维度下降一半的情况下,并没有丢失多少信息。