Fifa worldcup 2018 Round of 16 flags classification using Keras
Now that we have all our dependencies installed and also have a basic understanding of CNNs, we are ready to perform our classification task. Download the files from the google drive link given above, unzip and paste it in your working directory. Rename the directory name to Data
In your working directory, We will be going through each portion of the code to understand what is being done.
import keras from keras import optimizers from keras.models import Model, load_model from keras.layers import Dense, Dropout, Flatten,Input from keras.layers import Conv2D, MaxPooling2D from sklearn.datasets import load_files from sklearn.preprocessing import LabelBinarizer from sklearn.model_selection import train_test_split import os import cv2 import numpy as np
At first, we import the necessary dependencies.
#define number of epochs to train for epochs = 20 # input image dimensions img_rows, img_cols = 64, 64 DATA_DIR='./Data' #number of class labels = total number of countries datas=load_files(DATA_DIR, load_content= False) total_countries=len(datas.target_names)
Next, we define our constants. We train for 20 epochs. The input image size will be converted to a fixed size of 64*64 and “Data” is the directory where our training data is stored. The class labels is equal to the total number of countries in the training data.
The steps to follow in training the CNN model are:
- Prepare input
- Build the model
- Train the model
We define a separate function for each of these tasks
Prepare Input
def build_data(datas): X = [] y = [] encoder = LabelBinarizer() encoded_dict=dict() hotcoded_label = encoder.fit_transform(datas.target_names) for i in range(len(datas.target_names)): encoded_dict[datas.target_names[i]]=hotcoded_label[i] for country in os.listdir(DATA_DIR): label=encoded_dict[country] for each_flag in os.listdir(DATA_DIR+'/'+country): actual_path = os.path.join(DATA_DIR,country,each_flag) img_data = cv2.imread(actual_path) img_data = cv2.resize(img_data, (img_rows, img_cols)) X.append(np.array(img_data)) y.append(label) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=36) X_train = np.asarray(X_train) X_test = np.asarray(X_test) y_train = np.asarray(y_train) y_test = np.asarray(y_test) return [X_train, X_test, y_train, y_test]
Here, we prepare data as input for our CNN model. For X-label, we read input images using OpenCV and convert them to a fixed shape of 64*64. For y-label, we convert each of the country names to one hot encoded vector using sklearn’s LabelBinarizer. Finally, the data is split into test and training set using sklearn’s train_test_split with 90% of data as training data and 10% as test data.
Build the model
def create_model(input_shape,classes): img_input = Input(shape=input_shape) x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input) x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x) x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x) x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x) x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block4_conv1')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block5_conv1')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x) x = Flatten(name='flatten')(x) x = Dense(512, activation='relu', name='fc1')(x) x = Dropout(0.2)(x) x = Dense(256, activation='relu', name='fc2')(x) x = Dropout(0.2)(x) x = Dense(classes, activation='softmax', name='final_output')(x) model = Model(img_input, x, name='flag') return model
Here we build model for our CNN. The activation function we use on convolution layers is relu and on the final output layer is softmax. This is pretty much self-explanatory if you know the theories of CNN so I’m not going to dive deeper in this. If there is anything you’d like me to explain, please mention in the comment below and I’ll get back to you.
Train the model
def train_model(x_train, x_test, y_train, y_test): input_shape=(img_rows,img_cols,3) model=create_model(input_shape,total_countries) adams=optimizers.Adam(lr=1e-4) model.compile(loss='categorical_crossentropy', optimizer= adams, metrics=['accuracy']) model.fit(x = x_train, y = y_train, epochs=epochs) score = model.evaluate(x_test, y_test, verbose=1) print('Test loss:', score[0]) print('Test accuracy:', score[1]) model.save('final_roun16_flagdetection.h5') return model
We train our CNN model on the dataset we prepared earlier. The input shape is the shape of the image with the color channels (64*64*3) and the output shape total number of countries (16). We use adam optimizer with a learning rate of e^-4 as it seems to give much better accuracy than the default learning rate of e^-3. The loss function we use is categorical cross entropy and we train it for the number of epochs we defined earlier. We will later use this model to predict on input data so we save it.
Finally, we define our main function as
def main(): x_train, x_test, y_train, y_test = build_data(datas) train_model(x_train, x_test, y_train, y_test) if __name__ == "__main__": main()
The complete code for the file is posted below:
import keras from keras import optimizers from keras.models import Model, load_model from keras.layers import Dense, Dropout, Flatten,Input from keras.layers import Conv2D, MaxPooling2D from sklearn.datasets import load_files from sklearn.preprocessing import LabelBinarizer from sklearn.model_selection import train_test_split import os import cv2 import numpy as np #define number of epochs to train for epochs = 20 # input image dimensions img_rows, img_cols = 64, 64 DATA_DIR='./Data' #number of class labels = total number of countries datas=load_files(DATA_DIR, load_content= False) total_countries=len(datas.target_names) def build_data(datas): X = [] y = [] encoder = LabelBinarizer() encoded_dict=dict() hotcoded_label = encoder.fit_transform(datas.target_names) for i in range(len(datas.target_names)): encoded_dict[datas.target_names[i]]=hotcoded_label[i] for country in os.listdir(DATA_DIR): label=encoded_dict[country] for each_flag in os.listdir(DATA_DIR+'/'+country): actual_path = os.path.join(DATA_DIR,country,each_flag) img_data = cv2.imread(actual_path) img_data = cv2.resize(img_data, (img_rows, img_cols)) X.append(np.array(img_data)) y.append(label) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=36) X_train = np.asarray(X_train) X_test = np.asarray(X_test) y_train = np.asarray(y_train) y_test = np.asarray(y_test) return [X_train, X_test, y_train, y_test] def create_model(input_shape,classes): img_input = Input(shape=input_shape) x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input) x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x) x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x) x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x) x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block4_conv1')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block5_conv1')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x) x = Flatten(name='flatten')(x) x = Dense(512, activation='relu', name='fc1')(x) x = Dropout(0.2)(x) x = Dense(256, activation='relu', name='fc2')(x) x = Dropout(0.2)(x) x = Dense(classes, activation='softmax', name='final_output')(x) model = Model(img_input, x, name='flag') return model def train_model(x_train, x_test, y_train, y_test): input_shape=(img_rows,img_cols,3) model=create_model(input_shape,total_countries) adams=optimizers.Adam(lr=1e-4) model.compile(loss='categorical_crossentropy', optimizer= adams, metrics=['accuracy']) model.fit(x = x_train, y = y_train, epochs=epochs) score = model.evaluate(x_test, y_test, verbose=1) print('Test loss:', score[0]) print('Test accuracy:', score[1]) model.save('final_roun16_flagdetection.h5') return model def main(): x_train, x_test, y_train, y_test = build_data(datas) train_model(x_train, x_test, y_train, y_test) if __name__ == "__main__": main()
Save the file as “flags.py” in your working directory and run it using the command
flagspython3
.py
The training might take some time depending on your machine and when it’s complete, you should see an output like:
Epoch 18/20
583/583 [==============================] – 8s 13ms/step – loss: 0.2539 – acc: 0.9194
Epoch 19/20
583/583 [==============================] – 8s 13ms/step – loss: 0.1982 – acc: 0.9451
Epoch 20/20
583/583 [==============================] – 8s 13ms/step – loss: 0.2032 – acc: 0.9485
65/65 [==============================] – 0s 5ms/step
Test loss: 0.6747298387380747
Test accuracy: 0.8307692307692308
As we can see the model gives training accuracy of about 95% and testing accuracy of about 83%. (Actual results may vary).
Like us on facebook to receive more updates.
Hi Aryal!
Can you share the google drive link which refers to all files? You wrote: “Download the files from the google drive link given above”, but unfortunately I could not find the link. It would be very nice if I could get the files for a project which I’m doing right now.
Mark
Hello Mark,
The link to the files dataset is: https://drive.google.com/drive/folders/1bgb2tB2ljmjvOxgu2SqFI34jHJJ82tkK
Best of luck on your project.
Regards,
Aryal Bibek
can you show the directory structure of your photos
where should i give an input image for comparing images in the database(that means the images trained by cnn)
noice tutor mate! one question about model architecture; is there a motiviation to increasing the size of cnn from 64 layers, to 128, to 256; then quartering downto 64, and then go up again to 128?