Reputation: 1
I have built a one class anomaly detection deep learning model and I am training it on one class red-blood cell images.
I have calculated a threshold that will be able to differentiate between anomalous and normal images but for some reason it doesn't identify as many abnormal images as I would like.
What are some of the hyperparameters that I can tune to make my model learn well and predict better.
Here is my code.
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, BatchNormalization, LayerNormalization
from tensorflow.keras.models import Model
from tensorflow.keras.regularizers import l1
from tensorflow.keras.optimizers import Adam
optimizer = Adam(learning_rate=0.0001)
input_shape = (SIZE, SIZE, 3)
# Encoder
inputs = Input(shape=input_shape)
x = Conv2D(64, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(inputs)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(16, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)
# Decoder
x = Conv2D(16, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(64, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)
# Define the autoencoder model
autoencoder = Model(inputs, decoded)
# Compile the model
autoencoder.compile(optimizer=optimizer, loss='mean_squared_error')
# Print the model summary
autoencoder.summary()
#Fit the model.
history = autoencoder.fit(
train_generator,
steps_per_epoch= 250 // batch_size,
epochs=1000,
validation_data=validation_generator,
validation_steps= 250 // batch_size,
shuffle = True)
#plot the training and validation loss at each epoch
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.plot(epochs, loss, 'y', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
I want to have a low reconstruction error for the normal instances and a high reconstruction error for abnormal instances. Any idea on how I can improve the performance of my model ?
Here is a snapshot of the the loss.
Epoch 1/1000
7/7 [==============================] - 31s 4s/step - loss: 0.1420 - val_loss: 0.1355
Epoch 2/1000
7/7 [==============================] - 30s 4s/step - loss: 0.1302 - val_loss: 0.1266
Epoch 3/1000
7/7 [==============================] - 30s 4s/step - loss: 0.1228 - val_loss: 0.1201
Epoch 4/1000
7/7 [==============================] - 30s 4s/step - loss: 0.1152 - val_loss: 0.1111
Epoch 5/1000
7/7 [==============================] - 31s 5s/step - loss: 0.1028 - val_loss: 0.0920
Epoch 6/1000
7/7 [==============================] - 30s 4s/step - loss: 0.0785 - val_loss: 0.0630
Epoch 7/1000
7/7 [==============================] - 30s 4s/step - loss: 0.0571 - val_loss: 0.0507
Epoch 8/1000
7/7 [==============================] - 30s 4s/step - loss: 0.0470 - val_loss: 0.0430
Epoch 9/1000
7/7 [==============================] - 30s 4s/step - loss: 0.0412 - val_loss: 0.0392
Epoch 10/1000
7/7 [==============================] - 30s 4s/step - loss: 0.0381 - val_loss: 0.0366
Epoch 11/1000
7/7 [==============================] - 30s 5s/step - loss: 0.0361 - val_loss: 0.0347
Epoch 12/1000
7/7 [==============================] - 30s 4s/step - loss: 0.0341 - val_loss: 0.0333
Epoch 13/1000
7/7 [==============================] - 31s 5s/step - loss: 0.0330 - val_loss: 0.0320
Upvotes: -2
Views: 237
Reputation: 2066
The encoder architecture should progressively increase the number of filters in each convolution layer, and the decoder architecture should progressively decrease the number of filters in each convolution layer. Otherwise the size of the encoded bottleneck would be too small to retain the information of the original image.
The image pixel values are not binary, so try using a ReLU activation function in the final output layer. Even if you are normalizing your image pixel values to the range 0-1, ReLU will work just fine.
One more thing, your input image has 3 channels, and as your intention is to reconstruct the image, your final output layer should also contain 3 channels, unless you're reconstructing an RGB images to a Black & White image.
This would be an appropriate example:
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, BatchNormalization, LayerNormalization
from tensorflow.keras.models import Model
from tensorflow.keras.regularizers import l1
from tensorflow.keras.optimizers import Adam
optimizer = Adam(learning_rate=0.0001)
input_shape = (SIZE, SIZE, 3)
# Encoder
inputs = Input(shape=input_shape)
x = Conv2D(16, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(inputs)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(64, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)
# Decoder
x = Conv2D(64, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(16, (3, 3), activation='relu', padding='same', activity_regularizer=l1(1e-6))(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(3, (3, 3), activation='relu', padding='same')(x)
# Define the autoencoder model
autoencoder = Model(inputs, decoded)
# Compile the model
autoencoder.compile(optimizer=optimizer, loss='mean_squared_error')
# Print the model summary
autoencoder.summary()
#Fit the model.
history = autoencoder.fit(
train_generator,
steps_per_epoch= 250 // batch_size,
epochs=1000,
validation_data=validation_generator,
validation_steps= 250 // batch_size,
shuffle = True)
#plot the training and validation loss at each epoch
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.plot(epochs, loss, 'y', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
Upvotes: 0