pytest 中未涵盖的自定义 keras 层中的调用方法
call method in custom keras layers not covered in pytest
我正在尝试对使用自定义层的 keras 神经网络进行单元测试。当我尝试通过 pytest 和覆盖率 运行 它时,它指出 call
方法中的所有代码都没有被覆盖。
我不知道这是否是由于 pytest 将模型交付给单元测试的方式的特殊性,或者 call
方法是否真的没有在我的神经网络中使用,因此有些东西是错了。
下面是一些示例代码:
示例神经网络
class Linear(keras.layers.Layer):
def __init__(self, units=32, input_dim=32):
super(Linear, self).__init__()
self.w = self.add_weight(
shape=(input_dim, units), initializer="random_normal", trainable=True
)
self.b = self.add_weight(shape=(units,), initializer="zeros", trainable=True)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
def build_keras_model():
inputs = keras.layers.Input(shape = (32,))
x = Linear()(inputs)
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs, outputs)
return model
示例 PyTest 文件
from model import build_keras_model
import pytest
import numpy as np
def test_keras_model():
model = build_keras_model()
X = np.random.normal(size = (100, 32))
y = np.random.normal(size = 100)[:, None]
model.compile(loss = 'mae')
model.fit(X, y, epochs = 1)
assert model.predict(X).shape == (100, 1)
如果我在自己的目录中使用 coverage run -m pytest
和 coverage report -m
测试此代码,则它显示 call
方法内的行未被覆盖。
是 pytest、keras 还是我的设置方式有问题?
我认为如果您计划拥有 100% 的测试覆盖率,则必须显式调用 model
的 __call__()
方法。有趣的是,model.predict
似乎并没有这样做(至少,不是在您需要的抽象级别。它在内部也使用相同的方法)。试试这个:
%%file test_keras.py
import pytest
import numpy as np
import tensorflow as tf
class Linear(tf.keras.layers.Layer):
def __init__(self, units=32, input_dim=32):
super(Linear, self).__init__()
self.w = self.add_weight(
shape=(input_dim, units), initializer="random_normal", trainable=True
)
self.b = self.add_weight(shape=(units,), initializer="zeros", trainable=True)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
def build_keras_model():
inputs = tf.keras.layers.Input(shape = (32,))
x = Linear()(inputs)
outputs = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, outputs)
return model
def test_keras_model():
model = build_keras_model()
X = np.random.normal(size = (100, 32))
y = np.random.normal(size = 100)[:, None]
model.compile(loss = 'mae')
model.fit(X, y, epochs = 1)
assert model(X).shape == (100, 1)
!coverage run -m pytest
============================= test session starts ==============================
platform linux -- Python 3.7.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /content
plugins: cov-3.0.0, typeguard-2.7.1
collected 1 item
test_keras.py . [100%]
============================== 1 passed in 6.46s ===============================
!coverage report -m /content/test_keras.py
Name Stmts Miss Cover Missing
---------------------------------------------
test_keras.py 23 0 100%
---------------------------------------------
TOTAL 23 0 100%
检查此 on the differences between the call
method and predict
method and this。
我正在尝试对使用自定义层的 keras 神经网络进行单元测试。当我尝试通过 pytest 和覆盖率 运行 它时,它指出 call
方法中的所有代码都没有被覆盖。
我不知道这是否是由于 pytest 将模型交付给单元测试的方式的特殊性,或者 call
方法是否真的没有在我的神经网络中使用,因此有些东西是错了。
下面是一些示例代码:
示例神经网络
class Linear(keras.layers.Layer):
def __init__(self, units=32, input_dim=32):
super(Linear, self).__init__()
self.w = self.add_weight(
shape=(input_dim, units), initializer="random_normal", trainable=True
)
self.b = self.add_weight(shape=(units,), initializer="zeros", trainable=True)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
def build_keras_model():
inputs = keras.layers.Input(shape = (32,))
x = Linear()(inputs)
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs, outputs)
return model
示例 PyTest 文件
from model import build_keras_model
import pytest
import numpy as np
def test_keras_model():
model = build_keras_model()
X = np.random.normal(size = (100, 32))
y = np.random.normal(size = 100)[:, None]
model.compile(loss = 'mae')
model.fit(X, y, epochs = 1)
assert model.predict(X).shape == (100, 1)
如果我在自己的目录中使用 coverage run -m pytest
和 coverage report -m
测试此代码,则它显示 call
方法内的行未被覆盖。
是 pytest、keras 还是我的设置方式有问题?
我认为如果您计划拥有 100% 的测试覆盖率,则必须显式调用 model
的 __call__()
方法。有趣的是,model.predict
似乎并没有这样做(至少,不是在您需要的抽象级别。它在内部也使用相同的方法)。试试这个:
%%file test_keras.py
import pytest
import numpy as np
import tensorflow as tf
class Linear(tf.keras.layers.Layer):
def __init__(self, units=32, input_dim=32):
super(Linear, self).__init__()
self.w = self.add_weight(
shape=(input_dim, units), initializer="random_normal", trainable=True
)
self.b = self.add_weight(shape=(units,), initializer="zeros", trainable=True)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
def build_keras_model():
inputs = tf.keras.layers.Input(shape = (32,))
x = Linear()(inputs)
outputs = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, outputs)
return model
def test_keras_model():
model = build_keras_model()
X = np.random.normal(size = (100, 32))
y = np.random.normal(size = 100)[:, None]
model.compile(loss = 'mae')
model.fit(X, y, epochs = 1)
assert model(X).shape == (100, 1)
!coverage run -m pytest
============================= test session starts ==============================
platform linux -- Python 3.7.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /content
plugins: cov-3.0.0, typeguard-2.7.1
collected 1 item
test_keras.py . [100%]
============================== 1 passed in 6.46s ===============================
!coverage report -m /content/test_keras.py
Name Stmts Miss Cover Missing
---------------------------------------------
test_keras.py 23 0 100%
---------------------------------------------
TOTAL 23 0 100%
检查此 call
method and predict
method and this。