Tensorflow

Install

Docker

https://www.tensorflow.org/install

https://www.tensorflow.org/install/gpu

$ docker pull tensorflow/tensorflow:latest-gpu-jupyter # still need NVIDIA drivers

$ docker run -it -p 8888:8888 tensorflow/tensorflow:latest-gpu-jupyter

Conda (CPU)

name: tf

channels:

- conda-forge

- nodefaults

dependencies:

- python=3.9

- graphviz

- h5py

- ipykernel

- ipywidgets

- matplotlib

- pydot

- pyyaml

- tqdm

- pip

- pip:

- tensorflow

- tensorflow-datasets

- git+https://github.com/tensorflow/examples.git

Test CPU install

import tensorflow as tf


tf.config.list_physical_devices()


mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train, x_test = x_train / 255.0, x_test / 255.0


model = tf.keras.models.Sequential(

[

tf.keras.layers.Flatten(input_shape=(28, 28)),

tf.keras.layers.Dense(128, activation="relu"),

tf.keras.layers.Dropout(0.2),

tf.keras.layers.Dense(10),

]

)


loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

model.compile(optimizer="adam", loss=loss, metrics=["accuracy"])

model.fit(x_train, y_train, epochs=5)

loss, acc = model.evaluate(x_test, y_test, verbose=2)

Conda (GPU)

name: tf-gpu

channels:

- conda-forge

- nodefaults

dependencies:

- python=3.9

- tensorflow-gpu

Test GPU Install

import tensorflow as tf


print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))

tf.debugging.set_log_device_placement(True)

Imports

import tensorflow as tf

from tensorflow import keras

from tensorflow.keras import models

from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense

from tensorflow.keras import utils

from tensorflow.keras import optimizers

from tensorflow.keras.preprocessing.image import ImageDataGenerator

import tensorflow_probability as tfp

# Set random seed for reproducibility

tf.random.set_seed(42)

https://stackoverflow.com/a/66343730/6046019

IO, Math and initialization

https://github.com/mrdbourke/tensorflow-deep-learning/blob/main/00_tensorflow_fundamentals.ipynb

a = tf.constant(7)

a = tf.constant(numpy_arr)

a = tf.Variable(tf.cast([1, 2, 3], dtype=tf.float32)

tf.random.uniform(shape=[50])

a.ndim


tf.reduce_min(([1, 2, 3]) # np.min



tf.random.Generator.from_seed(42).normal(shape=(3, 2))

Probability

import tensorflow_probability as tfp

tfp.stats.variance(E)

math

tf.math.reduce_std

Multi-Classification problem

Data Preparation

Put numpy array into Tensorflow object

# Set data types for float features

x_train = x_train.astype('float32')

x_test = x_test.astype('float32')


# Set data types for categorical labels

y_train = utils.to_categorical(y_train)

y_test = utils.to_categorical(y_test)

Setup model

model = Sequential()

model.add(Dense(10, input_dim=len(features), activation='relu'))

model.add(Dense(10, input_dim=10, activation='relu'))

model.add(Dense(len(classes), input_dim=10, activation='softmax'))


print(model.summary())


#hyper-parameters for optimizer

learning_rate = 0.001

opt = optimizers.Adam(lr=learning_rate)


model.compile(loss='categorical_crossentropy',

optimizer=opt,

metrics=['accuracy'])

Run

# Train the model over 50 epochs using 10-observation batches and using the test holdout dataset for validation

num_epochs = 50

history = model.fit(x_train, y_train, epochs=num_epochs, batch_size=10, validation_data=(x_test, y_test))

Plot

epoch_nums = range(1,num_epochs+1)

training_loss = history.history["loss"]

validation_loss = history.history["val_loss"]

plt.plot(epoch_nums, training_loss)

plt.plot(epoch_nums, validation_loss)

plt.xlabel('epoch')

plt.ylabel('loss')

plt.legend(['training', 'validation'], loc='upper right')

plt.show()

See confusion matrix

import numpy as np

from sklearn.metrics import confusion_matrix

import matplotlib.pyplot as plt

%matplotlib inline


class_probabilities = model.predict(x_test)

predictions = np.argmax(class_probabilities, axis=1)

true_labels = np.argmax(y_test, axis=1)


# Plot the confusion matrix

cm = confusion_matrix(true_labels, predictions)

plt.imshow(cm, interpolation="nearest", cmap=plt.cm.Blues)

plt.colorbar()

tick_marks = np.arange(len(penguin_classes))

plt.xticks(tick_marks, classes, rotation=85)

plt.yticks(tick_marks, classes)

plt.xlabel("Actual Class")

plt.ylabel("Predicted Class")

plt.show()

Save model

modelFileName = 'models/penguin-classifier.h5'

model.save(modelFileName)

del model

Predict

model = models.load_model(modelFileName) # loads the saved model


x_new = np.array([[50.4, 15.3, 20, 50]])

print ('New sample: {}'.format(x_new))


class_probabilities = model.predict(x_new)

predictions = np.argmax(class_probabilities, axis=1)


print(classes[predictions[0]])

CNN

Load the data

data_folder = 'path'

img_size = (128, 128)

batch_size = 30


print("Getting Data...")

datagen = ImageDataGenerator(rescale=1./255, # normalize pixel values

validation_split=0.3) # hold back 30% of the images for validation


print("Preparing training dataset...")

train_generator = datagen.flow_from_directory(

data_folder,

target_size=img_size,

batch_size=batch_size,

class_mode='categorical',

subset='training') # set as training data


print("Preparing validation dataset...")

validation_generator = datagen.flow_from_directory(

data_folder,

target_size=img_size,

batch_size=batch_size,

class_mode='categorical',

subset='validation') # set as validation data


classnames = list(train_generator.class_indices.keys())

print("class names: ", classnames)

Setup model

# Define the model as a sequence of layers

model = Sequential()


# The input layer accepts an image and applies a convolution

# that uses 32 filters, a kernal size of 6x6 and a rectified linear unit activation function

model.add(Conv2D(32, (6, 6), input_shape=train_generator.image_shape, activation='relu'))


# Next we'll add a max pooling layer with a 2x2 patch

model.add(MaxPooling2D(pool_size=(2, 2)))


# We can add as many layers as we think necessary - here we'll add another convolution, max pooling, and dropout layer

model.add(Conv2D(32, (6, 6), activation='relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))


# And another set

model.add(Conv2D(32, (6, 6), activation='relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))


# A dropout layer randomly drops some nodes to reduce inter-dependencies (which can cause over-fitting)

model.add(Dropout(0.2))


# Now we'll flatten the feature maps and generate an output layer with a predicted probability for each class

model.add(Flatten())

model.add(Dense(train_generator.num_classes, activation='sigmoid'))


# With the layers defined, we can now compile the model for categorical (multi-class) classification

model.compile(loss='categorical_crossentropy',

optimizer='adam',

metrics=['accuracy'])


print(model.summary())

Train model

# Train the model over 5 epochs using 30-image batches and using the validation holdout dataset for validation

num_epochs = 5

history = model.fit(

train_generator,

steps_per_epoch = train_generator.samples // batch_size,

validation_data = validation_generator,

validation_steps = validation_generator.samples // batch_size,

epochs = num_epochs)

Predict

# Function to create a random image (of a square, circle, or triangle)

def create_image (size, shape):

from random import randint

import numpy as np

from PIL import Image, ImageDraw

xy1 = randint(10,40)

xy2 = randint(60,100)

col = (randint(0,200), randint(0,200), randint(0,200))


img = Image.new("RGB", size, (255, 255, 255))

draw = ImageDraw.Draw(img)

if shape == 'circle':

draw.ellipse([(xy1, xy1), (xy2, xy2)], fill=col)

elif shape == 'triangle':

draw.polygon([(xy1, xy1), (xy2, xy2), (xy2, xy1)], fill=col)

else: # square

draw.rectangle([(xy1, xy1), (xy2, xy2)], fill=col)

del draw

return np.array(img)


# Save the trained model

modelFileName = 'models/classifier.h5'

model.save(modelFileName)

del model # deletes the existing model variable


# Create a random test image

classnames = os.listdir(os.path.join('data', 'shapes'))

classnames.sort()

img = create_image ((128,128), classnames[randint(0, len(classnames)-1)])

plt.axis('off')

plt.imshow(img)


# The model expects a batch of images as input, so we'll create an array of 1 image

imgfeatures = img.reshape(1, img.shape[0], img.shape[1], img.shape[2])


# We need to format the input to match the training data

# The generator loaded the values as floating point numbers

# and normalized the pixel values, so...

imgfeatures = imgfeatures.astype('float32')

imgfeatures /= 255


# Use the classifier to predict the class

model = models.load_model(modelFileName) # loads the saved model

class_probabilities = model.predict(imgfeatures)

# Find the class predictions with the highest predicted probability

class_idx = np.argmax(class_probabilities, axis=1)

print (classnames[int(class_idx[0])])

Image segmentation using U-net

https://www.tensorflow.org/tutorials/images/segmentation

Data generation from xarray objects

class DataGenerator(keras.utils.Sequence):

def __init__(

self,

ds,

var_list=["t2m_norm"],

target="target",

batch_size=100,

shuffle=False,

mean=False,

std=False,

class_weights=None,

):

"""

Template from https://stanford.edu/~shervine/blog/keras-how-to-generate-data-on-the-fly

Args:

ds: Dataset containing all variables

var_lst: List of the form ['var1', 'var2']

target: Name of target value

batch_size: Batch size

shuffle: bool. If True, data is shuffled.

mean: If None, compute mean from data.

std: If None, compute standard deviation from data.

"""

self.ds = ds

self.var_list = var_list

self.batch_size = batch_size

self.shuffle = shuffle

self.class_weights = class_weights


self.data = (

ds[var_list]

.to_array(dim="feature")

.transpose("time", "latitude", "longitude", "feature")

)


self.n_samples = self.data.shape[0]


self.target = ds[target].transpose("time", "latitude", "longitude")


self.on_epoch_end()


def __len__(self):

"Denotes the number of batches per epoch"

return int(np.ceil(self.n_samples / self.batch_size))


def __getitem__(self, i):

"Generate one batch of data"

idxs = self.idxs[i * self.batch_size : (i + 1) * self.batch_size]

X = self.data.isel(time=idxs).values

y = self.target.isel(time=idxs).values

if self.class_weights is not None:

sample_weights = tf.gather(self.class_weights, indices=tf.cast(y, tf.int32))

return X, y, sample_weights

else:

return X, y


def on_epoch_end(self):

"Updates indexes after each epoch"

self.idxs = np.arange(self.n_samples)

if self.shuffle == True:

np.random.shuffle(self.idxs)

model

def get_model(height, width, num_features, num_classes):

inputs = keras.Input(shape=(height, width, num_features))


### [First half of the network: downsampling inputs] ###


# Entry block

x = layers.Conv2D(32, 3, strides=2, padding="same")(inputs)

x = layers.BatchNormalization()(x)

x = layers.Activation("relu")(x)


previous_block_activation = x # Set aside residual


# Scale up blocks

# Blocks 1, 2, 3 are identical apart from the feature depth.

for filters in [64, 128, 256]:

x = layers.Activation("relu")(x)

x = layers.SeparableConv2D(filters, 3, padding="same")(x)

x = layers.BatchNormalization()(x)


x = layers.Activation("relu")(x)

x = layers.SeparableConv2D(filters, 3, padding="same")(x)

x = layers.BatchNormalization()(x)


x = layers.MaxPooling2D(3, strides=2, padding="same")(x)


# Project residual

residual = layers.Conv2D(filters, 1, strides=2, padding="same")(

previous_block_activation

)

x = layers.add([x, residual]) # Add back residual

previous_block_activation = x # Set aside next residual


### [Second half of the network: upsampling inputs] ###

for filters in [256, 128, 64, 32]:

x = layers.Activation("relu")(x)

x = layers.Conv2DTranspose(filters, 3, padding="same")(x)

x = layers.BatchNormalization()(x)


x = layers.Activation("relu")(x)

x = layers.Conv2DTranspose(filters, 3, padding="same")(x)

x = layers.BatchNormalization()(x)


x = layers.UpSampling2D(2)(x)


# Project residual

residual = layers.UpSampling2D(2)(previous_block_activation)

residual = layers.Conv2D(filters, 1, padding="same")(residual)

x = layers.add([x, residual]) # Add back residual

previous_block_activation = x # Set aside next residual


# Add a per-pixel classification layer

x = layers.Conv2D(num_classes, 3, activation="softmax", padding="same")(x)

# Crop to match input sizes (if shapes mis-match)

outputs = layers.Cropping2D(cropping=((4, 4), (2, 2)))(x)


# Define the model

model = keras.Model(inputs, outputs)

return model


model = get_model(height, width, num_features, num_classes)

model.compile(

optimizer="rmsprop",

loss="sparse_categorical_crossentropy",

metrics=["accuracy"],

)

model.summary()

Model training and plotting

epochs = 250

model_history = model.fit(

dg_train, epochs=epochs, validation_data=dg_valid, callbacks=[DisplayCallback()]

)

Model evaluation

loss = model_history.history["loss"]

val_loss = model_history.history["val_loss"]


plt.figure()

plt.plot(model_history.epoch, loss, "r", label="Training loss")

plt.plot(model_history.epoch, val_loss, "bo", label="Validation loss")

plt.title("Training and Validation Loss")

plt.xlabel("Epoch")

plt.ylabel("Loss Value")

plt.legend()

plt.show()


loss = model_history.history["accuracy"]

val_loss = model_history.history["val_accuracy"]


plt.figure()

plt.plot(model_history.epoch, loss, "r", label="Training accuracy")

plt.plot(model_history.epoch, val_loss, "bo", label="Validation accuracy")

plt.title("Training and Validation accuracy")

plt.xlabel("Epoch")

plt.ylabel("Accuracy")

plt.legend()

plt.show()


plot_y_and_y_pred(y, prob_to_class(model.predict(dg_train)), epoch)

Metrics

m = tf.keras.metrics.IoU(num_classes=5, target_class_ids=[0, 1, 2, 3, 4])

m.update_state(preds_multiclass_yp, true_y)

m.result().numpy()

Callbacks

Plotting and saving images

from IPython.display import clear_output


def plot_y_and_y_pred(y, y_pred, epoch, i=0, save_plots=False, save_every_epoch=10):

da = xr.concat([xr.DataArray(y[i, :, :]), xr.DataArray(y_pred[i, :, :])], "y")

da.plot(

cmap=cmap,

norm=norm,

add_colorbar=False,

col="y",

size=6,

)

if save_plots:

if epoch % save_every_epoch == 0:

plt.savefig("plots/epoch_" + str(epoch).zfill(4))

plt.pause(0.05)


def show_predictions(epoch):

plot_y_and_y_pred(y, prob_to_class(model.predict(X)), epoch)


class DisplayCallback(tf.keras.callbacks.Callback):

def on_epoch_end(self, epoch, logs=None):

clear_output(wait=True)

show_predictions(epoch)

print("\nSample Prediction after epoch {}\n".format(epoch + 1))


callbacks=[DisplayCallback()]

Model saving

import os

from datetime import datetime


run = datetime.now().isoformat()

checkpoint_path = "training_" + run_cp.ckpt"

checkpoint_dir = os.path.dirname(checkpoint_path)

checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(

filepath=checkpoint_path,

verbose=1,

save_weights_only=True,

save_freq=5 * batch_size,

)

checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(

filepath="my_model.h5",

save_best_only=True,

)


callbacks=[checkpoint_callback]


latest = tf.train.latest_checkpoint(checkpoint_dir)