{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cbc8016f",
   "metadata": {},
   "source": [
    "# GenerateModel\n",
    "This tutorial shows how to define and generate a keras model for use with\n",
    "TMVA.\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "**Author:** TMVA Team  \n",
    "<i><small>This notebook tutorial was automatically generated with <a href= \"https://github.com/root-project/root/blob/master/documentation/doxygen/converttonotebook.py\">ROOTBOOK-izer</a> from the macro found in the ROOT repository  on Tuesday, May 19, 2026 at 08:21 PM.</small></i>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "cd05be6c",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:09.821895Z",
     "iopub.status.busy": "2026-05-19T20:21:09.821772Z",
     "iopub.status.idle": "2026-05-19T20:21:12.101831Z",
     "shell.execute_reply": "2026-05-19T20:21:12.101258Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n",
      "I0000 00:00:1779222070.011287  568646 port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n",
      "I0000 00:00:1779222070.012539  568646 cudart_stub.cc:31] Could not find cuda drivers on your machine, GPU will not be used.\n",
      "I0000 00:00:1779222070.050194  568646 cpu_feature_guard.cc:227] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n",
      "To enable the following instructions: AVX2 AVX512F AVX512_VNNI AVX512_BF16 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n",
      "I0000 00:00:1779222071.034433  568646 port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n",
      "I0000 00:00:1779222071.035133  568646 cudart_stub.cc:31] Could not find cuda drivers on your machine, GPU will not be used.\n"
     ]
    }
   ],
   "source": [
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense, Activation\n",
    "from tensorflow.keras.regularizers import l2\n",
    "from tensorflow.keras.optimizers import SGD\n",
    "from tensorflow.keras.utils import plot_model"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "765de834",
   "metadata": {},
   "source": [
    "Setup the model here"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "b7603253",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:12.103888Z",
     "iopub.status.busy": "2026-05-19T20:21:12.103622Z",
     "iopub.status.idle": "2026-05-19T20:21:12.107781Z",
     "shell.execute_reply": "2026-05-19T20:21:12.107320Z"
    }
   },
   "outputs": [],
   "source": [
    "num_input_nodes = 4\n",
    "num_output_nodes = 2\n",
    "num_hidden_layers = 1\n",
    "nodes_hidden_layer = 64\n",
    "l2_val = 1e-5\n",
    "\n",
    "model = Sequential()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22fbee19",
   "metadata": {},
   "source": [
    "Hidden layer 1\n",
    "NOTE: Number of input nodes need to be defined in this layer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "1a0fcffe",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:12.108984Z",
     "iopub.status.busy": "2026-05-19T20:21:12.108862Z",
     "iopub.status.idle": "2026-05-19T20:21:12.146501Z",
     "shell.execute_reply": "2026-05-19T20:21:12.145993Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/py-venv/ROOT-CI/lib64/python3.12/site-packages/keras/src/layers/core/dense.py:107: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.\n",
      "  super().__init__(activity_regularizer=activity_regularizer, **kwargs)\n",
      "E0000 00:00:1779222072.112280  568646 cuda_platform.cc:52] failed call to cuInit: INTERNAL: CUDA error: Failed call to cuInit: UNKNOWN ERROR (303)\n"
     ]
    }
   ],
   "source": [
    "model.add(Dense(nodes_hidden_layer, activation='relu', kernel_regularizer=l2(l2_val), input_dim=num_input_nodes))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd6422c3",
   "metadata": {},
   "source": [
    "Hidden layer 2 to num_hidden_layers\n",
    "NOTE: Here, you can do what you want"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f5e5f127",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:12.147830Z",
     "iopub.status.busy": "2026-05-19T20:21:12.147706Z",
     "iopub.status.idle": "2026-05-19T20:21:12.149845Z",
     "shell.execute_reply": "2026-05-19T20:21:12.149401Z"
    }
   },
   "outputs": [],
   "source": [
    "for k in range(num_hidden_layers-1):\n",
    "    model.add(Dense(nodes_hidden_layer, activation='relu', kernel_regularizer=l2(l2_val)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "350cb7d7",
   "metadata": {},
   "source": [
    "Output layer\n",
    "NOTE: Use following output types for the different tasks\n",
    "Binary classification: 2 output nodes with 'softmax' activation\n",
    "Regression: 1 output with any activation ('linear' recommended)\n",
    "Multiclass classification: (number of classes) output nodes with 'softmax' activation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4a373b0c",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:12.150967Z",
     "iopub.status.busy": "2026-05-19T20:21:12.150849Z",
     "iopub.status.idle": "2026-05-19T20:21:12.157977Z",
     "shell.execute_reply": "2026-05-19T20:21:12.157517Z"
    }
   },
   "outputs": [],
   "source": [
    "model.add(Dense(num_output_nodes, activation='softmax'))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff116734",
   "metadata": {},
   "source": [
    "Compile model\n",
    "NOTE: Use following settings for the different tasks\n",
    "Any classification: 'categorical_crossentropy' is recommended loss function\n",
    "Regression: 'mean_squared_error' is recommended loss function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "800faa7b",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:12.159434Z",
     "iopub.status.busy": "2026-05-19T20:21:12.159317Z",
     "iopub.status.idle": "2026-05-19T20:21:12.165770Z",
     "shell.execute_reply": "2026-05-19T20:21:12.165319Z"
    }
   },
   "outputs": [],
   "source": [
    "model.compile(loss='categorical_crossentropy', optimizer=SGD(learning_rate=0.01), weighted_metrics=['accuracy',])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15a7731a",
   "metadata": {},
   "source": [
    "Save model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "8240cd9f",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:12.166969Z",
     "iopub.status.busy": "2026-05-19T20:21:12.166848Z",
     "iopub.status.idle": "2026-05-19T20:21:12.190210Z",
     "shell.execute_reply": "2026-05-19T20:21:12.189743Z"
    }
   },
   "outputs": [],
   "source": [
    "model.save('model.keras')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cae29aec",
   "metadata": {},
   "source": [
    "Additional information about the model\n",
    "NOTE: This is not needed to run the model"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8545b43d",
   "metadata": {},
   "source": [
    "Print summary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b85e1132",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:12.191583Z",
     "iopub.status.busy": "2026-05-19T20:21:12.191459Z",
     "iopub.status.idle": "2026-05-19T20:21:12.201383Z",
     "shell.execute_reply": "2026-05-19T20:21:12.200936Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"sequential\"</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1mModel: \"sequential\"\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
       "┃<span style=\"font-weight: bold\"> Layer (type)                    </span>┃<span style=\"font-weight: bold\"> Output Shape           </span>┃<span style=\"font-weight: bold\">       Param # </span>┃\n",
       "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
       "│ dense (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>)                   │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>)             │           <span style=\"color: #00af00; text-decoration-color: #00af00\">320</span> │\n",
       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
       "│ dense_1 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>)                 │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">2</span>)              │           <span style=\"color: #00af00; text-decoration-color: #00af00\">130</span> │\n",
       "└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
       "</pre>\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;34m64\u001b[0m)             │           \u001b[38;5;34m320\u001b[0m │\n",
       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
       "│ dense_1 (\u001b[38;5;33mDense\u001b[0m)                 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m2\u001b[0m)              │           \u001b[38;5;34m130\u001b[0m │\n",
       "└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">450</span> (1.76 KB)\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m450\u001b[0m (1.76 KB)\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">450</span> (1.76 KB)\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m450\u001b[0m (1.76 KB)\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
       "</pre>\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": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7677eed6",
   "metadata": {},
   "source": [
    "Visualize model as graph"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "c409cd83",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:21:12.202614Z",
     "iopub.status.busy": "2026-05-19T20:21:12.202477Z",
     "iopub.status.idle": "2026-05-19T20:21:12.204916Z",
     "shell.execute_reply": "2026-05-19T20:21:12.204494Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You must install pydot (`pip install pydot`) for `plot_model` to work.\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    plot_model(model, to_file='model.png', show_shapes=True)\n",
    "except:\n",
    "    print('[INFO] Failed to make model plot')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 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.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
