+关注继续查看

# Tensorflow卷积实现原理+手写python代码实现卷积

## 1 Tensorflow卷积实现原理

2个通道，5*5的输入定义如下：

#输入，shape=[c,h,w]
input_data=[
[[1,0,1,2,1],
[0,2,1,0,1],
[1,1,0,2,0],
[2,2,1,1,0],
[2,0,1,2,0]],

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

]


#卷积核，shape=[in_c,k,k]=[2,3,3]
weights_data=[
[[ 1, 0, 1],
[-1, 1, 0],
[ 0,-1, 0]],
[[-1, 0, 1],
[ 0, 0, 1],
[ 1, 1, 1]]
]


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



import tensorflow as tf
import numpy as np
input_data=[
[[1,0,1,2,1],
[0,2,1,0,1],
[1,1,0,2,0],
[2,2,1,1,0],
[2,0,1,2,0]],

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

]
weights_data=[
[[ 1, 0, 1],
[-1, 1, 0],
[ 0,-1, 0]],
[[-1, 0, 1],
[ 0, 0, 1],
[ 1, 1, 1]]
]
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, 1, 1, 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")
#[2,5,5]------>[5,5,2]
input=chw2hwc(input)
#[5,5,2]------>[1,5,5,2]
input=tf.expand_dims(input,0)

weights = tf.Variable(const_weights,name="weights")
#[2,3,3]-->[3,3,2]
weights=chw2hwc(weights)
#[3,3,2]-->[3,3,2,1]
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()



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


## 2 手写Python代码实现卷积

import numpy as np
input_data=[
[[1,0,1,2,1],
[0,2,1,0,1],
[1,1,0,2,0],
[2,2,1,1,0],
[2,0,1,2,0]],

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

]

#fm:[h,w]
#kernel:[k,k]
#return rs:[h,w]
def compute_conv(fm,kernel):
[h,w]=fm.shape
[k,_]=kernel.shape
r=int(k/2)
#定义边界填充0后的map
#保存计算结果
rs=np.zeros([h,w],np.float32)
#将输入在指定该区域赋值，即除了4个边界后，剩下的区域
#对每个点为中心的区域遍历
for i in range(1,h+1):
for j in range(1,w+1):
#取出当前点为中心的k*k区域
#计算当前点的卷积,对k*k个点点乘后求和
rs[i-1][j-1]=np.sum(roi*kernel)

return rs

def my_conv2d(input,weights):
[c,h,w]=input.shape
[_,k,_]=weights.shape
outputs=np.zeros([h,w],np.float32)

#对每个feature map遍历，从而对每个feature map进行卷积
for i in range(c):
#feature map==>[h,w]
f_map=input[i]
#kernel ==>[k,k]
w=weights[i]
rs =compute_conv(f_map,w)
outputs=outputs+rs

return outputs

def main():

#shape=[c,h,w]
input = np.asarray(input_data,np.float32)
#shape=[in_c,k,k]
weights =  np.asarray(weights_data,np.float32)
rs=my_conv2d(input,weights)
print(rs)

if __name__=='__main__':
main()



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


## 3 小结

|
7天前
|

15 0
|
7天前
|
TensorFlow 算法框架/工具 Python

12 1
|
2月前
|

98 1
|
2月前
|

38 0
|
2月前
|

36 0
|
2月前
|

37 0
|
5月前
|
TensorFlow 算法框架/工具 Python
【TensorFlow】Python中Tensorflow包安装使用存在的问题

71 0
|
5月前
|

【TensorFlow】Python虚拟环境中的依赖包迁移到断网环境
Python虚拟环境中的依赖包迁移到断网环境
67 0
|
5月前
|

126 0
|
5月前
|

100 0