mirror of
https://github.com/socathie/circomlib-ml.git
synced 2026-01-09 14:08:04 -05:00
* 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
1160 lines
37 KiB
Plaintext
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
|
|
}
|