{"cells":[{"metadata":{"_uuid":"df3a8de564ae073ad187a1f8aa970eeb79fc405e"},"cell_type":"markdown","source":"# Домашняя работа. Dogs vs. Cats"},{"metadata":{"trusted":true,"_uuid":"90bcb534faec866b1e63dfd9ffd954bc24c42fb6","scrolled":false},"cell_type":"code","source":"! ls /.keras/models","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ac90cd7eb646998997e3a12628dee3d390f35ba7"},"cell_type":"code","source":"from keras import backend as K","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6335105e339ae348e58beef7a740b3f3ef063763"},"cell_type":"markdown","source":"https://www.kaggle.com/c/dogs-vs-cats-redux-kernels-edition"},{"metadata":{"trusted":true,"_uuid":"86b7f2c4f969cf6b72a69d675b777ead5a44d747"},"cell_type":"code","source":"import numpy as np\nimport keras\nfrom keras.models import Model\nfrom keras.applications.vgg16 import VGG16\nfrom keras.applications.vgg16 import preprocess_input\nfrom keras.preprocessing.image import load_img, img_to_array\nimport os\n\nfrom sklearn.metrics import log_loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3c3ac1e6f095b6450393203320eb9deab7794edf"},"cell_type":"code","source":"IMG_SIZE = (224, 224)  # размер входного изображения сети","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4bceeb7ee0f6ac16bab95098d4bd23914b3edf62"},"cell_type":"markdown","source":"## Функции загрузки данных"},{"metadata":{"trusted":true,"_uuid":"3a836b2f70b23b9e78da3b0c7171434fc9a45040"},"cell_type":"code","source":"print(len(os.listdir(\"../input/train\")))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8d126e2bc2459a81d1f2fce42673549435786fae"},"cell_type":"code","source":"import re\nfrom random import shuffle\nfrom glob import glob\n\nTRAIN_DIR = '../input/train'\nTEST_DIR = '../input/test'\n\ntrain_files = glob(\"../input/train/*.jpg\")\ntest_files = glob('../input/test/*.jpg')\n\n# загружаем входное изображение и предобрабатываем\ndef load_image(path, target_size=IMG_SIZE):\n    img = load_img(path, target_size=target_size)  # загрузка и масштабирование изображения\n    array = img_to_array(img)\n    return preprocess_input(array)  # предобработка для VGG16\n\n# генератор для последовательного чтения обучающих данных с диска\ndef fit_generator(files, batch_size=32):\n    while True:\n        shuffle(files)\n        for k in range(len(files) // batch_size):\n            i = k * batch_size\n            j = i + batch_size\n            if j > len(files):\n                j = - j % len(files)\n            x = np.array([load_image(path) for path in files[i:j]])\n            y = np.array([1. if re.match('.*/dog\\.\\d', path) else 0. for path in files[i:j]])\n            yield (x, y)\n\n# генератор последовательного чтения тестовых данных с диска\ndef predict_generator(files):\n    while True:\n        for path in files:\n            yield np.array([load_image(path)])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5f7ec99c5dd50f3bb7a17ad101c2f00438a12235"},"cell_type":"markdown","source":"## Визуализируем примеры для обучения"},{"metadata":{"trusted":true,"_uuid":"d45c759517ce46d97afb670d1ec603e6fa46a86a"},"cell_type":"code","source":"%matplotlib inline\nfrom matplotlib import pyplot as plt\nfig = plt.figure(figsize=(20, 20))\nfor i, path in enumerate(train_files[:10], 1):\n    subplot = fig.add_subplot(i // 5 + 1, 5, i)\n    plt.imshow(plt.imread(path));\n    subplot.set_title('%s' % path.split('/')[-1]);","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4173b527f94c58f8ff894de79f0f07ccc16b4e77"},"cell_type":"markdown","source":"## Загружаем предобученную модель"},{"metadata":{"trusted":true,"_uuid":"736d3cb8969bc43d05a795fc0c7b0dffa2d4104d","scrolled":true},"cell_type":"code","source":"# base_model -  объект класса keras.models.Model (Functional Model)\nbase_model = VGG16(include_top = False,\n                   weights = 'imagenet',\n                   input_shape = (IMG_SIZE[0], IMG_SIZE[1], 3))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5a5d31019a5d65e3c3ebdf56fa64dacc7ac8f60c"},"cell_type":"code","source":"# фиксируем все веса предобученной сети\nfor layer in base_model.layers:\n    layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"scrolled":true,"trusted":true,"_uuid":"abf7b5c3866e3ec74eb45d1969b0acf3495b00a6"},"cell_type":"code","source":"base_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2082be2911a138dc7db07c71ebe5771d65c1ddd6"},"cell_type":"markdown","source":"## Добавляем полносвязный слой"},{"metadata":{"trusted":true,"_uuid":"15ce180aaefa79748b37c421f019bcfa33cf30b8"},"cell_type":"code","source":"x = base_model.layers[-5].output\nx = keras.layers.Flatten()(x)\nx = keras.layers.BatchNormalization()(x)\nx = keras.layers.Dense(32,  # один выход\n                activation='sigmoid',  # функция активации  \n                #kernel_regularizer=keras.regularizers.l1(1e-4)\n                      )(x)\nx = keras.layers.Dense(32,  # один выход\n                activation='sigmoid',  # функция активации  \n                #kernel_regularizer=keras.regularizers.l1(1e-4)\n                      )(x)\nx = keras.layers.Dropout(0.5)(x)\nx = keras.layers.Dense(1,  # один выход\n                activation='sigmoid',  # функция активации  \n                kernel_regularizer=keras.regularizers.l2(1e-4)\n                      )(x)\nmodel = Model(inputs=base_model.input, outputs=x)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"bd405cb964ae04902ac0480bc43b6117cbbc54b1"},"cell_type":"markdown","source":"## Выводим архитектуру модели"},{"metadata":{"scrolled":true,"trusted":true,"_uuid":"dca7f661f2e2103ce87a643e770f75024f5c69f9"},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a0f81266cc6f1ca5d778bc4342fe21c800991c34"},"cell_type":"markdown","source":"## Компилируем модель и запускаем обучение"},{"metadata":{"trusted":true,"_uuid":"00db8fa3cf82e3d712cc0aa3f268f04626ff61cd","scrolled":true},"cell_type":"code","source":"model.compile(optimizer='adam', \n              loss='binary_crossentropy',  # функция потерь binary_crossentropy (log loss\n              metrics=['accuracy',  ])","execution_count":null,"outputs":[]},{"metadata":{"scrolled":true,"trusted":true,"_uuid":"40f32436b32d6a9ecc60f47b4cbbf04f93c94a84"},"cell_type":"code","source":"shuffle(train_files)  # перемешиваем обучающую выборку\n\ntrain_val_split = 100  # число изображений в валидационной выборке\n\nvalidation_data = next(fit_generator(train_files[:train_val_split], train_val_split))\n\n# запускаем процесс обучения\nmodel.fit_generator(fit_generator(train_files[train_val_split:]),  # данные читаем функцией-генератором\n        steps_per_epoch=10,  # число вызовов генератора за эпоху\n        epochs=15,  # число эпох обучения\n        validation_data=validation_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b972841eeb8f8496d88075715d53a79788e05f6d"},"cell_type":"code","source":"model.save('model')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"773a92ade53f971ea7578d0a863b797c39922c8d"},"cell_type":"markdown","source":"## Предсказания на проверочной выборке"},{"metadata":{"trusted":true,"_uuid":"f03ff56bf2812dc0d5efddb0ff392f4d20a4306c"},"cell_type":"code","source":"pred = model.predict_generator(predict_generator(test_files), len(test_files), max_queue_size=500)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"02a64d349a9b1746d0afd830a12b4be3c7d2adcf","scrolled":true},"cell_type":"code","source":"%matplotlib inline\nfrom matplotlib import pyplot as plt\nfig = plt.figure(figsize=(20, 20))\nfor i, (path, score) in enumerate(zip(test_files[80:][:10], pred[80:][:10]), 1):\n    subplot = fig.add_subplot(i // 5 + 1, 5, i)\n    plt.imshow(plt.imread(path));\n    subplot.set_title('%.3f' % score);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"998572e6a4245914eac0a1789e5170d7f048e89a"},"cell_type":"code","source":"# Рассмотрим метрики для анализа полученной модели","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e2f7252eca9d430f08940543289e2aee2dd15d14"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f7d2357612f4b798cbceeaf91be339c6e6d36df7"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"894692695c8de11cf738c84727f27e0d736aaa4b"},"cell_type":"markdown","source":"## Готовим данные для сабмита"},{"metadata":{"trusted":true,"_uuid":"af1e5705c188234405aad3f1785c4f9f4b965437","_kg_hide-output":true},"cell_type":"code","source":"with open('submit.txt', 'w') as dst:\n    dst.write('id,label\\n')\n    for path, score in zip(test_files, pred):\n        dst.write('%s,%f\\n' % (re.search('(\\d+)', path).group(0), score))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d368640a9d56144f60a2e4dca7fa26141c14ab4a"},"cell_type":"code","source":"# LogLoss = 1.04979","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"},"widgets":{"state":{},"version":"1.1.2"}},"nbformat":4,"nbformat_minor":1}