执行与theano的conv2d完全相同的卷积

时间:2014-09-02 08:52:45

标签: algorithm convolution theano

我有一个现有的分类模型,使用theano.tensor.nnet下的theano' conv2d进行训练。现在我必须使用这个模型在Java中进行某种预测。

我在Python中实现了一个简单的卷积(最后,我将用Java编写代码),根据一些文档(https://developer.apple.com/Library/ios/documentation/Performance/Conceptual/vImage/ConvolutionOperations/ConvolutionOperations.html)。例如,对于2 * 2内核(k11,k12,k21,k22),内核下的一个区域是(a11,a12,a21,a22)。卷积由a11 * k11 + a12 * k12 + a21 * k21 + a22 * k22执行。

不幸的是,当我用一些虚拟矩阵和内核测试我的卷积码和theano的转码时,它们给出了不同的结果。只有在极少数情况下,它们才会给出相同的结果。

在我看来,卷积算法有很多变种,我必须实现与theano的ConvOp使用的完全相同的卷积算法。但是,我找不到任何描述theano的Conv2d算法的材料。

你能解释一下theano的conv2d算法吗?

以下是我的卷积python代码:

def convolution(img_arr, kernel):
    h, w = img_arr.shape
    k = len(kernel)
    k_flat = kernel.flatten()
    neww = w - len(kernel) + 1
    newh = h - len(kernel) + 1
    after = np.zeros((newh, neww))
    for i in range(neww):
        for j in range(newh):
            after[j,i] = (img_arr[j:j+k,i:i+k].flatten()*k_flat).sum()
    return after

2 个答案:

答案 0 :(得分:3)

Theano卷积与scipy.signal.convolve2d完全相同。这被利用/测试,例如here。要获得自包含,请尝试复制+粘贴:

import numpy as np
from scipy.signal import convolve2d
import theano
import theano.tensor as T

rng = np.random.RandomState(42)
image = rng.randn(500, 500).astype(np.float32)
conv_filter = rng.randn(32, 32).astype(np.float32)

img = T.tensor4()
fil = T.tensor4()

for border_mode in ["full", "valid"]:
    scipy_convolved = convolve2d(image, conv_filter, mode=border_mode)
    theano_convolve2d = theano.function([img, fil], T.nnet.conv2d(img, fil,
                                        border_mode=border_mode))
    theano_convolved = theano_convolve2d(image.reshape(1, 1, 500, 500),
                                         conv_filter.reshape(1, 1, 32, 32))
    l2_discrepancy = np.sqrt(((scipy_convolved - theano_convolved) ** 2).sum())
    print "Discrepancy %1.5e for border mode %s" % (l2_discrepancy, border_mode)
    print "Norms of convolutions: %1.5e, %1.5e" % (
        np.linalg.norm(scipy_convolved.ravel()),
        np.linalg.norm(theano_convolved.ravel()))

输出

Discrepancy 9.42469e-03 for border mode full
Norms of convolutions: 1.65433e+04, 1.65440e+04
Discrepancy 9.03687e-03 for border mode valid
Norms of convolutions: 1.55051e+04, 1.55054e+04

由于scipy实现了标准卷积,theano也是如此。

答案 1 :(得分:1)

其实你和(Theano,Scripy)都没问题。原因是:你正在使用不同的卷积2D。 Theano和Script使用Math中定义的convolution2D来旋转内核。但你没有(参考:http://www.songho.ca/dsp/convolution/convolution.html#convolution_2d)。 如果您的内核是这样的话:

[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

而不是将其改为(中心对称):

[9, 8, 7]
[6, 5, 4]
[3, 2, 1]

因此,使用您的方法将获得与Theano / Scripy

相同的答案