Issues when loading custom xmodel on kria PYNQ

Hi,
I am using a Kria KV260 board with ubuntu 22.04 installed and the kria-PYNQ fork in version 3.0. In my host computer, I have a docker image of vitis AI 3.5 with tensorflow2. I have generated the xmodel for a basic simple linear regression model and I wanted to load it on the kria board. This are the scripts used to generate and quantize the model.
regression.py:

#! /usr/bin/env python3
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
plt.style.use('ggplot')

true_b = 1
true_w = 2
N = 100

# Data Generation
np.random.seed(42)
x = np.random.rand(N, 1)
epsilon = (.1 * np.random.randn(N, 1))
y = true_b + true_w * x + epsilon

print('x.shape():')
print(x.shape)
print('y.shape():')
print(y.shape)
plt.scatter(x, y, label='generated data')
plt.savefig("raw_data.png")

# Shuffles the indices
idx = np.arange(N)
np.random.shuffle(idx)

# Uses first 80 random indices for train
train_idx = idx[:int(N*.8)]

# Uses the remaining indices for validation
val_idx = idx[int(N*.8):]

# Generates train and validation sets
x_train, y_train = x[train_idx], y[train_idx]
x_val, y_val = x[val_idx], y[val_idx]

fig, axs = plt.subplots(1, 2)
axs[0].plot(x_train, y_train, '.', label='train data')
axs[1].plot(x_val, y_val, '.', label='validation data')
plt.savefig('train&validate.png')

model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(1, input_shape=[1]))
model.compile(loss='mean_squared_error', optimizer=tf.keras.optimizers.Adam(0.1))

model.summary()

history = model.fit(x_train, y_train, epochs=50)

plt.subplots(1, 1)
plt.plot(history.history['loss'])
plt.savefig('loss_vs_epoch.png')

y_hat = model.predict(x_val)

plt.subplots(1, 1)
plt.scatter(x_val, y_val, label='validation data')
plt.plot(x_val, y_hat, label='predicted data', color='c')
plt.savefig('validation_plot.png')

x_test = np.array([1, 2, 3, 4])
print(type(x_test))
y_pred = model.predict(x_test)
print(type(y_pred))
for idx in range(len(x_test)):
    print("x = {} => predicted y = {}".format(x_test[idx], int(y_pred[idx])))

#model.predict takes as an argument an np.array type
print(model.predict(np.array([5])))

model.save('saved_model.h5', save_format="h5")

quantizer.py:

#! /usr/bin/env python3
from tensorflow import keras
import numpy as np

true_b = 1
true_w = 2
N = 100

# Data Generation
np.random.seed(42)
x = np.random.rand(N, 1)
epsilon = (.1 * np.random.randn(N, 1))
y = true_b + true_w * x + epsilon

print('x.shape():')
print(x.shape)
print('y.shape():')
print(y.shape)

# Shuffles the indices
idx = np.arange(N)
np.random.shuffle(idx)

# Uses first 80 random indices for train
train_idx = idx[:int(N*.8)]

# Uses the remaining indices for validation
val_idx = idx[int(N*.8):]

# Generates train and validation sets
x_train, y_train = x[train_idx], y[train_idx]
x_val, y_val = x[val_idx], y[val_idx]

model = keras.models.load_model('saved_model.h5')
model.summary()

from tensorflow_model_optimization.quantization.keras import vitis_quantize
quantizer = vitis_quantize.VitisQuantizer(model)
q_model = quantizer.quantize_model(calib_dataset=x_train)

print("\n[DB INFO] Evaluation of Quantized Model...\n")
with vitis_quantize.quantize_scope():
    # categorical_crossentropy throws a warning related to shape, need to study more about that
    # q_model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
    q_model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
    q_eval_results = q_model.evaluate(x_val, y_val)
    print("\n***************** Summary *****************")
    print("X_Test Quantized model accuracy: ", q_eval_results[1])

print("\n[DB INFO] Saving Quantized Model...\n")
q_model.save('quantized_model.h5')
print("\n[DB INFO] showing predictions...\n")
x_test = np.array([1.0, 2.0, 3.0, 4.0])
print(type(x_test))
y_pred = model.predict(x_test)
print(type(y_pred))
for idx in range(len(x_test)):
    print("x = {} => predicted y = {}".format(x_test[idx], y_pred[idx]))

I have compiled using a modified version of the run_compile.sh that is shown in the vitis AI official repo. I had added this lines to be able to compile it for the kria:

elif [ $1 = kv260 ]; then
      ARCH=/opt/vitis_ai/compiler/arch/DPUCZDX8G/KV260/arch.json
      TARGET=KV260
      echo "-----------------------------------------"
      echo "COMPILING MODEL FOR KV260"
      echo "-----------------------------------------"

I cannot upload the final xmodel. After compiling, I had uploaded the xmodel, json and md5sum to the path: /root/jupyter_notebooks/test, in order to be able to run it with jupyter on the host’s web browser. On the same path a new notebook was added. First line:

from pynq_dpu import DpuOverlay
overlay = DpuOverlay("dpu.bit")

Everything is ok, but then I tried to load the xmodel, but there is an AssertionError


Just in case, I copy the output as text

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Input In [2], in <cell line: 1>()
----> 1 overlay.load_model("KV260_quantized_model.h5.xmodel")

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq_dpu/dpu.py:177, in DpuOverlay.load_model(self, model)
    175 self.graph = xir.Graph.deserialize(abs_model)
    176 subgraphs = get_child_subgraph_dpu(self.graph)
--> 177 assert len(subgraphs) == 1
    178 self.runner = vart.Runner.create_runner(subgraphs[0], "run")

AssertionError:

Does anyone knows what might the issue be?

Hi @Adev,

Welcome to the PYNQ community.

If you check, for the KV260 the Vitis AI 2.5 is used. Kria-PYNQ/install.sh at main · Xilinx/Kria-PYNQ · GitHub

You may need to update manually the installation or use Vitis AI 2.5 to generate the xmodel.

Mario

ahhh, great thanks!!