{"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":"# FreeBirds Crew\nQuick Draw - A Google Doodle Recognition Clone","metadata":{"id":"6H3ATAdp_URp"}},{"cell_type":"markdown","source":"This file contains a subset of the quick draw classes. I choose around 100 classes from the dataset. ","metadata":{"id":"zlx6-LFL_jbi"}},{"cell_type":"code","source":"!wget 'https://raw.githubusercontent.com/zaidalyafeai/zaidalyafeai.github.io/master/sketcher/mini_classes.txt'","metadata":{"id":"XXv-xzU1sd88","execution":{"iopub.status.busy":"2023-03-20T05:12:43.521976Z","iopub.execute_input":"2023-03-20T05:12:43.523459Z","iopub.status.idle":"2023-03-20T05:12:44.708622Z","shell.execute_reply.started":"2023-03-20T05:12:43.523398Z","shell.execute_reply":"2023-03-20T05:12:44.707094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Read the classes names ","metadata":{"id":"4GL_TdMffD6-"}},{"cell_type":"code","source":"f = open(\"mini_classes.txt\",\"r\")\n# And for reading use\nclasses = f.readlines()\nf.close()","metadata":{"id":"eP-OxOx5sy0b","execution":{"iopub.status.busy":"2023-03-20T05:12:44.711554Z","iopub.execute_input":"2023-03-20T05:12:44.71215Z","iopub.status.idle":"2023-03-20T05:12:44.719727Z","shell.execute_reply.started":"2023-03-20T05:12:44.71209Z","shell.execute_reply":"2023-03-20T05:12:44.718301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classes = [c.replace('\\n','').replace(' ','_') for c in classes]","metadata":{"id":"lTE6D3uxtMc5","execution":{"iopub.status.busy":"2023-03-20T05:12:44.857872Z","iopub.execute_input":"2023-03-20T05:12:44.858681Z","iopub.status.idle":"2023-03-20T05:12:44.865452Z","shell.execute_reply.started":"2023-03-20T05:12:44.858637Z","shell.execute_reply":"2023-03-20T05:12:44.864006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Download the Dataset ","metadata":{"id":"5NDfBHVjACAt"}},{"cell_type":"markdown","source":"Loop over the classes and download the currospondent data","metadata":{"id":"7MC_PUS-fKjH"}},{"cell_type":"code","source":"!mkdir data","metadata":{"id":"rdSUnpL0u22Q","execution":{"iopub.status.busy":"2023-03-20T05:12:46.025786Z","iopub.execute_input":"2023-03-20T05:12:46.026252Z","iopub.status.idle":"2023-03-20T05:12:47.113271Z","shell.execute_reply.started":"2023-03-20T05:12:46.02621Z","shell.execute_reply":"2023-03-20T05:12:47.111536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import urllib.request\ndef download():\n    base = 'https://storage.googleapis.com/quickdraw_dataset/full/numpy_bitmap/'\n    for c in classes:        \n        cls_url = c.replace('_', '%20')\n        path = base+cls_url+'.npy'\n        print(path)\n        urllib.request.urlretrieve(path, 'data/'+c+'.npy')","metadata":{"id":"22DPhL5FtWcQ","execution":{"iopub.status.busy":"2023-03-20T05:12:47.116435Z","iopub.execute_input":"2023-03-20T05:12:47.116971Z","iopub.status.idle":"2023-03-20T05:12:47.124784Z","shell.execute_reply.started":"2023-03-20T05:12:47.116898Z","shell.execute_reply":"2023-03-20T05:12:47.123663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"download()","metadata":{"id":"O5jF6TXXu-Bu","execution":{"iopub.status.busy":"2023-03-20T05:12:47.126249Z","iopub.execute_input":"2023-03-20T05:12:47.126818Z","iopub.status.idle":"2023-03-20T05:20:34.977153Z","shell.execute_reply.started":"2023-03-20T05:12:47.12678Z","shell.execute_reply":"2023-03-20T05:20:34.975194Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Imports ","metadata":{"id":"uEdnbBVXAI-X"}},{"cell_type":"code","source":"import os\nimport glob\nimport numpy as np\nfrom tensorflow.python.keras import layers\nfrom tensorflow import keras \nimport tensorflow as tf\n\nprint(len(os.listdir('data')))","metadata":{"id":"J2FYrPgOKh6t","execution":{"iopub.status.busy":"2023-03-20T05:25:19.283032Z","iopub.execute_input":"2023-03-20T05:25:19.283491Z","iopub.status.idle":"2023-03-20T05:25:30.341697Z","shell.execute_reply.started":"2023-03-20T05:25:19.283452Z","shell.execute_reply":"2023-03-20T05:25:30.340108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load the Data ","metadata":{"id":"6o30ipBPAQ5Y"}},{"cell_type":"markdown","source":"Each class contains different number samples of arrays stored as .npy format. Since we have some memory limitations we only load 5000 images per class.  ","metadata":{"id":"UBq3GXEKAYuO"}},{"cell_type":"code","source":"def load_data(root, vfold_ratio=0.2, max_items_per_class= 4000 ):\n    all_files = glob.glob(os.path.join(root, '*.npy'))\n\n    #initialize variables \n    x = np.empty([0, 784])\n    y = np.empty([0])\n    class_names = []\n\n    #load each data file \n    for idx, file in enumerate(all_files):\n        data = np.load(file)\n        data = data[0: max_items_per_class, :]\n        labels = np.full(data.shape[0], idx)\n\n        x = np.concatenate((x, data), axis=0)\n        y = np.append(y, labels)\n\n        class_name, ext = os.path.splitext(os.path.basename(file))\n        class_names.append(class_name)\n\n    data = None\n    labels = None\n    \n    #randomize the dataset \n    permutation = np.random.permutation(y.shape[0])\n    x = x[permutation, :]\n    y = y[permutation]\n\n    #separate into training and testing \n    vfold_size = int(x.shape[0]/100*(vfold_ratio*100))\n\n    x_test = x[0:vfold_size, :]\n    y_test = y[0:vfold_size]\n\n    x_train = x[vfold_size:x.shape[0], :]\n    y_train = y[vfold_size:y.shape[0]]\n    return x_train, y_train, x_test, y_test, class_names","metadata":{"id":"6HEIgQNHYQnl","execution":{"iopub.status.busy":"2023-03-20T05:25:32.974846Z","iopub.execute_input":"2023-03-20T05:25:32.975717Z","iopub.status.idle":"2023-03-20T05:25:32.988683Z","shell.execute_reply.started":"2023-03-20T05:25:32.97567Z","shell.execute_reply":"2023-03-20T05:25:32.987135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_train, y_train, x_test, y_test, class_names = load_data('data')\nnum_classes = len(class_names)\nimage_size = 28","metadata":{"id":"K6uUjN-WL2Y9","execution":{"iopub.status.busy":"2023-03-20T05:25:33.551666Z","iopub.execute_input":"2023-03-20T05:25:33.552144Z","iopub.status.idle":"2023-03-20T05:27:20.499479Z","shell.execute_reply.started":"2023-03-20T05:25:33.552102Z","shell.execute_reply":"2023-03-20T05:27:20.49798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(x_train))","metadata":{"id":"VhGEDS0SMgLK","execution":{"iopub.status.busy":"2023-03-20T05:27:20.50163Z","iopub.execute_input":"2023-03-20T05:27:20.502029Z","iopub.status.idle":"2023-03-20T05:27:20.509718Z","shell.execute_reply.started":"2023-03-20T05:27:20.501988Z","shell.execute_reply":"2023-03-20T05:27:20.508287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Show some random data ","metadata":{"id":"rNZmQvBWBBHE"}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom random import randint\n%matplotlib inline  \nidx = randint(0, len(x_train))\nplt.imshow(x_train[idx].reshape(28,28)) \nprint(class_names[int(y_train[idx].item())])","metadata":{"id":"KfpDaHRkyMQC","execution":{"iopub.status.busy":"2023-03-20T05:27:24.78439Z","iopub.execute_input":"2023-03-20T05:27:24.784839Z","iopub.status.idle":"2023-03-20T05:27:25.081979Z","shell.execute_reply.started":"2023-03-20T05:27:24.7848Z","shell.execute_reply":"2023-03-20T05:27:25.080476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocess the Data ","metadata":{"id":"n8InHz5NBFrV"}},{"cell_type":"code","source":"# Reshape and normalize\nx_train = x_train.reshape(x_train.shape[0], image_size, image_size, 1).astype('float32')\nx_test = x_test.reshape(x_test.shape[0], image_size, image_size, 1).astype('float32')\n\nx_train /= 255.0\nx_test /= 255.0\n\n# Convert class vectors to class matrices\ny_train = keras.utils.to_categorical(y_train, num_classes)\ny_test = keras.utils.to_categorical(y_test, num_classes)","metadata":{"id":"p2GHUq7D2r9e","execution":{"iopub.status.busy":"2023-03-20T05:27:28.509741Z","iopub.execute_input":"2023-03-20T05:27:28.510202Z","iopub.status.idle":"2023-03-20T05:27:29.316195Z","shell.execute_reply.started":"2023-03-20T05:27:28.510161Z","shell.execute_reply":"2023-03-20T05:27:29.314853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# The Model ","metadata":{"id":"rL6XAb4hBMSc"}},{"cell_type":"code","source":"# Define model\nmodel = keras.Sequential()\nmodel.add(layers.Convolution2D(16, (3, 3),\n                        padding='same',\n                        input_shape=x_train.shape[1:], activation='relu'))\nmodel.add(layers.MaxPooling2D(pool_size=(2, 2)))\nmodel.add(layers.Convolution2D(32, (3, 3), padding='same', activation= 'relu'))\nmodel.add(layers.MaxPooling2D(pool_size=(2, 2)))\nmodel.add(layers.Convolution2D(64, (3, 3), padding='same', activation= 'relu'))\nmodel.add(layers.MaxPooling2D(pool_size =(2,2)))\nmodel.add(layers.Flatten())\nmodel.add(layers.Dense(128, activation='relu'))\nmodel.add(layers.Dense(100, activation='softmax')) \n","metadata":{"id":"uYUVV2wf2z8H","execution":{"iopub.status.busy":"2023-03-20T05:27:33.081108Z","iopub.execute_input":"2023-03-20T05:27:33.08155Z","iopub.status.idle":"2023-03-20T05:27:33.244786Z","shell.execute_reply.started":"2023-03-20T05:27:33.081514Z","shell.execute_reply":"2023-03-20T05:27:33.243483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Train model\nadam = tf.optimizers.Adam()\nmodel.compile(loss='categorical_crossentropy',\n              optimizer=adam,\n              metrics=['top_k_categorical_accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-03-20T05:28:19.298459Z","iopub.execute_input":"2023-03-20T05:28:19.298924Z","iopub.status.idle":"2023-03-20T05:28:19.313905Z","shell.execute_reply.started":"2023-03-20T05:28:19.298883Z","shell.execute_reply":"2023-03-20T05:28:19.312838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training ","metadata":{"id":"_YRSRkOyBP1P"}},{"cell_type":"code","source":"model.fit(x = x_train, y = y_train, validation_split=0.3,epochs=8)","metadata":{"id":"7OMEJ7kF3lsP","execution":{"iopub.status.busy":"2023-03-20T05:37:12.928551Z","iopub.execute_input":"2023-03-20T05:37:12.929031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing ","metadata":{"id":"d2KztY7qEn9_"}},{"cell_type":"code","source":"score = model.evaluate(x_test, y_test, verbose=0)\nprint('Test accuarcy: {:0.2f}%'.format(score[1] * 100))","metadata":{"id":"ssaZczS7DxeA","execution":{"iopub.status.busy":"2023-03-20T05:21:49.363231Z","iopub.status.idle":"2023-03-20T05:21:49.363844Z","shell.execute_reply.started":"2023-03-20T05:21:49.363535Z","shell.execute_reply":"2023-03-20T05:21:49.363569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference ","metadata":{"id":"9xBM_w0VBbNr"}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom random import randint\n%matplotlib inline  \nidx = randint(0, len(x_test))\nimg = x_test[idx]\nplt.imshow(img.squeeze()) ","metadata":{"id":"nH3JfoiYHdpk","execution":{"iopub.status.busy":"2023-03-20T05:21:49.365966Z","iopub.status.idle":"2023-03-20T05:21:49.366651Z","shell.execute_reply.started":"2023-03-20T05:21:49.36632Z","shell.execute_reply":"2023-03-20T05:21:49.366356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred = model.predict(np.expand_dims(img, axis=0))[0]\nind = (-pred).argsort()[:5]\nlatex = [class_names[x] for x in ind]\nprint(latex)","metadata":{"id":"OrYTmFByqcN_","outputId":"f38b3e71-5891-493d-d76f-867a7c77afa7","execution":{"iopub.status.busy":"2023-03-20T05:21:49.368498Z","iopub.status.idle":"2023-03-20T05:21:49.369118Z","shell.execute_reply.started":"2023-03-20T05:21:49.368788Z","shell.execute_reply":"2023-03-20T05:21:49.368821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Store the classes ","metadata":{"id":"YPp5D82YBhM-"}},{"cell_type":"code","source":"with open('class_names.txt', 'w') as file_handler:\n    for item in class_names:\n        file_handler.write(\"{}\\n\".format(item))","metadata":{"id":"NoFI1msFYpCN","execution":{"iopub.status.busy":"2023-03-20T05:21:49.371321Z","iopub.status.idle":"2023-03-20T05:21:49.371956Z","shell.execute_reply.started":"2023-03-20T05:21:49.371628Z","shell.execute_reply":"2023-03-20T05:21:49.371661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Install TensorFlowJS","metadata":{"id":"mfJ6dpaDBpRx"}},{"cell_type":"code","source":"!pip install tensorflowjs ","metadata":{"id":"hJJDfp9mY9Xh","execution":{"iopub.status.busy":"2023-03-20T05:21:49.373621Z","iopub.status.idle":"2023-03-20T05:21:49.37407Z","shell.execute_reply.started":"2023-03-20T05:21:49.37385Z","shell.execute_reply":"2023-03-20T05:21:49.373872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Save and Convert ","metadata":{"id":"-oBl0ZKVB00d"}},{"cell_type":"code","source":"model.save('keras.h5')","metadata":{"id":"XVICB3TbZGb2","execution":{"iopub.status.busy":"2023-03-20T05:21:49.37638Z","iopub.status.idle":"2023-03-20T05:21:49.376855Z","shell.execute_reply.started":"2023-03-20T05:21:49.376634Z","shell.execute_reply":"2023-03-20T05:21:49.376659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir model\n!tensorflowjs_converter --input_format keras keras.h5 model/","metadata":{"id":"bTWWlGdWZOvs","execution":{"iopub.status.busy":"2023-03-20T05:21:49.378953Z","iopub.status.idle":"2023-03-20T05:21:49.379802Z","shell.execute_reply.started":"2023-03-20T05:21:49.379566Z","shell.execute_reply":"2023-03-20T05:21:49.379595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Zip and Download ","metadata":{"id":"JKYxE2MEB6LV"}},{"cell_type":"code","source":"!cp class_names.txt model/class_names.txt","metadata":{"id":"865-t79uaB63","execution":{"iopub.status.busy":"2023-03-20T05:21:49.381374Z","iopub.status.idle":"2023-03-20T05:21:49.382547Z","shell.execute_reply.started":"2023-03-20T05:21:49.382265Z","shell.execute_reply":"2023-03-20T05:21:49.382294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!zip -r model.zip model ","metadata":{"id":"GLC-MzW8ZXTa","execution":{"iopub.status.busy":"2023-03-20T05:21:49.384194Z","iopub.status.idle":"2023-03-20T05:21:49.384694Z","shell.execute_reply.started":"2023-03-20T05:21:49.384433Z","shell.execute_reply":"2023-03-20T05:21:49.384466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from google.colab import files\nfiles.download('model.zip')","metadata":{"id":"4vfPR03xZZeD","execution":{"iopub.status.busy":"2023-03-20T05:21:49.385918Z","iopub.status.idle":"2023-03-20T05:21:49.386407Z","shell.execute_reply.started":"2023-03-20T05:21:49.386197Z","shell.execute_reply":"2023-03-20T05:21:49.386222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}