{ "cells": [ { "cell_type": "markdown", "id": "1587aa08", "metadata": {}, "source": [ "# Lesson 28: TensorFlow/Keras neural network demonstration - part 2\n", "\n", "## Notebook set up\n", "\n", "### Vocareum compatibility\n", "\n", "Check the notebook path to determine if we are running in Vocareum, if so, install TensorFlow 2.17 and Keras 3.2.0 via pip." ] }, { "cell_type": "code", "execution_count": 1, "id": "97aa2375", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running in Vocareum environment\n", "Note: you may need to restart the kernel to use updated packages.\n" ] } ], "source": [ "from pathlib import Path\n", "\n", "# Get the parts of the current directory path as a tuple\n", "path_parts = Path.cwd().parts\n", "\n", "# Check if 'voc' is the first directory level\n", "is_voc_root = len(path_parts) > 1 and path_parts[1] == \"voc\"\n", "\n", "# If we are in a Vocareum instance, upgrade TensorFlow and Keras\n", "if is_voc_root:\n", " print(\"Running in Vocareum environment\")\n", "\n", " get_ipython().run_line_magic(\n", " \"pip\", \"install -qq --no-warn-script-location tensorflow==2.17.0 keras==3.2.0\"\n", " )" ] }, { "cell_type": "markdown", "id": "b0391f6f", "metadata": {}, "source": [ "### Imports" ] }, { "cell_type": "code", "execution_count": null, "id": "39b9bf45", "metadata": {}, "outputs": [], "source": [ "# Suppress noisy TensorFlow logs before importing\n", "import os\n", "os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'\n", "\n", "# Third party imports\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", "import tensorflow as tf\n", "\n", "from tensorflow import keras\n", "from tensorflow.keras import layers\n", "from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, TensorBoard" ] }, { "cell_type": "markdown", "id": "e5a41854", "metadata": {}, "source": [ "### GPU configuration (if present)" ] }, { "cell_type": "code", "execution_count": null, "id": "7b7ac2dd", "metadata": {}, "outputs": [], "source": [ "# Configure GPU settings\n", "gpus = tf.config.list_physical_devices('GPU')\n", "\n", "if gpus:\n", " try:\n", " # Use only GPU 0\n", " tf.config.set_visible_devices(gpus[0], 'GPU')\n", "\n", " # Enable memory growth\n", " tf.config.experimental.set_memory_growth(gpus[0], True)\n", "\n", " # Get GPU\n", " details = tf.config.experimental.get_device_details(gpus[0])\n", " cc = details.get('compute_capability', (0, 0))\n", " device = details.get('device_name', '')\n", "\n", " print(f'Using GPU: {device}, compute capability {cc[0]}.{cc[1]}')\n", " print('Memory growth enabled')\n", "\n", " except RuntimeError as e:\n", " print(e)\n", "\n", "else:\n", " print('No GPU found')" ] }, { "cell_type": "markdown", "id": "98f5eab8", "metadata": {}, "source": [ "## 1. Load California housing data\n", "\n", "Load the preprocessed data from part 1 of the demo:" ] }, { "cell_type": "code", "execution_count": null, "id": "e94bf1e5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Data dictionary contains: ['training_df', 'testing_df', 'features', 'label', 'feature_scaler', 'label_scaler']\n" ] } ], "source": [ "data = pd.read_pickle('https://github.com/gperdrizet/fullstack-2605/raw/refs/heads/main/data/preprocessed_housing_data.pkl')\n", "print(f'Data dictionary contains: {list(data.keys())}')" ] }, { "cell_type": "code", "execution_count": 5, "id": "0561763f", "metadata": {}, "outputs": [], "source": [ "training_df = data['training_df']\n", "testing_df = data['testing_df']\n", "features = data['features']\n", "label = data['label']" ] }, { "cell_type": "markdown", "id": "01f45893", "metadata": {}, "source": [ "## 2. Build model" ] }, { "cell_type": "code", "execution_count": 6, "id": "d285821c", "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",
"│ dense (Dense) │ (None, 32) │ 288 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout (Dropout) │ (None, 32) │ 0 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_1 (Dense) │ (None, 64) │ 2,112 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout_1 (Dropout) │ (None, 64) │ 0 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_2 (Dense) │ (None, 32) │ 2,080 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout_2 (Dropout) │ (None, 32) │ 0 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_3 (Dense) │ (None, 1) │ 33 │\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",
"│ dense (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m288\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_1 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m2,112\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout_1 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_2 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m2,080\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout_2 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_3 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1\u001b[0m) │ \u001b[38;5;34m33\u001b[0m │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Total params: 4,513 (17.63 KB)\n", "\n" ], "text/plain": [ "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m4,513\u001b[0m (17.63 KB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Trainable params: 4,513 (17.63 KB)\n", "\n" ], "text/plain": [ "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m4,513\u001b[0m (17.63 KB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Non-trainable params: 0 (0.00 B)\n", "\n" ], "text/plain": [ "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tf.random.set_seed(315)\n", "\n", "model = keras.Sequential([\n", " layers.Input(shape=(8,)),\n", " layers.Dense(32, activation='relu'),\n", " layers.Dropout(0.2),\n", " layers.Dense(64, activation='relu'),\n", " layers.Dropout(0.2),\n", " layers.Dense(32, activation='relu'),\n", " layers.Dropout(0.2),\n", " layers.Dense(1)\n", "])\n", "\n", "model.compile(\n", " optimizer=keras.optimizers.Adam(learning_rate=1e-4),\n", " loss='mse',\n", " metrics=['mae']\n", ")\n", "\n", "model.summary()" ] }, { "cell_type": "markdown", "id": "9a746b8d", "metadata": {}, "source": [ "## 3. Callbacks\n", "\n", "1. [Custom callbacks](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/Callback)\n", "2. [Early stopping callback](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/EarlyStopping)\n", "3. [Model checkpoint](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/ModelCheckpoint)\n", "4. [Tensorboard](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/TensorBoard)\n", "\n", "To start tensorboard via a terminal, run:\n", "\n", "```bash\n", "tensorboard --logdir=path/to/log_dir/from/notebook_dir\n", "```\n", "\n", "Then visit the URL provided in your browser or via the 'ports' tab in VS Code. **Note**: if you are using the course's containerized deeplearning environment, you do not need to start TensorBoard manually. You can access it via the command pallette under `Python: Launch TensorBoard`.\n", "\n", "Alternatively, if you are using a Jupyter notebook in a remote environment (Such as vocareum or CoLab) you can run TensorBoard inline with these cell magics:\n", "\n", "```bash\n", "%load_ext tensorboard\n", "%tensorboard --logdir path/to/log_dir/from/notebook_dir\n", "```" ] }, { "cell_type": "code", "execution_count": 7, "id": "c8fd4460", "metadata": {}, "outputs": [], "source": [ "es_callback = EarlyStopping(\n", " monitor='val_loss',\n", " patience=5,\n", " restore_best_weights=True,\n", " verbose=1\n", ")\n", "\n", "checkpoint = ModelCheckpoint(\n", " filepath='best_model.keras',\n", " monitor='val_loss',\n", " save_best_only=True\n", ")\n", "\n", "tensorboard = TensorBoard(\n", " log_dir='./logs',\n", " histogram_freq=1,\n", " write_graph=True\n", ")" ] }, { "cell_type": "markdown", "id": "04aa4af3", "metadata": {}, "source": [ "## 4. Train model" ] }, { "cell_type": "code", "execution_count": 8, "id": "5178fc7f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Training complete.\n", "Final training loss: 0.2343\n", "Final validation loss: 0.2418\n", "CPU times: user 2min 8s, sys: 8.38 s, total: 2min 16s\n", "Wall time: 1min 48s\n" ] } ], "source": [ "%%time\n", "\n", "history = model.fit(\n", " training_df[features],\n", " training_df[label],\n", " epochs=500,\n", " batch_size=128,\n", " validation_split=0.2,\n", " callbacks=[checkpoint, tensorboard],\n", " verbose=0\n", ")\n", "\n", "print('Training complete.')\n", "print(f'Final training loss: {history.history[\"loss\"][-1]:.4f}')\n", "print(f'Final validation loss: {history.history[\"val_loss\"][-1]:.4f}')" ] }, { "cell_type": "markdown", "id": "d74f3b7e", "metadata": {}, "source": [ "## 5. Learning curves" ] }, { "cell_type": "code", "execution_count": 9, "id": "e0f48c27", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
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",
"│ dense (Dense) │ (None, 32) │ 288 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout (Dropout) │ (None, 32) │ 0 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_1 (Dense) │ (None, 64) │ 2,112 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout_1 (Dropout) │ (None, 64) │ 0 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_2 (Dense) │ (None, 32) │ 2,080 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout_2 (Dropout) │ (None, 32) │ 0 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_3 (Dense) │ (None, 1) │ 33 │\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",
"│ dense (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m288\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_1 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m2,112\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout_1 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_2 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m2,080\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dropout_2 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_3 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1\u001b[0m) │ \u001b[38;5;34m33\u001b[0m │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Total params: 13,541 (52.90 KB)\n", "\n" ], "text/plain": [ "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m13,541\u001b[0m (52.90 KB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Trainable params: 4,513 (17.63 KB)\n", "\n" ], "text/plain": [ "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m4,513\u001b[0m (17.63 KB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Non-trainable params: 0 (0.00 B)\n", "\n" ], "text/plain": [ "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Optimizer params: 9,028 (35.27 KB)\n", "\n" ], "text/plain": [ "\u001b[1m Optimizer params: \u001b[0m\u001b[38;5;34m9,028\u001b[0m (35.27 KB)\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "loaded_model = keras.models.load_model('housing_price_model_sequential_api.keras')\n", "loaded_model.summary()" ] } ], "metadata": { "kernelspec": { "display_name": ".venv (3.12.3)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }