# 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()```

1. 由于输出通道为1，因此可以对卷积核数据转换的时候直接调用chw2hwc，如果输入通道不为1，则不能这样完成转换。
2. 输入完成chw转hwc后，记得在第0维扩充维数，因为卷积要求输入为[n,h,w,c]
3. 为了方便我们查看结果，记得将hwc的shape转为chw

```[[ 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 小结

0 条评论

• ### Tensorflow反卷积（DeConv）实现原理+手写python代码实现反卷积（DeConv）

上一篇文章已经介绍过卷积的实现，这篇文章我们学习反卷积原理，同样，在了解反卷积原理后，在后面手写python代码实现反卷积。

• ### MobileNet原理+手写python代码实现MobileNet

MobileNet是针对移动端优化的卷积，所以当需要压缩模型时，可以考虑使用MobileNet替换卷积。下面我们开始学习MobileNet原理，并且先通过Ten...

• ### Tensorflow MobileNet移植到Android

在柯林斯原始网络中使用函数tf.nn.top_k电子杂志概率最大的3类，函数将tf.nn.top_k作为网络中的一个计算节点。

• ### Tensorflow反卷积（DeConv）实现原理+手写python代码实现反卷积（DeConv）

上一篇文章已经介绍过卷积的实现，这篇文章我们学习反卷积原理，同样，在了解反卷积原理后，在后面手写python代码实现反卷积。

• ### [Tensorflow] Tensorflow卷积理解

CNN对于学习深度学习的人来说应该是比较耳熟的名词了.但很多人只是听过,但不知道是什么.

• ### “顶流”腾讯的双11饭局：排排坐，战天猫

今年的双十一战役更加火热，天猫自然是祭出各种大招捍卫双11主场，京东和他的小老弟拼多多当然也是先后加入，一时之间好不热闹。

• ### OpenCV 基于Inception模型图像分类

要介绍Inception网络结构首先应该介绍一下NIN(Network in Network)网络模型，2014年新加坡国立大学发表了一篇关于计算机视觉图像分类...

• ### tensorflow 在加载大型的embedding模型参数时，会遇到cannot be larger than 2GB

这种问题是，对于每一个变量 variable 由于是基于protobuf存在这大小限制(2G),这个时候，我们需要将embedding拆开，拆分成N...

勘误：开始之前说一下，昨天介绍的环境搭建的那篇，里面我忘记写cudnn的安装说明了，只贴了在哪下载，我在word版里面已经更新了，欢迎需要的童鞋下载查看。还有一...