大家好,又见面了,我是你们的朋友全栈君。
我们知道,tensorflow里面自带卷积函数,tf.nn.conv2d()就可以实现相关功能,本文主要是自己实现卷积操作,然后和tf.nn.conv2d()函数的结果对比,验证正确性。
调用tf.nn.conv2d()实现卷积
首先是调用卷积函数实现卷积操作:
这里说明一下conv2d的定义及参数含义: 参考
【定义:】
tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
【参数:】
input : 输入的要做卷积的图片,要求为一个张量,shape为 [ batch, in_height, in_weight, in_channel ],其中batch为图片的数量,in_height 为图片高度,in_weight 为图片宽度,in_channel 为图片的通道数,灰度图该值为1,彩色图为3。(也可以用其它值,但是具体含义不是很理解)
filter: 卷积核,要求也是一个张量,shape为 [ filter_height, filter_weight, in_channel, out_channels ],其中 filter_height 为卷积核高度,filter_weight 为卷积核宽度,in_channel 是图像通道数 ,和 input 的 in_channel 要保持一致,out_channel 是卷积核数量。
strides: 卷积时在图像每一维的步长,这是一个一维的向量,[ 1, strides, strides, 1],第一位和最后一位固定必须是1
padding: string类型,值为“SAME” 和 “VALID”,表示的是卷积的形式,是否考虑边界。”SAME”是考虑边界,不足的时候用0去填充周围,”VALID”则不考虑
use_cudnn_on_gpu: bool类型,是否使用cudnn加速,默认为true
import tensorflow as tf
import numpy as np
input = np.array([[1,1,1,0,0],[0,1,1,1,0],[0,0,1,1,1],[0,0,1,1,0],[0,1,1,0,0]])
input = input.reshape([1,5,5,1]) #因为conv2d的参数都是四维的,因此要reshape成四维
kernel = np.array([[1,0,1],[0,1,0],[1,0,1]])
kernel = kernel.reshape([3,3,1,1]) #kernel也要reshape
print(input.shape,kernel.shape) #(1, 5, 5, 1) (3, 3, 1, 1)
x = tf.placeholder(tf.float32,[1,5,5,1])
k = tf.placeholder(tf.float32,[3,3,1,1])
output = tf.nn.conv2d(x,k,strides=[1,1,1,1],padding='VALID')
with tf.Session() as sess:
y = sess.run(output,feed_dict={
x:input,k:kernel})
print(y.shape) #(1,3,3,1)
print(y) #因为y有四维,输出太长了,我就只写一下中间两维的结果(3*3部分):[[4,3,4],[2,4,3],[2,3,4]]
自己实现卷积函数
下面我们自己实现一个卷积操作,就不care batch和channel那两维了,直接拿中间的二维为例。下面是 实现的代码(我这个太偷懒了,步长、padding这些都没有考虑进去):
import numpy as np
input = np.array([[1,1,1,0,0],[0,1,1,1,0],[0,0,1,1,1],[0,0,1,1,0],[0,1,1,0,0]])
kernel = np.array([[1,0,1],[0,1,0],[1,0,1]])
print(input.shape,kernel.shape)
def my_conv(input,kernel):
output_size = (len(input)-len(kernel)+1)
res = np.zeros([output_size,output_size],np.float32)
for i in range(len(res)):
for j in range(len(res)):
res[i][j] = compute_conv(input,kernel,i,j)
return res
def compute_conv(input,kernel,i,j):
res = 0
for kk in range(3):
for k in range(3):
print(input[i+kk][j+k])
res +=input[i+kk][j+k]*kernel[kk][k] #这句是关键代码,实现了两个矩阵的点乘操作
return res
print(my_conv(input,kernel))
输出:
[[4. 3. 4.]
[2. 4. 3.]
[2. 3. 4.]]
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/140438.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...