怎么实现一个卷积运算
2018-01-26 19:59
281 查看
神经网络中的卷积运算具有较快的运算速度,现有的神经网络中所需要的卷积运算已经写的比较方便了,即便要写新的网络层,继承下来这些类也差不多满足所需要的要求。但有的时候不尽然,比如我需要运算一个固定卷积核的卷积运算。
下面通过numpy来实现,在贴代码之前,
首先先说一下卷积快速运算的逻辑
快速的实现卷积运算,是将所需要的卷积核和所卷积核所对应的元素拉伸到一维向量,然后所有需要卷积计算的位置都准备这种长度的向量,排列起来成为一个新的矩阵,然后再以矩阵运算的方式进行快速计算。
矩阵运算,是numpy,Tensor(估计其他的神经框架语言的基本实现核接口都相类似)所擅长的,速度快。而且像numpy和pytorch 的Tensor都支持broadcast广播计算(比如,5*3*1维度的向量和1*4维度的向量之间运算时,这些库会按照对应维度补齐的方式来运算,这俩运算相当于5*3*4和5*3*4的两个向量之间的矩阵计算结果)。
所以,给定卷积核的快速运算的关键,是怎么将所需要的卷积核大小的矩阵元素组织成相应的向量。
图示说明
比如一个2*2的卷积核,如图中标识出数字的部分,如果要对这幅图进行卷积运算,就要依次将234位置的像素拍到1后面,形成一个向量。其他形式的卷积核也是如此操作。
代码:
so,类似的方法可用在简单的求梯度上面,
像这样求算图像的梯度
下面通过numpy来实现,在贴代码之前,
首先先说一下卷积快速运算的逻辑
快速的实现卷积运算,是将所需要的卷积核和所卷积核所对应的元素拉伸到一维向量,然后所有需要卷积计算的位置都准备这种长度的向量,排列起来成为一个新的矩阵,然后再以矩阵运算的方式进行快速计算。
矩阵运算,是numpy,Tensor(估计其他的神经框架语言的基本实现核接口都相类似)所擅长的,速度快。而且像numpy和pytorch 的Tensor都支持broadcast广播计算(比如,5*3*1维度的向量和1*4维度的向量之间运算时,这些库会按照对应维度补齐的方式来运算,这俩运算相当于5*3*4和5*3*4的两个向量之间的矩阵计算结果)。
所以,给定卷积核的快速运算的关键,是怎么将所需要的卷积核大小的矩阵元素组织成相应的向量。
图示说明
比如一个2*2的卷积核,如图中标识出数字的部分,如果要对这幅图进行卷积运算,就要依次将234位置的像素拍到1后面,形成一个向量。其他形式的卷积核也是如此操作。
代码:
image = Variable(torch.from_numpy(image)).unsqueeze(0).unsqueeze(0).float()#模拟了pytorch中常见的四维矩阵 # creat four layer kernel = Variable(torch.FloatTensor([1, -1, -1, 1]))#2*2的卷积核 #这以下两个为了模拟固定的错位,从而使相应位置的像素排列过来 mod_1 = sign.clone() mod = nn.ZeroPad2d((0, 1, 0, 0)) mod_2 = mod(sign)[:, :, :, 1:] mod = nn.ZeroPad2d((0, 0, 0, 1)) mod_3 = mod(sign)[:, :, 1:, :] mod = nn.ZeroPad2d((0, 1, 0, 1)) mod_4 = mod(sign)[:, :, 1:, 1:] mod_ = torch.cat((mod_1, mod_2, mod_3, mod_4), 1)#将这些组合起来,形成上面所说的向量 mod_ = mod_.transpose(1, 2).transpose(2, 3) # 使用的时候需要改变一下维度,卷积核的大小长度放到最后一个维度上 out = torch.matmul(mod_, kernel)
so,类似的方法可用在简单的求梯度上面,
像这样求算图像的梯度
image = Variable(torch.from_numpy(image)).unsqueeze(0).unsqueeze(0).float() # # 下面两个变量为了形成一定的错位 image_x = nn.ZeroPad2d((1, 0, 0, 0)) # move left by 1 pixel image_y = nn.ZeroPad2d((0, 0, 1, 0)) # move up by 1 pixel grad_x = image - image_x(image)[:, :, :, :-1] + 1e-15 #计算梯度 grad_y = image - image_y(image)[:, :, :-1, :] + 1e-15 sign_x = (grad_x / grad_x.abs()) # .char() #下面的这几行代码是为了让特定的模式表现出某种特征,(正负) sign_y = (grad_y / grad_y.abs()) # .char() sign = sign_x * sign_y # useful valid = (image > 0).float() # useful sign = sign * valid + (1 - valid) # image_xy will has misplacement
相关文章推荐
- 小数运算需要注意什么? 接口和抽象类 WinForm窗体上两个panel,怎么实现一个panel固定漂浮在另一个panel之上
- 实现一个正整数加、减、乘、除四则混合运算求值方法
- switch实现一个两数的运算代码示例
- 如果系统要使用超大整数(超过long长度范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数加法运算
- c语言:编写一个简易计算器,打印菜单界面,实现加减乘除运算,可以退出菜单界面
- 用位运算实现四则运算之加减乘除(用位运算求一个数的1/3)
- 设计一个计算器类Calculator,它只有一个计数的成员count。该计算器的有效范围说0~65535,实现计算器的前自增、后自增、前自减、后自减、两个计算器相加减等运算
- 编写一个程序,实现两个256位的十进制整数的乘法运算.
- 编写一个函数实现矩阵的转置运算
- jquery怎么实现点击一个元素更换背景图片,连续点击永远在2张图片之间更换
- ios开发:怎么实现点击一个按钮,跳转到一个新的界面,并回退到上一界面
- C# 一步一步完成一个简单的计算器 第三步---实现双目运算
- 自己写的一个ArrayLIST,but 不知道怎么很好的实现System底下的arraycopy方法
- 怎么用BigDecimal实现大数字运算?
- 怎么用两个堆栈实现一个队列?
- (1)定义一个接口Compute含有一个方法int computer(int n,int m); (2)设计四个类分别实现此接口,完成+-*/运算 (3)设计一个类UseCompute,含有方法: public void useCom(Compute com, int one, int two) (4)设计一个测试类
- 怎么实现一个站点的list列引用另外一个站点的list列数据?
- 一个有趣的问题:怎么在JS的数组中去除重复元素?(JAVA实现吧..)
- 5-17编写一个类实现复数的运算
- 想要实现pdf文件5页数据,每页都有一个图片,怎么实现?