In [1]:
    
from PIL import Image
import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt
import os
from keras.utils import np_utils
from keras.models import Sequential, load_model
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D, ZeroPadding2D, AveragePooling2D
    
    
In [2]:
    
def load_data(data_list, sourceFile, label, imageSize):
    photoList = os.listdir(sourceFile)
    for photo in photoList:
        img = Image.open(sourceFile+photo)
        rsize = img.resize((imageSize, imageSize))
        rsizeArr = np.asarray(rsize)
        rsize_la = (rsizeArr, label)
        data_list.append(rsize_la)
    
In [3]:
    
# Load training faces from directory
# 'female_faces_datagen/' is the source directory of female faces, and has been labeled '0' 
photoDir1 = 'female_faces_datagen/'
# 'male_faces_datagen/' is the source directory of male faces, and has been labeled '1'
photoDir2 = 'male_faces_datagen/'
x_data = []
# Set image size
imageSize = 96
load_data(x_data, photoDir1, 0, imageSize)
load_data(x_data, photoDir2, 1, imageSize)
train_length = int(len(x_data)*0.8)
np.random.shuffle(x_data)
x_data = list(zip(*x_data))
# Use 80% for training, and 20% for testing
x_train = np.asarray(list(x_data[0])[:train_length])
y_train = np.asarray(list(x_data[1])[:train_length])
x_test = np.asarray(list(x_data[0])[train_length:])
y_test = np.asarray(list(x_data[1])[train_length:])
# Feature scaling
x_train_nor = x_train.astype('float32') / 255.0
x_test_nor = x_test.astype('float32') / 255.0
    
In [4]:
    
model = Sequential()
model.add(Conv2D(filters=16,kernel_size=(5,5),
                 input_shape=(imageSize, imageSize, 3), 
                 activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(filters=32, kernel_size=(3, 3), 
                 activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(filters=64, kernel_size=(3, 3), 
                 activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dropout(rate=0.8))
model.add(Dense(128, activation='relu'))
model.add(Dropout(rate=0.5))
model.add(Dense(128, activation='relu'))
model.add(Dropout(rate=0.3))
model.add(Dense(units=1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
              optimizer='adam', metrics=['accuracy'])
    
In [5]:
    
model.summary()
    
    
In [200]:
    
train_history=model.fit(x_train_nor, y_train,
                        validation_split=0.2,
                        epochs=1, batch_size=64, verbose=1)
    
    
In [7]:
    
def show_train_history(train_history, train, validation):
    plt.plot(train_history.history[train])
    plt.plot(train_history.history[validation])
    plt.title('Train History')
    plt.ylabel(train)
    plt.xlabel('Epoch')
    plt.legend(['train', 'validation'], loc='upper left')
    plt.show()
    
In [8]:
    
show_train_history(train_history, 'acc', 'val_acc')
    
    
In [9]:
    
show_train_history(train_history, 'loss', 'val_loss')
    
    
In [223]:
    
# Only save weights, need to create model before load weights
#model.save_weights("gender_classify_middle_hiar_man.h5")
# Save entire model
model.save('gender_classify_middle_hiar_man.h5')
    
In [201]:
    
scores = model.evaluate(x_test_nor, 
                        y_test, verbose=0)
scores[1]
    
    Out[201]:
In [202]:
    
prediction=model.predict_classes(x_test_nor)
prediction.shape
    
    
    Out[202]:
In [203]:
    
# Draw confusion matrix
pd.crosstab(y_test,prediction.reshape(-1),
            rownames=['label'],colnames=['predict'])
    
    Out[203]:
In [227]:
    
# Load testing images from directory
# 'female_test_final/' is the source directory of female faces, and have been labeled '0' 
photoDir1 = 'female_test_final/'
# 'male_test_final/' is the source directory of male faces, and have been labeled '1'
photoDir2 = 'male_test_final/'
x_data_alt = []
load_data(x_data_alt, photoDir1, 0, imageSize)
load_data(x_data_alt, photoDir2, 1, imageSize)
x_data_alt = list(zip(*x_data_alt))
x_test_alt = np.asarray(list(x_data_alt[0]))
y_test_alt = np.asarray(list(x_data_alt[1]))
# Feature scaling
x_test_alt_nor = x_test_alt.astype('float32') / 255.0
    
In [224]:
    
# Only load weights, need to create model before load weights
#model.load_weights("gender_classify_middle_hiar_man.h5")
# Load entire model
model = load_model('gender_classify_middle_hiar_man.h5')
    
In [228]:
    
scores = model.evaluate(x_test_alt_nor, 
                        y_test_alt, verbose=0)
scores[1]
    
    Out[228]:
In [229]:
    
prediction=model.predict_classes(x_test_alt_nor)
prediction.shape
    
    
    Out[229]:
In [230]:
    
# Draw confusion matrix
pd.crosstab(y_test_alt,prediction.reshape(-1),
            rownames=['label'],colnames=['predict'])
    
    Out[230]:
In [231]:
    
fig = plt.gcf()
fig.set_size_inches(16,20)
for i in range(len(x_test_alt)):
    ax = plt.subplot(5,7,1+i)
    ax.imshow(x_test_alt[i], cmap='binary')
    title ="label=" + str(y_test_alt[i]) + " pred= " +str(prediction[i]) 
    ax.set_title(title,fontsize=10)
plt.show()