{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Import","metadata":{}},{"cell_type":"code","source":"import os\nimport re\nfrom glob import glob\nfrom tqdm import tqdm\nimport numpy as np\nimport pandas as pd\nimport ast\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nimport tensorflow as tf\nfrom PIL import Image, ImageDraw ","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:39:49.285498Z","iopub.execute_input":"2021-10-24T05:39:49.285795Z","iopub.status.idle":"2021-10-24T05:39:49.324325Z","shell.execute_reply.started":"2021-10-24T05:39:49.285742Z","shell.execute_reply":"2021-10-24T05:39:49.323658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"INPUT_ROOT = '../input/quickdraw-doodle-recognition'\nINPUT_DIR = 'train_simplified'\nprint(os.listdir(INPUT_ROOT))","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:39:49.325991Z","iopub.execute_input":"2021-10-24T05:39:49.326291Z","iopub.status.idle":"2021-10-24T05:39:49.332223Z","shell.execute_reply.started":"2021-10-24T05:39:49.326244Z","shell.execute_reply":"2021-10-24T05:39:49.331196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Read and Summarize the Data (discard actual value)","metadata":{}},{"cell_type":"code","source":"csv_filenames = glob(os.path.join(INPUT_ROOT, INPUT_DIR, '*.csv'))\ncolumn_names = ['countrycode', 'drawing', 'key_id', 'recognized', 'timestamp', 'word']\n\nrow_counts = []\nwords = []\nmin_row_count = 999999999\n\nimport sys\ntotalmem_mb = 0\nfor csv_filename in tqdm(csv_filenames):\n    row_count = sum(1 for row in pd.read_csv(csv_filename))\n    words.append(pd.read_csv(csv_filename, nrows=1)['word'].values[0])\n    row_counts.append(row_count)\n    min_row_count = min(min_row_count, row_count)","metadata":{"_kg_hide-input":true,"_uuid":"978b1e827e598c53df3ef09838a6d85591d83052","execution":{"iopub.status.busy":"2021-10-24T05:39:49.334261Z","iopub.execute_input":"2021-10-24T05:39:49.334877Z","iopub.status.idle":"2021-10-24T05:47:39.890511Z","shell.execute_reply.started":"2021-10-24T05:39:49.334764Z","shell.execute_reply":"2021-10-24T05:47:39.889622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df =  pd.read_csv(csv_filenames[0], nrows=1)\ndf.iloc[:,5].values[0]","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:39.89249Z","iopub.execute_input":"2021-10-24T05:47:39.893036Z","iopub.status.idle":"2021-10-24T05:47:39.909031Z","shell.execute_reply.started":"2021-10-24T05:47:39.892981Z","shell.execute_reply":"2021-10-24T05:47:39.908206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Generator Maker","metadata":{}},{"cell_type":"code","source":"IMHEIGHT, IMWIDTH = 64, 64\nNUM_CLASSES = len(row_counts)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:39.910516Z","iopub.execute_input":"2021-10-24T05:47:39.910932Z","iopub.status.idle":"2021-10-24T05:47:39.915087Z","shell.execute_reply.started":"2021-10-24T05:47:39.910765Z","shell.execute_reply":"2021-10-24T05:47:39.914159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def random_row_gen_maker(csv_path, max_index, reservoir_min=3):\n    reservoir = [] # list of strokes\n    def gen():\n        while True:\n            if len(reservoir) == 0:\n                while len(reservoir) < reservoir_min:\n                    r = np.random.randint(1, max_index+1) # [0, max_index) -> [1, max_index]\n                    if r==1: df = pd.read_csv(csv_path, nrows=1)\n                    else: df = pd.read_csv(csv_path, skiprows=r, nrows=5)\n\n                    if not bool(df.iloc[:, 3].values[0]): continue # 3 -> recognized\n                    reservoir.append(ast.literal_eval(df.iloc[:, 1].values[0])) # 1 -> drawing\n            strokes = reservoir.pop()\n            \n            image = Image.new(\"P\", (256,256), color=255)\n            image_draw = ImageDraw.Draw(image)\n            for stroke in strokes:\n                for i in range(len(stroke[0])-1):\n                    image_draw.line( [stroke[0][i], stroke[1][i], \n                                      stroke[0][i+1], stroke[1][i+1]],\n                                    fill=0, width=5 )\n            image = image.resize((IMHEIGHT, IMWIDTH))\n            yield (np.array(image)/255.0).copy()\n    return gen()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:39.922458Z","iopub.execute_input":"2021-10-24T05:47:39.922978Z","iopub.status.idle":"2021-10-24T05:47:39.937694Z","shell.execute_reply.started":"2021-10-24T05:47:39.922929Z","shell.execute_reply":"2021-10-24T05:47:39.936594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Testing Generator - Single Output","metadata":{}},{"cell_type":"code","source":"G = random_row_gen_maker(csv_filenames[words.index('star')], 100)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:39.938573Z","iopub.execute_input":"2021-10-24T05:47:39.938783Z","iopub.status.idle":"2021-10-24T05:47:39.950232Z","shell.execute_reply.started":"2021-10-24T05:47:39.938743Z","shell.execute_reply":"2021-10-24T05:47:39.949446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = next(G)\nplt.imshow(img, cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:39.951113Z","iopub.execute_input":"2021-10-24T05:47:39.951348Z","iopub.status.idle":"2021-10-24T05:47:40.183676Z","shell.execute_reply.started":"2021-10-24T05:47:39.951308Z","shell.execute_reply":"2021-10-24T05:47:40.18291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Testing Generator - Multiple Output","metadata":{}},{"cell_type":"code","source":"fig = plt.figure(figsize=(15,12))\nrows, cols = 5, 8\n\nfor i in range(rows):\n    row_idx = np.random.randint(0, len(words))\n    G = random_row_gen_maker(csv_filenames[row_idx], 100)\n    for j in range(cols): \n        # plot and titles\n        plt.subplot(rows, cols, i*cols+j+1)\n        plt.title(words[row_idx])\n        \n        # turn off axis ticks\n        plt.gca().axes.get_xaxis().set_visible(False)\n        plt.gca().axes.get_yaxis().set_visible(False)\n        \n        # gray scale\n        plt.imshow(next(G), cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:40.184767Z","iopub.execute_input":"2021-10-24T05:47:40.185197Z","iopub.status.idle":"2021-10-24T05:47:41.641848Z","shell.execute_reply.started":"2021-10-24T05:47:40.185145Z","shell.execute_reply":"2021-10-24T05:47:41.641108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create a Generic CNN Model","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D\nfrom tensorflow.keras.metrics import top_k_categorical_accuracy\nfrom tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:41.642717Z","iopub.execute_input":"2021-10-24T05:47:41.642956Z","iopub.status.idle":"2021-10-24T05:47:41.650506Z","shell.execute_reply.started":"2021-10-24T05:47:41.642913Z","shell.execute_reply":"2021-10-24T05:47:41.647269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Generator for fit, test","metadata":{}},{"cell_type":"code","source":"def gen(batchsize, max_index=1000):\n    while True:\n        images = []\n        labels = []\n        while len(images) < batchsize:\n            csv_path = np.random.choice(csv_filenames)\n            r = np.random.randint(1, max_index+1) # [0, max_index) -> [1, max_index]\n            if r==1: df = pd.read_csv(csv_path, nrows=1)\n            else: df = pd.read_csv(csv_path, skiprows=r, nrows=5)\n\n            if not bool(df.iloc[:, 3].values[0]): continue # 3 -> recognized\n\n            ## Get lable\n            word = df.iloc[:,5].values[0]\n\n            ## Render the strokes onto an image\n            strokes = ast.literal_eval(df.iloc[:, 1].values[0]) # 1 -> drawing\n\n            image = Image.new(\"P\", (256,256), color=255)\n            image_draw = ImageDraw.Draw(image)\n            for stroke in strokes:\n                for i in range(len(stroke[0])-1):\n                    image_draw.line( [stroke[0][i], stroke[1][i], \n                                      stroke[0][i+1], stroke[1][i+1]],\n                                    fill=0, width=5 )\n            image = image.resize((IMHEIGHT, IMWIDTH))\n            image = np.array(image)/255.0\n            # TODO reshape image to input shape\n\n            images.append(image)\n            labels.append(words.index(word))\n        images = np.array(images)\n        \n        ## Transform for fitting/testing\n        x = images.reshape(images.shape[0], IMHEIGHT, IMWIDTH, 1)\n        y = keras.utils.to_categorical(labels, NUM_CLASSES)\n        yield (x, y)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:41.651462Z","iopub.execute_input":"2021-10-24T05:47:41.651685Z","iopub.status.idle":"2021-10-24T05:47:41.667157Z","shell.execute_reply.started":"2021-10-24T05:47:41.651637Z","shell.execute_reply":"2021-10-24T05:47:41.666366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 1024\ntrain_gen = gen(BATCH_SIZE)\ntest_gen = gen(BATCH_SIZE)\nprint(train_gen)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:41.66842Z","iopub.execute_input":"2021-10-24T05:47:41.668957Z","iopub.status.idle":"2021-10-24T05:47:41.676613Z","shell.execute_reply.started":"2021-10-24T05:47:41.66889Z","shell.execute_reply":"2021-10-24T05:47:41.675916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Build Model - CPU/GPU","metadata":{}},{"cell_type":"code","source":"model = Sequential()\nmodel.add(Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu', input_shape=(IMHEIGHT, IMWIDTH, 1)))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.2))\nmodel.add(Flatten())\nmodel.add(Dense(680, activation='relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(NUM_CLASSES, activation='softmax'))\nmodel.summary()\n\nmodel.compile(loss='categorical_crossentropy', optimizer='adam',\n              metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:41.6774Z","iopub.execute_input":"2021-10-24T05:47:41.677676Z","iopub.status.idle":"2021-10-24T05:47:41.938764Z","shell.execute_reply.started":"2021-10-24T05:47:41.677581Z","shell.execute_reply":"2021-10-24T05:47:41.938009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Build Model - TPU","metadata":{}},{"cell_type":"code","source":"# # detect and init the TPU\n# tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()\n\n# # instantiate a distribution strategy\n# tpu_strategy = tf.distribute.experimental.TPUStrategy(tpu)\n\n# # instantiating the model in the strategy scope creates the model on the TPU\n# with tpu_strategy.scope():\n#     model = Sequential()\n#     model.add(Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu', input_shape=(IMHEIGHT, IMWIDTH, 1)))\n#     model.add(MaxPooling2D(pool_size=(2, 2)))\n#     model.add(Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu'))\n#     model.add(MaxPooling2D(pool_size=(2, 2)))\n#     model.add(Dropout(0.2))\n#     model.add(Flatten())\n#     model.add(Dense(680, activation='relu'))\n#     model.add(Dropout(0.5))\n#     model.add(Dense(NUM_CLASSES, activation='softmax'))\n#     model.summary()\n\n#     model.compile(loss='categorical_crossentropy', optimizer='adam',\n#                   metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:41.939638Z","iopub.execute_input":"2021-10-24T05:47:41.939867Z","iopub.status.idle":"2021-10-24T05:47:41.944854Z","shell.execute_reply.started":"2021-10-24T05:47:41.939825Z","shell.execute_reply":"2021-10-24T05:47:41.944122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Training the model","metadata":{}},{"cell_type":"code","source":"history = model.fit_generator(epochs = 50, verbose = 1,\n                              generator=train_gen, steps_per_epoch = 16,\n                              validation_data = test_gen, validation_steps = 16, )\nmodel.save('g-cnn-generator.h5')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T05:47:41.945993Z","iopub.execute_input":"2021-10-24T05:47:41.946502Z","iopub.status.idle":"2021-10-24T08:00:52.808087Z","shell.execute_reply.started":"2021-10-24T05:47:41.946452Z","shell.execute_reply":"2021-10-24T08:00:52.807259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Plot Loss/Accuracy","metadata":{}},{"cell_type":"code","source":"import keras\nfrom matplotlib import pyplot as plt\nplt.plot(history.history['acc'])\nplt.plot(history.history['val_acc'])\nplt.title('model accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(['train', 'val'], loc='upper left')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:52.811649Z","iopub.execute_input":"2021-10-24T08:00:52.811929Z","iopub.status.idle":"2021-10-24T08:00:53.285329Z","shell.execute_reply.started":"2021-10-24T08:00:52.81188Z","shell.execute_reply":"2021-10-24T08:00:53.284407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Predicting","metadata":{}},{"cell_type":"code","source":"test_gen = gen(16)\nX, y = next(test_gen)\ny = y.tolist()\nanswers = [words[yi.index(1)] for yi in y]\n\ny_pred = model.predict(X, verbose=0)\nargs = np.argsort(-y_pred)[:, 0:3]\n\nfig = plt.figure(figsize=(15,12))\nrows, cols = 4, 4\nfor i in range(rows):\n    for j in range(cols):   \n        idx = i*cols + j\n        answer = answers[idx]\n        \n        if words[args[idx][0]] == answer:\n            answer += ' (Y)'\n        else:\n            answer += ' (N)'\n        \n        # plot and titles\n        plt.subplot(rows, cols, i*cols+j+1)\n        plt.title(answer, fontsize=15)\n        infotext = \"1. {}\\n2. {}\\n3. {}\".format(words[args[idx][0]], words[args[idx][1]], words[args[idx][2]])\n        \n        plt.text(32, 58, infotext, style='italic', color='white', fontsize='large',\n            bbox={'facecolor': '#486678', 'alpha': 0.8, 'pad': 10})\n\n        # turn off axis ticks\n        plt.gca().axes.get_xaxis().set_visible(False)\n        plt.gca().axes.get_yaxis().set_visible(False)\n        \n        img = X[idx]\n        img = img.reshape((IMHEIGHT, IMWIDTH))\n        \n        # gray scale\n        plt.imshow(img, cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:53.290152Z","iopub.execute_input":"2021-10-24T08:00:53.290593Z","iopub.status.idle":"2021-10-24T08:00:54.268716Z","shell.execute_reply.started":"2021-10-24T08:00:53.290424Z","shell.execute_reply":"2021-10-24T08:00:54.26782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ~~Gather X and y~~","metadata":{}},{"cell_type":"code","source":"# X, y = [], []\n# for idx in tqdm(range(len(draw_df))):\n#     X.append(render(draw_df.iloc[idx].drawing))\n#     y.append( words.index(draw_df.iloc[idx].word) )\n\n# X, y = np.array(X), np.array(y)\n# print(X.shape)\n# print(y.shape)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:54.269715Z","iopub.execute_input":"2021-10-24T08:00:54.269988Z","iopub.status.idle":"2021-10-24T08:00:54.274369Z","shell.execute_reply.started":"2021-10-24T08:00:54.269946Z","shell.execute_reply":"2021-10-24T08:00:54.273535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ~~Splitting to Test and Train Data~~","metadata":{}},{"cell_type":"code","source":"# X_train, X_test, y_train, y_test = train_test_split(X, y)\n\n# y_train = keras.utils.to_categorical(y_train, num_classes)\n# X_train = X_train.reshape(X_train.shape[0], imheight, imwidth, 1)\n# y_test = keras.utils.to_categorical(y_test, num_classes)\n# X_test = X_test.reshape(X_test.shape[0], imheight, imwidth, 1)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:54.275276Z","iopub.execute_input":"2021-10-24T08:00:54.275531Z","iopub.status.idle":"2021-10-24T08:00:54.28758Z","shell.execute_reply.started":"2021-10-24T08:00:54.275488Z","shell.execute_reply":"2021-10-24T08:00:54.286784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ~~Preparing data~~","metadata":{}},{"cell_type":"code","source":"# print(y_train.shape)\n# print(X_train.shape)\n# print(y_test.shape)\n# print(X_test.shape)\n\n# # Correct should be\n# #  (612000, 340) \n# #  (612000, 32, 32, 1) \n# #  (68000, 340) \n# #  (68000, 32, 32, 1)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:54.288415Z","iopub.execute_input":"2021-10-24T08:00:54.288625Z","iopub.status.idle":"2021-10-24T08:00:54.297579Z","shell.execute_reply.started":"2021-10-24T08:00:54.288585Z","shell.execute_reply":"2021-10-24T08:00:54.297004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ~~Building the First Model (Generic CNN)~~","metadata":{}},{"cell_type":"markdown","source":"### ~~Building the Layers~~","metadata":{}},{"cell_type":"code","source":"# model = Sequential()\n# model.add(Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu', input_shape=(imheight, imwidth, 1)))\n# model.add(MaxPooling2D(pool_size=(2, 2)))\n# model.add(Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu'))\n# model.add(MaxPooling2D(pool_size=(2, 2)))\n# model.add(Dropout(0.2))\n# model.add(Flatten())\n# model.add(Dense(680, activation='relu'))\n# model.add(Dropout(0.5))\n# model.add(Dense(num_classes, activation='softmax'))\n# model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:54.298361Z","iopub.execute_input":"2021-10-24T08:00:54.298581Z","iopub.status.idle":"2021-10-24T08:00:54.310602Z","shell.execute_reply.started":"2021-10-24T08:00:54.298538Z","shell.execute_reply":"2021-10-24T08:00:54.309673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ~~Compiling and Training the model~~","metadata":{}},{"cell_type":"code","source":"# model.compile(loss='categorical_crossentropy', optimizer='adam',\n#               metrics=['accuracy'])\n\n# history = model.fit(x=X_train, y=y_train, batch_size = 32, epochs = 10,\n#           validation_data = (X_test, y_test), verbose = 1)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:54.311736Z","iopub.execute_input":"2021-10-24T08:00:54.311976Z","iopub.status.idle":"2021-10-24T08:00:54.319009Z","shell.execute_reply.started":"2021-10-24T08:00:54.311936Z","shell.execute_reply":"2021-10-24T08:00:54.31821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model.save('g-cnn-testing.h5')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:54.319728Z","iopub.execute_input":"2021-10-24T08:00:54.319934Z","iopub.status.idle":"2021-10-24T08:00:54.328852Z","shell.execute_reply.started":"2021-10-24T08:00:54.319895Z","shell.execute_reply":"2021-10-24T08:00:54.327858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import keras\n# from matplotlib import pyplot as plt\n# plt.plot(history.history['acc'])\n# plt.plot(history.history['val_acc'])\n# plt.title('model accuracy')\n# plt.ylabel('accuracy')\n# plt.xlabel('epoch')\n# plt.legend(['train', 'val'], loc='upper left')\n# plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:54.329811Z","iopub.execute_input":"2021-10-24T08:00:54.33008Z","iopub.status.idle":"2021-10-24T08:00:54.337675Z","shell.execute_reply.started":"2021-10-24T08:00:54.330038Z","shell.execute_reply":"2021-10-24T08:00:54.33692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ~~Predicting~~","metadata":{}},{"cell_type":"code","source":"# fig = plt.figure(figsize=(15,12))\n# rows, cols = 3, 3\n\n# for i in range(rows):\n#     for j in range(cols): \n#         idx = randint(0, len(X_test)-1)\n#         img = render(draw_df.iloc[idx].drawing)\n#         rsimg = np.reshape(img, (-1, imheight, imwidth, 1))\n#         answer = draw_df.iloc[idx].word\n        \n#         # predict\n#         preds = model.predict(rsimg, verbose=0)\n#         args = np.argsort(-preds)[:, 0:3]  # top 3\n#         args = args[0]\n#         if words[args[0]] == answer:\n#             answer += ' (Y)'\n#         else:\n#             answer += ' (N)'\n        \n#         # plot and titles\n#         plt.subplot(rows, cols, i*cols+j+1)\n#         plt.title(answer, fontsize=15)\n#         infotext = \"1. {}\\n2. {}\\n3. {}\".format(words[args[0]], words[args[1]], words[args[2]])\n        \n#         plt.text(32, 58, infotext, style='italic', color='white', fontsize='large',\n#             bbox={'facecolor': '#486678', 'alpha': 0.8, 'pad': 10})\n\n#         # turn off axis ticks\n#         plt.gca().axes.get_xaxis().set_visible(False)\n#         plt.gca().axes.get_yaxis().set_visible(False)\n        \n#         # gray scale\n#         plt.imshow(img, cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:00:54.338449Z","iopub.execute_input":"2021-10-24T08:00:54.33868Z","iopub.status.idle":"2021-10-24T08:00:54.35193Z","shell.execute_reply.started":"2021-10-24T08:00:54.338639Z","shell.execute_reply":"2021-10-24T08:00:54.351041Z"},"trusted":true},"execution_count":null,"outputs":[]}]}