{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \nfrom glob import glob\nimport re\nimport ast\nimport cv2\nimport csv\nimport time\nimport ast\nimport urllib\nfrom PIL import Image, ImageDraw\nfrom tqdm import tqdm\nfrom dask import bag, threaded\nimport matplotlib\nimport matplotlib.pyplot as pltc\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nfrom dask import bag, threaded\nfrom tensorflow import keras\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten, Activation\nfrom tensorflow.keras.metrics import categorical_accuracy, top_k_categorical_accuracy, categorical_crossentropy\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.applications.nasnet import NASNetMobile\nfrom tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2D\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.applications import MobileNet\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\nBASE_SIZE = 256\nDP_DIR = '../input/shuffle-csvs/'\nINPUT_DIR = '../input/quickdraw-doodle-recognition/'\nNCSVS = 100\nNCATS = 340\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"95cca8690a82b00d26f4e63a635e746e1f55389c"},"cell_type":"code","source":"startTime = time.time()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"#clean spaces in name\nclasses_path = os.listdir(INPUT_DIR + 'train_simplified/')\nclasses_path = sorted(classes_path, key=lambda s: s.lower())\nclass_dict = {x[:-4].replace(\" \", \"_\"):i for i, x in enumerate(classes_path)}\nlabels = {x[:-4].replace(\" \", \"_\") for i, x in enumerate(classes_path)}\n\nn_labels = len(labels)\nprint(\"Number of labels: {}\".format(n_labels))\n\nfileList = glob(INPUT_DIR + \"train_simplified/*.csv\")     \n\nn_files = n_labels #number of csv files same as labels due to stupid structure.\n\n#time is sacred HARDCODED FOR THE COMP\nn_records = 49707919\nsize = 80\n\n#for f in fileList: saving time\n#    n_records += sum(1 for line in open(f))\nprint(\"Number of records: {}\".format(n_records))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4a5825305429b7f4095ba371467a477ae0a49472"},"cell_type":"code","source":"def top_3_accuracy(y_true, y_pred):\n    return top_k_categorical_accuracy(y_true, y_pred, k=3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6c5311002def8107d5c73f866b399446a6a05ed4"},"cell_type":"code","source":"# to image from stroke\ndef drawing_to_np(drawing, shape=(size, size)):\n    drawing = eval(drawing)\n    fig, ax = plt.subplots()\n    for x,y in drawing:\n        ax.plot(x, y, marker='.')\n        ax.axis('off')\n    fig.canvas.draw()\n    # Convert images to numpy arrat\n    np_drawing = np.array(fig.canvas.renderer._renderer)\n    plt.close(fig)\n    img = cv2.resize(np_drawing, shape)\n    img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n    img_expanded = img_gray[:, :, np.newaxis]\n    return img_expanded","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9102e216d298ee8d3f9c1ff7991ada57119e2323"},"cell_type":"code","source":"def draw_cv2_reshape_normalized(raw_strokes, size=size, lw=6):\n    img = np.zeros((BASE_SIZE, BASE_SIZE), np.uint8)\n    for stroke in raw_strokes:\n        for i in range(len(stroke[0]) - 1):\n            _ = cv2.line(img, (stroke[0][i], stroke[1][i]), (stroke[0][i + 1], stroke[1][i + 1]), 255, lw)\n\n    img = cv2.resize(img, (size, size))\n    img = img / 255.\n    img = img[:, :, np.newaxis]\n    return img\n    \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"97522d9de29d9ff35c5086f55f2c8eef64d84f90"},"cell_type":"code","source":"def draw_cv2(raw_strokes, size=256, lw=6):\n    img = np.zeros((BASE_SIZE, BASE_SIZE), np.uint8)\n    for stroke in raw_strokes:\n        for i in range(len(stroke[0]) - 1):\n            _ = cv2.line(img, (stroke[0][i], stroke[1][i]), (stroke[0][i + 1], stroke[1][i + 1]), 255, lw)\n    if size != BASE_SIZE:\n        return cv2.resize(img, (size, size))\n    else:\n        return img\n\n#ADD DATA AUGMENTATION TO BOOST\ndef image_generator(size, batchsize, ks, lw=6):\n    while True:\n        for k in np.random.permutation(ks):\n            filename = os.path.join(DP_DIR, 'train_k{}.csv.gz'.format(k))\n            for df in pd.read_csv(filename, chunksize=batchsize):\n                df['drawing'] = df['drawing'].apply(ast.literal_eval)\n                x = np.zeros((len(df), size, size))\n                for i, raw_strokes in enumerate(df.drawing.values):\n                    x[i] = draw_cv2(raw_strokes, size=size, lw=lw)\n                x = x / 255.\n                x = x.reshape((len(df), size, size, 1)).astype(np.float32)\n                y = tf.keras.utils.to_categorical(df.y, num_classes=NCATS)\n                yield x, y\n\ndef df_to_image_array(df, size=size, lw=6):\n    df['drawing'] = df['drawing'].apply(ast.literal_eval)\n    x = np.zeros((len(df), size, size))\n    for i, raw_strokes in enumerate(df.drawing.values):\n        x[i] = draw_cv2(raw_strokes, size=size, lw=lw)\n    x = x / 255.\n    x = x.reshape((len(df), size, size, 1)).astype(np.float32)\n    return x\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a6b041e1365a69cc0576e081e1e7db9c5928742e"},"cell_type":"code","source":"STEPS = 1000\nbatchsize = 512\nepochs = 15","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"18162bacd65b3b8d25107d58a738a92edd415f30"},"cell_type":"code","source":"valid_df = pd.read_csv(os.path.join(DP_DIR, 'train_k{}.csv.gz'.format(NCSVS - 1)), nrows=30000)\nx_valid = df_to_image_array(valid_df, size)\ny_valid = tf.keras.utils.to_categorical(valid_df.y, num_classes=NCATS)\nprint(x_valid.shape, y_valid.shape)\nprint('Validation array memory {:.2f} GB'.format(x_valid.nbytes / 1024.**3 ))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"10ddcecba462b047aa8dc74008615cde7452ad63"},"cell_type":"code","source":"train_datagen = image_generator(size=size, batchsize=batchsize, ks=range(NCSVS - 1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5b11507f5b2d5e3f33462c59db06fd79282ef96e"},"cell_type":"code","source":"base_model = MobileNet(input_shape=(size, size, 1), include_top=False, weights=None, classes=n_labels)\n\n# add a global spatial average pooling layer\nx = base_model.output\nx = Flatten()(x)\n# let's add a fully-connected layer\nx = Dense(1024, activation='relu')(x)\npredictions = Dense(n_labels, activation='softmax')(x)\n# this is the model we will train\nmodel = Model(inputs=base_model.input, outputs=predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cca5f88517c8d7c935c68b36082d4959828718b8"},"cell_type":"code","source":"model.compile(optimizer=Adam(lr=1e-4), loss='categorical_crossentropy',\n              metrics=[categorical_crossentropy, categorical_accuracy, top_3_accuracy])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f997c27a6f3ac201e35f0947bc4db60d9dc44124"},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b702dbec4f03127909f3c0fab9d48b86c265c74f"},"cell_type":"code","source":"callbacks = [\n    ReduceLROnPlateau(monitor='val_categorical_accuracy', factor=0.5, patience=5,\n                      min_delta=0.005, mode='max', cooldown=3, verbose=1)\n]\n\nhist = model.fit_generator(\n    train_datagen, steps_per_epoch=STEPS, epochs=epochs, verbose=1,\n    validation_data=(x_valid, y_valid),\n    callbacks = callbacks\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"97e830678323a599deb8fb4b22fd1d986e893aaa"},"cell_type":"code","source":"def gen_graph(history, title):\n    plt.plot(history.history['categorical_accuracy'])\n    plt.plot(history.history['val_categorical_accuracy'])\n    plt.plot(history.history['top_3_accuracy'])\n    plt.plot(history.history['val_top_3_accuracy'])\n    plt.title('Accuracy ' + title)\n    plt.ylabel('Accuracy')\n    plt.xlabel('Epoch')\n    plt.legend(['train', 'validation', 'Test top 3', 'Validation top 3'], loc='upper left')\n    plt.show()\n    plt.plot(history.history['categorical_crossentropy'])\n    plt.plot(history.history['val_categorical_crossentropy'])\n    plt.title('Loss ' + title)\n    plt.ylabel('MLogLoss')\n    plt.xlabel('Epoch')\n    plt.legend(['train', 'validation'], loc='upper left')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a6404ecead97faa36c8cf7f6cfacefb5b5f3d920"},"cell_type":"code","source":"#plot\ngen_graph(hist, \n              \"Simple net lul\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d36a3540618ccba3308a8d33fb948db012b88dc5"},"cell_type":"code","source":"pred_results = []\nchunksize = 10000\nreader = pd.read_csv(INPUT_DIR + 'test_simplified.csv', chunksize=chunksize)\nfor chunk in tqdm(reader):\n    imgs = df_to_image_array(chunk)\n    pred = model.predict(imgs, verbose=1)\n    top_3 =  np.argsort(-pred)[:, 0:3]  \n    pred_results.append(top_3)\nprint(\"Finished test predictions...\")\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"85acaa27c8c28458f7c132279ea4a3e11596b178"},"cell_type":"code","source":"#prepare data for saving\nreverse_dict = {v: k for k, v in class_dict.items()}\npred_results = np.concatenate(pred_results)\nprint(\"Finished data prep...\")\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e962bffec419cf26be76577c4185fef0532b0cd6"},"cell_type":"code","source":"preds_df = pd.DataFrame({'first': pred_results[:,0], 'second': pred_results[:,1], 'third': pred_results[:,2]})\npreds_df = preds_df.replace(reverse_dict)\n\npreds_df['words'] = preds_df['first'] + \" \" + preds_df['second'] + \" \" + preds_df['third']\n\nsub = pd.read_csv(INPUT_DIR + 'sample_submission.csv', index_col=['key_id'])\nsub['word'] = preds_df.words.values\nsub.to_csv('1class_per_label_proto.csv')\nsub.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"97f621ecfec4e794b4b4c44c6e72415a33de4a1a"},"cell_type":"code","source":"endTime = time.time()\nprint(endTime - startTime)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}