如何在python中测试自定义Keras图层

时间:2019-04-02 10:46:18

标签: python unit-testing keras-layer

根据我在this问题中提出的需求,我决定对Conv2D图层进行子类化,以便它首先正确包裹输入张量。

但是我无法使其工作。具体来说,我什至无法进行单元测试,以使用给定的内核初始化该层,然后将给定的输入张量传递给它,并验证.call()方法中定义的计算是否产生了预期的结果

因此,我退后一步,为了避免我的代码成为问题,我首先集中精力于如何处理已经存在的Keras父层Conv2D

import unittest

from numpy import asarray, arange

import keras.backend as K
from keras.models import Sequential  #, Model, 
from keras.layers import Conv2D  #, Input, MaxPooling2D
from keras.initializers import Constant
from keras.optimizers import SGD

class Test(unittest.TestCase):

    def testConv2D(self):
        ''' verify that I can initialize, invoke, and test a given Keras layer
        '''
        # kernel to make convolution constant except at borders 
        kern = asarray([[ 1, 0, -1]]).T + asarray([[ 0.5, 1, 0, -1, -0.5 ]]) 
        print(kern)
        kern = Constant(kern)

        input_shape = (10, 10, 3)
        sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)

        base_model = Sequential()
        base_layer = Conv2D(10, (3, 5),
                             input_shape=input_shape,
                             kernel_initializer=kern,
                             use_bias=False)
        base_model.add(base_layer)
        base_model.compile(loss='mean_squared_error', optimizer=sgd)

        x = arange(5 * 10 * 10 * 3).reshape((5, 10, 10, 3))  # 5 samples, 3 channels
        x = K.variable(x)
        # the print() statements to be replaced by asserts of course
        y = base_layer(x)
        print(y)                      # this just prints     Tensor("conv2d_1_1/convolution:0", shape=(5, 8, 6, 10), dtype=float32)
        yp = base_model.predict(x)    # this throws a        ValueError about specifying the `steps` argument
        print(yp)
        pass
        # once this works I'll replace Conv2D with a subclass of it, and 
        # verify that I can preprocess the input tensor; and will be able 
        # to verify that the convolution gives the right result
        pass
        # once also this works, I'll replace partial tests with a single test that verifies only the result
        pass

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()

尝试执行此操作,表明我什至无法在给定数据上调用现有的Keras层。我不知道如何做得更好(也许我最好使用功能性API?)

我怀疑我完全迷路了。如果有一些示例或链接可以启发我,或者有任何关于正确执行上述操作方法的提示,我将不胜感激。

PS。我还检查了这些问题,这些问题为如何实现所需的内容提供了一些启示,但实际上我专注于如何测试实现的内容

Upadate 1:两个发现

在其他人指出这一点之前,我找到了一些初步答案,我可以说出我要遵循的方向:

  • y = base_layer(x);不直接适合测试,因为它不会产生任何值(在Functional API中,它只是声明如何转换变量x以获取层的输出)
  • 相反, yp = base_model.predict(x)是正确的,但是x必须是numpy数组。比任何Keras variableConstant都简单得多(我更认为它是 declarative 对象)
  • 使用从keras.initializers.Constant数组创建的numpy对象显式初始化内核,只要提供的内核大小合适,就可以正常工作!< / strong>在这种情况下,我想使用[3,5]内核,但这样做却非常糟糕:如果我们要处理具有C颜色层的图像,则一个滤镜意味着一个内核[3,5,C] 。最后,由于Conv2D层具有F=10过滤器,因此正确的内核初始化程序必须来自形状为[3,5,C,F]的四维数组。请注意,过滤器尺寸是最后一个(不是第一个)。
  • 从测试的角度来看,我可以通过调用get_weights()层方法并检查初始化程序的形状是否一致(描述为here)来实现这一点(可以进行特定的检查和警告消息)初始化程序包含显式数组时将其插入Keras代码中,以防止发生此错误。

所以现在我知道要去的方向了。我会及时通知您,希望能为您提供完整的答案以及可行的解决方案。

0 个答案:

没有答案