{"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"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":30096,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"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\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 read-only \"../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# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-06-01T04:27:42.497057Z","iopub.execute_input":"2021-06-01T04:27:42.497358Z","iopub.status.idle":"2021-06-01T04:27:42.504177Z","shell.execute_reply.started":"2021-06-01T04:27:42.497331Z","shell.execute_reply":"2021-06-01T04:27:42.503023Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"https://www.kaggle.com/lepeshkinvyacheslav/8-vgg16","metadata":{}},{"cell_type":"code","source":"import zipfile","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:27:48.466337Z","iopub.execute_input":"2021-06-01T04:27:48.466638Z","iopub.status.idle":"2021-06-01T04:27:48.472113Z","shell.execute_reply.started":"2021-06-01T04:27:48.46661Z","shell.execute_reply":"2021-06-01T04:27:48.471091Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Разорхивируем архив с тестовыми картинками","metadata":{}},{"cell_type":"code","source":"zipfile.ZipFile('../input/dogs-vs-cats/train.zip', 'r').extractall()","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:27:50.117503Z","iopub.execute_input":"2021-06-01T04:27:50.117815Z","iopub.status.idle":"2021-06-01T04:28:02.481559Z","shell.execute_reply.started":"2021-06-01T04:27:50.117783Z","shell.execute_reply":"2021-06-01T04:28:02.480701Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import keras\nfrom keras.preprocessing import image\nfrom keras.applications.imagenet_utils import preprocess_input\nfrom keras.layers import Dense,GlobalMaxPooling2D,Dropout\nfrom keras.models import Model\nimport matplotlib.pyplot as plt\nimport random\nfrom sklearn.model_selection import train_test_split\nfrom keras.utils import to_categorical\nfrom keras import optimizers\n%matplotlib inline ","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:04.309024Z","iopub.execute_input":"2021-06-01T04:28:04.309361Z","iopub.status.idle":"2021-06-01T04:28:09.896386Z","shell.execute_reply.started":"2021-06-01T04:28:04.30933Z","shell.execute_reply":"2021-06-01T04:28:09.893325Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Посмотрим первую картинку.","metadata":{}},{"cell_type":"code","source":"img_path = 'train/cat.0.jpg'\nimg = image.load_img(img_path, target_size=(224, 224))\nplt.imshow(img)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:13.797294Z","iopub.execute_input":"2021-06-01T04:28:13.797605Z","iopub.status.idle":"2021-06-01T04:28:13.97141Z","shell.execute_reply.started":"2021-06-01T04:28:13.797577Z","shell.execute_reply":"2021-06-01T04:28:13.970565Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Сформируем датафрейм с метками классов и названиями файлов 1 - собака, 0 - кот.","metadata":{}},{"cell_type":"code","source":"filenames = os.listdir(\"./train\")\ncategories = []\nfor filename in filenames:\n    category = filename.split('.')[0]\n    if category == 'dog':\n        categories.append(\"1\")\n    else:\n        categories.append(\"0\")\n\ndf = pd.DataFrame({\n    'filename': filenames,\n    'category': categories\n})\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:17.001649Z","iopub.execute_input":"2021-06-01T04:28:17.001977Z","iopub.status.idle":"2021-06-01T04:28:17.051816Z","shell.execute_reply.started":"2021-06-01T04:28:17.001945Z","shell.execute_reply":"2021-06-01T04:28:17.050804Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Разделим датафрейм на тренировочный и для тестирования.","metadata":{}},{"cell_type":"code","source":"train_df, validate_df = train_test_split(df, test_size=0.1)\ntrain_df = train_df.reset_index()\nvalidate_df = validate_df.reset_index()\n\ntotal_train = train_df.shape[0]\ntotal_validate = validate_df.shape[0]","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:20.469392Z","iopub.execute_input":"2021-06-01T04:28:20.469707Z","iopub.status.idle":"2021-06-01T04:28:20.481535Z","shell.execute_reply.started":"2021-06-01T04:28:20.469678Z","shell.execute_reply":"2021-06-01T04:28:20.480537Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Создадим тренировочный и тестовый генераторы с помощью image.ImageDataGenerator","metadata":{}},{"cell_type":"code","source":"train_datagen = image.ImageDataGenerator(\n    rotation_range=15,\n    rescale=1./255,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    fill_mode='nearest',\n    width_shift_range=0.1,\n    height_shift_range=0.1\n)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    \"./train\", \n    x_col='filename',\n    y_col='category',\n    class_mode='binary',\n    target_size=(224, 224),\n    batch_size=16\n)","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:22.641387Z","iopub.execute_input":"2021-06-01T04:28:22.641697Z","iopub.status.idle":"2021-06-01T04:28:22.868067Z","shell.execute_reply.started":"2021-06-01T04:28:22.641668Z","shell.execute_reply":"2021-06-01T04:28:22.867286Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validation_datagen = image.ImageDataGenerator(rescale=1./255)\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df, \n    \"./train\", \n    x_col='filename',\n    y_col='category',\n    class_mode='binary',\n    target_size=(224, 224),\n    batch_size=16\n)","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:25.325267Z","iopub.execute_input":"2021-06-01T04:28:25.325583Z","iopub.status.idle":"2021-06-01T04:28:25.360076Z","shell.execute_reply.started":"2021-06-01T04:28:25.325554Z","shell.execute_reply":"2021-06-01T04:28:25.359114Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Загрузим нейросеть VGG16.","metadata":{}},{"cell_type":"code","source":"vgg = keras.applications.VGG16(weights='imagenet', include_top=True)\nvgg.summary()","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:28.005019Z","iopub.execute_input":"2021-06-01T04:28:28.005363Z","iopub.status.idle":"2021-06-01T04:28:34.083766Z","shell.execute_reply.started":"2021-06-01T04:28:28.005334Z","shell.execute_reply":"2021-06-01T04:28:34.082968Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"last_layer = vgg.get_layer('block5_pool')\nlast_output = last_layer.output","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:37.348006Z","iopub.execute_input":"2021-06-01T04:28:37.348404Z","iopub.status.idle":"2021-06-01T04:28:37.353959Z","shell.execute_reply.started":"2021-06-01T04:28:37.348373Z","shell.execute_reply":"2021-06-01T04:28:37.352112Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Настроим модель.\nСглаживаем выходной слой до 1.\nДобавим полностью связанный слой с 512 скрытыми блоками и функцией активации relu.\nДобавим коэффициент отсева 0,5.\nДобавим последний сигмовидный слой для классификации.\n","metadata":{}},{"cell_type":"code","source":"x = GlobalMaxPooling2D()(last_output)\nx = Dense(512, activation='relu')(x)\nx = Dropout(0.5)(x)\nx = Dense(1, activation='sigmoid')(x)","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:39.646064Z","iopub.execute_input":"2021-06-01T04:28:39.646431Z","iopub.status.idle":"2021-06-01T04:28:39.674414Z","shell.execute_reply.started":"2021-06-01T04:28:39.6464Z","shell.execute_reply":"2021-06-01T04:28:39.6736Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = Model(vgg.input, x)\nmodel.compile(loss='binary_crossentropy',\n              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),\n              metrics=['accuracy'])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:41.48152Z","iopub.execute_input":"2021-06-01T04:28:41.481915Z","iopub.status.idle":"2021-06-01T04:28:41.518298Z","shell.execute_reply.started":"2021-06-01T04:28:41.481877Z","shell.execute_reply":"2021-06-01T04:28:41.516974Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Проверим, чтобы последний слой обучал а не замораживал.","metadata":{}},{"cell_type":"code","source":"for l, layer in enumerate(model.layers[:-1]):\n    layer.trainable = False\n\n# ensure the last layer is trainable/not frozen\nfor l, layer in enumerate(model.layers[-1:]):\n    layer.trainable = True","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:45.552935Z","iopub.execute_input":"2021-06-01T04:28:45.553266Z","iopub.status.idle":"2021-06-01T04:28:45.559054Z","shell.execute_reply.started":"2021-06-01T04:28:45.553237Z","shell.execute_reply":"2021-06-01T04:28:45.557868Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Обучаем модель.","metadata":{}},{"cell_type":"code","source":"model.fit(train_generator,validation_data=validation_generator, epochs=4,validation_steps=total_validate//16,\n    steps_per_epoch=total_train//16)","metadata":{"execution":{"iopub.status.busy":"2021-06-01T04:28:54.981288Z","iopub.execute_input":"2021-06-01T04:28:54.981594Z","iopub.status.idle":"2021-06-01T07:35:59.275317Z","shell.execute_reply.started":"2021-06-01T04:28:54.981565Z","shell.execute_reply":"2021-06-01T07:35:59.274475Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Разархивируем архив с тестовым набором изображений. ","metadata":{}},{"cell_type":"code","source":"zipfile.ZipFile('../input/dogs-vs-cats/test1.zip', 'r').extractall()","metadata":{"execution":{"iopub.status.busy":"2021-06-01T08:01:46.157349Z","iopub.execute_input":"2021-06-01T08:01:46.15774Z","iopub.status.idle":"2021-06-01T08:01:54.135246Z","shell.execute_reply.started":"2021-06-01T08:01:46.157705Z","shell.execute_reply":"2021-06-01T08:01:54.134372Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Сформируем датафрейм с именами тестовых картинок.","metadata":{}},{"cell_type":"code","source":"test_filenames = os.listdir(\"./test1\")\ntest_df = pd.DataFrame({\n    'filename': test_filenames\n})\nnb_samples = test_df.shape[0]","metadata":{"execution":{"iopub.status.busy":"2021-06-01T08:01:57.180262Z","iopub.execute_input":"2021-06-01T08:01:57.180575Z","iopub.status.idle":"2021-06-01T08:01:57.194197Z","shell.execute_reply.started":"2021-06-01T08:01:57.180545Z","shell.execute_reply":"2021-06-01T08:01:57.193391Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Создадим генератор для тестового набора данных.","metadata":{}},{"cell_type":"code","source":"test_gen = image.ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    \"./test1\", \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    batch_size=16,\n    target_size=(224, 224),\n    shuffle=False\n)","metadata":{"execution":{"iopub.status.busy":"2021-06-01T08:02:47.539992Z","iopub.execute_input":"2021-06-01T08:02:47.540328Z","iopub.status.idle":"2021-06-01T08:02:47.644669Z","shell.execute_reply.started":"2021-06-01T08:02:47.540296Z","shell.execute_reply":"2021-06-01T08:02:47.643866Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Делаем предсказания для тестовых картинок.","metadata":{}},{"cell_type":"code","source":"predict = model.predict_generator(test_generator, steps=np.ceil(nb_samples/16))\nthreshold = 0.5\ntest_df['category'] = np.where(predict > threshold, 1,0)","metadata":{"execution":{"iopub.status.busy":"2021-06-01T08:04:41.752859Z","iopub.execute_input":"2021-06-01T08:04:41.753192Z","iopub.status.idle":"2021-06-01T08:27:04.626817Z","shell.execute_reply.started":"2021-06-01T08:04:41.753139Z","shell.execute_reply":"2021-06-01T08:27:04.625897Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Посмотрим некоторые результаты предсказаний.","metadata":{}},{"cell_type":"code","source":"sample_test = test_df.sample(n=9).reset_index()\nsample_test.head()\nplt.figure(figsize=(12, 12))\nfor index, row in sample_test.iterrows():\n    filename = row['filename']\n    category = row['category']\n    img = image.load_img(\"./test1/\"+filename, target_size=(256, 256))\n    plt.subplot(3, 3, index+1)\n    plt.imshow(img)\n    plt.xlabel(filename + '(' + \"{}\".format(category) + ')')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-01T08:33:49.133613Z","iopub.execute_input":"2021-06-01T08:33:49.133932Z","iopub.status.idle":"2021-06-01T08:33:50.832049Z","shell.execute_reply.started":"2021-06-01T08:33:49.133903Z","shell.execute_reply":"2021-06-01T08:33:50.831289Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Точность обученной модели очень большая. И ей удалось правильно определить картинки выше.","metadata":{}}]}