我正在尝试使用numpy操作实现tensorflow的conv1d,暂时不考虑跨步和填充。我以为previous question之后我就理解了,但是今天意识到当处理大于1的内核时,我仍然没有得到正确的答案。
所以现在我试图将tflearn用作模板,因为它可以为我计算内核形状。现在,我知道可以将卷积计算为矩阵乘法,因此我尝试相应地使用内核矩阵,但是我没有得到与tflearn相同的答案。检查源代码非常不透明,因为它只是调用tensorflow的专用编译实现。
这是我到目前为止所拥有的:
inp = np.arange(10).reshape(1,10,1).astype(np.float32)
filters = 2
width = 3
z = tflearn.conv_1d(inp, filters, width, strides=1, padding='same', bias=False)
s = tf.Session()
s.run(tf.global_variables_initializer())
z1, w = s.run([z, z.W])
print('tflearn output shape', z1.shape)
print('tflearn kernel shape', w.shape)
print('numpy matmul shape', (inp @ w).shape)
这表明tflearn内核将宽度作为在开头插入的额外尺寸:
tflearn output shape (1, 10, 2)
tflearn kernel shape (3, 1, 1, 2)
numpy matmul shape (3, 1, 10, 2)
因此,我得到的结果具有额外的3
维。很好,那么我如何正确地减小它以获得与tensorflow相同的答案?我尝试对这个维度求和,但这是不正确的:
print('tflearn output:')
print(z1)
print('numpy output:')
print(np.sum(inp @ w, axis=0))
给予,
tflearn output:
[[[-0.02252221 0.24712706]
[ 0.49539018 1.0828717 ]
[ 0.0315876 2.0945265 ]
[-0.43221498 3.1061814 ]
[-0.89601755 4.117836 ]
[-1.3598201 5.129491 ]
[-1.823623 6.141146 ]
[-2.2874253 7.152801 ]
[-2.7512276 8.164455 ]
[-2.989808 6.7048397 ]]]
numpy output:
[[[ 0. 0. ]
[-0.46380258 1.0116549 ]
[-0.92760515 2.0233097 ]
[-1.3914077 3.0349646 ]
[-1.8552103 4.0466194 ]
[-2.319013 5.0582743 ]
[-2.7828155 6.069929 ]
[-3.2466178 7.0815845 ]
[-3.7104206 8.093239 ]
[-4.174223 9.104893 ]]]
这显然是不同的。 z.W
当然已经被初始化为随机值,所以这些数字也是随机的,但是我正在寻找numpy计算,使它们等于z1
,因为它们执行相同的内核。显然,它不像inp @ w
那样简单。
谢谢。
[对不起,经过一番思考,我已经回答了我自己的问题...这是滑动窗口操作的来源,我试图在上一个问题中引入它:
y = (inp @ w)
y[0,:,:-2,:] + y[1,:,1:-1,:] + y[2,:,2:,:]
给予,
array([[[ 0.49539018, 1.0828717 ],
[ 0.0315876 , 2.0945265 ],
[-0.43221498, 3.1061814 ],
[-0.89601755, 4.117836 ],
[-1.3598201 , 5.129491 ],
[-1.823623 , 6.141146 ],
[-2.2874253 , 7.152801 ],
[-2.7512276 , 8.164455 ]]], dtype=float32)
等于z1
,忽略了第一行和最后一行,正是我期望的三点卷积。
编辑:但是如果有人可以提出一种更简洁/有效的方式来表示滑动窗口,我将非常有义务。我从我之前的问题中认为,即使在矩阵乘法中也可以考虑滑动窗口,所以不幸的是,需要显式地编写索引逻辑。