Skip to content

Commit d3b3daa

Browse files
committed
add pytest for binary cnn
1 parent a65ab34 commit d3b3daa

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

test/pytest/test_binary_cnn.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import numpy as np
2+
import pytest
3+
from qkeras import QActivation, QBatchNormalization, QConv2D, QDense
4+
from tensorflow.keras.layers import Flatten, Input, MaxPooling2D
5+
from tensorflow.keras.models import Model
6+
from tensorflow.keras.regularizers import l2
7+
8+
import hls4ml
9+
10+
11+
@pytest.mark.parametrize('backend', ['Vivado', 'Vitis', 'Quartus'])
12+
@pytest.mark.parametrize('io_type', ['io_parallel', 'io_stream'])
13+
def test_model2(backend, io_type):
14+
x_in = Input(shape=(28, 28, 1))
15+
16+
x = QConv2D(
17+
4,
18+
(3, 3),
19+
kernel_quantizer="binary",
20+
bias_quantizer="binary",
21+
name="conv2d_1",
22+
kernel_regularizer=l2(0.0001),
23+
)(x_in)
24+
x = QBatchNormalization()(x)
25+
x = QActivation("binary", name="act1")(x)
26+
27+
x = QConv2D(
28+
8,
29+
(3, 3),
30+
kernel_quantizer="binary",
31+
bias_quantizer="binary",
32+
name="conv2d_2",
33+
kernel_regularizer=l2(0.0001),
34+
)(x)
35+
x = QBatchNormalization()(x)
36+
x = QActivation("binary", name="act2")(x)
37+
x = MaxPooling2D(pool_size=(2, 2))(x)
38+
39+
x = QConv2D(
40+
8,
41+
(3, 3),
42+
kernel_quantizer="binary",
43+
bias_quantizer="binary",
44+
name="conv2d_3",
45+
kernel_regularizer=l2(0.0001),
46+
)(x)
47+
x = QBatchNormalization()(x)
48+
x = QActivation("binary", name="act3")(x)
49+
x = MaxPooling2D(pool_size=(2, 2))(x)
50+
51+
x = Flatten()(x)
52+
53+
x = QDense(10, kernel_quantizer="binary", bias_quantizer="binary", name="q_dense_6")(x)
54+
x = QBatchNormalization()(x)
55+
x = QActivation("binary_tanh", name="act4")(x)
56+
57+
x = QDense(
58+
10,
59+
kernel_quantizer="binary",
60+
bias_quantizer="binary",
61+
activation="softmax",
62+
name="q_dense_7",
63+
)(x)
64+
65+
model2 = Model(inputs=x_in, outputs=x)
66+
67+
model2.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
68+
69+
model2.summary()
70+
71+
hls_config = hls4ml.utils.config_from_keras_model(model2, granularity="name")
72+
hls_config["Model"]["Strategy"] = "Resource"
73+
hls_config["IOTtype"] = "io_stream"
74+
75+
hls_config["LayerName"]["conv2d_1"]["ReuseFactor"] = 36
76+
hls_config["LayerName"]["conv2d_2"]["ReuseFactor"] = 288
77+
hls_config["LayerName"]["conv2d_3"]["ReuseFactor"] = 576
78+
hls_config["LayerName"]["q_dense_6"]["ReuseFactor"] = 2000
79+
hls_config["LayerName"]["q_dense_7"]["ReuseFactor"] = 100
80+
81+
hls_model = hls4ml.converters.convert_from_keras_model(
82+
model2,
83+
hls_config=hls_config,
84+
output_dir=f"hls4mlprj_binary_cnn_{backend}_{io_type}",
85+
backend=backend,
86+
io_type=io_type,
87+
)
88+
89+
hls_model.compile()
90+
y = model2.predict(np.zeros((1, 28, 28, 1)))
91+
y_hls = hls_model.predict(np.zeros((1, 28, 28, 1)))
92+
93+
print(f"{y_hls=}")
94+
print(f"{y=}")
95+
96+
np.testing.assert_allclose(np.squeeze(y_hls), np.squeeze(y), rtol=1e-2, atol=0.01)
97+
98+
99+
if __name__ == "__main__":
100+
test_model2("Vivado", "io_stream")

0 commit comments

Comments
 (0)