{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","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"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np, pandas as pd, tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import MobileNetV2\nfrom tensorflow.keras.applications.mobilenet_v2 import preprocess_input as mnv2_pre\n\nSPEC = '/kaggle/input/datasets/kelbycraft/kwc-freesound-2018-melspec-256/spectrograms'\nTRAIN_DIR, TEST_DIR = f'{SPEC}/train', f'{SPEC}/test'\nIMG_H, IMG_W = 256, 384\nBATCH, SEED, NUM_CLASSES = 32, 42, 41\n\ndef mapk_from_probs(probs, true_idx, k=3):\n    top_k = np.argsort(-probs, axis=1)[:, :k]\n    s = 0.0\n    for i, t in enumerate(true_idx):\n        h = np.where(top_k[i] == t)[0]\n        if len(h): s += 1.0/(h[0]+1)\n    return s/len(true_idx)\n\ngen = ImageDataGenerator(preprocessing_function=mnv2_pre, validation_split=0.2)\ntr = gen.flow_from_directory(TRAIN_DIR, target_size=(IMG_H,IMG_W), batch_size=BATCH,\n    class_mode='categorical', subset='training', shuffle=True, seed=SEED)\nva = gen.flow_from_directory(TRAIN_DIR, target_size=(IMG_H,IMG_W), batch_size=BATCH,\n    class_mode='categorical', subset='validation', shuffle=False, seed=SEED)\n\nbase = MobileNetV2(include_top=False, weights='imagenet',\n                   input_shape=(IMG_H,IMG_W,3), pooling='avg')\nbase.trainable = False\nmodel = models.Sequential([base,\n    layers.Dropout(0.3), layers.Dense(256, activation='relu'),\n    layers.Dropout(0.3), layers.Dense(NUM_CLASSES, activation='softmax')])\nmodel.compile('adam','categorical_crossentropy',metrics=['accuracy'])\n\nmodel.fit(tr, validation_data=va, epochs=20,\n          callbacks=[tf.keras.callbacks.EarlyStopping(patience=6, restore_best_weights=True),\n                     tf.keras.callbacks.ReduceLROnPlateau(patience=2, factor=0.5)])\n\nprint(f'MNV2 256mel val MAP@3: {mapk_from_probs(model.predict(va,verbose=0), va.classes):.4f}')\nmodel.save('/kaggle/working/mnv2_256mel.keras')\n\n# submission\ntf_ = ImageDataGenerator(preprocessing_function=mnv2_pre).flow_from_directory(\n    TEST_DIR, target_size=(IMG_H,IMG_W), batch_size=BATCH, class_mode=None, shuffle=False)\nprobs = model.predict(tf_, verbose=1)\nidx_to_label = {v:k for k,v in tr.class_indices.items()}\nlabels = [' '.join(idx_to_label[i] for i in r) for r in np.argsort(-probs,axis=1)[:,:3]]\nfnames = [f.split('/')[-1].replace('.png','.wav') for f in tf_.filenames]\npd.DataFrame({'fname':fnames,'label':labels}).to_csv('/kaggle/working/submission.csv', index=False)\nprint('submission written')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null}]}