{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"## Import các gói thư viện cần thiết để sử dụng xuyên suốt notebook này\n\n# Các gói cơ bản\nimport numpy as np # thư viện tính toán đại số tuyến tính\nimport pandas as pd # thư viện tiện lợi để làm việc trên các \"dataframe\", hay gọi là file bảng (.csv)\nimport os # thư viện liên quan tới hệ thống (kiểm tra thư mục hiện tại xem có những file gì...)\nprint(os.listdir(\"../input\")) # chạy dòng này sẽ hiện ra các file/folder trong thư mục hiện hành (nhấn Ctrl+Enter sẽ chạy cả ô code này)\n\n# Tiến hành gán tên một số thư mục cho tiện sử dụng\nDP_DIR = '../input/doodle-kha/'\nDP_DIR_2 = '../input/doodle-kha-2/'\nINPUT_DIR = '../input/quickdraw-doodle-recognition/'\n#MODEL_DIR = '../input/doodle-modelweights/'","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# Các gói nâng cao\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten, Activation, Conv2D, MaxPooling2D # các lớp trong neural network\nfrom tensorflow.keras.metrics import categorical_accuracy, top_k_categorical_accuracy, categorical_crossentropy # Các hàm mục tiêu\nfrom tensorflow.keras.models import Sequential # dạng mô hình (Sequential là mô hình tuần tự, tức là khi sử dụng ta sẽ add tuần tự các layers, hồi sau sẽ rõ)\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint # các hàm gọi về trong quá trình huấn luyện\nfrom tensorflow.keras.optimizers import Adam # giải thuật Adam cho việc huấn luyện\nfrom tensorflow.keras.applications import MobileNet # mô hình MobileNet, đã được nhóm nghiên cứu khác phát triển, ta chỉ việc sử dụng\nfrom tensorflow.keras.applications.mobilenet import preprocess_input\n\n#%matplotlib inline\nfrom IPython.core.interactiveshell import InteractiveShell\nInteractiveShell.ast_node_interactivity = \"all\"\nimport ast\nimport json\nimport datetime as dt\nimport cv2\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tqdm import tqdm_notebook as tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f3795209fcb3922df24b97940fe23cf96ca549b9"},"cell_type":"code","source":"def f2cat(filename: str) -> str:\n    return filename.split('.')[0]\n\ndef list_all_categories():\n    files = os.listdir(os.path.join(INPUT_DIR, 'train_simplified'))\n    return sorted([f2cat(f) for f in files], key=str.lower)\n\ndef apk(actual, predicted, k=3):\n    \"\"\"\n    Source: https://github.com/benhamner/Metrics/blob/master/Python/ml_metrics/average_precision.py\n    \"\"\"\n    if len(predicted) > k:\n        predicted = predicted[:k]\n    score = 0.0\n    num_hits = 0.0\n    for i, p in enumerate(predicted):\n        if p in actual and p not in predicted[:i]:\n            num_hits += 1.0\n            score += num_hits / (i + 1.0)\n    if not actual:\n        return 0.0\n    return score / min(len(actual), k)\n\ndef mapk(actual, predicted, k=3):\n    \"\"\"\n    Source: https://github.com/benhamner/Metrics/blob/master/Python/ml_metrics/average_precision.py\n    \"\"\"\n    return np.mean([apk(a, p, k) for a, p in zip(actual, predicted)])\n\ndef preds2catids(predictions):\n    return pd.DataFrame(np.argsort(-predictions, axis=1)[:, :3], columns=['a', 'b', 'c'])\n\ndef top_3_accuracy(y_true, y_pred):\n    return top_k_categorical_accuracy(y_true, y_pred, k=3)\n\ndef draw_cv2(raw_strokes, size=256, lw=6, time_color=True):\n    img = np.zeros((BASE_SIZE, BASE_SIZE), np.uint8)\n    for t, stroke in enumerate(raw_strokes):\n        for i in range(len(stroke[0]) - 1):\n            color = 255 - min(t, 10) * 13 if time_color else 255\n            _ = cv2.line(img, (stroke[0][i], stroke[1][i]),\n                         (stroke[0][i + 1], stroke[1][i + 1]), color, lw)\n    if size != BASE_SIZE: return cv2.resize(img, (size, size))\n    else: return img\n\ndef image_generator_xd(size, batchsize, ks, lw=6, time_color=True):\n    while True:\n        for k in np.random.permutation(ks):\n            if k < 32: filename = os.path.join(DP_DIR, 'train_kha{}.csv/train_kha{}.csv'.format(k,k))\n            else: filename = os.path.join(DP_DIR_2, 'train_kha{}.csv/train_kha{}.csv'.format(k,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, 1))\n                for i, raw_strokes in enumerate(df.drawing.values):\n                    x[i, :, :, 0] = draw_cv2(raw_strokes, size=size, lw=lw,\n                                             time_color=time_color)\n                x = preprocess_input(x).astype(np.float16)\n                y = keras.utils.to_categorical(df.y, num_classes=NCATS)\n                yield x, y\n\ndef df_to_image_array_xd(df, size, lw=6, time_color=True):\n    df['drawing'] = df['drawing'].apply(json.loads) #  json.loads , ast.literal_eval\n    x = np.zeros((len(df), size, size, 1))\n    for i, raw_strokes in enumerate(df.drawing.values):\n        x[i, :, :, 0] = draw_cv2(raw_strokes, size=size, lw=lw, time_color=time_color)\n    x = preprocess_input(x).astype(np.float32)\n    return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7a40750799cca0c930c25578bad5dea9daf4b0b3"},"cell_type":"code","source":"MODEL_WEIGHTS = None\n#MODEL_WEIGHTS = '../input/mbn-crossentropy-size64/model_first32csv-epoch4-size64-crossentropy'\nOUTPUT_NAME = 'epoch1'\nTRAIN_KS = range(10)\n\nbatchsize = 512\nSTEPS =   993000*len(TRAIN_KS)//batchsize  # 23500000//batchsize # steps per epoch (1 csv ~ 990K rows, 24 csvs ~ 23,500,000)\nEPOCHS = 1\nsize = 64 # image size after resized (less or equal 256)\nSEED = 1991\n\nBASE_SIZE = 256 # original image size before downsampling\nNCATS = 340 # no. classes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"df6acdadc1df83ea1ce08bee342596de81feecda"},"cell_type":"code","source":"np.random.seed(seed=SEED)\ntf.set_random_seed(seed=SEED)\n\nmodel = MobileNet(input_shape=(size, size, 1), alpha=1., weights=None, classes=NCATS)\nmodel.compile(optimizer=Adam(lr=0.002), loss='categorical_crossentropy',\n              metrics=[categorical_crossentropy, categorical_accuracy, top_3_accuracy])\nprint(model.summary())\n\nif MODEL_WEIGHTS is not None:\n    model.load_weights(MODEL_WEIGHTS + '.h5')\n\ntrain_datagen = image_generator_xd(size=size, batchsize=batchsize, ks=TRAIN_KS)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7348fdd197cfd4664aa1e35ec00930d61259d88d"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a699f10426e49d650f4b02093dac456e700cd6ea"},"cell_type":"code","source":"hists = []\nhist = model.fit_generator(\n    train_datagen, steps_per_epoch=STEPS, epochs=EPOCHS, verbose=1,\n    validation_data=None,\n   # callbacks = callbacks\n)\nhists.append(hist)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"92e51b2578809ee5c893791593383dfdd19121be"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"611eff36d1170f2176b54b24d1b80df1d67e1186"},"cell_type":"code","source":"model.save_weights(\"model_\" + OUTPUT_NAME +\".h5\")\nprint(\"Model weights saved.\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fb0b28437d8e3c6989aa5e37dd468eca8ed8b352"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"62bc6c4610dbecefac00323fdd3ec9cb2d34104a"},"cell_type":"code","source":"test = pd.read_csv(os.path.join(INPUT_DIR, 'test_simplified.csv'))\nx_test = df_to_image_array_xd(test, size)\nprint(test.shape, x_test.shape)\nprint('Test array memory {:.2f} GB'.format(x_test.nbytes / 1024.**3 ))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8a61bdb0cf4782ad2cfec824467406d2f12f7ea3"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"33858b560101e2bf30b98d51951f8dc7d992a813"},"cell_type":"code","source":"test_predictions = model.predict(x_test, batch_size=128, verbose=1)\n\ntop3 = preds2catids(test_predictions)\n\ncats = list_all_categories()\nid2cat = {k: cat.replace(' ', '_') for k, cat in enumerate(cats)}\ntop3cats = top3.replace(id2cat)\n\ntest_predictions\nnp.save('test_prediction_'+OUTPUT_NAME, test_predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"765635ea730a89cc3ce69d183e9671e769426d7f"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fb378e569bde4e7ea5ed3c9f5540bed0bd357be1"},"cell_type":"code","source":"test['word'] = top3cats['a'] + ' ' + top3cats['b'] + ' ' + top3cats['c']\nsubmission = test[['key_id', 'word']]\nsubmission.to_csv('Submission_'+OUTPUT_NAME, index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"56ab969a06b83bf00c2f9cc3631b9c8327d96a1f"},"cell_type":"code","source":"","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}