I am developing a speaker identification model in Keras, and I have saved the weights from a trained custom model. Now, I am looking to use the trained weights to fine tune the model on a new dataset, but I am having trouble since the new dataset contains a different number of speakers than the first, so the new output shape will be different from the original.
Here's the code that I am using to create and evaluate the model:
# Create Model
def createModel(model_input, model_output, first_session=True):
# Define Input Layer
inputs = model_input
# Define First Conv2D Layer
conv = Conv2D(filters=32,
kernel_size=(5, 5),
activation='relu',
padding='same',
strides=3)(inputs)
conv = Conv2D(filters=32,
kernel_size=(5, 5),
activation='relu',
padding='same',
strides=3)(conv)
conv = MaxPooling2D(pool_size=(3, 3), padding='same')(conv)
conv = Dropout(0.3)(conv)
# Define Second Conv2D Layer
conv = Conv2D(filters=64,
kernel_size=(3, 3),
activation='relu',
padding='same',
strides=3)(conv)
conv = Conv2D(filters=64,
kernel_size=(3, 3),
activation='relu',
padding='same',
strides=3)(conv)
conv = MaxPooling2D(pool_size=(3, 3), padding='same')(conv)
conv = Dropout(0.3)(conv)
# Define Third Conv2D Layer
conv = Conv2D(filters=128,
kernel_size=(3, 3),
activation='relu',
padding='same',
strides=3)(conv)
conv = Conv2D(filters=128,
kernel_size=(3, 3),
activation='relu',
padding='same',
strides=3)(conv)
conv = MaxPooling2D(pool_size=(3, 3), padding='same')(conv)
conv = Dropout(0.3)(conv)
# Define Flatten Layer
conv = Flatten()(conv)
# Define First Dense Layer
conv = Dense(256, activation='relu')(conv)
conv = Dropout(0.2)(conv)
# Define Second Dense Layer
conv = Dense(128, activation='relu')(conv)
conv = Dropout(0.2)(conv)
# Define Output Layer
outputs = Dense(model_output, activation='softmax')(conv)
# Create Model
model = Model(inputs, outputs)
model.summary()
if first_session != True:
model.load_weights('SI_ideal_weights_simple.hdf5')
return model
# Train Model
def evaluateModel(x_train, x_val, y_train, y_val, num_classes, first_session=True):
# Model Parameters
verbose, epochs, batch_size, patience = 1, 100, 64, 10
# Determine Input and Output Dimensions
x = x_train[0].shape[0] # Number of MFCC rows
y = x_train[0].shape[1] # Number of MFCC columns
c = 1 # Number of channels
n_outputs = num_classes # Number of outputs
# Create Model
inputs = Input(shape=(x, y, c))
model = createModel(model_input=inputs,
model_output=n_outputs,
first_session=first_session)
# Compile Model
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
# Callbacks
es = EarlyStopping(monitor='val_loss',
mode='min',
verbose=verbose,
patience=patience,
min_delta=0.0001) # Stop training at right time
mc = ModelCheckpoint('SI_ideal_weights_simple.hdf5',
monitor='val_accuracy',
verbose=verbose,
save_weights_only=True,
save_best_only=True,
mode='max') # Save best model after each epoch
reduce_lr = ReduceLROnPlateau(monitor='val_loss',
factor=0.2,
patience=patience//2,
min_lr=1e-3) # Reduce learning rate once learning stagnates
# Evaluate Model
model.fit(x=x_train, y=y_train, epochs=epochs,
callbacks=[es,mc,reduce_lr], batch_size=batch_size,
validation_data=(x_val, y_val))
accuracy = model.evaluate(x=x_train, y=y_train,
batch_size=batch_size,
verbose=verbose)
return (accuracy[1], model)
Attempting to run the model on the second dataset throws the following error:
ValueError: Shapes (128, 40) and (128, 15) are incompatible
Which occurs at the output layer because of the difference in the number of speakers (i.e. from 40 to 15). The last layer contains 5160 trainable parameters, so I was trying to find a solution other than dropping it and adding an equivalent one with a new output shape to retain accuracy, if possible. (That being said, I am new to ML/Keras, and I can't say for certain that this would make a substantial difference.)
Ultimately, my question is: How can I apply the weights from a custom trained convolutional neural net to a dataset with the same data shape but different number of classes?
Any help is greatly appreciated.