diff --git a/examples/vision/3D_image_classification.py b/examples/vision/3D_image_classification.py
index 2987dc96d6..77996d0b89 100644
--- a/examples/vision/3D_image_classification.py
+++ b/examples/vision/3D_image_classification.py
@@ -2,9 +2,10 @@
Title: 3D image classification from CT scans
Author: [Hasib Zunair](https://twitter.com/hasibzunair)
Date created: 2020/09/23
-Last modified: 2020/09/23
+Last modified: 2024/01/11
Description: Train a 3D convolutional neural network to predict presence of pneumonia.
Accelerator: GPU
+Converted to Keras 3 by: [Sitam Meur](https://github.com/sitamgithub-MSIT)
"""
"""
## Introduction
@@ -27,12 +28,15 @@
"""
import os
+
+os.environ["KERAS_BACKEND"] = "tensorflow"
import zipfile
import numpy as np
-import tensorflow as tf
-from tensorflow import keras
-from tensorflow.keras import layers
+import keras
+from keras import ops
+from keras import layers
+import tensorflow as tf
"""
## Downloading the MosMedData: Chest CT Scans with COVID-19 Related Findings
@@ -177,19 +181,19 @@ def process_scan(path):
# Read and process the scans.
# Each scan is resized across height, width, and depth and rescaled.
-abnormal_scans = np.array([process_scan(path) for path in abnormal_scan_paths])
-normal_scans = np.array([process_scan(path) for path in normal_scan_paths])
+abnormal_scans = ops.array([process_scan(path) for path in abnormal_scan_paths])
+normal_scans = ops.array([process_scan(path) for path in normal_scan_paths])
# For the CT scans having presence of viral pneumonia
# assign 1, for the normal ones assign 0.
-abnormal_labels = np.array([1 for _ in range(len(abnormal_scans))])
-normal_labels = np.array([0 for _ in range(len(normal_scans))])
+abnormal_labels = ops.array([1 for _ in range(len(abnormal_scans))])
+normal_labels = ops.array([0 for _ in range(len(normal_scans))])
# Split data in the ratio 70-30 for training and validation.
-x_train = np.concatenate((abnormal_scans[:70], normal_scans[:70]), axis=0)
-y_train = np.concatenate((abnormal_labels[:70], normal_labels[:70]), axis=0)
-x_val = np.concatenate((abnormal_scans[70:], normal_scans[70:]), axis=0)
-y_val = np.concatenate((abnormal_labels[70:], normal_labels[70:]), axis=0)
+x_train = ops.concatenate((abnormal_scans[:70], normal_scans[:70]), axis=0)
+y_train = ops.concatenate((abnormal_labels[:70], normal_labels[:70]), axis=0)
+x_val = ops.concatenate((abnormal_scans[70:], normal_scans[70:]), axis=0)
+y_val = ops.concatenate((abnormal_labels[70:], normal_labels[70:]), axis=0)
print(
"Number of samples in train and validation are %d and %d."
% (x_train.shape[0], x_val.shape[0])
@@ -210,37 +214,28 @@ def process_scan(path):
from scipy import ndimage
+random_rotation = layers.RandomRotation(factor=(-0.06, 0.06))
+
-@tf.function
def rotate(volume):
"""Rotate the volume by a few degrees"""
-
- def scipy_rotate(volume):
- # define some rotation angles
- angles = [-20, -10, -5, 5, 10, 20]
- # pick angles at random
- angle = random.choice(angles)
- # rotate volume
- volume = ndimage.rotate(volume, angle, reshape=False)
- volume[volume < 0] = 0
- volume[volume > 1] = 1
- return volume
-
- augmented_volume = tf.numpy_function(scipy_rotate, [volume], tf.float32)
- return augmented_volume
+ # rotate volume
+ volume = random_rotation(volume)
+ volume = ops.clip(volume, 0, 1)
+ return volume
def train_preprocessing(volume, label):
"""Process training data by rotating and adding a channel."""
# Rotate volume
volume = rotate(volume)
- volume = tf.expand_dims(volume, axis=3)
+ volume = ops.expand_dims(volume, axis=3)
return volume, label
def validation_preprocessing(volume, label):
"""Process validation data by only adding a channel."""
- volume = tf.expand_dims(volume, axis=3)
+ volume = ops.expand_dims(volume, axis=3)
return volume, label
@@ -278,10 +273,10 @@ def validation_preprocessing(volume, label):
data = train_dataset.take(1)
images, labels = list(data)[0]
-images = images.numpy()
+images = ops.convert_to_numpy(images)
image = images[0]
print("Dimension of the CT scan is:", image.shape)
-plt.imshow(np.squeeze(image[:, :, 30]), cmap="gray")
+plt.imshow(ops.squeeze(image[:, :, 30]), cmap="gray")
"""
@@ -291,9 +286,9 @@ def validation_preprocessing(volume, label):
def plot_slices(num_rows, num_columns, width, height, data):
"""Plot a montage of 20 CT slices"""
- data = np.rot90(np.array(data))
- data = np.transpose(data)
- data = np.reshape(data, (num_rows, num_columns, width, height))
+ data = ndimage.rotate(ops.array(data), 90, reshape=False)
+ data = ops.transpose(data)
+ data = ops.reshape(data, (num_rows, num_columns, width, height))
rows_data, columns_data = data.shape[0], data.shape[1]
heights = [slc[0].shape[0] for slc in data]
widths = [slc.shape[1] for slc in data[0]]
@@ -379,7 +374,7 @@ def get_model(width=128, height=128, depth=64):
# Define callbacks.
checkpoint_cb = keras.callbacks.ModelCheckpoint(
- "3d_image_classification.h5", save_best_only=True
+ "3d_image_classification.keras", save_best_only=True
)
early_stopping_cb = keras.callbacks.EarlyStopping(monitor="val_acc", patience=15)
@@ -426,8 +421,8 @@ def get_model(width=128, height=128, depth=64):
"""
# Load best weights.
-model.load_weights("3d_image_classification.h5")
-prediction = model.predict(np.expand_dims(x_val[0], axis=0))[0]
+model.load_weights("3d_image_classification.keras")
+prediction = model.predict(ops.expand_dims(x_val[0], axis=0))[0]
scores = [1 - prediction[0], prediction[0]]
class_names = ["normal", "abnormal"]
diff --git a/examples/vision/ipynb/3D_image_classification.ipynb b/examples/vision/ipynb/3D_image_classification.ipynb
index a2ecf82785..3c2f2bbe4d 100644
--- a/examples/vision/ipynb/3D_image_classification.ipynb
+++ b/examples/vision/ipynb/3D_image_classification.ipynb
@@ -10,7 +10,7 @@
"\n",
"**Author:** [Hasib Zunair](https://twitter.com/hasibzunair)
\n",
"**Date created:** 2020/09/23
\n",
- "**Last modified:** 2020/09/23
\n",
+ "**Last modified:** 2024/01/11
\n",
"**Description:** Train a 3D convolutional neural network to predict presence of pneumonia."
]
},
@@ -47,19 +47,21 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
"outputs": [],
"source": [
"import os\n",
+ "os.environ[\"KERAS_BACKEND\"] = \"tensorflow\"\n",
"import zipfile\n",
"import numpy as np\n",
- "import tensorflow as tf\n",
"\n",
- "from tensorflow import keras\n",
- "from tensorflow.keras import layers"
+ "import keras\n",
+ "from keras import ops\n",
+ "from keras import layers\n",
+ "import tensorflow as tf"
]
},
{
@@ -81,7 +83,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -135,7 +137,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -199,8 +201,7 @@
" volume = normalize(volume)\n",
" # Resize width, height and depth\n",
" volume = resize_volume(volume)\n",
- " return volume\n",
- ""
+ " return volume\n"
]
},
{
@@ -214,7 +215,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -234,8 +235,7 @@
"]\n",
"\n",
"print(\"CT scans with normal lung tissue: \" + str(len(normal_scan_paths)))\n",
- "print(\"CT scans with abnormal lung tissue: \" + str(len(abnormal_scan_paths)))\n",
- ""
+ "print(\"CT scans with abnormal lung tissue: \" + str(len(abnormal_scan_paths)))\n"
]
},
{
@@ -252,7 +252,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -260,19 +260,19 @@
"source": [
"# Read and process the scans.\n",
"# Each scan is resized across height, width, and depth and rescaled.\n",
- "abnormal_scans = np.array([process_scan(path) for path in abnormal_scan_paths])\n",
- "normal_scans = np.array([process_scan(path) for path in normal_scan_paths])\n",
+ "abnormal_scans = ops.array([process_scan(path) for path in abnormal_scan_paths])\n",
+ "normal_scans = ops.array([process_scan(path) for path in normal_scan_paths])\n",
"\n",
"# For the CT scans having presence of viral pneumonia\n",
"# assign 1, for the normal ones assign 0.\n",
- "abnormal_labels = np.array([1 for _ in range(len(abnormal_scans))])\n",
- "normal_labels = np.array([0 for _ in range(len(normal_scans))])\n",
+ "abnormal_labels = ops.array([1 for _ in range(len(abnormal_scans))])\n",
+ "normal_labels = ops.array([0 for _ in range(len(normal_scans))])\n",
"\n",
"# Split data in the ratio 70-30 for training and validation.\n",
- "x_train = np.concatenate((abnormal_scans[:70], normal_scans[:70]), axis=0)\n",
- "y_train = np.concatenate((abnormal_labels[:70], normal_labels[:70]), axis=0)\n",
- "x_val = np.concatenate((abnormal_scans[70:], normal_scans[70:]), axis=0)\n",
- "y_val = np.concatenate((abnormal_labels[70:], normal_labels[70:]), axis=0)\n",
+ "x_train = ops.concatenate((abnormal_scans[:70], normal_scans[:70]), axis=0)\n",
+ "y_train = ops.concatenate((abnormal_labels[:70], normal_labels[:70]), axis=0)\n",
+ "x_val = ops.concatenate((abnormal_scans[70:], normal_scans[70:]), axis=0)\n",
+ "y_val = ops.concatenate((abnormal_labels[70:], normal_labels[70:]), axis=0)\n",
"print(\n",
" \"Number of samples in train and validation are %d and %d.\"\n",
" % (x_train.shape[0], x_val.shape[0])\n",
@@ -297,7 +297,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -307,39 +307,29 @@
"\n",
"from scipy import ndimage\n",
"\n",
+ "random_rotation = layers.RandomRotation(factor=(-0.06, 0.06))\n",
+ "\n",
"\n",
- "@tf.function\n",
"def rotate(volume):\n",
" \"\"\"Rotate the volume by a few degrees\"\"\"\n",
- "\n",
- " def scipy_rotate(volume):\n",
- " # define some rotation angles\n",
- " angles = [-20, -10, -5, 5, 10, 20]\n",
- " # pick angles at random\n",
- " angle = random.choice(angles)\n",
- " # rotate volume\n",
- " volume = ndimage.rotate(volume, angle, reshape=False)\n",
- " volume[volume < 0] = 0\n",
- " volume[volume > 1] = 1\n",
- " return volume\n",
- "\n",
- " augmented_volume = tf.numpy_function(scipy_rotate, [volume], tf.float32)\n",
- " return augmented_volume\n",
+ " # rotate volume\n",
+ " volume = random_rotation(volume)\n",
+ " volume = ops.clip(volume, 0, 1)\n",
+ " return volume\n",
"\n",
"\n",
"def train_preprocessing(volume, label):\n",
" \"\"\"Process training data by rotating and adding a channel.\"\"\"\n",
" # Rotate volume\n",
" volume = rotate(volume)\n",
- " volume = tf.expand_dims(volume, axis=3)\n",
+ " volume = ops.expand_dims(volume, axis=3)\n",
" return volume, label\n",
"\n",
"\n",
"def validation_preprocessing(volume, label):\n",
" \"\"\"Process validation data by only adding a channel.\"\"\"\n",
- " volume = tf.expand_dims(volume, axis=3)\n",
- " return volume, label\n",
- ""
+ " volume = ops.expand_dims(volume, axis=3)\n",
+ " return volume, label\n"
]
},
{
@@ -355,7 +345,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -393,7 +383,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -403,11 +393,10 @@
"\n",
"data = train_dataset.take(1)\n",
"images, labels = list(data)[0]\n",
- "images = images.numpy()\n",
+ "images = ops.convert_to_numpy(images)\n",
"image = images[0]\n",
"print(\"Dimension of the CT scan is:\", image.shape)\n",
- "plt.imshow(np.squeeze(image[:, :, 30]), cmap=\"gray\")\n",
- ""
+ "plt.imshow(ops.squeeze(image[:, :, 30]), cmap=\"gray\")\n"
]
},
{
@@ -421,7 +410,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -430,9 +419,9 @@
"\n",
"def plot_slices(num_rows, num_columns, width, height, data):\n",
" \"\"\"Plot a montage of 20 CT slices\"\"\"\n",
- " data = np.rot90(np.array(data))\n",
- " data = np.transpose(data)\n",
- " data = np.reshape(data, (num_rows, num_columns, width, height))\n",
+ " data = ndimage.rotate(ops.array(data), 90, reshape=False)\n",
+ " data = ops.transpose(data)\n",
+ " data = ops.reshape(data, (num_rows, num_columns, width, height))\n",
" rows_data, columns_data = data.shape[0], data.shape[1]\n",
" heights = [slc[0].shape[0] for slc in data]\n",
" widths = [slc.shape[1] for slc in data[0]]\n",
@@ -472,7 +461,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -527,7 +516,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -546,7 +535,7 @@
"\n",
"# Define callbacks.\n",
"checkpoint_cb = keras.callbacks.ModelCheckpoint(\n",
- " \"3d_image_classification.h5\", save_best_only=True\n",
+ " \"3d_image_classification.keras\", save_best_only=True\n",
")\n",
"early_stopping_cb = keras.callbacks.EarlyStopping(monitor=\"val_acc\", patience=15)\n",
"\n",
@@ -590,7 +579,7 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
@@ -619,15 +608,15 @@
},
{
"cell_type": "code",
- "execution_count": 0,
+ "execution_count": null,
"metadata": {
"colab_type": "code"
},
"outputs": [],
"source": [
"# Load best weights.\n",
- "model.load_weights(\"3d_image_classification.h5\")\n",
- "prediction = model.predict(np.expand_dims(x_val[0], axis=0))[0]\n",
+ "model.load_weights(\"3d_image_classification.keras\")\n",
+ "prediction = model.predict(ops.expand_dims(x_val[0], axis=0))[0]\n",
"scores = [1 - prediction[0], prediction[0]]\n",
"\n",
"class_names = [\"normal\", \"abnormal\"]\n",
@@ -668,4 +657,4 @@
},
"nbformat": 4,
"nbformat_minor": 0
-}
\ No newline at end of file
+}
diff --git a/examples/vision/md/3D_image_classification.md b/examples/vision/md/3D_image_classification.md
index c2cc2a7d4d..d8ff99f65f 100644
--- a/examples/vision/md/3D_image_classification.md
+++ b/examples/vision/md/3D_image_classification.md
@@ -2,7 +2,7 @@
**Author:** [Hasib Zunair](https://twitter.com/hasibzunair)
**Date created:** 2020/09/23
-**Last modified:** 2020/09/23
+**Last modified:** 2024/01/11
**Description:** Train a 3D convolutional neural network to predict presence of pneumonia.
@@ -33,12 +33,14 @@ equivalent: it takes as input a 3D volume or a sequence of 2D frames (e.g. slice
```python
import os
+os.environ["KERAS_BACKEND"] = "tensorflow"
import zipfile
import numpy as np
-import tensorflow as tf
-from tensorflow import keras
-from tensorflow.keras import layers
+import keras
+from keras import ops
+from keras import layers
+import tensorflow as tf
```
---
@@ -206,19 +208,19 @@ Lastly, split the dataset into train and validation subsets.
```python
# Read and process the scans.
# Each scan is resized across height, width, and depth and rescaled.
-abnormal_scans = np.array([process_scan(path) for path in abnormal_scan_paths])
-normal_scans = np.array([process_scan(path) for path in normal_scan_paths])
+abnormal_scans = ops.array([process_scan(path) for path in abnormal_scan_paths])
+normal_scans = ops.array([process_scan(path) for path in normal_scan_paths])
# For the CT scans having presence of viral pneumonia
# assign 1, for the normal ones assign 0.
-abnormal_labels = np.array([1 for _ in range(len(abnormal_scans))])
-normal_labels = np.array([0 for _ in range(len(normal_scans))])
+abnormal_labels = ops.array([1 for _ in range(len(abnormal_scans))])
+normal_labels = ops.array([0 for _ in range(len(normal_scans))])
# Split data in the ratio 70-30 for training and validation.
-x_train = np.concatenate((abnormal_scans[:70], normal_scans[:70]), axis=0)
-y_train = np.concatenate((abnormal_labels[:70], normal_labels[:70]), axis=0)
-x_val = np.concatenate((abnormal_scans[70:], normal_scans[70:]), axis=0)
-y_val = np.concatenate((abnormal_labels[70:], normal_labels[70:]), axis=0)
+x_train = ops.concatenate((abnormal_scans[:70], normal_scans[:70]), axis=0)
+y_train = ops.concatenate((abnormal_labels[:70], normal_labels[:70]), axis=0)
+x_val = ops.concatenate((abnormal_scans[70:], normal_scans[70:]), axis=0)
+y_val = ops.concatenate((abnormal_labels[70:], normal_labels[70:]), axis=0)
print(
"Number of samples in train and validation are %d and %d."
% (x_train.shape[0], x_val.shape[0])
@@ -247,37 +249,28 @@ import random
from scipy import ndimage
+random_rotation = layers.RandomRotation(factor=(-0.06, 0.06))
+
-@tf.function
def rotate(volume):
"""Rotate the volume by a few degrees"""
-
- def scipy_rotate(volume):
- # define some rotation angles
- angles = [-20, -10, -5, 5, 10, 20]
- # pick angles at random
- angle = random.choice(angles)
- # rotate volume
- volume = ndimage.rotate(volume, angle, reshape=False)
- volume[volume < 0] = 0
- volume[volume > 1] = 1
- return volume
-
- augmented_volume = tf.numpy_function(scipy_rotate, [volume], tf.float32)
- return augmented_volume
+ # rotate volume
+ volume = random_rotation(volume)
+ volume = ops.clip(volume, 0, 1)
+ return volume
def train_preprocessing(volume, label):
"""Process training data by rotating and adding a channel."""
# Rotate volume
volume = rotate(volume)
- volume = tf.expand_dims(volume, axis=3)
+ volume = ops.expand_dims(volume, axis=3)
return volume, label
def validation_preprocessing(volume, label):
"""Process validation data by only adding a channel."""
- volume = tf.expand_dims(volume, axis=3)
+ volume = ops.expand_dims(volume, axis=3)
return volume, label
```
@@ -317,10 +310,10 @@ import matplotlib.pyplot as plt
data = train_dataset.take(1)
images, labels = list(data)[0]
-images = images.numpy()
+images = ops.convert_to_numpy(images)
image = images[0]
print("Dimension of the CT scan is:", image.shape)
-plt.imshow(np.squeeze(image[:, :, 30]), cmap="gray")
+plt.imshow(ops.squeeze(image[:, :, 30]), cmap="gray")
```
@@ -342,9 +335,9 @@ Since a CT scan has many slices, let's visualize a montage of the slices.
def plot_slices(num_rows, num_columns, width, height, data):
"""Plot a montage of 20 CT slices"""
- data = np.rot90(np.array(data))
- data = np.transpose(data)
- data = np.reshape(data, (num_rows, num_columns, width, height))
+ data = ndimage.rotate(ops.array(data), 90, reshape=False)
+ data = ops.transpose(data)
+ data = ops.reshape(data, (num_rows, num_columns, width, height))
rows_data, columns_data = data.shape[0], data.shape[1]
heights = [slc[0].shape[0] for slc in data]
widths = [slc.shape[1] for slc in data[0]]
@@ -485,7 +478,7 @@ model.compile(
# Define callbacks.
checkpoint_cb = keras.callbacks.ModelCheckpoint(
- "3d_image_classification.h5", save_best_only=True
+ "3d_image_classification.keras", save_best_only=True
)
early_stopping_cb = keras.callbacks.EarlyStopping(monitor="val_acc", patience=15)
@@ -607,8 +600,8 @@ for i, metric in enumerate(["acc", "loss"]):
```python
# Load best weights.
-model.load_weights("3d_image_classification.h5")
-prediction = model.predict(np.expand_dims(x_val[0], axis=0))[0]
+model.load_weights("3d_image_classification.keras")
+prediction = model.predict(ops.expand_dims(x_val[0], axis=0))[0]
scores = [1 - prediction[0], prediction[0]]
class_names = ["normal", "abnormal"]