CNN-卷积计算
2018-01-01 15:06
671 查看
本文介绍卷积3种计算方式
卷积:
我们先认为图片是由不同的波形组成。在时域空间下,图片就是我们看到的图片,由很多不同频率波形混杂在一起。频域空间下,图片波型变的离散化,可以清楚看到每一个波形的å频率(这块解释非常的粗糙,如果看不明白,搜一下时域图和频域图)。在时域空间下,我们很难把一张图片上噪音完全过滤掉,一种做法,我认为是遍历整张图片,然后修改噪音部分,类似PS过程。另一种办法是将图片转换到频域空间下,开启上帝视角,直接滤掉某一固定频率的波,之后在转回时域空间。对于后一个操作是:傅里叶变化->滤波->反傅里叶变化
再来看一下卷积算法:
F(f*g) = F(f)F(g)
也就是两个函数的卷积等于两个函数傅里叶变化后乘积的反傅里叶变化。
那么,可以将卷积运算对应于上述操作,个人觉得可以作为为什么CNN用卷积操作可以提取图像特种的解释。同时,这也提供了一种计算卷积的方法。
1.概念计算
这是我们最容易想明白并且可以很快自己实现的一种算法。
1)从左上到右下,对位相乘相加,然后移位。
def convolve2d(img, kernel): k_w = kernel.shape[0] def calc(pos_x, pos_y): sum = 0 for i in range(k_w): for j in range(k_w): sum += img[pos_x+i][pos_y+j] * kernel[i][j] return sum rtval = np.array(np.zeros([img.shape[0], img.shape[1]])) for j in range(img.shape[1] - k_w): for i in range(img.shape[0] - k_w): rtval[i][j] = calc(i,j) return rtval
2.FFT(快速傅里叶)
1)F(f*g) = F(f)F(g)
from scipy import fftpack import numpy as np def convolve2d(in1, in2): in1 = np.asarray(in1) in2 = np.asarray(in2) if in1.ndim == in2.ndim == 0: return in1*in2 elif not in1.ndim == in2.ndim: raise ValueError("in1 and in2 should have the same dimensionality") elif in1.size==0 or in2.size==0: return array([]) s1 = np.array(in1.shape) s2 = np.array(in2.shape) shape = s1 + s2 -1 complex_result = (np.issubdtype(in1.dtype, np.complexfloating) or np.issubdtype(in2.dtype, np.complexfloating)) fshape = [fftpack.helper.next_fast_len(int(d)) for d in shape] fslice = tuple([slice(0, int(sz)) for sz in shape]) sp1 = np.fft.rfftn(in1, fshape) sp2 = np.fft.rfftn(in2, fshape) ret = (np.fft.irfftn(sp1 * sp2, fshape)[fslice].copy()) return ret
3.im2col
1)将移位乘加,转换为举证乘法。不重复讲思路了,可以搜索im2col去了解。
具体算法参考这篇
http://lib.csdn.net/article/aiframework/62849
def convolve2d(img, kernel): img_row = img.shape[0] img_col = img.shape[1] kernel_row = kernel.shape[0] kernel_col = kernel.shape[1] output_row = img_row - kernel_row + 1 output_col = img_col - kernel_col + 1 N_h = kernel_row * kernel_col N_w = output_row * output_col N_matric = np.array(np.zeros([N_h,N_w])) line = 0 for k_row in range(kernel_row): for k_col in range(kernel_col): tmp = 0 for row in range(output_row): for col in range(output_col): N_matric[line][tmp] = img[k_row+row][k_col+col] tmp +=1 line += 1 K = kernel.reshape(-1) rtval = np.matmul(K, N_matric) return rtval.reshape(output_row,output_col)
图像尺寸:450 * 300
原图如下:
运行时间:
方法1:1.64s
方法2:0.013s
方法3: 0.98s
傅里叶变化效果非常诡异,感觉特别淡,不知道为什么。改写矩阵乘法再计算,确实可以加快卷积过程。
(之后需要回来补一下不同填充方式的处理)
相关文章推荐
- cnn学习之卷积或者池化后输出的map的size计算
- CNN之卷积计算层
- CNN卷积各层的参数和链接个数的计算
- CNN 卷积之后 map大小的计算
- cnn学习之卷积或者池化后输出的map的size计算
- CNN之卷积计算层
- 用sklearn和tensorflow做boston房价的回归计算的比较(2)--卷积神经网路CNN
- 深度学习系列(十):从卷积计算到卷积神经网络CNN
- (Tensorflow之十一)cnn卷积神经网络LeNet-5模型以及卷积核的计算
- CNN卷积各层的参数和链接个数的计算
- caffe中CNN卷积计算量估算
- CNN中的卷积操作的参数数计算
- CNN中感受野的计算
- 如何理解最简单的CNN代码(卷积层到全链接层)
- caffe学习:卷积计算
- cnn的卷积层和池化层
- CNN中1×1的卷积核的作用
- 神经网络中关于卷积池化的计算
- 深度学习算法实践11---卷积神经网络(CNN)之卷积操作
- CNN不同领域的共性 & 1X1卷积核