{ "cells": [ { "cell_type": "markdown", "id": "7915f17e", "metadata": {}, "source": [ "### Инициализация Keras" ] }, { "cell_type": "code", "execution_count": 1, "id": "560de685", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.9.2\n" ] } ], "source": [ "import os\n", "\n", "os.environ[\"KERAS_BACKEND\"] = \"torch\"\n", "import keras\n", "\n", "print(keras.__version__)" ] }, { "cell_type": "markdown", "id": "27d07c7a", "metadata": {}, "source": [ "#### Загрузка набора данных для задачи классификации\n", "\n", "В данном примере используется фрагмент набора данных Cats and Dogs Classification Dataset\n", "\n", "В наборе данных два класса: кошки и собаки\n", "\n", "Ссылка: https://www.kaggle.com/datasets/bhavikjikadara/dog-and-cat-classification-dataset" ] }, { "cell_type": "code", "execution_count": 2, "id": "24dd788e", "metadata": {}, "outputs": [], "source": [ "import kagglehub\n", "import os\n", "\n", "path = kagglehub.dataset_download(\"bhavikjikadara/dog-and-cat-classification-dataset\")\n", "path = os.path.join(path, \"PetImages\")" ] }, { "cell_type": "markdown", "id": "85652835", "metadata": {}, "source": [ "#### Формирование выборок" ] }, { "cell_type": "code", "execution_count": 3, "id": "f68de944", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Found 20000 images belonging to 2 classes.\n", "Found 4998 images belonging to 2 classes.\n" ] }, { "data": { "text/plain": [ "{'Cat': 0, 'Dog': 1}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from keras.src.legacy.preprocessing.image import ImageDataGenerator\n", "\n", "batch_size = 32\n", "\n", "data_loader = ImageDataGenerator(validation_split=0.2)\n", "\n", "train = data_loader.flow_from_directory(\n", " directory=path,\n", " target_size=(224, 224),\n", " color_mode=\"rgb\",\n", " class_mode=\"binary\",\n", " batch_size=batch_size,\n", " shuffle=True,\n", " seed=9,\n", " subset=\"training\",\n", ")\n", "\n", "valid = data_loader.flow_from_directory(\n", " directory=path,\n", " target_size=(224, 224),\n", " color_mode=\"rgb\",\n", " class_mode=\"binary\",\n", " batch_size=batch_size,\n", " shuffle=True,\n", " seed=9,\n", " subset=\"validation\",\n", ")\n", "\n", "train.class_indices" ] }, { "cell_type": "markdown", "id": "bfb9434d", "metadata": {}, "source": [ "### Пример переноса обучения с использованием предобученной модели VGGNet19" ] }, { "cell_type": "markdown", "id": "ae32c572", "metadata": {}, "source": [ "Загрузка предобученной модели и отключение обучения для ее слоев" ] }, { "cell_type": "code", "execution_count": 4, "id": "f4f1ade5", "metadata": {}, "outputs": [], "source": [ "from keras.api.applications.vgg19 import VGG19\n", "\n", "vgg19 = VGG19(include_top=False, weights=\"imagenet\", input_shape=(224, 224, 3), pooling=None)\n", "\n", "vgg19.trainable = False" ] }, { "cell_type": "markdown", "id": "3250d20b", "metadata": {}, "source": [ "#### Проектирование архитектуры ИНС на основе предобученной модели" ] }, { "cell_type": "code", "execution_count": 5, "id": "904b01b0", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Model: \"sequential\"\n",
"
\n"
],
"text/plain": [
"\u001b[1mModel: \"sequential\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n", "┃ Layer (type) ┃ Output Shape ┃ Param # ┃\n", "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n", "│ vgg19 (Functional) │ (None, 7, 7, 512) │ 20,024,384 │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ flattened (Flatten) │ (None, 25088) │ 0 │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ dropout (Dropout) │ (None, 25088) │ 0 │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ predictions (Dense) │ (None, 1) │ 25,089 │\n", "└─────────────────────────────────┴────────────────────────┴───────────────┘\n", "\n" ], "text/plain": [ "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n", "┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n", "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n", "│ vgg19 (\u001b[38;5;33mFunctional\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m7\u001b[0m, \u001b[38;5;34m7\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m20,024,384\u001b[0m │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ flattened (\u001b[38;5;33mFlatten\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m25088\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ dropout (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m25088\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ predictions (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1\u001b[0m) │ \u001b[38;5;34m25,089\u001b[0m │\n", "└─────────────────────────────────┴────────────────────────┴───────────────┘\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Total params: 20,049,473 (76.48 MB)\n", "\n" ], "text/plain": [ "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m20,049,473\u001b[0m (76.48 MB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Trainable params: 25,089 (98.00 KB)\n", "\n" ], "text/plain": [ "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m25,089\u001b[0m (98.00 KB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Non-trainable params: 20,024,384 (76.39 MB)\n", "\n" ], "text/plain": [ "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m20,024,384\u001b[0m (76.39 MB)\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from keras.api.models import Sequential\n", "from keras.api.layers import Dropout, Flatten, Dense\n", "\n", "tl_model = Sequential()\n", "tl_model.add(vgg19)\n", "\n", "# Добавление собственных слоев (в них будет проводиться обучение для текущей задачи)\n", "tl_model.add(Flatten(name=\"flattened\"))\n", "tl_model.add(Dropout(0.5, name=\"dropout\"))\n", "tl_model.add(Dense(1, activation=\"sigmoid\", name=\"predictions\"))\n", "\n", "tl_model.summary()" ] }, { "cell_type": "markdown", "id": "49fceead", "metadata": {}, "source": [ "#### Обучение глубокой модели" ] }, { "cell_type": "code", "execution_count": 6, "id": "fe650631", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "d:\\Projects\\Python\\mai\\.venv\\Lib\\site-packages\\keras\\src\\trainers\\data_adapters\\py_dataset_adapter.py:121: UserWarning: Your `PyDataset` class should call `super().__init__(**kwargs)` in its constructor. `**kwargs` can include `workers`, `use_multiprocessing`, `max_queue_size`. Do not pass these arguments to `fit()`, as they will be ignored.\n", " self._warn_if_super_not_called()\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/5\n", "\u001b[1m 15/625\u001b[0m \u001b[37m━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[1m19:08\u001b[0m 2s/step - accuracy: 0.6655 - loss: 3.8879" ] }, { "name": "stderr", "output_type": "stream", "text": [ "d:\\Projects\\Python\\mai\\.venv\\Lib\\site-packages\\PIL\\TiffImagePlugin.py:900: UserWarning: Truncated File Read\n", " warnings.warn(str(msg))\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1m625/625\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1449s\u001b[0m 2s/step - accuracy: 0.9067 - loss: 1.1503 - val_accuracy: 0.9602 - val_loss: 0.5733\n", "Epoch 2/5\n", "\u001b[1m625/625\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1453s\u001b[0m 2s/step - accuracy: 0.9551 - loss: 0.6339 - val_accuracy: 0.9638 - val_loss: 0.5131\n", "Epoch 3/5\n", "\u001b[1m 2/625\u001b[0m \u001b[37m━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[1m19:54\u001b[0m 2s/step - accuracy: 0.9297 - loss: 0.6612" ] }, { "ename": "KeyboardInterrupt", "evalue": "", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[6], line 7\u001b[0m\n\u001b[0;32m 1\u001b[0m tl_model\u001b[38;5;241m.\u001b[39mcompile(\n\u001b[0;32m 2\u001b[0m loss\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbinary_crossentropy\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 3\u001b[0m optimizer\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124madam\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 4\u001b[0m metrics\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124maccuracy\u001b[39m\u001b[38;5;124m\"\u001b[39m],\n\u001b[0;32m 5\u001b[0m )\n\u001b[1;32m----> 7\u001b[0m \u001b[43mtl_model\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtrain\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvalidation_data\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvalid\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mepochs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m5\u001b[39;49m\u001b[43m)\u001b[49m\n", "File \u001b[1;32md:\\Projects\\Python\\mai\\.venv\\Lib\\site-packages\\keras\\src\\utils\\traceback_utils.py:117\u001b[0m, in \u001b[0;36mfilter_traceback.