{"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 \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport shutil\nimport re\nimport math\n\nimport pandas as pd\nimport numpy as np\n\nimport PIL.Image\n\nfrom random import shuffle\nfrom glob import glob\n\nfrom sklearn.model_selection import train_test_split\n\n#from tensorflow.python.keras.applications import VGG16\n\nfrom keras.applications import VGG16\n\nfrom tensorflow.python.keras.preprocessing.image import ImageDataGenerator\n\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Model\n#from tensorflow.keras.applications.vgg16 import VGG16\nfrom tensorflow.keras.applications.vgg16 import preprocess_input\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\n\nfrom keras import models\nfrom keras import layers\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\n\nfrom keras.optimizers import Adam","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"base_image_dir = os.path.join('..', 'input/aptos2019-blindness-detection/')\ntrain_dir = os.path.join(base_image_dir,'train_images/')\ndf = pd.read_csv(os.path.join(base_image_dir, 'train.csv'))\ndf['path'] = df['id_code'].map(lambda x: os.path.join(train_dir,'{}.png'.format(x)))\ndf = df.drop(columns=['id_code'])\ndf = df.sample(frac=1).reset_index(drop=True) #shuffle dataframe\ndf.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.diagnosis.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_train, image_test, y_train, y_test = train_test_split(np.array(df.path), \n                                                            np.array(df.diagnosis), \n                                                            test_size=0.3,\n                                                            random_state=123, \n                                                            stratify=df.diagnosis)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_train","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Создадим словарь вида {имя_картинки : класс, ...} для быстрого доступа к метке класса по имени картинки"},{"metadata":{"trusted":true},"cell_type":"code","source":"image_and_class_train = dict(zip(image_train, y_train))\nimage_and_class_test = dict(zip(image_test, y_test))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Предобработка данных:**"},{"metadata":{"trusted":true},"cell_type":"code","source":"IMG_SIZE = (224, 224)  # размер входного изображения сети\nNUM_CLASSES = 5        # число классов","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# загружаем входное изображение и предобрабатываем\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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# генератор для последовательного чтения обучающих данных с диска\ndef fit_generator(files, batch_size=32):\n    while True:\n        shuffle(files)\n        for k in range(math.ceil(len(files) / batch_size)):   # округляем до ближайшего целого вверх\n            i = k * batch_size                                # k -- номер батча в проходе                      \n            j = i + batch_size\n            if j > len(files):\n                j = len(files)\n            x = np.array([load_image(path) for path in files[i:j]])         # картинки в виде матрицы\n            label = np.array([image_and_class_train[path] for path in files[i:j]])   # метки классов\n            y = keras.utils.to_categorical(label, num_classes=NUM_CLASSES)      # one hot кодирование\n            yield (x, y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# генератор последовательного чтения тестовых данных с диска\ndef predict_generator(files):\n    while True:\n        for path in files:\n            yield np.array([load_image(path)])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Визуализация примеров для обучения**"},{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\nfrom matplotlib import pyplot as plt\nfig = plt.figure(figsize=(20, 20))\nfor i, path in enumerate(image_train[:10], 1):\n    subplot = fig.add_subplot(math.ceil(i / 5), 5, i)\n    plt.imshow(plt.imread(path));\n    subplot.set_title('{} \\n label: {}'.format(os.path.basename(path), image_and_class_train[path]))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Строим модель**\n\nЗагружаем преобученную на датасете 'ImagNet' модель VGG16 "},{"metadata":{"trusted":true},"cell_type":"code","source":"conv_base = VGG16(include_top=False, weights='imagenet', input_shape=(IMG_SIZE[0], IMG_SIZE[1], 3))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# фиксируем все веса предобученной сети кроме последнего блока \nset_trainable = False\nfor layer in conv_base.layers:\n    if layer.name == 'block5_conv3':\n        set_trainable = True\n    if set_trainable:\n        layer.trainable = True\n    else:\n        layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"conv_base.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_2 = models.Sequential()\nmodel_2.add(conv_base)  # кусок VGG-16 добавлен в модель\nmodel_2.add(layers.BatchNormalization())\nmodel_2.add(layers.Flatten())\n#model_1.add(layers.Dense(512, activation='relu'))\nmodel_2.add(layers.Dense(NUM_CLASSES, activation='softmax'))\nmodel_2.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_2.compile(optimizer=Adam(lr=0.005), \n              loss='categorical_crossentropy',  # функция потерь 'categorical_crossentropy' (log loss\n              metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"shuffle(image_train)  # перемешиваем обучающую выборку\n\ntrain_val_split = 100  # число изображений в валидационной выборке\n\nvalidation_data = next(fit_generator(image_train[:train_val_split], train_val_split))\n\n# запускаем процесс обучения\nhistory = model_2.fit_generator(fit_generator(image_train[train_val_split:]),  # данные читаем функцией-генератором\n        steps_per_epoch=10,  # число вызовов генератора за эпоху\n        epochs=100,  # число эпох обучения\n        validation_data=validation_data\n#         callbacks=[EarlyStopping(patience = 5),\n#                    ModelCheckpoint(filepath='weights.{epoch:02d}-{val_loss:.2f}.hdf5',\n#                                   verbose=1,\n#                                   save_best_only=True)]\n                               )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"start = 0\nplt.plot(history.history['loss'][start:])\nplt.plot(history.history['val_loss'][start:])\nplt.legend(['Train loss', 'Validation loss'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(history.history['acc'][start:])\nplt.plot(history.history['val_acc'][start:])\nplt.legend(['Train acc', 'Validation acc'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# загружаем веса модели для наименьшего loss \n#model_2.load_weights('weights.10-3.12.hdf5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = model_2.predict_generator(predict_generator(image_test), len(image_test), max_queue_size=500)","execution_count":null,"outputs":[]},{"metadata":{"trusted":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(image_test[70:][:10], pred[70:][:10]), 1):\n    subplot = fig.add_subplot(math.ceil(i / 5), 5, i)\n    plt.imshow(plt.imread(path))\n    subplot.set_title('label: {} \\n prediction: {} \\n model confidence: {:.3f}'\\\n                      .format(image_and_class_test[path],\n                              int(np.argmax(score)),\n                             np.max(score)))","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":1}