# Core libraries. Tensorflow for making Neural Networks
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense, Flatten, Input, Dropout
from tensorflow.keras.applications import VGG16
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import *
from sklearn.model_selection import train_test_split
# Data Visualization
import matplotlib.pyplot as plt
import seaborn as sns
# Define the folder where all the images are there
folder = '../input/face-attributes-ml-thon-2021/images/images/'
# Reading the train data
train = pd.read_csv('../input/face-attributes-ml-thon-2021/face_attribute_train.csv')
train
plt.title("Wearing Accessories or not")
sns.countplot(y='Wearing_Accessories', data=train, color="c")
plt.show()
print("Percentage of positives")
(train['Wearing_Accessories'] == 1).sum() / len(train) * 100
Percentage of positives
plt.title('Thick Lips or not')
sns.countplot(y='Thick_Lips_Nose', data=train, color="c")
plt.show()
print("Percentage of positives")
(train['Thick_Lips_Nose'] == 1).sum() / len(train) * 100
Percentage of positives
img = plt.imread(folder + "0.jpg")
print("Image dimensions")
print(img.shape)
plt.imshow(img)
Image dimensions
(218, 178, 3)
train_df, val_df = train_test_split(train, test_size=0.1)
datagen = ImageDataGenerator(rescale=1./255.)
columns = ['Wearing_Accessories', 'Thick_Lips_Nose']
train_generator = datagen.flow_from_dataframe(train_df,
folder,
x_col = 'image_id',
y_col = columns,
class_mode='raw',
target_size=(218, 178),
batch_size = 128,
color_mode = 'rgb',
shuffle = True)
val_generator = datagen.flow_from_dataframe(val_df,
folder,
x_col = 'image_id',
y_col = columns,
target_size =(218, 178),
class_mode = 'raw',
batch_size = 128,
color_mode = 'rgb',
shuffle = True)
Found 154979 validated image filenames.
Found 17220 validated image filenames.
def create_model():
# Input dimensions of our image (checked above)
x_input = Input(shape=(218, 178, 3))
# VGG16 network
vgg = VGG16(weights='imagenet', include_top=False, input_shape=(218, 178, 3))
x = vgg(x_input)
# The output of a VGG network is also 3 dimensional. We need to convert it to 1 dimension and then to 2 outputs
x = Flatten()(x) #Converting to one dimension by concatenating everything
x = Dense(512, activation='relu')(x)
x = Dropout(0.2)(x) # Dropout randomly drops neurons in the network to prevent overfitting. This is kind of an arbitrary value
x = Dense(128, activation='relu')(x)
x = Dense(2, activation='sigmoid')(x)
# Define our full model will inputs and outputs
model = Model(inputs=x_input, outputs = x)
# We will be using Adam, it is the most common optimizer. This also has hyperparameters, but we are ignoring it for now.
# Binary Cross Entropy (log loss) is the metric we are optimizing. For our understanding, we are tracking accuracy and AUC (ignore this if you don't know it). Logloss is still the priority
model.compile(optimizer = "Adam", loss='binary_crossentropy', metrics=['accuracy', "AUC"])
return model
model = create_model()
model.summary() # Plot the architecture of the model
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
58892288/58889256 [==============================] - 1s 0us/step
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 218, 178, 3)] 0
_________________________________________________________________
vgg16 (Functional) (None, 6, 5, 512) 14714688
_________________________________________________________________
flatten (Flatten) (None, 15360) 0
_________________________________________________________________
dense (Dense) (None, 512) 7864832
_________________________________________________________________
dropout (Dropout) (None, 512) 0
_________________________________________________________________
dense_1 (Dense) (None, 128) 65664
_________________________________________________________________
dense_2 (Dense) (None, 2) 258
=================================================================
Total params: 22,645,442
Trainable params: 22,645,442
Non-trainable params: 0
_________________________________________________________________
# Fitting the model on the data.
# Epochs is the number of times the model goes through the entire dataset.
# You should choose a higher value to give it more time to learn. But too high a value can lead to memorization rather than learning.
history = model.fit(train_generator, epochs=5, validation_data = val_generator)
Epoch 1/5
1211/1211 [==============================] - 1165s 955ms/step - loss: 0.6880 - accuracy: 0.3079 - auc: 0.5083 - val_loss: 0.6691 - val_accuracy: 0.2231 - val_auc: 0.5387
Epoch 2/5
1211/1211 [==============================] - 832s 687ms/step - loss: 0.6684 - accuracy: 0.2396 - auc: 0.5149 - val_loss: 0.6702 - val_accuracy: 0.2231 - val_auc: 0.5114
Epoch 3/5
1211/1211 [==============================] - 826s 682ms/step - loss: 0.6682 - accuracy: 0.2290 - auc: 0.5157 - val_loss: 0.6702 - val_accuracy: 0.2231 - val_auc: 0.5114
Epoch 4/5
1211/1211 [==============================] - 834s 689ms/step - loss: 0.6684 - accuracy: 0.2283 - auc: 0.5139 - val_loss: 0.6705 - val_accuracy: 0.2231 - val_auc: 0.5114
Epoch 5/5
1211/1211 [==============================] - 832s 687ms/step - loss: 0.6690 - accuracy: 0.2293 - auc: 0.5146 - val_loss: 0.6703 - val_accuracy: 0.2231 - val_auc: 0.5114
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model Loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model Accuracy')
plt.ylabel('Accurcy')
plt.xlabel('Epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()
sub = pd.read_csv("../input/face-attributes-ml-thon-2021/sampleSubmission.csv")
sub
test_generator = datagen.flow_from_dataframe(sub, folder, x_col = 'image_id', y_col=None,
batch_size=128,
class_mode=None,
target_size =(218, 178),
shuffle=False,
color_mode = 'rgb')
Found 30400 validated image filenames.
# Making predictions and storing it in a variable.
preds = model.predict(test_generator)
# Adding predictions to the dataframe so that we can easily submit.
sub[['Wearing_Accessories', 'Thick_Lips_Nose']] = preds
sub
sub.to_csv("submission.csv", index=False)