之前在不用框架的情况推导过cnn的前向和后向传播算法,并且实现了.
地址如下:
https://blog.csdn.net/u010866505/article/details/77857394
由于项目中要用tensorflow的框架,因此需要用tensorflow的API:
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)
接下来对该api的参数进行一定的解释:
- input:这是神经网络的输入,是一个tensor,[b,h,w,c]这样的type,b是batch(每次参与训练的图片数量),h=height,w=width,c=channels。如下面那gif图,h=7,w=7,c = 3
- filter:这是卷积核参数,即滤波器参数。[filter_height, filter_width, channels, out_channels]。如下面那gif的w0,w1,height=3,width=3,channels=3
- stride:步幅,即滤波器每次移动的格数.如下面的gif图是:stride=1
- padding:就是在输入的外面那一圈添加的数.zero-padding=1表示在输入的外面添加一圈的1,padding取值是SAME或者VALID:这两个的选项解释如下:
- SAME means that the output feature map has the same spatial dimensions as the input feature map. Zero padding is introduced to make the shapes match as needed, equally on every side of the input map.
VALID means no padding.
- use_cudnn_gpu:是否使用cudnn加速.
- 返回的数据是一个tensor:[batch,h,w,channels]:
接下来,用代码实现上述input和Filter w1的卷积过程.
import tensorflow as tf
import numpy as np
input_data=[
[[0,1,1,2,2],
[0,1,1,0,0],
[1,1,0,1,0],
[1,0,1,1,1],
[0,2,0,1,0]],
[[1,1,1,2,0],
[0,2,1,1,2],
[1,2,0,0,2],
[0,2,1,2,1],
[2,0,1,2,0]],
[[2,0,2,0,2],
[0,0,1,2,1],
[1,0,2,2,1],
[2,0,2,0,0],
[0,0,1,1,2]]
]
weights_data=[
[[ -1, -1, 0],
[-1, 1, 0],
[ -1,1, 0]],
[[1, -1, 0],
[ -1, 0, -1],
[ -1, 0, 0]],
[[-1, 0, 1],
[ 1, 0, 1],
[ 0, -1, 0]]
]
def get_shape(tensor):
[s1,s2,s3]= tensor.get_shape()
s1=int(s1)
s2=int(s2)
s3=int(s3)
return s1,s2,s3
def chw2hwc(chw_tensor):
[c,h,w]=get_shape(chw_tensor)
cols=[]
for i in range(c):
#每个通道里面的二维数组转为[w*h,1]即1列
line = tf.reshape(chw_tensor[i],[h*w,1])
cols.append(line)
#横向连接,即将所有竖直数组横向排列连接
input = tf.concat(cols,1)#[w*h,c]
#[w*h,c]-->[h,w,c]
input = tf.reshape(input,[h,w,c])
return input
def hwc2chw(hwc_tensor):
[h,w,c]=get_shape(hwc_tensor)
cs=[]
for i in range(c):
#[h,w]-->[1,h,w]
channel=tf.expand_dims(hwc_tensor[:,:,i],0)
cs.append(channel)
#[1,h,w]...[1,h,w]---->[c,h,w]
input = tf.concat(cs,0)#[c,h,w]
return input
def tf_conv2d(input,weights):
conv = tf.nn.conv2d(input, weights, strides=[1, 2, 2, 1], padding='SAME')
return conv
def main():
const_input = tf.constant(input_data , tf.float32)
const_weights = tf.constant(weights_data , tf.float32 )
input = tf.Variable(const_input,name="input")
#[3,5,5]------>[5,5,3]
input=chw2hwc(input)
#[5,5,3]------>[1,5,5,3]
input=tf.expand_dims(input,0)
weights = tf.Variable(const_weights,name="weights")
#[3,3,3]-->[3,3,3]
weights=chw2hwc(weights)
#[3,3,3]-->[3,3,2,3]
weights=tf.expand_dims(weights,3)
#[b,h,w,c]
conv=tf_conv2d(input,weights)
rs=hwc2chw(conv[0])
init=tf.global_variables_initializer()
sess=tf.Session()
sess.run(init)
conv_val = sess.run(rs)
print(conv_val[0])
if __name__=='__main__':
main()