I am trying to get weights for every batch / epoch from Keras model after it is trained. To do so I use callback to make model save weights during training. Yet after model is trained it looks like I get weights only from the final epoch. How to get all weights that model generates? Here is a simple example:
import numpy as np
import tensorflow as tf
from tensorflow import keras
from keras import layers
# Generate data
start, stop = 1,100
cnt = stop - start + 1
xs = np.linspace(start, stop, num = cnt)
b,k = 1,2
ys = np.array([k*x + b for x in xs])
# Simple model with one feature and one unit for regression task
model = keras.Sequential([
layers.Dense(units=1, input_shape=[1], activation='relu')
])
model.compile(loss='mae', optimizer='adam')
batch_size = int(cnt / 5)
epochs = 80
Next goes callback to save the Keras model weights at some frequency. According to Keras docs:
save_freq: 'epoch' or integer. When using 'epoch', the callback should save the model after each epoch. When using integer, the callback should save the model at end of this many batches.
checkpoint_filepath = './checkpoint.hdf5'
model_checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_filepath,
save_weights_only=True,
save_freq ='epoch', # 1 for every batch
save_best_only=False
)
# Train model
history = model.fit(xs, ys, batch_size=batch_size, epochs=epochs,
callbacks=[model_checkpoint_callback])
I use two different ways to get weights. First:
w, b = model.weights
print("Weights: \n {} \n Bias: \n {}".format(w,b))
Weights:
<tf.Variable 'dense/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[-0.1450262]], dtype=float32)>
Bias:
<tf.Variable 'dense/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>
This results in one weight and one bias, not all weights generated by model at every batch /epoch.
And second method to get weights directly from h5 file:
# Functions to read weights from h5 file
import h5py
def getH5Keys(fileName):
keys = []
with h5py.File(fileName, mode='r') as f:
for key in f:
keys.append(key)
return keys
def isGroup(obj):
if isinstance(obj, h5py.Group):
return True
else:
return False
def isDataset(obj):
if isinstance(obj, h5py.Dataset):
return True
else:
return False
def getDataSetsFromGroup(datasets, obj):
if isGroup(obj):
for key in obj:
x = obj[key]
getDataSetsFromGroup(datasets, x)
else:
datasets.append(obj)
def getWeightsForLayer(layerName, fileName):
weights = []
with h5py.File(fileName, mode='r') as f:
for key in f:
if layerName in key:
obj = f[key]
datasets = []
getDataSetsFromGroup(datasets, obj)
for dataset in datasets:
w = np.array(dataset)
weights.append(w)
return weights
This method returns the same singular values for one weight and one bias:
layers = getH5Keys(checkpoint_filepath)
firstLayer = layers[0]
print(layers) # ['dense']
weights = getWeightsForLayer(firstLayer, checkpoint_filepath)
for w in weights:
print(w.shape)
print(weights)
Output:
(1,)
(1, 1)
[array([0.], dtype=float32), array([[-0.1450262]], dtype=float32)]
Again I get only one weight and one bias. How to get all weights generated by model for every batch /epoch?
Update
Answer from 10xAI
works for me. However, in my case I have one level of network with one unit, so I access weights and bias differently:
weights_dict = {}
weight_callback = tf.keras.callbacks.LambdaCallback \
( on_epoch_end=lambda epoch, logs: weights_dict.update({epoch:model.get_weights()}))
# Train model
history = model.fit(xs, ys, batch_size=batch_size, epochs=epochs,
callbacks=[weight_callback])
print(weights_dict[0])
Output: [array([[1.5375139]], dtype=float32), array([0.00499998], dtype=float32)]
print("*** Epoch: ", epoch, "\nWeight: ", weights_dict[0][0][0], " bias: ", weights_dict[1][0])
Output: *** Epoch: 79
Weight: [1.5375139] bias: [[1.5424858]]