{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "7765UFHoyGx6" }, "source": [ "##### Copyright 2020 The TensorFlow Authors." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "cellView": "form", "execution": { "iopub.execute_input": "2024-12-15T12:19:46.164539Z", "iopub.status.busy": "2024-12-15T12:19:46.164022Z", "iopub.status.idle": "2024-12-15T12:19:46.168387Z", "shell.execute_reply": "2024-12-15T12:19:46.167727Z" }, "id": "KsOkK8O69PyT" }, "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "ZS8z-_KeywY9" }, "source": [ "# Creating Keras Models with TFL Layers" ] }, { "cell_type": "markdown", "metadata": { "id": "r61fkA2i9Y3_" }, "source": [ "\n", " \n", " \n", " \n", " \n", "
\n", " View on TensorFlow.org\n", " \n", " Run in Google Colab\n", " \n", " View source on GitHub\n", " \n", " Download notebook\n", "
" ] }, { "cell_type": "markdown", "metadata": { "id": "ecLbJCvJSSCd" }, "source": [ "##Overview\n", "\n", "You can use TFL Keras layers to construct Keras models with monotonicity and other shape constraints. This example builds and trains a calibrated lattice model for the UCI heart dataset using TFL layers.\n", "\n", "In a calibrated lattice model, each feature is transformed by a `tfl.layers.PWLCalibration` or a `tfl.layers.CategoricalCalibration` layer and the results are nonlinearly fused using a `tfl.layers.Lattice`." ] }, { "cell_type": "markdown", "metadata": { "id": "x769lI12IZXB" }, "source": [ "## Setup" ] }, { "cell_type": "markdown", "metadata": { "id": "fbBVAR6UeRN5" }, "source": [ "Installing TF Lattice package:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:19:46.171747Z", "iopub.status.busy": "2024-12-15T12:19:46.171187Z", "iopub.status.idle": "2024-12-15T12:19:47.976280Z", "shell.execute_reply": "2024-12-15T12:19:47.975263Z" }, "id": "bpXjJKpSd3j4" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: tensorflow in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (2.18.0)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: tf-keras in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (2.18.0)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Collecting tensorflow-lattice\r\n", " Using cached tensorflow_lattice-2.1.1-py2.py3-none-any.whl.metadata (1.8 kB)\r\n", "Requirement already satisfied: pydot in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (3.0.3)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Collecting graphviz\r\n", " Using cached graphviz-0.20.3-py3-none-any.whl.metadata (12 kB)\r\n", "Requirement already satisfied: absl-py>=1.0.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (2.1.0)\r\n", "Requirement already satisfied: astunparse>=1.6.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (1.6.3)\r\n", "Requirement already satisfied: flatbuffers>=24.3.25 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (24.3.25)\r\n", "Requirement already satisfied: gast!=0.5.0,!=0.5.1,!=0.5.2,>=0.2.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (0.6.0)\r\n", "Requirement already satisfied: google-pasta>=0.1.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (0.2.0)\r\n", "Requirement already satisfied: libclang>=13.0.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (18.1.1)\r\n", "Requirement already satisfied: opt-einsum>=2.3.2 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (3.4.0)\r\n", "Requirement already satisfied: packaging in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (24.2)\r\n", "Requirement already satisfied: protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev,>=3.20.3 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (3.20.3)\r\n", "Requirement already satisfied: requests<3,>=2.21.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (2.32.3)\r\n", "Requirement already satisfied: setuptools in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (75.6.0)\r\n", "Requirement already satisfied: six>=1.12.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (1.17.0)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: termcolor>=1.1.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (2.5.0)\r\n", "Requirement already satisfied: typing-extensions>=3.6.6 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (4.12.2)\r\n", "Requirement already satisfied: wrapt>=1.11.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (1.17.0)\r\n", "Requirement already satisfied: grpcio<2.0,>=1.24.3 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (1.68.1)\r\n", "Requirement already satisfied: tensorboard<2.19,>=2.18 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (2.18.0)\r\n", "Requirement already satisfied: keras>=3.5.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (3.7.0)\r\n", "Requirement already satisfied: numpy<2.1.0,>=1.26.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (2.0.2)\r\n", "Requirement already satisfied: h5py>=3.11.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (3.12.1)\r\n", "Requirement already satisfied: ml-dtypes<0.5.0,>=0.4.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (0.4.1)\r\n", "Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.23.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow) (0.37.1)\r\n", "Requirement already satisfied: matplotlib in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow-lattice) (3.9.4)\r\n", "Requirement already satisfied: pandas in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow-lattice) (2.2.3)\r\n", "Requirement already satisfied: scikit-learn in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow-lattice) (1.6.0)\r\n", "Requirement already satisfied: pyparsing>=3.0.9 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from pydot) (3.2.0)\r\n", "Requirement already satisfied: wheel<1.0,>=0.23.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from astunparse>=1.6.0->tensorflow) (0.43.0)\r\n", "Requirement already satisfied: rich in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from keras>=3.5.0->tensorflow) (13.9.4)\r\n", "Requirement already satisfied: namex in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from keras>=3.5.0->tensorflow) (0.0.8)\r\n", "Requirement already satisfied: optree in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from keras>=3.5.0->tensorflow) (0.13.1)\r\n", "Requirement already satisfied: charset-normalizer<4,>=2 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from requests<3,>=2.21.0->tensorflow) (3.4.0)\r\n", "Requirement already satisfied: idna<4,>=2.5 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from requests<3,>=2.21.0->tensorflow) (3.10)\r\n", "Requirement already satisfied: urllib3<3,>=1.21.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from requests<3,>=2.21.0->tensorflow) (2.2.3)\r\n", "Requirement already satisfied: certifi>=2017.4.17 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from requests<3,>=2.21.0->tensorflow) (2024.12.14)\r\n", "Requirement already satisfied: markdown>=2.6.8 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorboard<2.19,>=2.18->tensorflow) (3.7)\r\n", "Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorboard<2.19,>=2.18->tensorflow) (0.7.2)\r\n", "Requirement already satisfied: werkzeug>=1.0.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorboard<2.19,>=2.18->tensorflow) (3.1.3)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: contourpy>=1.0.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from matplotlib->tensorflow-lattice) (1.3.0)\r\n", "Requirement already satisfied: cycler>=0.10 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from matplotlib->tensorflow-lattice) (0.12.1)\r\n", "Requirement already satisfied: fonttools>=4.22.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from matplotlib->tensorflow-lattice) (4.55.3)\r\n", "Requirement already satisfied: kiwisolver>=1.3.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from matplotlib->tensorflow-lattice) (1.4.7)\r\n", "Requirement already satisfied: pillow>=8 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from matplotlib->tensorflow-lattice) (11.0.0)\r\n", "Requirement already satisfied: python-dateutil>=2.7 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from matplotlib->tensorflow-lattice) (2.9.0.post0)\r\n", "Requirement already satisfied: importlib-resources>=3.2.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from matplotlib->tensorflow-lattice) (6.4.5)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: pytz>=2020.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from pandas->tensorflow-lattice) (2024.2)\r\n", "Requirement already satisfied: tzdata>=2022.7 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from pandas->tensorflow-lattice) (2024.2)\r\n", "Requirement already satisfied: scipy>=1.6.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from scikit-learn->tensorflow-lattice) (1.13.1)\r\n", "Requirement already satisfied: joblib>=1.2.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from scikit-learn->tensorflow-lattice) (1.4.2)\r\n", "Requirement already satisfied: threadpoolctl>=3.1.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from scikit-learn->tensorflow-lattice) (3.5.0)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: zipp>=3.1.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from importlib-resources>=3.2.0->matplotlib->tensorflow-lattice) (3.21.0)\r\n", "Requirement already satisfied: importlib-metadata>=4.4 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from markdown>=2.6.8->tensorboard<2.19,>=2.18->tensorflow) (8.5.0)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: MarkupSafe>=2.1.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from werkzeug>=1.0.1->tensorboard<2.19,>=2.18->tensorflow) (3.0.2)\r\n", "Requirement already satisfied: markdown-it-py>=2.2.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from rich->keras>=3.5.0->tensorflow) (3.0.0)\r\n", "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from rich->keras>=3.5.0->tensorflow) (2.18.0)\r\n", "Requirement already satisfied: mdurl~=0.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from markdown-it-py>=2.2.0->rich->keras>=3.5.0->tensorflow) (0.1.2)\r\n", "Using cached tensorflow_lattice-2.1.1-py2.py3-none-any.whl (219 kB)\r\n", "Using cached graphviz-0.20.3-py3-none-any.whl (47 kB)\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Installing collected packages: graphviz, tensorflow-lattice\r\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Successfully installed graphviz-0.20.3 tensorflow-lattice-2.1.1\r\n" ] } ], "source": [ "#@test {\"skip\": true}\n", "!pip install -U tensorflow tf-keras tensorflow-lattice pydot graphviz" ] }, { "cell_type": "markdown", "metadata": { "id": "jSVl9SHTeSGX" }, "source": [ "Importing required packages:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "cellView": "both", "execution": { "iopub.execute_input": "2024-12-15T12:19:47.980022Z", "iopub.status.busy": "2024-12-15T12:19:47.979597Z", "iopub.status.idle": "2024-12-15T12:19:51.018427Z", "shell.execute_reply": "2024-12-15T12:19:51.017596Z" }, "id": "pm0LD8iyIZXF" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2024-12-15 12:19:48.259455: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n", "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n", "E0000 00:00:1734265188.283238 43838 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n", "E0000 00:00:1734265188.290507 43838 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n" ] } ], "source": [ "import tensorflow as tf\n", "\n", "import logging\n", "import numpy as np\n", "import pandas as pd\n", "import sys\n", "import tensorflow_lattice as tfl\n", "from tensorflow import feature_column as fc\n", "logging.disable(sys.maxsize)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:19:51.021953Z", "iopub.status.busy": "2024-12-15T12:19:51.021444Z", "iopub.status.idle": "2024-12-15T12:19:51.029231Z", "shell.execute_reply": "2024-12-15T12:19:51.028595Z" }, "id": "m8TsvLIe4Az-" }, "outputs": [], "source": [ "# Use Keras 2.\n", "version_fn = getattr(tf.keras, \"version\", None)\n", "if version_fn and version_fn().startswith(\"3.\"):\n", " import tf_keras as keras\n", "else:\n", " keras = tf.keras" ] }, { "cell_type": "markdown", "metadata": { "id": "svPuM6QNxlrH" }, "source": [ "Downloading the UCI Statlog (Heart) dataset:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "cellView": "both", "execution": { "iopub.execute_input": "2024-12-15T12:19:51.031891Z", "iopub.status.busy": "2024-12-15T12:19:51.031527Z", "iopub.status.idle": "2024-12-15T12:19:51.051290Z", "shell.execute_reply": "2024-12-15T12:19:51.050676Z" }, "id": "PG3pFtK-IZXM" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agesexcptrestbpscholfbsrestecgthalachexangoldpeakslopecathaltarget
061141202600014013.621reversible1
145131102640113201.210normal0
247131302530017900.010normal0
359131502121015701.610normal0
455041282050113012.021reversible1
\n", "
" ], "text/plain": [ " age sex cp trestbps chol fbs restecg thalach exang oldpeak slope \\\n", "0 61 1 4 120 260 0 0 140 1 3.6 2 \n", "1 45 1 3 110 264 0 1 132 0 1.2 1 \n", "2 47 1 3 130 253 0 0 179 0 0.0 1 \n", "3 59 1 3 150 212 1 0 157 0 1.6 1 \n", "4 55 0 4 128 205 0 1 130 1 2.0 2 \n", "\n", " ca thal target \n", "0 1 reversible 1 \n", "1 0 normal 0 \n", "2 0 normal 0 \n", "3 0 normal 0 \n", "4 1 reversible 1 " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# UCI Statlog (Heart) dataset.\n", "csv_file = keras.utils.get_file(\n", " 'heart.csv', 'http://storage.googleapis.com/download.tensorflow.org/data/heart.csv')\n", "training_data_df = pd.read_csv(csv_file).sample(\n", " frac=1.0, random_state=41).reset_index(drop=True)\n", "training_data_df.head()" ] }, { "cell_type": "markdown", "metadata": { "id": "nKkAw12SxvGG" }, "source": [ "Setting the default values used for training in this guide:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "cellView": "both", "execution": { "iopub.execute_input": "2024-12-15T12:19:51.054091Z", "iopub.status.busy": "2024-12-15T12:19:51.053570Z", "iopub.status.idle": "2024-12-15T12:19:51.056769Z", "shell.execute_reply": "2024-12-15T12:19:51.056136Z" }, "id": "krAJBE-yIZXR" }, "outputs": [], "source": [ "LEARNING_RATE = 0.1\n", "BATCH_SIZE = 128\n", "NUM_EPOCHS = 100" ] }, { "cell_type": "markdown", "metadata": { "id": "0TGfzhPHzpix" }, "source": [ "## Sequential Keras Model\n", "\n", "This example creates a Sequential Keras model and only uses TFL layers.\n", "\n", "Lattice layers expect `input[i]` to be within `[0, lattice_sizes[i] - 1.0]`, so we need to define the lattice sizes ahead of the calibration layers so we can properly specify output range of the calibration layers.\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:19:51.059437Z", "iopub.status.busy": "2024-12-15T12:19:51.059039Z", "iopub.status.idle": "2024-12-15T12:19:51.062219Z", "shell.execute_reply": "2024-12-15T12:19:51.061578Z" }, "id": "nOQWqPAbQS3o" }, "outputs": [], "source": [ "# Lattice layer expects input[i] to be within [0, lattice_sizes[i] - 1.0], so\n", "lattice_sizes = [3, 2, 2, 2, 2, 2, 2]" ] }, { "cell_type": "markdown", "metadata": { "id": "W3DnEKWvQYXm" }, "source": [ "We use a `tfl.layers.ParallelCombination` layer to group together calibration layers which have to be executed in parallel in order to be able to create a Sequential model.\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:19:51.064809Z", "iopub.status.busy": "2024-12-15T12:19:51.064391Z", "iopub.status.idle": "2024-12-15T12:19:51.071680Z", "shell.execute_reply": "2024-12-15T12:19:51.070974Z" }, "id": "o_hyk5GkQfl8" }, "outputs": [], "source": [ "combined_calibrators = tfl.layers.ParallelCombination()" ] }, { "cell_type": "markdown", "metadata": { "id": "BPZsSUZiQiwc" }, "source": [ "We create a calibration layer for each feature and add it to the parallel combination layer. For numeric features we use `tfl.layers.PWLCalibration`, and for categorical features we use `tfl.layers.CategoricalCalibration`." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:19:51.074492Z", "iopub.status.busy": "2024-12-15T12:19:51.074218Z", "iopub.status.idle": "2024-12-15T12:19:51.099140Z", "shell.execute_reply": "2024-12-15T12:19:51.098438Z" }, "id": "DXPc6rSGxzFZ" }, "outputs": [], "source": [ "# ############### age ###############\n", "calibrator = tfl.layers.PWLCalibration(\n", " # Every PWLCalibration layer must have keypoints of piecewise linear\n", " # function specified. Easiest way to specify them is to uniformly cover\n", " # entire input range by using numpy.linspace().\n", " input_keypoints=np.linspace(\n", " training_data_df['age'].min(), training_data_df['age'].max(), num=5),\n", " # You need to ensure that input keypoints have same dtype as layer input.\n", " # You can do it by setting dtype here or by providing keypoints in such\n", " # format which will be converted to desired tf.dtype by default.\n", " dtype=tf.float32,\n", " # Output range must correspond to expected lattice input range.\n", " output_min=0.0,\n", " output_max=lattice_sizes[0] - 1.0,\n", ")\n", "combined_calibrators.append(calibrator)\n", "\n", "# ############### sex ###############\n", "# For boolean features simply specify CategoricalCalibration layer with 2\n", "# buckets.\n", "calibrator = tfl.layers.CategoricalCalibration(\n", " num_buckets=2,\n", " output_min=0.0,\n", " output_max=lattice_sizes[1] - 1.0,\n", " # Initializes all outputs to (output_min + output_max) / 2.0.\n", " kernel_initializer='constant')\n", "combined_calibrators.append(calibrator)\n", "\n", "# ############### cp ###############\n", "calibrator = tfl.layers.PWLCalibration(\n", " # Here instead of specifying dtype of layer we convert keypoints into\n", " # np.float32.\n", " input_keypoints=np.linspace(1, 4, num=4, dtype=np.float32),\n", " output_min=0.0,\n", " output_max=lattice_sizes[2] - 1.0,\n", " monotonicity='increasing',\n", " # You can specify TFL regularizers as a tuple ('regularizer name', l1, l2).\n", " kernel_regularizer=('hessian', 0.0, 1e-4))\n", "combined_calibrators.append(calibrator)\n", "\n", "# ############### trestbps ###############\n", "calibrator = tfl.layers.PWLCalibration(\n", " # Alternatively, you might want to use quantiles as keypoints instead of\n", " # uniform keypoints\n", " input_keypoints=np.quantile(training_data_df['trestbps'],\n", " np.linspace(0.0, 1.0, num=5)),\n", " dtype=tf.float32,\n", " # Together with quantile keypoints you might want to initialize piecewise\n", " # linear function to have 'equal_slopes' in order for output of layer\n", " # after initialization to preserve original distribution.\n", " kernel_initializer='equal_slopes',\n", " output_min=0.0,\n", " output_max=lattice_sizes[3] - 1.0,\n", " # You might consider clamping extreme inputs of the calibrator to output\n", " # bounds.\n", " clamp_min=True,\n", " clamp_max=True,\n", " monotonicity='increasing')\n", "combined_calibrators.append(calibrator)\n", "\n", "# ############### chol ###############\n", "calibrator = tfl.layers.PWLCalibration(\n", " # Explicit input keypoint initialization.\n", " input_keypoints=[126.0, 210.0, 247.0, 286.0, 564.0],\n", " dtype=tf.float32,\n", " output_min=0.0,\n", " output_max=lattice_sizes[4] - 1.0,\n", " # Monotonicity of calibrator can be decreasing. Note that corresponding\n", " # lattice dimension must have INCREASING monotonicity regardless of\n", " # monotonicity direction of calibrator.\n", " monotonicity='decreasing',\n", " # Convexity together with decreasing monotonicity result in diminishing\n", " # return constraint.\n", " convexity='convex',\n", " # You can specify list of regularizers. You are not limited to TFL\n", " # regularizrs. Feel free to use any :)\n", " kernel_regularizer=[('laplacian', 0.0, 1e-4),\n", " keras.regularizers.l1_l2(l1=0.001)])\n", "combined_calibrators.append(calibrator)\n", "\n", "# ############### fbs ###############\n", "calibrator = tfl.layers.CategoricalCalibration(\n", " num_buckets=2,\n", " output_min=0.0,\n", " output_max=lattice_sizes[5] - 1.0,\n", " # For categorical calibration layer monotonicity is specified for pairs\n", " # of indices of categories. Output for first category in pair will be\n", " # smaller than output for second category.\n", " #\n", " # Don't forget to set monotonicity of corresponding dimension of Lattice\n", " # layer to '1'.\n", " monotonicities=[(0, 1)],\n", " # This initializer is identical to default one('uniform'), but has fixed\n", " # seed in order to simplify experimentation.\n", " kernel_initializer=keras.initializers.RandomUniform(\n", " minval=0.0, maxval=lattice_sizes[5] - 1.0, seed=1))\n", "combined_calibrators.append(calibrator)\n", "\n", "# ############### restecg ###############\n", "calibrator = tfl.layers.CategoricalCalibration(\n", " num_buckets=3,\n", " output_min=0.0,\n", " output_max=lattice_sizes[6] - 1.0,\n", " # Categorical monotonicity can be partial order.\n", " monotonicities=[(0, 1), (0, 2)],\n", " # Categorical calibration layer supports standard Keras regularizers.\n", " kernel_regularizer=keras.regularizers.l1_l2(l1=0.001),\n", " kernel_initializer='constant')\n", "combined_calibrators.append(calibrator)" ] }, { "cell_type": "markdown", "metadata": { "id": "inyNlSBeQyp7" }, "source": [ "We then create a lattice layer to nonlinearly fuse the outputs of the calibrators.\n", "\n", "Note that we need to specify the monotonicity of the lattice to be increasing for required dimensions. The composition with the direction of the monotonicity in the calibration will result in the correct end-to-end direction of monotonicity. This includes partial monotonicity of CategoricalCalibration layer." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:19:51.101908Z", "iopub.status.busy": "2024-12-15T12:19:51.101380Z", "iopub.status.idle": "2024-12-15T12:19:51.106810Z", "shell.execute_reply": "2024-12-15T12:19:51.106159Z" }, "id": "DNCc9oBTRo6w" }, "outputs": [], "source": [ "lattice = tfl.layers.Lattice(\n", " lattice_sizes=lattice_sizes,\n", " monotonicities=[\n", " 'increasing', 'none', 'increasing', 'increasing', 'increasing',\n", " 'increasing', 'increasing'\n", " ],\n", " output_min=0.0,\n", " output_max=1.0)" ] }, { "cell_type": "markdown", "metadata": { "id": "T5q2InayRpDr" }, "source": [ "We can then create a sequential model using the combined calibrators and lattice layers." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:19:51.109464Z", "iopub.status.busy": "2024-12-15T12:19:51.108971Z", "iopub.status.idle": "2024-12-15T12:19:51.197015Z", "shell.execute_reply": "2024-12-15T12:19:51.196252Z" }, "id": "xX6lroYZQy3L" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2024-12-15 12:19:51.161765: E external/local_xla/xla/stream_executor/cuda/cuda_driver.cc:152] failed call to cuInit: INTERNAL: CUDA error: Failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n" ] } ], "source": [ "model = keras.models.Sequential()\n", "model.add(combined_calibrators)\n", "model.add(lattice)" ] }, { "cell_type": "markdown", "metadata": { "id": "W3UFxD3fRzIC" }, "source": [ "Training works the same as any other keras model." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:19:51.200169Z", "iopub.status.busy": "2024-12-15T12:19:51.199681Z", "iopub.status.idle": "2024-12-15T12:20:00.391820Z", "shell.execute_reply": "2024-12-15T12:20:00.391168Z" }, "id": "2jz4JvI-RzSj" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r", " 1/10 [==>...........................] - ETA: 0s - loss: 0.1265" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r", "10/10 [==============================] - 0s 2ms/step - loss: 0.1551\n" ] }, { "data": { "text/plain": [ "0.15509344637393951" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "features = training_data_df[[\n", " 'age', 'sex', 'cp', 'trestbps', 'chol', 'fbs', 'restecg'\n", "]].values.astype(np.float32)\n", "target = training_data_df[['target']].values.astype(np.float32)\n", "\n", "model.compile(\n", " loss=keras.losses.mean_squared_error,\n", " optimizer=keras.optimizers.Adagrad(learning_rate=LEARNING_RATE))\n", "model.fit(\n", " features,\n", " target,\n", " batch_size=BATCH_SIZE,\n", " epochs=NUM_EPOCHS,\n", " validation_split=0.2,\n", " shuffle=False,\n", " verbose=0)\n", "\n", "model.evaluate(features, target)" ] }, { "cell_type": "markdown", "metadata": { "id": "RTHoW_5lxwT5" }, "source": [ "## Functional Keras Model\n", "\n", "This example uses a functional API for Keras model construction.\n", "\n", "As mentioned in the previous section, lattice layers expect `input[i]` to be within `[0, lattice_sizes[i] - 1.0]`, so we need to define the lattice sizes ahead of the calibration layers so we can properly specify output range of the calibration layers." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:20:00.394927Z", "iopub.status.busy": "2024-12-15T12:20:00.394335Z", "iopub.status.idle": "2024-12-15T12:20:00.397752Z", "shell.execute_reply": "2024-12-15T12:20:00.397150Z" }, "id": "gJjUYvBuW1qE" }, "outputs": [], "source": [ "# We are going to have 2-d embedding as one of lattice inputs.\n", "lattice_sizes = [3, 2, 2, 3, 3, 2, 2]" ] }, { "cell_type": "markdown", "metadata": { "id": "Z03qY5MYW1yT" }, "source": [ "For each feature, we need to create an input layer followed by a calibration layer. For numeric features we use `tfl.layers.PWLCalibration` and for categorical features we use `tfl.layers.CategoricalCalibration`." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:20:00.400547Z", "iopub.status.busy": "2024-12-15T12:20:00.400346Z", "iopub.status.idle": "2024-12-15T12:20:00.504841Z", "shell.execute_reply": "2024-12-15T12:20:00.504201Z" }, "id": "DCIUz8apzs0l" }, "outputs": [], "source": [ "model_inputs = []\n", "lattice_inputs = []\n", "# ############### age ###############\n", "age_input = keras.layers.Input(shape=[1], name='age')\n", "model_inputs.append(age_input)\n", "age_calibrator = tfl.layers.PWLCalibration(\n", " # Every PWLCalibration layer must have keypoints of piecewise linear\n", " # function specified. Easiest way to specify them is to uniformly cover\n", " # entire input range by using numpy.linspace().\n", " input_keypoints=np.linspace(\n", " training_data_df['age'].min(), training_data_df['age'].max(), num=5),\n", " # You need to ensure that input keypoints have same dtype as layer input.\n", " # You can do it by setting dtype here or by providing keypoints in such\n", " # format which will be converted to desired tf.dtype by default.\n", " dtype=tf.float32,\n", " # Output range must correspond to expected lattice input range.\n", " output_min=0.0,\n", " output_max=lattice_sizes[0] - 1.0,\n", " monotonicity='increasing',\n", " name='age_calib',\n", ")(\n", " age_input)\n", "lattice_inputs.append(age_calibrator)\n", "\n", "# ############### sex ###############\n", "# For boolean features simply specify CategoricalCalibration layer with 2\n", "# buckets.\n", "sex_input = keras.layers.Input(shape=[1], name='sex')\n", "model_inputs.append(sex_input)\n", "sex_calibrator = tfl.layers.CategoricalCalibration(\n", " num_buckets=2,\n", " output_min=0.0,\n", " output_max=lattice_sizes[1] - 1.0,\n", " # Initializes all outputs to (output_min + output_max) / 2.0.\n", " kernel_initializer='constant',\n", " name='sex_calib',\n", ")(\n", " sex_input)\n", "lattice_inputs.append(sex_calibrator)\n", "\n", "# ############### cp ###############\n", "cp_input = keras.layers.Input(shape=[1], name='cp')\n", "model_inputs.append(cp_input)\n", "cp_calibrator = tfl.layers.PWLCalibration(\n", " # Here instead of specifying dtype of layer we convert keypoints into\n", " # np.float32.\n", " input_keypoints=np.linspace(1, 4, num=4, dtype=np.float32),\n", " output_min=0.0,\n", " output_max=lattice_sizes[2] - 1.0,\n", " monotonicity='increasing',\n", " # You can specify TFL regularizers as tuple ('regularizer name', l1, l2).\n", " kernel_regularizer=('hessian', 0.0, 1e-4),\n", " name='cp_calib',\n", ")(\n", " cp_input)\n", "lattice_inputs.append(cp_calibrator)\n", "\n", "# ############### trestbps ###############\n", "trestbps_input = keras.layers.Input(shape=[1], name='trestbps')\n", "model_inputs.append(trestbps_input)\n", "trestbps_calibrator = tfl.layers.PWLCalibration(\n", " # Alternatively, you might want to use quantiles as keypoints instead of\n", " # uniform keypoints\n", " input_keypoints=np.quantile(training_data_df['trestbps'],\n", " np.linspace(0.0, 1.0, num=5)),\n", " dtype=tf.float32,\n", " # Together with quantile keypoints you might want to initialize piecewise\n", " # linear function to have 'equal_slopes' in order for output of layer\n", " # after initialization to preserve original distribution.\n", " kernel_initializer='equal_slopes',\n", " output_min=0.0,\n", " output_max=lattice_sizes[3] - 1.0,\n", " # You might consider clamping extreme inputs of the calibrator to output\n", " # bounds.\n", " clamp_min=True,\n", " clamp_max=True,\n", " monotonicity='increasing',\n", " name='trestbps_calib',\n", ")(\n", " trestbps_input)\n", "lattice_inputs.append(trestbps_calibrator)\n", "\n", "# ############### chol ###############\n", "chol_input = keras.layers.Input(shape=[1], name='chol')\n", "model_inputs.append(chol_input)\n", "chol_calibrator = tfl.layers.PWLCalibration(\n", " # Explicit input keypoint initialization.\n", " input_keypoints=[126.0, 210.0, 247.0, 286.0, 564.0],\n", " output_min=0.0,\n", " output_max=lattice_sizes[4] - 1.0,\n", " # Monotonicity of calibrator can be decreasing. Note that corresponding\n", " # lattice dimension must have INCREASING monotonicity regardless of\n", " # monotonicity direction of calibrator.\n", " monotonicity='decreasing',\n", " # Convexity together with decreasing monotonicity result in diminishing\n", " # return constraint.\n", " convexity='convex',\n", " # You can specify list of regularizers. You are not limited to TFL\n", " # regularizrs. Feel free to use any :)\n", " kernel_regularizer=[('laplacian', 0.0, 1e-4),\n", " keras.regularizers.l1_l2(l1=0.001)],\n", " name='chol_calib',\n", ")(\n", " chol_input)\n", "lattice_inputs.append(chol_calibrator)\n", "\n", "# ############### fbs ###############\n", "fbs_input = keras.layers.Input(shape=[1], name='fbs')\n", "model_inputs.append(fbs_input)\n", "fbs_calibrator = tfl.layers.CategoricalCalibration(\n", " num_buckets=2,\n", " output_min=0.0,\n", " output_max=lattice_sizes[5] - 1.0,\n", " # For categorical calibration layer monotonicity is specified for pairs\n", " # of indices of categories. Output for first category in pair will be\n", " # smaller than output for second category.\n", " #\n", " # Don't forget to set monotonicity of corresponding dimension of Lattice\n", " # layer to '1'.\n", " monotonicities=[(0, 1)],\n", " # This initializer is identical to default one ('uniform'), but has fixed\n", " # seed in order to simplify experimentation.\n", " kernel_initializer=keras.initializers.RandomUniform(\n", " minval=0.0, maxval=lattice_sizes[5] - 1.0, seed=1),\n", " name='fbs_calib',\n", ")(\n", " fbs_input)\n", "lattice_inputs.append(fbs_calibrator)\n", "\n", "# ############### restecg ###############\n", "restecg_input = keras.layers.Input(shape=[1], name='restecg')\n", "model_inputs.append(restecg_input)\n", "restecg_calibrator = tfl.layers.CategoricalCalibration(\n", " num_buckets=3,\n", " output_min=0.0,\n", " output_max=lattice_sizes[6] - 1.0,\n", " # Categorical monotonicity can be partial order.\n", " monotonicities=[(0, 1), (0, 2)],\n", " # Categorical calibration layer supports standard Keras regularizers.\n", " kernel_regularizer=keras.regularizers.l1_l2(l1=0.001),\n", " kernel_initializer='constant',\n", " name='restecg_calib',\n", ")(\n", " restecg_input)\n", "lattice_inputs.append(restecg_calibrator)" ] }, { "cell_type": "markdown", "metadata": { "id": "Fr0k8La_YgQG" }, "source": [ "We then create a lattice layer to nonlinearly fuse the outputs of the calibrators.\n", "\n", "Note that we need to specify the monotonicity of the lattice to be increasing for required dimensions. The composition with the direction of the monotonicity in the calibration will result in the correct end-to-end direction of monotonicity. This includes partial monotonicity of `tfl.layers.CategoricalCalibration` layer." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:20:00.507814Z", "iopub.status.busy": "2024-12-15T12:20:00.507317Z", "iopub.status.idle": "2024-12-15T12:20:00.580613Z", "shell.execute_reply": "2024-12-15T12:20:00.579965Z" }, "id": "X15RE0NybNbU" }, "outputs": [], "source": [ "lattice = tfl.layers.Lattice(\n", " lattice_sizes=lattice_sizes,\n", " monotonicities=[\n", " 'increasing', 'none', 'increasing', 'increasing', 'increasing',\n", " 'increasing', 'increasing'\n", " ],\n", " output_min=0.0,\n", " output_max=1.0,\n", " name='lattice',\n", ")(\n", " lattice_inputs)" ] }, { "cell_type": "markdown", "metadata": { "id": "31VzsnMCA9dh" }, "source": [ "To add more flexibility to the model, we add an output calibration layer." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:20:00.583440Z", "iopub.status.busy": "2024-12-15T12:20:00.582982Z", "iopub.status.idle": "2024-12-15T12:20:00.599339Z", "shell.execute_reply": "2024-12-15T12:20:00.598707Z" }, "id": "efCP3Yx2A9n7" }, "outputs": [], "source": [ "model_output = tfl.layers.PWLCalibration(\n", " input_keypoints=np.linspace(0.0, 1.0, 5),\n", " name='output_calib',\n", ")(\n", " lattice)" ] }, { "cell_type": "markdown", "metadata": { "id": "1SURnNl8bNgw" }, "source": [ "We can now create a model using the inputs and outputs." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:20:00.602070Z", "iopub.status.busy": "2024-12-15T12:20:00.601530Z", "iopub.status.idle": "2024-12-15T12:20:00.716713Z", "shell.execute_reply": "2024-12-15T12:20:00.715950Z" }, "id": "7gY-VXuYbZLa" }, "outputs": [ { "data": { "image/png": "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QE5ODjp37qx0DLOXnp6udASiFjN8+HAcP34c77zzDubNm4cvvvgCGzZsQN++fZWORkRELaDOOzhT+xQaGso7ODeBSqVSOgKRUZpyx/FTp05hxowZOHjwIBYtWoS//OUvHBKaiKhtSTIoFoiIiBpKRPDxxx8jOjoa3bt3x+effw6NRqN0LCIiah5JvGaBiIgaTaVS4aWXXsKhQ4dgZ2eHgIAArFy5Evw7FBFR28BigYiImszX1xf79+/HggULMG/ePIwbNw5XrlxROhYRETURT0MiIqJmlZGRgbCwMFRXV2Pz5s0YOHCg0pGIiKhxeBoSERE1r379+iEzMxN+fn4YMmQIVq5cqXQkIiJqJBYLRETU7O6++258++23iI2NRUxMDJ5//nlUVlYqHYuIiIzE05CIiKhF7dy5E5MnT0avXr3w9ddfw9PTU+lIRETUMDwNiYiIWtbIkSORnp6OoqIiPProozh69KjSkYiIqIFYLBARUYvz9fXFwYMH4evri8DAQOzdu1fpSERE1AAsFoiIqFW4uLhg69atGD16NEaNGoWEhASlIxERUT2slA5ARETth42NDb744gu4u7vjmWeeQVFREaKiopSORUREdWCxQERErcrCwgKrVq2Cp6cnZs6cifLycrz22mtKxyIiolqwWCAiIkX85S9/gaurK6KiolBRUYE333xT6UhERHQbFgtERKSYGTNmQKVS4eWXX4aIYOHChUpHIiKiW7BYICIiRUVGRsLCwgIzZsyAVqvF4sWLlY5ERET/h8UCEREpbvr06aiurkZUVBSsra3xl7/8RelIREQEFgtERGQiZsyYARHBK6+8AmdnZ8ycOVPpSERE7R6LBSIiMhkvv/wyKisrMWvWLNjb2+PFF19UOhIRUbvGYoGIiEzKnDlzcPnyZURGRuKuu+7CxIkTlY5ERNRusVggIiKTs3TpUlRUVGDq1KlwcnLCk08+qXQkIqJ2SSUionQIIiKi22m1WkRERODrr7/Gvn378MgjjygdiYiovUlisUBERCaruroaISEhOHDgAA4cOICePXsqHYmIqD1hsUBERKattLQUgYGBuHr1KtLT0+Hu7q50JCKi9iLJQukEREREd+Ls7IytW7eiuroawcHBuH79utKRiIjaDYNfFhITExEWFqZUHlJYaGgokpKSlI7RKBMnTsSWLVuUjkFERmroD9yn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", "text/plain": [ "" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model = keras.models.Model(\n", " inputs=model_inputs,\n", " outputs=model_output)\n", "keras.utils.plot_model(model, rankdir='LR')" ] }, { "cell_type": "markdown", "metadata": { "id": "tvFJTs94bZXK" }, "source": [ "Training works the same as any other keras model. Note that, with our setup, input features are passed as separate tensors." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "execution": { "iopub.execute_input": "2024-12-15T12:20:00.719993Z", "iopub.status.busy": "2024-12-15T12:20:00.719374Z", "iopub.status.idle": "2024-12-15T12:20:07.508701Z", "shell.execute_reply": "2024-12-15T12:20:07.508049Z" }, "id": "vMQTGbFAYgYS" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r", " 1/10 [==>...........................] - ETA: 0s - loss: 0.1372" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r", "10/10 [==============================] - 0s 2ms/step - loss: 0.1580\n" ] }, { "data": { "text/plain": [ "0.15800504386425018" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "feature_names = ['age', 'sex', 'cp', 'trestbps', 'chol', 'fbs', 'restecg']\n", "features = np.split(\n", " training_data_df[feature_names].values.astype(np.float32),\n", " indices_or_sections=len(feature_names),\n", " axis=1)\n", "target = training_data_df[['target']].values.astype(np.float32)\n", "\n", "model.compile(\n", " loss=keras.losses.mean_squared_error,\n", " optimizer=keras.optimizers.Adagrad(LEARNING_RATE))\n", "model.fit(\n", " features,\n", " target,\n", " batch_size=BATCH_SIZE,\n", " epochs=NUM_EPOCHS,\n", " validation_split=0.2,\n", " shuffle=False,\n", " verbose=0)\n", "\n", "model.evaluate(features, target)" ] } ], "metadata": { "colab": { "name": "keras_layers.ipynb", "private_outputs": true, "provenance": [], "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "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.9.21" } }, "nbformat": 4, "nbformat_minor": 0 }