The Keras functional API

目录

<!DOCTYPE html>

Coding_Tutorial
In [3]:
import tensorflow as tf
print(tf.__version__)
2.0.0

The Keras functional API


Multiple inputs and outputs

In [2]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

Load the acute inflammations dataset

The acute inflammations was created by a medical expert as a data set to test the expert system, which will perform the presumptive diagnosis of two diseases of the urinary system. You can find out more about the dataset here.

Attribute information:

Inputs:

  • Temperature of patient : 35C-42C
  • Occurrence of nausea : yes/no
  • Lumbar pain : yes/no
  • Urine pushing (continuous need for urination) : yes/no
  • Micturition pains : yes/no
  • Burning of urethra, itch, swelling of urethra outlet : yes/no

Outputs:

  • decision 1: Inflammation of urinary bladder : yes/no
  • decision 2: Nephritis of renal pelvis origin : yes/no

Load the data

In [3]:
# Load the dataset

from sklearn.model_selection import train_test_split

pd_dat = pd.read_csv('data/diagnosis.csv')
dataset = pd_dat.values
In [1]:
dataset[0]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-55a9d71005c6> in <module>
----> 1 dataset[0]

NameError: name 'dataset' is not defined
In [7]:
# Build train and test data splits

X_train, X_test, Y_train, Y_test = train_test_split(dataset[:,:6], dataset[:,6:], test_size=0.33)
In [8]:
# Assign training and testing inputs/outputs

temp_train, nocc_train, lumbp_train, up_train, mict_train, bis_train = np.transpose(X_train)
temp_test, nocc_test, lumbp_test, up_test, mict_test, bis_test = np.transpose(X_test)

inflam_train, nephr_train = Y_train[:, 0], Y_train[:, 1]
inflam_test, nephr_test = Y_test[:, 0], Y_test[:, 1]

Build the model

In [19]:
# Build the input layers
from tensorflow.keras import Input, layers
input_shape = (1, )
temperature = Input(shape=input_shape, name="temp")
nausea_occurence = Input(shape=input_shape, name="nocc")
lumbar_pain = Input(shape=input_shape, name="lumb")
urine_pushing = Input(shape=input_shape, name="urin")
micturition_pains = Input(shape=input_shape, name="mict")
bis = Input(shape=input_shape, name="bis")
In [20]:
# Create a list of all the inputs

list_inputs = [temperature, nausea_occurence, lumbar_pain, urine_pushing, 
               micturition_pains, bis]
In [28]:
# Merge all input features into a single large vector
input_merge = layers.concatenate(list_inputs)
In [29]:
# Use a logistic regression classifier for disease prediction
inflammation_pred = layers.Dense(units=1, activation="sigmoid", name="inflam")(input_merge)
nephritis_pred = layers.Dense(units=1, activation="sigmoid", name="neph")(input_merge)
In [30]:
# Create a list of all the outputs

list_outputs = [inflammation_pred, nephritis_pred]
In [32]:
# Create the model object

model = tf.keras.Model(inputs=list_inputs, outputs=list_outputs)

Plot the model

In [35]:
# Display the multiple input/output model
tf.keras.utils.plot_model(model, "mulit_input_output_model.png", show_shapes=True)
Out[35]:

Compile the model

In [38]:
# Compile the model

model.compile(optimizer=tf.keras.optimizers.RMSprop(1e-3),
             loss={"inflam":"binary_crossentropy",
                  "neph": "binary_crossentropy"},
             metrics = [["acc"], ["acc"]],
             loss_weights=[1, 0.2])

Fit the model

In [41]:
# Define training inputs and outputs

inputs_train = {'temp': temp_train, 'nocc': nocc_train, 'lumb': lumbp_train,
                'urin': up_train, 'mict': mict_train, 'bis': bis_train}

outputs_train = {'inflam': inflam_train, 'neph': nephr_train}
In [54]:
# Train the model

history = model.fit(inputs_train, outputs_train,
         epochs=1000,
         batch_size=128,

         verbose=False)

Plot the learning curves

In [55]:
history.history.keys()
Out[55]:
dict_keys(['loss', 'inflam_loss', 'neph_loss', 'inflam_acc', 'neph_acc'])
In [56]:
# Plot the training accuracy

acc_keys = [k for k in history.history.keys() if k in ('inflam_acc', 'neph_acc')] 
loss_keys = [k for k in history.history.keys() if not k in acc_keys]

for k, v in history.history.items():
    if k in acc_keys:
        plt.figure(1)
        plt.plot(v)
    else:
        plt.figure(2)
        plt.plot(v)

plt.figure(1)
plt.title('Accuracy vs. epochs')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(acc_keys, loc='upper right')

plt.figure(2)
plt.title('Loss vs. epochs')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(loss_keys, loc='upper right')

plt.show()
In [57]:
# Evaluate the model
model.evaluate([temp_test, nocc_test, lumbp_test, up_test, mict_test, bis_test], [inflam_test, nephr_test], verbose=2)
40/1 - 0s - loss: 0.1161 - inflam_loss: 0.0987 - neph_loss: 0.1007 - inflam_acc: 1.0000 - neph_acc: 1.0000
Out[57]:
[0.12732672691345215, 0.09873616, 0.10068256, 1.0, 1.0]

Tensors and Variables

In [1]:
import numpy as np

Create Variable objects

In [4]:
# Create Variable objects of different type with tf.Variable

strings = tf.Variable(["Hello world!"], tf.string)
floats  = tf.Variable([3.14159, 2.71828], tf.float64)
ints = tf.Variable([1, 2, 3], tf.int32)
complexs = tf.Variable([25.9 - 7.39j, 1.23 - 4.91j], tf.complex128)
In [8]:
# Initialise a Variable value
tf.Variable(tf.constant(4.4, shape=(3,3)))
Out[8]:
<tf.Variable 'Variable:0' shape=(3, 3) dtype=float32, numpy=
array([[4.4, 4.4, 4.4],
       [4.4, 4.4, 4.4],
       [4.4, 4.4, 4.4]], dtype=float32)>

Use and modify Variable values

In [9]:
# Use the value of a Variable

v = tf.Variable(0.0)
w = v + 1  # w is a tf.Tensor which is computed based on the value of v.

print(type(w))
<class 'tensorflow.python.framework.ops.EagerTensor'>
In [11]:
# Increment the value of a Variable

v.assign_add(1)
v
Out[11]:
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>
In [12]:
# Decrement the value of a Variable
v.assign_sub(1)
Out[12]:
<tf.Variable 'UnreadVariable' shape=() dtype=float32, numpy=0.0>

Create Tensor objects

Create a constant tensor and print its type as well as its shape:

In [13]:
# Create a constant Tensor

x = tf.constant([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(x)
print("dtype:", x.dtype)
print("shape:", x.shape)
tf.Tensor(
[[1 2 3]
 [4 5 6]
 [7 8 9]], shape=(3, 3), dtype=int32)
dtype: <dtype: 'int32'>
shape: (3, 3)
In [14]:
# Obtain the value as a numpy array

x.numpy()
Out[14]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]], dtype=int32)
In [15]:
# Create a Tensor of type float32

x = tf.constant([[1,2,3],[4,5,6],[7,8,9]], dtype=tf.float32)
print(x.dtype)
<dtype: 'float32'>
In [16]:
# Create coefficients

coeffs = np.arange(16)
In [17]:
# Initialise shapes
shape1 = [8,2]
shape2 = [4, 4]
shape3 = [2,2,2,2]
In [18]:
# Create Tensors of different shape

a = tf.constant(coeffs, shape=shape1)
print("\n a:\n ", a)

b = tf.constant(coeffs, shape=shape2)
print("\n b:\n ", b)

c = tf.constant(coeffs, shape=shape3)
print("\n c:\n ", c)
 a:
  tf.Tensor(
[[ 0  1]
 [ 2  3]
 [ 4  5]
 [ 6  7]
 [ 8  9]
 [10 11]
 [12 13]
 [14 15]], shape=(8, 2), dtype=int64)

 b:
  tf.Tensor(
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]], shape=(4, 4), dtype=int64)

 c:
  tf.Tensor(
[[[[ 0  1]
   [ 2  3]]

  [[ 4  5]
   [ 6  7]]]


 [[[ 8  9]
   [10 11]]

  [[12 13]
   [14 15]]]], shape=(2, 2, 2, 2), dtype=int64)

Useful Tensor operations

In [19]:
# Create a constant Tensor

t = tf.constant(np.arange(80), shape=[5,2,8])
In [21]:
# Get the rank of a Tensor

rank = tf.rank(t)
In [22]:
# Display the rank

print("rank: ", rank)
rank:  tf.Tensor(3, shape=(), dtype=int32)
In [24]:
# Reshape a Tensor

t2 = tf.reshape(t, [8,10])
In [25]:
# Display the new shape

print("t2.shape: ", t2.shape)
t2.shape:  (8, 10)
In [29]:
# Create ones, zeros, identity and constant Tensors
ones = tf.ones(shape=(3,3))
zeros = tf.zeros(shape=(3,3))
eye = tf.eye(3)
tensor7 = tf.constant(7, shape=(3,3))
In [30]:
# Display the created tensors

print("\n Ones:\n ", ones)
print("\n Zeros:\n ", zeros)
print("\n Identity:\n ", eye)
print("\n Tensor filled with 7: ", tensor7)
 Ones:
  tf.Tensor(
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]], shape=(3, 3), dtype=float32)

 Zeros:
  tf.Tensor(
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]], shape=(3, 3), dtype=float32)

 Identity:
  tf.Tensor(
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]], shape=(3, 3), dtype=float32)

 Tensor filled with 7:  tf.Tensor(
[[7 7 7]
 [7 7 7]
 [7 7 7]], shape=(3, 3), dtype=int32)
In [31]:
# Create a ones Tensor and a zeros Tensor

t1 = tf.ones(shape=(2, 2))
t2 = tf.zeros(shape=(2, 2))
In [32]:
# Concatentate two Tensors
concat0 = tf.concat([t1, t2], axis=0)
concat1 = tf.concat([t1, t2], axis=1)
In [33]:
# Display the concatenated tensors

print(concat0)
print(concat1)
tf.Tensor(
[[1. 1.]
 [1. 1.]
 [0. 0.]
 [0. 0.]], shape=(4, 2), dtype=float32)
tf.Tensor(
[[1. 1. 0. 0.]
 [1. 1. 0. 0.]], shape=(2, 4), dtype=float32)
In [34]:
# Create a constant Tensor

t = tf.constant(np.arange(24), shape=(3, 2, 4))
print("\n t shape: ", t.shape)
 t shape:  (3, 2, 4)
In [46]:
# Expanding the rank of Tensors
t1 = tf.expand_dims(t, 0)
t2 = tf.expand_dims(t, 1)
t3 = tf.expand_dims(t, 3)
In [47]:
# Display the shapes after tf.expand_dims

print("\n After expanding dims:\n t1 shape: ", t1.shape, "\n t2 shape: ", t2.shape, "\n t3 shape: ", t3.shape)
 After expanding dims:
 t1 shape:  (1, 3, 2, 4) 
 t2 shape:  (3, 1, 2, 4) 
 t3 shape:  (3, 2, 4, 1)
In [48]:
# Squeezing redundant dimensions
t1 = tf.squeeze(t1, 0)
t2 = tf.squeeze(t2, 1)
t3 = tf.squeeze(t3, 3)
In [49]:
# Display the shapes after tf.squeeze

print("\n After squeezing:\n t1 shape: ", t1.shape, "\n t2 shape: ", t2.shape, "\n t3 shape: ", t3.shape)
 After squeezing:
 t1 shape:  (3, 2, 4) 
 t2 shape:  (3, 2, 4) 
 t3 shape:  (3, 2, 4)
In [50]:
# Slicing a Tensor
x = tf.constant([1,2,3,4,5,6,7])
print(x[1:4])
tf.Tensor([2 3 4], shape=(3,), dtype=int32)

Doing maths with Tensors

In [51]:
# Create two constant Tensors

c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
In [52]:
# Matrix multiplication

matmul_cd = tf.matmul(c,d)
In [53]:
# Display the result

print("\n tf.matmul(c,d):\n", matmul_cd)
 tf.matmul(c,d):
 tf.Tensor(
[[1. 3.]
 [3. 7.]], shape=(2, 2), dtype=float32)
In [54]:
# Elementwise operations
c_times_d = c*d
c_plus_d = c+d
c_minus_d = c-d
c_div_c = c / c
In [55]:
# Display the results

print("\n c*d:\n", c_times_d)
print("\n c+d:\n", c_plus_d)
print("\n c-d:\n", c_minus_d)
print("\n c/c:\n", c_div_c)
 c*d:
 tf.Tensor(
[[1. 2.]
 [0. 4.]], shape=(2, 2), dtype=float32)

 c+d:
 tf.Tensor(
[[2. 3.]
 [3. 5.]], shape=(2, 2), dtype=float32)

 c-d:
 tf.Tensor(
[[0. 1.]
 [3. 3.]], shape=(2, 2), dtype=float32)

 c/c:
 tf.Tensor(
[[1. 1.]
 [1. 1.]], shape=(2, 2), dtype=float32)
In [56]:
# Create Tensors

a = tf.constant([[2, 3], [3, 3]])
b = tf.constant([[8, 7], [2, 3]])
x = tf.constant([[-6.89 + 1.78j], [-2.54 + 2.15j]])
In [57]:
# Absolute value of a Tensor

absx = tf.abs(x)
In [60]:
# Power of a Tensor
powab = tf.pow(a, a)
In [61]:
# Display the results

print("\n ", absx)
print("\n ", powab)
  tf.Tensor(
[[7.11621388]
 [3.32777704]], shape=(2, 1), dtype=float64)

  tf.Tensor(
[[ 4 27]
 [27 27]], shape=(2, 2), dtype=int32)

Randomly sampled constant tensors

In [70]:
# Create a Tensor with samples from a Normal distribution
tn = tf.random.normal(shape=(2,2), mean=1, stddev=1.)
tn
Out[70]:
<tf.Tensor: id=186, shape=(2, 2), dtype=float32, numpy=
array([[1.01108  , 2.021771 ],
       [0.661181 , 0.6205955]], dtype=float32)>
In [72]:
# Create a Tensor with samples from a Uniform distribution
tu = tf.random.uniform(shape=(2,1), minval=0, maxval=10, dtype="int32")
tu
Out[72]:
<tf.Tensor: id=194, shape=(2, 1), dtype=int32, numpy=
array([[6],
       [4]], dtype=int32)>
In [74]:
# Create a Tensor with samples from a Poisson distribution
tp = tf.random.poisson((2,2),5)
tp
Out[74]:
<tf.Tensor: id=200, shape=(2, 2), dtype=float32, numpy=
array([[3., 6.],
       [3., 4.]], dtype=float32)>
In [75]:
# More maths operations

d = tf.square(tn)
e = tf.exp(d)
f = tf.cos(c)
In [76]:
print(d)
print(e)
print(f)
tf.Tensor(
[[1.0222828  4.087558  ]
 [0.43716028 0.38513878]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[ 2.7795327 59.594173 ]
 [ 1.5483042  1.4698182]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[ 0.96017027 -0.9899925 ]
 [ 0.75390226 -0.6536436 ]], shape=(2, 2), dtype=float32)

Accessing model layers

In [77]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

Load the pre-trained model

In this section, we aim to demonstrate accessing layer attributes within a model.

Let's get started by loading the VGG19 pre-trained model from the keras.applications library, which is a very deep network trained on more than a million images from the ImageNet database. The network is trained to classify images into 1000 object categories.

In [79]:
# Load the VGG19 model
#from tensorflow.keras.applications import VGG19
#vgg_model = VGG19()
from tensorflow.keras.models import load_model
vgg_model = load_model("models/Vgg19.h5")
WARNING:tensorflow:No training configuration found in save file: the model was *not* compiled. Compile it manually.
In [80]:
# Get the inputs, layers and display the summary

vgg_input = vgg_model.input
vgg_layers = vgg_model.layers
vgg_model.summary()
Model: "vgg19"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_4 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv4 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv4 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv4 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544 
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
predictions (Dense)          (None, 1000)              4097000   
=================================================================
Total params: 143,667,240
Trainable params: 143,667,240
Non-trainable params: 0
_________________________________________________________________

Build a model to access the layer outputs

In [81]:
from tensorflow.keras.models import Model
In [83]:
# Build a model that returns the layer outputs

layer_outputs = [layer.output for layer in vgg_layers]
features = Model(inputs=vgg_input, outputs=layer_outputs)
In [84]:
# Plot the model

tf.keras.utils.plot_model(features, "vgg19_model.png", show_shapes=True)
Out[84]:
In [85]:
# Test the model on a random input

img = np.random.random((1, 224, 224, 3)).astype("float32")
extracted_features = features(img)

Load the 'cool cat' picture

In Zambia’s South Luangwa National Park, a photographer had been watching a pride of lions while they slept off a feast from a buffalo kill. When this female walked away, he anticipated that she might be going for a drink and so he positioned his vehicle on the opposite side of the waterhole. The cool cat picture is one of the highly commended 2018 Image from Wildlife Photographer of the Year.

In [87]:
# Display the original image

import IPython.display as display
from PIL import Image

display.display(Image.open('data/cool_cat.jpg'))

Visualise network features from the input image

In [88]:
# Preprocess the image

from tensorflow.keras.applications.vgg19 import preprocess_input
from tensorflow.keras.preprocessing import image

img_path = 'data/cool_cat.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
In [89]:
# Extract the features

extracted_features = features(x)
In [91]:
# Visualise the input channels
f1 = extracted_features[0]
print("\n f1.shape: ", f1.shape)

imgs = f1[0,:,:]
plt.figure(figsize=(15,15))
for n in range(3):
    ax = plt.subplot(1, 3, n+1)
    plt.imshow(imgs[:,:,n])
    plt.axis("off")
plt.subplots_adjust(wspace=0.01, hspace=0.01)
 f1.shape:  (1, 224, 224, 3)
In [100]:
# Visualise some features in the first hidden layer
f2 = extracted_features[1]
print("\n f1.shape: ", f2.shape)

imgs = f2[0,:,:]
plt.figure(figsize=(15,15))
for n in range(16):
    ax = plt.subplot(4, 4, n+1)
    plt.imshow(imgs[:,:,n])
    plt.axis("off")
plt.subplots_adjust(wspace=0.01, hspace=0.01)
 f1.shape:  (1, 224, 224, 64)
In [101]:
# Build a model to extract features by layer name
extracted_features_block1_pool = Model(inputs=features.input, outputs=features.get_layer("block1_pool").output)
block1_pool_features = extracted_features_block1_pool.predict(x)
In [103]:
# Visualise some features from the extracted layer output
imgs = block1_pool_features[0]
plt.figure(figsize=(15,15))
for n in range(16):
    plt.subplot(4, 4, n+1)
    plt.imshow(imgs[...,n])
    plt.axis("off")
plt.subplots_adjust(wspace=0.01, hspace=0.01)
In [ ]:
# Extract features from a layer deeper in the network
In [ ]:
# Visualise some features from the extracted layer output

Freezing layers

In [1]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

Build the model

In [26]:
# Build a small Sequential model

from tensorflow.keras.models import Sequential
from tensorflow.keras import layers

model = Sequential([
    layers.Dense(4, input_shape=(4,), activation='relu', kernel_initializer='random_uniform',
                 bias_initializer='ones'),
    layers.Dense(2, activation='relu', kernel_initializer='lecun_normal', bias_initializer='ones'),
    layers.Dense(4, activation='softmax'),
])
In [27]:
# Display the model summary

model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_3 (Dense)              (None, 4)                 20        
_________________________________________________________________
dense_4 (Dense)              (None, 2)                 10        
_________________________________________________________________
dense_5 (Dense)              (None, 4)                 12        
=================================================================
Total params: 42
Trainable params: 42
Non-trainable params: 0
_________________________________________________________________

Examine the weight matrix variation over training

In [40]:
model.layers[0].weights
Out[40]:
[<tf.Variable 'dense_3/kernel:0' shape=(4, 4) dtype=float32, numpy=
 array([[ 0.15957606, -0.12781528, -0.16882017,  0.15015067],
        [-0.11435224, -0.2010291 , -0.05086384, -0.07262113],
        [-0.11275095, -0.1094114 ,  0.03246083, -0.08805598],
        [-0.14300443, -0.21087791, -0.03426016, -0.02844799]],
       dtype=float32)>,
 <tf.Variable 'dense_3/bias:0' shape=(4,) dtype=float32, numpy=array([0.89698577, 0.8189835 , 0.9457451 , 0.9591466 ], dtype=float32)>]
In [52]:
def get_weights(model):
    return [layer.weights[0].numpy() for layer in model.layers]
def get_biases(model):
    return [layer.bias.numpy() for layer in model.layers]
def plot_delta_weights(W0_layers, W1_layers, b0_layers, b1_layers):
    plt.figure(figsize=(8,8))
    for n in range(3):
        delta_l = W1_layers[n] - W0_layers[n]
        print('Layer '+str(n)+': bias variation: ', np.linalg.norm(b1_layers[n] - b0_layers[n]))
        ax = plt.subplot(1,3,n+1)
        plt.imshow(delta_l)
        plt.title('Layer '+str(n))
        plt.axis('off')
    plt.colorbar()
    plt.suptitle('Weight matrices variation');
In [53]:
# Retrieve the weights and biases
W0_layers = get_weights(model)
b0_layers = get_biases(model)
In [54]:
W0_layers
Out[54]:
[array([[ 0.31087244,  0.01386734, -0.31979367,  0.29473418],
        [-0.26224628, -0.3479199 ,  0.08676323,  0.033449  ],
        [-0.09660406, -0.0684736 ,  0.03902972, -0.20547062],
        [-0.2173447 , -0.33025837, -0.03198687,  0.12628536]],
       dtype=float32), array([[ 0.4610964 , -1.0318487 ],
        [ 0.2627502 , -0.26987368],
        [-0.09867311,  0.5406226 ],
        [-0.16696206, -0.14095087]], dtype=float32), array([[ 0.1749695 , -0.67264044,  0.04430439, -0.68133503],
        [-0.31890485,  1.1634933 ,  0.69932014,  0.7994865 ]],
       dtype=float32)]
In [55]:
b0_layers
Out[55]:
[array([0.8846095 , 0.76612884, 0.9171301 , 1.0686563 ], dtype=float32),
 array([0.7302363, 0.9310596], dtype=float32),
 array([ 0.07342546,  0.14034374, -0.23567154,  0.3374511 ], dtype=float32)]
In [56]:
# Construct a synthetic dataset

x_train = np.random.random((100, 4))
y_train = x_train

x_test = np.random.random((20, 4))
y_test = x_test
In [57]:
# Compile and fit the model

model.compile(optimizer='adam',
              loss='mse',
              metrics=['acc'])

model.fit(x_train, y_train, epochs=50, verbose=False);
In [58]:
# Retrieve weights and biases

W1_layers = get_weights(model)
b1_layers = get_biases(model)
In [59]:
W1_layers
Out[59]:
[array([[ 0.46403506,  0.17602505, -0.47024918,  0.34819978],
        [-0.35312292, -0.43904358,  0.1798745 , -0.02357748],
        [-0.1172233 , -0.02541036,  0.0930674 , -0.36809874],
        [-0.27380702, -0.4091159 ,  0.010541  ,  0.25068277]],
       dtype=float32), array([[ 0.55269426, -1.0738444 ],
        [ 0.39513934, -0.30068234],
        [-0.13140506,  0.6362386 ],
        [-0.17419505, -0.13593939]], dtype=float32), array([[ 0.2584568 , -0.6610866 ,  0.00727793, -0.7427577 ],
        [-0.47741294,  1.2484635 ,  0.78716695,  0.82326037]],
       dtype=float32)]
In [49]:
b1_layers
Out[49]:
[array([0.8846095 , 0.76612884, 0.9171301 , 1.0686563 ], dtype=float32),
 array([0.7302363, 0.9310596], dtype=float32),
 array([ 0.07342546,  0.14034374, -0.23567154,  0.3374511 ], dtype=float32)]
In [60]:
# Plot the variation
plot_delta_weights(W0_layers, W1_layers, b0_layers, b1_layers)
Layer 0: bias variation:  0.09476235
Layer 1: bias variation:  0.045481257
Layer 2: bias variation:  0.07436677

Freeze layers at build time

In [61]:
# Count the trainable and non trainable variables before the freezing
n_trainable_variables = len(model.trainable_variables)
n_non_trainable_variables = len(model.non_trainable_variables)
In [62]:
# Display the number of trainable and non trainable variables before the freezing

print("\n Before freezing:\n\t Number of trainable variables: ", n_trainable_variables,
                         "\n\t Number of non trainable variables: ", n_non_trainable_variables)
 Before freezing:
	 Number of trainable variables:  6 
	 Number of non trainable variables:  0
In [77]:
del model
In [78]:
# Build the model
model = Sequential([
    layers.Dense(4, input_shape=(4,), activation='relu', kernel_initializer='random_uniform',
                 bias_initializer='ones', trainable=False),
    layers.Dense(2, activation='relu', kernel_initializer='lecun_normal', bias_initializer='ones'),
    layers.Dense(4, activation='softmax'),
])
In [79]:
# Count the trainable and non trainable variables after the freezing

n_trainable_variables = len(model.trainable_variables)
n_non_trainable_variables = len(model.non_trainable_variables)
In [80]:
# Display the number of trainable and non trainable variables after the freezing

print("\n After freezing:\n\t Number of trainable variables: ", n_trainable_variables,
                         "\n\t Number of non trainable variables: ", n_non_trainable_variables)
 After freezing:
	 Number of trainable variables:  4 
	 Number of non trainable variables:  2
In [81]:
# Retrieve weights and biases

W0_layers = get_weights(model)
b0_layers = get_biases(model)
In [87]:
b0_layers
Out[87]:
[array([1., 1., 1., 1.], dtype=float32),
 array([1., 1.], dtype=float32),
 array([0., 0., 0., 0.], dtype=float32)]
In [82]:
# Compile and fit the model

model.compile(optimizer='adam',
              loss='mse',
              metrics=['acc'])

model.fit(x_train, y_train, epochs=50, verbose=False);
In [90]:
# Retrieve weights and biases
W1_layers = get_weights(model)
b1_layers = get_biases(model)
In [91]:
b1_layers
Out[91]:
[array([1., 1., 1., 1.], dtype=float32),
 array([1.       , 0.9582705], dtype=float32),
 array([-0.03853627,  0.03682943,  0.03921586, -0.0388594 ], dtype=float32)]
In [92]:
# Plot the variation

plot_delta_weights(W0_layers, W1_layers, b0_layers, b1_layers)
Layer 0: bias variation:  0.0
Layer 1: bias variation:  0.04172951
Layer 2: bias variation:  0.07674235

Freeze layers of a pre-built model

In [93]:
# Count the trainable and non trainable variables before the freezing

print("\n Before freezing:\n\t Number of trainable variables: ", len(model.trainable_variables),
                         "\n\t Number of non trainable variables: ", len(model.non_trainable_variables))
 Before freezing:
	 Number of trainable variables:  4 
	 Number of non trainable variables:  2
In [94]:
# Freeze the second layer

model.layers[1].trainable = False
In [95]:
# Count the trainable and non trainable variables after the freezing

print("\n After freezing:\n\t Number of trainable variables: ", len(model.trainable_variables),
                        "\n\t Number of non trainable variables: ", len(model.non_trainable_variables))
 After freezing:
	 Number of trainable variables:  2 
	 Number of non trainable variables:  4
In [96]:
# Compile and fit the model

model.compile(optimizer='adam',
              loss='mse',
              metrics=['acc'])

model.fit(x_train, y_train, epochs=50, verbose=False);
In [97]:
# Retrieve weights and biases

W2_layers = get_weights(model)
b2_layers = get_biases(model)
In [98]:
# Plot the variation

plot_delta_weights(W1_layers, W2_layers, b1_layers, b2_layers)
Layer 0: bias variation:  0.0
Layer 1: bias variation:  0.0
Layer 2: bias variation:  0.026031002
In [ ]: