本人在卷积神经网络的卷积层、池化层的im2col和反向传播的col2im方法上有所启发,考虑到IDL本身并没有im2col和col2im函数,于是编写了相关的IDL函数。话不多说,直接上代码!
1. im2col;input_data: 由(高, 长)的2维数组构成的输入数据
;filter_h: 滤波器的高
;filter_w: 滤波器的长
;stride=stride: 步幅
;pad=pad: 填充的个数(默认填充值为0)
;return 二维数组
FUNCTION fun_im2col, input_data, filter_h, filter_w, stride=stride, pad=pad
param_number = N_PARAMS() ;返回非关键字参数的个数(即位置参数的个数)
IF param_number EQ 3 THEN BEGIN
arr_info = SIZE( input_data )
w = arr_info[1] ;w和h为矩阵的长(列)和高(行)
h = arr_info[2]
;out_h和out_w分别为输出矩阵的长和高
out_h = FLOOR( (h + 2*pad - filter_h) / stride ) + 1
out_w = FLOOR( (w + 2*pad - filter_w) / stride ) + 1
img = REPLICATE(0.0, w + 2 * pad, h + 2 * pad)
end_w = w - 1 + pad
end_h = h - 1 + pad
img[pad:end_w, pad:end_h] = input_data
column = FLTARR(filter_w, filter_h, out_w, out_h)
FOR x = 0, filter_w-1 DO BEGIN
x_max = x + stride*out_w
FOR y = 0, filter_h-1 DO BEGIN
y_max = y + stride*out_h
; if y_max ge h + 2 * pad or x_max ge w + 2 * pad then break
; print, x, x_max, y, y_max
column[x, y, *, *] = img[x:x_max-1:stride, y:y_max-1:stride]
ENDFOR
ENDFOR
column = TRANSPOSE(column, [2, 3, 0, 1])
column = REFORM(column, [out_h*out_w, filter_w*filter_h])
RETURN, column
ENDIF ELSE BEGIN
PRINT, "Function params is not enough!"
RETURN, 0
ENDELSE
END
2. col2im
;input_shape : 输入数据的形状(例:[28, 28])
;filter_h: 滤波器的高
;filter_w: 滤波器的长
;stride: 步幅
;pad: 填充的个数(默认填充值为0)
FUNCTION fun_col2im, column, input_shape, filter_h, filter_w, stride=stride, pad=pad
param_number = N_PARAMS()
IF param_number EQ 4 THEN BEGIN
w= input_shape[0]
h = input_shape[1]
out_h = FLOOR( (h + 2*pad - filter_h) / stride ) + 1
out_w = FLOOR( (w + 2*pad - filter_w) / stride ) + 1
column = REFORM(column, [out_w, out_h, filter_w, filter_h])
; column = TRANSPOSE(column, [2, 3, 0, 1])
img = FLTARR(w + 2*pad + stride - 1, h + 2*pad + stride - 1)
FOR x = 0, filter_w-1 DO BEGIN
x_max = x + stride*out_w
FOR y = 0, filter_h-1 DO BEGIN
y_max = y + stride*out_h
; print, x, x_max, y, y_max
img[x:x_max-1:stride, y:y_max-1:stride] = column[*, *, x, y]
ENDFOR
ENDFOR
end_w = w - 1 + pad
end_h = h - 1 + pad
RETURN, img[pad:end_w, pad:end_h]
ENDIF ELSE BEGIN
PRINT, "Function params is not enough!"
RETURN, 0
ENDELSE
END
3. 运行结果
首先来看一下im2col的运行结果
pro test
;输入数据为4*4的二维数组,滤波器大小为3*3
input_data = findGEN(4, 4)
filter_h = 3
filter_w = 3
column = fun_im2col(input_data, filter_h, filter_w, stride=1, pad=0)
PRINT, "输入数据",input_data
PRINT, "输出数据", column
end
结果如下,输出的每一列对应一组滤波器的数据
输入数据
0.000000 1.00000 2.00000 3.00000
4.00000 5.00000 6.00000 7.00000
8.00000 9.00000 10.0000 11.0000
12.0000 13.0000 14.0000 15.0000
输出数据
0.000000 1.00000 4.00000 5.00000
1.00000 2.00000 5.00000 6.00000
2.00000 3.00000 6.00000 7.00000
4.00000 5.00000 8.00000 9.00000
5.00000 6.00000 9.00000 10.0000
6.00000 7.00000 10.0000 11.0000
8.00000 9.00000 12.0000 13.0000
9.00000 10.0000 13.0000 14.0000
10.0000 11.0000 14.0000 15.0000
在来看一下col2im的运行结果,将im2col的结果还原回去
pro test
input_data = FINDGEN(4, 4)
filter_h = 3
filter_w = 3
column = fun_im2col(input_data, filter_h, filter_w, stride=1, pad=0)
PRINT, input_data
PRINT, column
b = fun_col2im(column, [4, 4], filter_h, filter_w, stride=1, pad=0)
PRINT, b
end
结果如下,可以看到完美的将矩阵还原了回去
;im2col得到的column
0.000000 1.00000 4.00000 5.00000
1.00000 2.00000 5.00000 6.00000
2.00000 3.00000 6.00000 7.00000
4.00000 5.00000 8.00000 9.00000
5.00000 6.00000 9.00000 10.0000
6.00000 7.00000 10.0000 11.0000
8.00000 9.00000 12.0000 13.0000
9.00000 10.0000 13.0000 14.0000
10.0000 11.0000 14.0000 15.0000
;col2im得到的input_data
0.000000 1.00000 2.00000 3.00000
4.00000 5.00000 6.00000 7.00000
8.00000 9.00000 10.0000 11.0000
12.0000 13.0000 14.0000 15.0000
最后看一下如果有填充值的话是什么样的结果
;原始输入矩阵
0.000000 1.00000 2.00000
3.00000 4.00000 5.00000
6.00000 7.00000 8.00000
;填充后的矩阵,填充一个数值
0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 1.00000 2.00000 0.000000
0.000000 3.00000 4.00000 5.00000 0.000000
0.000000 6.00000 7.00000 8.00000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000
;输出的col矩阵
0.000000 0.000000 0.000000 0.000000 0.000000 1.00000 0.000000 3.00000 4.00000
0.000000 0.000000 0.000000 0.000000 1.00000 2.00000 3.00000 4.00000 5.00000
0.000000 0.000000 0.000000 1.00000 2.00000 0.000000 4.00000 5.00000 0.000000
0.000000 0.000000 1.00000 0.000000 3.00000 4.00000 0.000000 6.00000 7.00000
0.000000 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000
1.00000 2.00000 0.000000 4.00000 5.00000 0.000000 7.00000 8.00000 0.000000
0.000000 3.00000 4.00000 0.000000 6.00000 7.00000 0.000000 0.000000 0.000000
3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 0.000000 0.000000 0.000000
4.00000 5.00000 0.000000 7.00000 8.00000 0.000000 0.000000 0.000000 0.000000
派上用场的话请给个赞哦,如有疑问,欢迎留言!