Files
circomlib-ml/models/mnist.ipynb
drCathieSo.eth 30a43a2712 Version 2.0.0 (#5)
* feat: `Poly` renamed to `ZeLU` with scaling implemented

* fix: assertion in `ZeLU`

* feat: `AveragePooling2D` with scaling

* feat: `BatchNorm` with scaling

* feat: `Conv1D` with scaling

* feat: `Conv2D` with scaling

* feat: `Dense` with scaling

* fix: assertion in `Dense`

* feat: `GlobalAveragePooling2D` with scaling

* feat: input-only `ArgMax`

* feat: input-only `Flatten2D`

* feat: input-only `GlobalMaxPooling2D`

* feat: input-only `MaxPooling2D`

* feat: input-only `ReLU`

* test: precision up to 36 decimals

* chore: clean up

* test: model1 with 36 decimals

* fix: ReLU should use `p//2` as threshold

* test: clean up

* test: mnist model with 18 decimals

* build: Update package.json version to 2.0.0

* chore: Update README with warning message
2023-10-24 02:50:34 +07:00

1160 lines
37 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"p = 21888242871839275222246405745257275088548364400416034343698204186575808495617"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from tensorflow.keras.layers import Input, Conv2D, AveragePooling2D, Flatten, Softmax, Dense, Lambda, BatchNormalization, ReLU\n",
"from tensorflow.keras import Model\n",
"from tensorflow.keras.datasets import mnist\n",
"from tensorflow.keras.utils import to_categorical\n",
"from tensorflow.keras.optimizers.legacy import SGD\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import tensorflow as tf"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"(X_train, y_train), (X_test, y_test) = mnist.load_data()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# Convert y_train into one-hot format\n",
"temp = []\n",
"for i in range(len(y_train)):\n",
" temp.append(to_categorical(y_train[i], num_classes=10))\n",
"y_train = np.array(temp)\n",
"# Convert y_test into one-hot format\n",
"temp = []\n",
"for i in range(len(y_test)): \n",
" temp.append(to_categorical(y_test[i], num_classes=10))\n",
"y_test = np.array(temp)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"#reshaping\n",
"X_train = X_train.reshape(X_train.shape[0], 28, 28, 1)\n",
"X_test = X_test.reshape(X_test.shape[0], 28, 28, 1)\n",
"\n",
"#normalizing\n",
"X_train = X_train.astype('float32')\n",
"X_test = X_test.astype('float32')\n",
"X_train /= 255.0\n",
"X_test /= 255.0"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"inputs = Input(shape=(28,28,1))\n",
"out = Conv2D(4, 3, use_bias=True)(inputs)\n",
"out = BatchNormalization()(out)\n",
"out = ReLU()(out)\n",
"out = AveragePooling2D()(out)\n",
"out = Conv2D(8, 3, use_bias=True)(out)\n",
"out = BatchNormalization()(out)\n",
"out = ReLU()(out)\n",
"out = AveragePooling2D()(out)\n",
"out = Flatten()(out)\n",
"out = Dense(10, activation=None)(out)\n",
"out = Softmax()(out)\n",
"model = Model(inputs, out)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"model\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" input_1 (InputLayer) [(None, 28, 28, 1)] 0 \n",
" \n",
" conv2d (Conv2D) (None, 26, 26, 4) 40 \n",
" \n",
" batch_normalization (BatchN (None, 26, 26, 4) 16 \n",
" ormalization) \n",
" \n",
" re_lu (ReLU) (None, 26, 26, 4) 0 \n",
" \n",
" average_pooling2d (AverageP (None, 13, 13, 4) 0 \n",
" ooling2D) \n",
" \n",
" conv2d_1 (Conv2D) (None, 11, 11, 8) 296 \n",
" \n",
" batch_normalization_1 (Batc (None, 11, 11, 8) 32 \n",
" hNormalization) \n",
" \n",
" re_lu_1 (ReLU) (None, 11, 11, 8) 0 \n",
" \n",
" average_pooling2d_1 (Averag (None, 5, 5, 8) 0 \n",
" ePooling2D) \n",
" \n",
" flatten (Flatten) (None, 200) 0 \n",
" \n",
" dense (Dense) (None, 10) 2010 \n",
" \n",
" softmax (Softmax) (None, 10) 0 \n",
" \n",
"=================================================================\n",
"Total params: 2,394\n",
"Trainable params: 2,370\n",
"Non-trainable params: 24\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"model.compile(\n",
" loss='categorical_crossentropy',\n",
" optimizer=SGD(learning_rate=0.01, momentum=0.9),\n",
" metrics=['acc']\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/15\n",
" 1/1875 [..............................] - ETA: 5:16 - loss: 2.6515 - acc: 0.0625"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"2023-10-24 02:23:16.557845: W tensorflow/tsl/platform/profile_utils/cpu_utils.cc:128] Failed to get CPU frequency: 0 Hz\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.1896 - acc: 0.9434 - val_loss: 0.0808 - val_acc: 0.9753\n",
"Epoch 2/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0787 - acc: 0.9761 - val_loss: 0.0602 - val_acc: 0.9808\n",
"Epoch 3/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0650 - acc: 0.9803 - val_loss: 0.0546 - val_acc: 0.9831\n",
"Epoch 4/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0592 - acc: 0.9816 - val_loss: 0.0613 - val_acc: 0.9812\n",
"Epoch 5/15\n",
"1875/1875 [==============================] - 7s 4ms/step - loss: 0.0536 - acc: 0.9837 - val_loss: 0.0594 - val_acc: 0.9808\n",
"Epoch 6/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0497 - acc: 0.9847 - val_loss: 0.0618 - val_acc: 0.9794\n",
"Epoch 7/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0470 - acc: 0.9855 - val_loss: 0.0824 - val_acc: 0.9748\n",
"Epoch 8/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0451 - acc: 0.9863 - val_loss: 0.0410 - val_acc: 0.9843\n",
"Epoch 9/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0433 - acc: 0.9865 - val_loss: 0.0561 - val_acc: 0.9822\n",
"Epoch 10/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0425 - acc: 0.9871 - val_loss: 0.0455 - val_acc: 0.9847\n",
"Epoch 11/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0397 - acc: 0.9875 - val_loss: 0.0524 - val_acc: 0.9825\n",
"Epoch 12/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0391 - acc: 0.9879 - val_loss: 0.0382 - val_acc: 0.9875\n",
"Epoch 13/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0381 - acc: 0.9879 - val_loss: 0.0371 - val_acc: 0.9868\n",
"Epoch 14/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0360 - acc: 0.9887 - val_loss: 0.0371 - val_acc: 0.9870\n",
"Epoch 15/15\n",
"1875/1875 [==============================] - 8s 4ms/step - loss: 0.0354 - acc: 0.9887 - val_loss: 0.0378 - val_acc: 0.9874\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x143103e80>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.fit(X_train, y_train, epochs=15, batch_size=32, validation_data=(X_test, y_test))"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"((28, 28, 1), 0.0, 1.0)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X = X_test[0]\n",
"X.shape, X.min(), X.max()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1/1 [==============================] - 0s 45ms/step\n"
]
},
{
"data": {
"text/plain": [
"7"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.predict(X.reshape(1,28,28,1)).argmax()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"def Conv2DInt(nRows, nCols, nChannels, nFilters, kernelSize, strides, n, input, weights, bias):\n",
" Input = [[[str(input[i][j][k] % p) for k in range(nChannels)] for j in range(nCols)] for i in range(nRows)]\n",
" Weights = [[[[str(weights[i][j][k][l] % p) for l in range(nFilters)] for k in range(nChannels)] for j in range(kernelSize)] for i in range(kernelSize)]\n",
" Bias = [str(bias[i] % p) for i in range(nFilters)]\n",
" out = [[[0 for _ in range(nFilters)] for _ in range((nCols - kernelSize)//strides + 1)] for _ in range((nRows - kernelSize)//strides + 1)]\n",
" remainder = [[[None for _ in range(nFilters)] for _ in range((nCols - kernelSize)//strides + 1)] for _ in range((nRows - kernelSize)//strides + 1)]\n",
" for i in range((nRows - kernelSize)//strides + 1):\n",
" for j in range((nCols - kernelSize)//strides + 1):\n",
" for m in range(nFilters):\n",
" for k in range(nChannels):\n",
" for x in range(kernelSize):\n",
" for y in range(kernelSize):\n",
" out[i][j][m] += input[i*strides+x][j*strides+y][k] * weights[x][y][k][m]\n",
" out[i][j][m] += bias[m]\n",
" remainder[i][j][m] = str(out[i][j][m] % n)\n",
" out[i][j][m] = str(out[i][j][m] // n % p)\n",
" return Input, Weights, Bias, out, remainder"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"X_in = [[[int(X[i][j][0]*1e18)] for j in range(28)] for i in range(28)]\n",
"conv2d_1_weights = [[[[int(model.layers[1].weights[0][i][j][k][l]*1e18) for l in range(4)] for k in range(1)] for j in range(3)] for i in range(3)]\n",
"conv2d_1_bias = [int(model.layers[1].weights[1][i]*1e36) for i in range(4)]"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['21888242871839275222246405745257275088548364400416034343698204178650554445275',\n",
" '21888242871839275222246405745257275088548364400416034343698203817637026120037',\n",
" '21888242871839275222246405745257275088548364400416034343698204118313744391231',\n",
" '48458611567652']"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_in, conv2d_1_weights, conv2d_1_bias, conv2d_1_out, conv2d_1_remainder = Conv2DInt(28, 28, 1, 4, 3, 1, 10**18, X_in, conv2d_1_weights, conv2d_1_bias)\n",
"conv2d_1_out[0][0]"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1/1 [==============================] - 0s 18ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([-7.9252541e-06, -3.6893881e-04, -6.8262067e-05, 4.8458613e-05],\n",
" dtype=float32)"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conv2d_model = Model(inputs, model.layers[1].output)\n",
"conv2d_model.predict(X.reshape(1,28,28,1))[0][0][0]"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"gamma = model.layers[2].weights[0].numpy()\n",
"beta = model.layers[2].weights[1].numpy()\n",
"moving_mean = model.layers[2].weights[2].numpy()\n",
"moving_var = model.layers[2].weights[3].numpy()\n",
"epsilon = model.layers[2].epsilon"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(array([2.841136 , 2.7350745, 2.0774858, 1.246628 ], dtype=float32),\n",
" array([ 0.9730277 , -0.0507403 , -0.07507665, -0.5589396 ], dtype=float32))"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a1 = gamma/(moving_var+epsilon)**.5\n",
"b1 = beta-gamma*moving_mean/(moving_var+epsilon)**.5\n",
"a1, b1"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"def BatchNormalizationInt(nRows, nCols, nChannels, n, X_in, a_in, b_in):\n",
" X = [[[str(X_in[i][j][k] % p) for k in range(nChannels)] for j in range(nCols)] for i in range(nRows)]\n",
" A = [str(a_in[k] % p) for k in range(nChannels)]\n",
" B = [str(b_in[k] % p) for k in range(nChannels)]\n",
" out = [[[None for _ in range(nChannels)] for _ in range(nCols)] for _ in range(nRows)]\n",
" remainder = [[[None for _ in range(nChannels)] for _ in range(nCols)] for _ in range(nRows)]\n",
" for i in range(nRows):\n",
" for j in range(nCols):\n",
" for k in range(nChannels):\n",
" out[i][j][k] = (X_in[i][j][k]*a_in[k] + b_in[k])\n",
" remainder[i][j][k] = str(out[i][j][k] % n)\n",
" out[i][j][k] = str(out[i][j][k] // n % p)\n",
" return X, A, B, out, remainder"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"bn_1_in = [[[int(conv2d_1_out[i][j][k]) if int(conv2d_1_out[i][j][k]) < p//2 else int(conv2d_1_out[i][j][k]) - p for k in range(4)] for j in range(26)] for i in range(26)]\n",
"bn_1_a = [int(a1[i]*1e18) for i in range(4)]\n",
"bn_1_b = [int(b1[i]*1e36) for i in range(4)]"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['973005189421817592',\n",
" '21888242871839275222246405745257275088548364400416034343698152437199136300055',\n",
" '21888242871839275222246405745257275088548364400416034343698128968107786241045',\n",
" '21888242871839275222246405745257275088548364400416034343697645307409523760974']"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"_, bn_1_a, bn_1_b, bn_1_out, bn_1_remainder = BatchNormalizationInt(26, 26, 4, 10**18, bn_1_in, bn_1_a, bn_1_b)\n",
"bn_1_out[0][0]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1/1 [==============================] - 0s 22ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([ 0.97300524, -0.05174941, -0.07521845, -0.55887914], dtype=float32)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bn_1_model = Model(inputs, model.layers[2].output)\n",
"bn_1_model.predict(X.reshape(1,28,28,1))[0][0][0]"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"relu_1_in = [[[int(bn_1_out[i][j][k]) for k in range(4)] for j in range(26)] for i in range(26)]\n",
"relu_1_out = [[[str(relu_1_in[i][j][k]) if relu_1_in[i][j][k] < p//2 else 0 for k in range(4)] for j in range(26)] for i in range(26)]"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"avg2d_1_in = [[[int(relu_1_out[i][j][k]) for k in range(4)] for j in range(26)] for i in range(26)]"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"def AveragePooling2DInt (nRows, nCols, nChannels, poolSize, strides, input):\n",
" Input = [[[str(input[i][j][k] % p) for k in range(nChannels)] for j in range(nCols)] for i in range(nRows)]\n",
" out = [[[0 for _ in range(nChannels)] for _ in range((nCols-poolSize)//strides + 1)] for _ in range((nRows-poolSize)//strides + 1)]\n",
" remainder = [[[None for _ in range(nChannels)] for _ in range((nCols-poolSize)//strides + 1)] for _ in range((nRows-poolSize)//strides + 1)]\n",
" for i in range((nRows-poolSize)//strides + 1):\n",
" for j in range((nCols-poolSize)//strides + 1):\n",
" for k in range(nChannels):\n",
" for x in range(poolSize):\n",
" for y in range(poolSize):\n",
" out[i][j][k] += input[i*strides+x][j*strides+y][k]\n",
" remainder[i][j][k] = str(out[i][j][k] % poolSize**2 % p)\n",
" out[i][j][k] = str(out[i][j][k] // poolSize**2 % p)\n",
" return Input, out, remainder"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['1312195747641412224', '17351024717876988', '381448215010339593', '0']"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"_, avg2d_1_out, avg2d_1_remainder = AveragePooling2DInt(26, 26, 4, 2, 2, avg2d_1_in)\n",
"avg2d_1_out[5][6]"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1/1 [==============================] - 0s 28ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([1.3121958 , 0.01735102, 0.38144833, 0. ], dtype=float32)"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"avg2d_1_model = Model(inputs, model.layers[4].output)\n",
"avg2d_1_model.predict(X.reshape(1,28,28,1))[0][5][6]"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"conv2d_2_in = [[[int(avg2d_1_out[i][j][k]) for k in range(4)] for j in range(13)] for i in range(13)]\n",
"conv2d_2_weights = [[[[int(model.layers[5].weights[0][i][j][k][l]*1e18) for l in range(8)] for k in range(4)] for j in range(3)] for i in range(3)]\n",
"conv2d_2_bias = [int(model.layers[5].weights[1][i]*1e36) for i in range(8)]"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['151443532606342120',\n",
" '21888242871839275222246405745257275088548364400416034343695445103896159586204',\n",
" '1368543458414900467',\n",
" '21888242871839275222246405745257275088548364400416034343697889320797389307844',\n",
" '21888242871839275222246405745257275088548364400416034343696909822999783625702',\n",
" '3064925807006993607',\n",
" '273553711551724155',\n",
" '21888242871839275222246405745257275088548364400416034343697690313879935243528']"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"_, conv2d_2_weights, conv2d_2_bias, conv2d_2_out, conv2d_2_remainder = Conv2DInt(13, 13, 4, 8, 3, 1, 10**18, conv2d_2_in, conv2d_2_weights, conv2d_2_bias)\n",
"conv2d_2_out[0][0]"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:5 out of the last 5 calls to <function Model.make_predict_function.<locals>.predict_function at 0x147387d30> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.\n",
"1/1 [==============================] - 0s 27ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([ 0.15144362, -2.7590828 , 1.3685436 , -0.3148657 , -1.2943636 ,\n",
" 3.064926 , 0.27355385, -0.5138727 ], dtype=float32)"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conv2d_2_model = Model(inputs, model.layers[5].output)\n",
"conv2d_2_model.predict(X.reshape(1,28,28,1))[0][0][0]"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"gamma = model.layers[6].weights[0].numpy()\n",
"beta = model.layers[6].weights[1].numpy()\n",
"moving_mean = model.layers[6].weights[2].numpy()\n",
"moving_var = model.layers[6].weights[3].numpy()\n",
"epsilon = model.layers[6].epsilon"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(array([1.4172864, 1.0896717, 1.2455306, 1.9744203, 1.5216775, 1.6048892,\n",
" 1.5560555, 1.5188278], dtype=float32),\n",
" array([ 0.9693597 , 2.5460322 , -2.3216164 , 1.1771976 , 1.7650728 ,\n",
" -5.5845942 , -0.36191303, 0.58835894], dtype=float32))"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a2 = gamma/(moving_var+epsilon)**.5\n",
"b2 = beta-gamma*moving_mean/(moving_var+epsilon)**.5\n",
"a2, b2"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"bn_2_in = [[[int(conv2d_2_out[i][j][k]) if int(conv2d_2_out[i][j][k]) < p//2 else int(conv2d_2_out[i][j][k]) - p for k in range(8)] for j in range(11)] for i in range(11)]\n",
"bn_2_a = [int(a2[i]*1e18) for i in range(8)]\n",
"bn_2_b = [int(b2[i]*1e36) for i in range(8)]"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['1183998554440588778',\n",
" '21888242871839275222246405745257275088548364400416034343697743724366639529790',\n",
" '21888242871839275222246405745257275088548364400416034343697587132926760373824',\n",
" '555520188028190246',\n",
" '21888242871839275222246405745257275088548364400416034343697999655475625376512',\n",
" '21888242871839275222246405745257275088548364400416034343697538458512894177905',\n",
" '63751744556936369',\n",
" '21888242871839275222246405745257275088548364400416034343698012061380413810399']"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"_, bn_2_a, bn_2_b, bn_2_out, bn_2_remainder = BatchNormalizationInt(11, 11, 8, 10**18, bn_2_in, bn_2_a, bn_2_b)\n",
"bn_2_out[0][0]"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:6 out of the last 6 calls to <function Model.make_predict_function.<locals>.predict_function at 0x1475103a0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.\n",
"1/1 [==============================] - 0s 32ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([ 1.1839986 , -0.46046233, -0.61705345, 0.5555204 , -0.20453101,\n",
" -0.66572803, 0.06375193, -0.1921252 ], dtype=float32)"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bn_2_model = Model(inputs, model.layers[6].output)\n",
"bn_2_model.predict(X.reshape(1,28,28,1))[0][0][0]"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['1183998554440588778',\n",
" 0,\n",
" 0,\n",
" '555520188028190246',\n",
" 0,\n",
" 0,\n",
" '63751744556936369',\n",
" 0]"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"relu_2_in = [[[int(bn_2_out[i][j][k]) for k in range(8)] for j in range(11)] for i in range(11)]\n",
"relu_2_out = [[[str(relu_2_in[i][j][k]) if relu_2_in[i][j][k] < p//2 else 0 for k in range(8)] for j in range(11)] for i in range(11)]\n",
"relu_2_out[0][0]"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1/1 [==============================] - 0s 30ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([1.1839986 , 0. , 0. , 0.5555204 , 0. ,\n",
" 0. , 0.06375193, 0. ], dtype=float32)"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"relu_2_model = Model(inputs, model.layers[7].output)\n",
"relu_2_model.predict(X.reshape(1,28,28,1))[0][0][0]"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [],
"source": [
"avg2d_2_in = [[[int(relu_2_out[i][j][k]) if int(relu_2_out[i][j][k]) < p//2 else int(relu_2_out[i][j][k]) - p for k in range(8)] for j in range(11)] for i in range(11)]"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['0',\n",
" '3041275199357812815',\n",
" '880404200542187368',\n",
" '751626574290071696',\n",
" '4631629684299696339',\n",
" '0',\n",
" '0',\n",
" '141002623674408652']"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"_, avg2d_2_out, avg2d_2_remainder = AveragePooling2DInt(11, 11, 8, 2, 2, avg2d_2_in)\n",
"avg2d_2_out[3][3]"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1/1 [==============================] - 0s 30ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([0. , 3.0412755 , 0.88040376, 0.7516271 , 4.6316295 ,\n",
" 0. , 0. , 0.14100271], dtype=float32)"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"avg2d_2_model = Model(inputs, model.layers[8].output)\n",
"avg2d_2_model.predict(X.reshape(1,28,28,1))[0][3][3]"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['240465720017978049',\n",
" '312962931075997403',\n",
" '16422062895818568',\n",
" '0',\n",
" '0',\n",
" '1115397662044723147',\n",
" '3743826354975568930',\n",
" '1282135426254877774',\n",
" '2558492900397241085',\n",
" '0',\n",
" '69224497325539673',\n",
" '0',\n",
" '60798814494206494',\n",
" '2302583886918782205',\n",
" '379552091654971946',\n",
" '0',\n",
" '1609754191355983350',\n",
" '0',\n",
" '27599924897036794',\n",
" '30247813336316648']"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"flatten_out = [avg2d_2_out[i][j][k] for i in range(5) for j in range(5) for k in range(8)]\n",
"flatten_out[100:120]"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1/1 [==============================] - 0s 32ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([0.24046564, 0.312963 , 0.0164221 , 0. , 0. ,\n",
" 1.1153977 , 3.7438262 , 1.2821352 , 2.5584927 , 0. ,\n",
" 0.0692246 , 0. , 0.06079884, 2.3025842 , 0.37955213,\n",
" 0. , 1.6097541 , 0. , 0.02759986, 0.03024786],\n",
" dtype=float32)"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"flatten_model = Model(inputs, model.layers[9].output)\n",
"flatten_model.predict(X.reshape(1,28,28,1))[0][100:120]"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [],
"source": [
"dense_in = [int(flatten_out[i]) if int(flatten_out[i]) < p//2 else int(flatten_out[i]) - p for i in range(200)]\n",
"dense_weights = [[int(model.layers[10].weights[0][i][j]*1e18) for j in range(10)] for i in range(200)]\n",
"dense_bias = [int(model.layers[10].weights[1][i]*1e36) for i in range(10)]"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [],
"source": [
"def DenseInt(nInputs, nOutputs, n, input, weights, bias):\n",
" Input = [str(input[i] % p) for i in range(nInputs)]\n",
" Weights = [[str(weights[i][j] % p) for j in range(nOutputs)] for i in range(nInputs)]\n",
" Bias = [str(bias[i] % p) for i in range(nOutputs)]\n",
" out = [0 for _ in range(nOutputs)]\n",
" remainder = [None for _ in range(nOutputs)]\n",
" for j in range(nOutputs):\n",
" for i in range(nInputs):\n",
" out[j] += input[i] * weights[i][j]\n",
" out[j] += bias[j]\n",
" remainder[j] = str(out[j] % n)\n",
" out[j] = str(out[j] // n % p)\n",
" return Input, Weights, Bias, out, remainder"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['21888242871839275222246405745257275088548364400416034343696001558406187208579',\n",
" '21888242871839275222246405745257275088548364400416034343694494011253998843463',\n",
" '2502586410316628302',\n",
" '7723360444146681933',\n",
" '21888242871839275222246405745257275088548364400416034343688179933383346961393',\n",
" '21888242871839275222246405745257275088548364400416034343697101907583287035462',\n",
" '21888242871839275222246405745257275088548364400416034343680804147065276585857',\n",
" '21047995401855287971',\n",
" '21888242871839275222246405745257275088548364400416034343695951614145619839501',\n",
" '4230622081176419220']"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"_, dense_weights, dense_bias, dense_out, dense_remainder = DenseInt(200, 10, 10**18, dense_in, dense_weights, dense_bias)\n",
"dense_out"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['21888242871839275222246405745257275088548364400416034343696001558406187208579',\n",
" '21888242871839275222246405745257275088548364400416034343694494011253998843463',\n",
" '2502586410316628302',\n",
" '7723360444146681933',\n",
" '21888242871839275222246405745257275088548364400416034343688179933383346961393',\n",
" '21888242871839275222246405745257275088548364400416034343697101907583287035462',\n",
" '21888242871839275222246405745257275088548364400416034343680804147065276585857',\n",
" '21047995401855287971',\n",
" '21888242871839275222246405745257275088548364400416034343695951614145619839501',\n",
" '4230622081176419220']"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dense_out"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1/1 [==============================] - 0s 35ms/step\n"
]
},
{
"data": {
"text/plain": [
"array([ -2.2026286, -3.7101758, 2.5025864, 7.7233634, -10.024254 ,\n",
" -1.1022782, -17.40004 , 21.047997 , -2.2525737, 4.230623 ],\n",
" dtype=float32)"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dense_model = Model(inputs, model.layers[-2].output)\n",
"dense_model.predict(X.reshape(1,28,28,1))[0]"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"in_json = {\n",
" \"in\": X_in,\n",
" \"conv2d_1_weights\": conv2d_1_weights,\n",
" \"conv2d_1_bias\": conv2d_1_bias,\n",
" \"conv2d_1_out\": conv2d_1_out,\n",
" \"conv2d_1_remainder\": conv2d_1_remainder,\n",
" \"bn_1_a\": bn_1_a,\n",
" \"bn_1_b\": bn_1_b,\n",
" \"bn_1_out\": bn_1_out,\n",
" \"bn_1_remainder\": bn_1_remainder,\n",
" \"relu_1_out\": relu_1_out,\n",
" \"avg2d_1_out\": avg2d_1_out,\n",
" \"avg2d_1_remainder\": avg2d_1_remainder,\n",
" \"conv2d_2_weights\": conv2d_2_weights,\n",
" \"conv2d_2_bias\": conv2d_2_bias,\n",
" \"conv2d_2_out\": conv2d_2_out,\n",
" \"conv2d_2_remainder\": conv2d_2_remainder,\n",
" \"bn_2_a\": bn_2_a,\n",
" \"bn_2_b\": bn_2_b,\n",
" \"bn_2_out\": bn_2_out,\n",
" \"bn_2_remainder\": bn_2_remainder,\n",
" \"relu_2_out\": relu_2_out,\n",
" \"avg2d_2_out\": avg2d_2_out,\n",
" \"avg2d_2_remainder\": avg2d_2_remainder,\n",
" \"flatten_out\": flatten_out,\n",
" \"dense_weights\": dense_weights,\n",
" \"dense_bias\": dense_bias,\n",
" \"dense_out\": dense_out,\n",
" \"dense_remainder\": dense_remainder,\n",
" \"argmax_out\": \"7\"\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
"import json"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [],
"source": [
"with open(\"mnist_input.json\", \"w\") as f:\n",
" json.dump(in_json, f)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"interpreter": {
"hash": "11280bdb37aa6bc5d4cf1e4de756386eb1f9eecd8dcdefa77636dfac7be2370d"
},
"kernelspec": {
"display_name": "Python 3.8.6 ('tf24')",
"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.9.16"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}