{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Found 2199 images belonging to 2 classes.\n", "Found 549 images belonging to 2 classes.\n", "Training samples: 2199\n", "Validation samples: 549\n" ] } ], "source": [ "import tensorflow as tf\n", "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n", "\n", "dataset_dir = 'C:/Users/vsavelev/GITHUB/DS_projet/jan24_cds_mushrooms/data'\n", "\n", "# Create ImageDataGenerator with validation split\n", "datagen = ImageDataGenerator(rescale=1.0/255, validation_split=0.2)\n", "\n", "train_generator = datagen.flow_from_directory(\n", " dataset_dir,\n", " target_size=(224, 224),\n", " batch_size=32,\n", " class_mode='categorical',\n", " subset='training' # Set as training data\n", ")\n", "\n", "validation_generator = datagen.flow_from_directory(\n", " dataset_dir,\n", " target_size=(224, 224),\n", " batch_size=32,\n", " class_mode='categorical',\n", " subset='validation' # Set as validation data\n", ")\n", "\n", "print(f'Training samples: {train_generator.samples}')\n", "print(f'Validation samples: {validation_generator.samples}')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from tensorflow.keras.applications import ResNet50\n", "from tensorflow.keras import layers, models\n", "import keras_tuner as kt\n", "\n", "def build_model(hp):\n", " base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))\n", " base_model.trainable = False\n", "\n", " model = models.Sequential()\n", " model.add(base_model)\n", " model.add(layers.GlobalAveragePooling2D())\n", " model.add(layers.Dense(hp.Int('units', min_value=256, max_value=1024, step=256), activation='relu'))\n", " model.add(layers.Dropout(hp.Float('dropout', min_value=0.2, max_value=0.5, step=0.1)))\n", " model.add(layers.Dense(train_generator.num_classes, activation='softmax'))\n", " \n", " model.compile(optimizer=tf.keras.optimizers.Adam(hp.Choice('learning_rate', [1e-2, 1e-3, 1e-4])),\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy'])\n", " \n", " return model\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "#Set Up the Tuner\n", "\n", "tuner = kt.RandomSearch(\n", " build_model,\n", " objective='val_accuracy',\n", " max_trials=5,\n", " executions_per_trial=3,\n", " directory='my_dir',\n", " project_name='mushroom_classification'\n", ")\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Trial 5 Complete [05h 32m 33s]\n", "val_accuracy: 0.8870673775672913\n", "\n", "Best val_accuracy So Far: 0.8870673775672913\n", "Total elapsed time: 11h 14m 56s\n" ] } ], "source": [ "tuner.search(train_generator, epochs=10, validation_data=validation_generator)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "The hyperparameter search is complete. The optimal number of units in the dense layer is 768.\n", "The optimal learning rate for the optimizer is 0.001.\n", "\n" ] }, { "data": { "text/html": [ "
Model: \"sequential_1\"\n",
       "
\n" ], "text/plain": [ "\u001b[1mModel: \"sequential_1\"\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
       "┃ Layer (type)                     Output Shape                  Param # ┃\n",
       "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
       "│ resnet50 (Functional)           │ ?                      │    23,587,712 │\n",
       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
       "│ global_average_pooling2d_1      │ ?                      │   0 (unbuilt) │\n",
       "│ (GlobalAveragePooling2D)        │                        │               │\n",
       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
       "│ dense_2 (Dense)                 │ ?                      │   0 (unbuilt) │\n",
       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
       "│ dropout_1 (Dropout)             │ ?                      │   0 (unbuilt) │\n",
       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
       "│ dense_3 (Dense)                 │ ?                      │   0 (unbuilt) │\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", "│ resnet50 (\u001b[38;5;33mFunctional\u001b[0m) │ ? │ \u001b[38;5;34m23,587,712\u001b[0m │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ global_average_pooling2d_1 │ ? │ \u001b[38;5;34m0\u001b[0m (unbuilt) │\n", "│ (\u001b[38;5;33mGlobalAveragePooling2D\u001b[0m) │ │ │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ dense_2 (\u001b[38;5;33mDense\u001b[0m) │ ? │ \u001b[38;5;34m0\u001b[0m (unbuilt) │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ dropout_1 (\u001b[38;5;33mDropout\u001b[0m) │ ? │ \u001b[38;5;34m0\u001b[0m (unbuilt) │\n", "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", "│ dense_3 (\u001b[38;5;33mDense\u001b[0m) │ ? │ \u001b[38;5;34m0\u001b[0m (unbuilt) │\n", "└─────────────────────────────────┴────────────────────────┴───────────────┘\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
 Total params: 23,587,712 (89.98 MB)\n",
       "
\n" ], "text/plain": [ "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m23,587,712\u001b[0m (89.98 MB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
 Trainable params: 0 (0.00 B)\n",
       "
\n" ], "text/plain": [ "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
 Non-trainable params: 23,587,712 (89.98 MB)\n",
       "
\n" ], "text/plain": [ "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m23,587,712\u001b[0m (89.98 MB)\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "best_hps = tuner.get_best_hyperparameters(num_trials=1)[0]\n", "\n", "print(f\"\"\"\n", "The hyperparameter search is complete. The optimal number of units in the dense layer is {best_hps.get('units')}.\n", "The optimal learning rate for the optimizer is {best_hps.get('learning_rate')}.\n", "\"\"\")\n", "\n", "# Build the best model\n", "model = tuner.hypermodel.build(best_hps)\n", "model.summary()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m164s\u001b[0m 2s/step - accuracy: 0.8856 - loss: 0.4458 - val_accuracy: 0.8860 - val_loss: 0.3645\n", "Epoch 2/10\n", "\u001b[1m 1/68\u001b[0m \u001b[37m━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[1m1:57\u001b[0m 2s/step - accuracy: 0.9062 - loss: 0.3521" ] }, { "name": "stderr", "output_type": "stream", "text": [ "c:\\Users\\vsavelev\\AppData\\Local\\anaconda3\\Lib\\contextlib.py:158: UserWarning: Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches. You may need to use the `.repeat()` function when building your dataset.\n", " self.gen.throw(typ, value, traceback)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 11ms/step - accuracy: 0.9062 - loss: 0.3521 - val_accuracy: 1.0000 - val_loss: 0.0784\n", "Epoch 3/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m153s\u001b[0m 2s/step - accuracy: 0.8923 - loss: 0.3465 - val_accuracy: 0.8879 - val_loss: 0.3535\n", "Epoch 4/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 6ms/step - accuracy: 0.8750 - loss: 0.4432 - val_accuracy: 0.8000 - val_loss: 0.5806\n", "Epoch 5/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m151s\u001b[0m 2s/step - accuracy: 0.8817 - loss: 0.3742 - val_accuracy: 0.8860 - val_loss: 0.3608\n", "Epoch 6/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 8ms/step - accuracy: 0.9375 - loss: 0.2319 - val_accuracy: 1.0000 - val_loss: 0.0935\n", "Epoch 7/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m156s\u001b[0m 2s/step - accuracy: 0.8882 - loss: 0.3576 - val_accuracy: 0.8860 - val_loss: 0.3543\n", "Epoch 8/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 7ms/step - accuracy: 0.8438 - loss: 0.4161 - val_accuracy: 1.0000 - val_loss: 0.1267\n", "Epoch 9/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m154s\u001b[0m 2s/step - accuracy: 0.8969 - loss: 0.3322 - val_accuracy: 0.8860 - val_loss: 0.3748\n", "Epoch 10/10\n", "\u001b[1m68/68\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 6ms/step - accuracy: 0.9375 - loss: 0.2687 - val_accuracy: 1.0000 - val_loss: 0.1681\n" ] } ], "source": [ "history = model.fit(\n", " train_generator,\n", " steps_per_epoch=train_generator.samples // train_generator.batch_size,\n", " validation_data=validation_generator,\n", " validation_steps=validation_generator.samples // validation_generator.batch_size,\n", " epochs=10\n", ")\n", "\n", "#This specifies the number of complete passes through the training dataset. Here, the model will train for 10 epochs." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1m18/18\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m30s\u001b[0m 2s/step - accuracy: 0.8850 - loss: 0.3732\n", "Validation loss: 0.36864525079727173\n", "Validation accuracy: 0.8870673775672913\n" ] } ], "source": [ "loss, accuracy = model.evaluate(validation_generator)\n", "print(f'Validation loss: {loss}')\n", "print(f'Validation accuracy: {accuracy}')\n" ] } ], "metadata": { "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.11.7" } }, "nbformat": 4, "nbformat_minor": 2 }