From 8e8798c19ad4662c3f92047b3ea9fd5a150d55cb Mon Sep 17 00:00:00 2001 From: Chang Sun Date: Mon, 27 Nov 2023 14:05:10 -0800 Subject: [PATCH] add qkeras example --- examples/qkeras.ipynb | 249 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 examples/qkeras.ipynb diff --git a/examples/qkeras.ipynb b/examples/qkeras.ipynb new file mode 100644 index 0000000..3774bae --- /dev/null +++ b/examples/qkeras.ipynb @@ -0,0 +1,249 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "os.environ['CUDA_VISIBLE_DEVICES'] = '-1'\n", + "\n", + "from HGQ import shutup\n", + "import numpy as np\n", + "import keras\n", + "import qkeras\n", + "from HGQ import to_proxy_model\n", + "\n", + "with shutup:\n", + " from hls4ml.converters import convert_from_keras_model" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "qkeras_model = keras.models.Sequential([\n", + " qkeras.QActivation('quantized_bits(8, 0, 0, False, alpha=1)'), # This layer can NOT be removed\n", + " keras.layers.Reshape((28, 28, 1)),\n", + " qkeras.QConv2D(4,\n", + " (3, 3),\n", + " kernel_quantizer='quantized_bits(8, 3, alpha=1)',\n", + " bias_quantizer='quantized_bits(8, 3, alpha=1)',\n", + " activation='quantized_relu(8, 4)'\n", + " ),\n", + " keras.layers.MaxPooling2D(pool_size=(2, 2)),\n", + " qkeras.QConv2D(4,\n", + " (3, 3),\n", + " kernel_quantizer='quantized_bits(8, 3, alpha=1)',\n", + " bias_quantizer='quantized_bits(8, 3, alpha=1)',\n", + " activation='quantized_relu(8, 4)'\n", + " ),\n", + " keras.layers.MaxPooling2D(pool_size=(2, 2)),\n", + " keras.layers.Flatten(),\n", + " qkeras.QDense(32,\n", + " kernel_quantizer='quantized_bits(8, 3, alpha=1)',\n", + " bias_quantizer='quantized_bits(8, 3, alpha=1)',\n", + " activation='quantized_relu(8, 4)'\n", + " ),\n", + " qkeras.QDense(10,\n", + " kernel_quantizer='quantized_bits(8, 3, alpha=1)',\n", + " bias_quantizer='quantized_bits(8, 3, alpha=1)',\n", + " activation='quantized_bits(8, 4, alpha=1)'\n", + " )\n", + "])\n", + "\n", + "qkeras_model.build((None, 28, 28, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()\n", + "x_train = x_train / np.float32(256.0)\n", + "x_test = x_test / np.float32(256.0)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "opt = keras.optimizers.Adam(0.003)\n", + "loss = keras.losses.SparseCategoricalCrossentropy(from_logits=True)\n", + "qkeras_model.compile(optimizer=opt, loss=loss, metrics=['accuracy'])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/3\n", + "469/469 [==============================] - 8s 13ms/step - loss: 0.4635 - accuracy: 0.8571 - val_loss: 0.1471 - val_accuracy: 0.9543\n", + "Epoch 2/3\n", + "469/469 [==============================] - 5s 10ms/step - loss: 0.1513 - accuracy: 0.9535 - val_loss: 0.1258 - val_accuracy: 0.9597\n", + "Epoch 3/3\n", + "469/469 [==============================] - 5s 10ms/step - loss: 0.1190 - accuracy: 0.9641 - val_loss: 0.1071 - val_accuracy: 0.9667\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qkeras_model.fit(x_train, y_train, epochs=3, batch_size=128, verbose=1, validation_data=(x_test, y_test))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "proxy = to_proxy_model(qkeras_model, aggressive=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "r_qkeras = qkeras_model(x_test).numpy()\n", + "r_proxy = proxy(x_test).numpy()\n", + "\n", + "assert np.all(r_qkeras == r_proxy)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Interpreting Model\n", + "Topology:\n", + "Layer name: input_1, layer type: InputLayer, input shapes: [[None, 28, 28, 1]], output shape: [None, 28, 28, 1]\n", + "Layer name: fixed_point_quantizer, layer type: FixedPointQuantizer, input shapes: [[None, 28, 28, 1]], output shape: [None, 28, 28, 1]\n", + "Layer name: reshape, layer type: Reshape, input shapes: [[None, 28, 28, 1]], output shape: [None, 28, 28, 1]\n", + "Layer name: q_conv2d, layer type: Conv2D, input shapes: [[None, 28, 28, 1]], output shape: [None, 26, 26, 4]\n", + "Layer name: fixed_point_quantizer_1, layer type: FixedPointQuantizer, input shapes: [[None, 26, 26, 4]], output shape: [None, 26, 26, 4]\n", + "Layer name: activation, layer type: Activation, input shapes: [[None, 26, 26, 4]], output shape: [None, 26, 26, 4]\n", + "Layer name: fixed_point_quantizer_2, layer type: FixedPointQuantizer, input shapes: [[None, 26, 26, 4]], output shape: [None, 26, 26, 4]\n", + "Layer name: max_pooling2d, layer type: MaxPooling2D, input shapes: [[None, 26, 26, 4]], output shape: [None, 13, 13, 4]\n", + "Layer name: q_conv2d_1, layer type: Conv2D, input shapes: [[None, 13, 13, 4]], output shape: [None, 11, 11, 4]\n", + "Layer name: fixed_point_quantizer_3, layer type: FixedPointQuantizer, input shapes: [[None, 11, 11, 4]], output shape: [None, 11, 11, 4]\n", + "Layer name: activation_1, layer type: Activation, input shapes: [[None, 11, 11, 4]], output shape: [None, 11, 11, 4]\n", + "Layer name: fixed_point_quantizer_4, layer type: FixedPointQuantizer, input shapes: [[None, 11, 11, 4]], output shape: [None, 11, 11, 4]\n", + "Layer name: max_pooling2d_1, layer type: MaxPooling2D, input shapes: [[None, 11, 11, 4]], output shape: [None, 5, 5, 4]\n", + "Layer name: flatten, layer type: Reshape, input shapes: [[None, 5, 5, 4]], output shape: [None, 100]\n", + "Layer name: q_dense, layer type: Dense, input shapes: [[None, 100]], output shape: [None, 32]\n", + "Layer name: fixed_point_quantizer_5, layer type: FixedPointQuantizer, input shapes: [[None, 32]], output shape: [None, 32]\n", + "Layer name: activation_2, layer type: Activation, input shapes: [[None, 32]], output shape: [None, 32]\n", + "Layer name: fixed_point_quantizer_6, layer type: FixedPointQuantizer, input shapes: [[None, 32]], output shape: [None, 32]\n", + "Layer name: q_dense_1, layer type: Dense, input shapes: [[None, 32]], output shape: [None, 10]\n", + "Layer name: fixed_point_quantizer_7, layer type: FixedPointQuantizer, input shapes: [[None, 10]], output shape: [None, 10]\n", + "Creating HLS model\n", + "WARNING: Layer q_conv2d requires \"dataflow\" pipeline style. Switching to \"dataflow\" pipeline style.\n" + ] + } + ], + "source": [ + "hls_conf = {'model': {'Precision': 'fixed<1,0>', 'ReuseFactor': 1}}\n", + "hls_model = convert_from_keras_model(proxy, output_dir='/tmp/qkeras_mnist', io_type='io_stream', hls_config=hls_conf)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing HLS project\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/calad/mambaforge/envs/HGQ/lib/python3.11/site-packages/keras/src/engine/training.py:3000: UserWarning: You are saving your model as an HDF5 file via `model.save()`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')`.\n", + " saving_api.save_model(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Done\n" + ] + } + ], + "source": [ + "hls_model.compile()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r_hls = hls_model.predict(x_test)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assert np.all(r_qkeras == r_hls.reshape(r_qkeras.shape))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "HGQ", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}