我正在尝试使用相同的数据集在Keras中重现面部形状分类(https://github.com/adonistio/inception-face-shape-classifier/blob/master/Paper%20v3.pdf)。该数据集由500个5类(每组100个)的图像组成:心形,椭圆形,椭圆形,圆形和方形。图像有不同的尺寸,但面部是对齐的。
示例图片:heart_agreene_003.jpg。类:心形。
不幸的是我无法训练一个好的模型,我的准确率被卡在20%(roc_auc_score = 0.5)。现在有些反馈会非常好。
我尝试了各种CNN架构,批量大小,学习率,优化器和数据扩充。
import os
import cv2
import numpy as np
import pandas as pd
from sklearn.model_selection import KFold, train_test_split
import matplotlib.pyplot as plt
from sklearn import metrics
import keras
from keras.models import Model
from keras.optimizers import SGD
from keras.applications.inception_v3 import InceptionV3
from keras.layers import Dense, Input, Flatten, Dropout, GlobalAveragePooling2D
from keras.layers.normalization import BatchNormalization
from keras.preprocessing.image import ImageDataGenerator
from keras.utils import np_utils
path = '...'
folders = next(os.walk(path))[1]
filepaths = []
labels = []
for i, cls in enumerate(folders):
files = next(os.walk(path + cls + '/'))[2]
for file in files:
filepaths.append(path + cls + '/' + file)
labels.append(i)
# convert to dummies
labels = np_utils.to_categorical(labels)
fps_train, fps_test, labels_train, labels_test = train_test_split(filepaths, labels, test_size=0.2, random_state=2018)
img_height = 299
img_width = 299
img_channels = 3
img_dim = (img_height, img_width, img_channels)
img_size = (img_height, img_width)
datagen = ImageDataGenerator(
rescale=1./255,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.15,
zoom_range=0.15,
horizontal_flip=True)
def arc(img_dim=img_dim):
base_model = InceptionV3(weights="imagenet", include_top=False, input_shape=img_dim)
for l in base_model.layers:
l.trainable = False
x = base_model.output
x = Flatten()(x)
x = Dense(2048, activation="relu")(x)
x = Dropout(0.5)(x)
predictions = Dense(len(folders), activation="softmax")(x)
# creating the final model
model = Model(inputs = base_model.input, outputs = predictions)
return model
model = arc()
batch_size = 16
epochs = 100
n_folds = 3
preds_test = 0
train_scores = []; valid_scores = []
kf = KFold(n_splits=n_folds, random_state=10, shuffle=True)
history = []
for i, (train_index, test_index) in enumerate(kf.split(fps_train)):
x_train = [fps_train[j] for j in train_index]; x_valid = [fps_train[j] for j in test_index]
y_train = labels_train[train_index]; y_valid = labels_train[test_index]
def train_generator():
while 1:
for start in range(0, len(x_train), batch_size):
x_batch = []
end = min(start + batch_size, len(x_train))
train_batch = x_train[start:end]
for filepath in train_batch:
img = cv2.imread(filepath)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, img_size)
# data augmentation
img = np.expand_dims(img, axis=0)
img = next(datagen.flow(img, batch_size=1))[0]
x_batch.append(img)
y_batch = y_train[start:end]
x_batch = np.array(x_batch, np.float32)
y_batch = np.array(y_batch, np.uint8)
yield x_batch, y_batch
def valid_generator():
while 1:
for start in range(0, len(x_valid), batch_size):
x_batch = []
end = min(start + batch_size, len(x_valid))
valid_batch = x_valid[start:end]
for filepath in valid_batch:
img = cv2.imread(filepath)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, img_size)
# data augmentation
img = np.expand_dims(img, axis=0)
img = next(datagen.flow(img, batch_size=1))[0]
x_batch.append(img)
y_batch = y_train[start:end]
x_batch = np.array(x_batch, np.float32)
y_batch = np.array(y_batch, np.uint8)
yield x_batch, y_batch
def test_generator():
while 1:
for start in range(0, len(labels_test), batch_size):
x_batch = []
end = min(start + batch_size, len(labels_test))
test_batch = fps_test[start:end]
for filepath in test_batch:
img = cv2.imread(filepath)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, img_size)
x_batch.append(img)
x_batch = np.array(x_batch, np.float32)
yield x_batch
train_steps = len(x_train) / batch_size
valid_steps = len(x_valid) / batch_size
test_steps = len(labels_test) / batch_size
model = model
model.compile(optimizer=SGD(lr=0.00001, momentum=0.9), loss='categorical_crossentropy',
metrics = ['accuracy'])
# sparse_categorical_crossentropy
history.append(model.fit_generator(train_generator(),
train_steps,
epochs=epochs,
verbose=1,
validation_data=valid_generator(),
validation_steps=valid_steps,
shuffle=True))
preds_valid = model.predict_generator(generator=valid_generator(),
steps=valid_steps, verbose=1)
preds_train = model.predict_generator(generator=train_generator(),
steps=train_steps, verbose=1)
preds_test_fold = model.predict_generator(generator=test_generator(),
steps=test_steps, verbose=1)
valid_score = metrics.roc_auc_score(y_valid, preds_valid)
train_score = metrics.roc_auc_score(y_train, preds_train)
print('valid score:{} for fold {}'.format(valid_score, i))
print('train score: {} for fold {}'.format(train_score, i))
valid_scores.append(valid_score)
train_scores.append(train_score)
print('avg valid score:{0:0.5f} after {1:0.5f} folds'.format(np.mean(valid_scores), i))
print('avg train score:{0:0.5f} after {1:0.5f} folds'.format(np.mean(train_scores), i))
preds_test += preds_test_fold
preds_test /= n_folds
test_score = metrics.roc_auc_score(labels_test, preds_test)
print(test_score)
Epoch 1/100
13/12 [===============================] - 114s 9s/step - loss: 1.7377 - acc: 0.2696 - val_loss: 1.7597 - val_acc: 0.2300
Epoch 2/100
13/12 [===============================] - 110s 8s/step - loss: 1.6934 - acc: 0.3023 - val_loss: 1.8588 - val_acc: 0.1550
Epoch 3/100
13/12 [===============================] - 111s 9s/step - loss: 1.7105 - acc: 0.3643 - val_loss: 1.7486 - val_acc: 0.2500
Epoch 4/100
13/12 [===============================] - 111s 9s/step - loss: 1.6023 - acc: 0.3164 - val_loss: 1.8622 - val_acc: 0.1950
Epoch 5/100
13/12 [===============================] - 119s 9s/step - loss: 1.6091 - acc: 0.3316 - val_loss: 1.7544 - val_acc: 0.2100
Epoch 6/100
13/12 [===============================] - 119s 9s/step - loss: 1.6923 - acc: 0.2882 - val_loss: 1.7124 - val_acc: 0.2600
Epoch 7/100
13/12 [===============================] - 118s 9s/step - loss: 1.6071 - acc: 0.3602 - val_loss: 1.8326 - val_acc: 0.2100
Epoch 8/100
13/12 [===============================] - 110s 8s/step - loss: 1.6666 - acc: 0.2882 - val_loss: 1.7460 - val_acc: 0.2250
Epoch 9/100
13/12 [===============================] - 107s 8s/step - loss: 1.5762 - acc: 0.3684 - val_loss: 1.7904 - val_acc: 0.1850
Epoch 10/100
13/12 [===============================] - 106s 8s/step - loss: 1.6371 - acc: 0.3550 - val_loss: 1.8316 - val_acc: 0.2000
Epoch 11/100
13/12 [===============================] - 105s 8s/step - loss: 1.5918 - acc: 0.3602 - val_loss: 1.6973 - val_acc: 0.2650
Epoch 12/100
13/12 [===============================] - 106s 8s/step - loss: 1.5225 - acc: 0.3987 - val_loss: 1.7811 - val_acc: 0.2100
Epoch 13/100
13/12 [===============================] - 105s 8s/step - loss: 1.6055 - acc: 0.3561 - val_loss: 1.8557 - val_acc: 0.1450
Epoch 14/100
13/12 [===============================] - 108s 8s/step - loss: 1.5136 - acc: 0.3368 - val_loss: 1.8463 - val_acc: 0.1650
Epoch 15/100
13/12 [===============================] - 108s 8s/step - loss: 1.5672 - acc: 0.3654 - val_loss: 1.7392 - val_acc: 0.2050
Epoch 16/100
13/12 [===============================] - 109s 8s/step - loss: 1.5112 - acc: 0.3939 - val_loss: 1.7721 - val_acc: 0.2200
Epoch 17/100
13/12 [===============================] - 106s 8s/step - loss: 1.3944 - acc: 0.4614 - val_loss: 1.7274 - val_acc: 0.2200
Epoch 18/100
13/12 [===============================] - 106s 8s/step - loss: 1.3603 - acc: 0.4559 - val_loss: 1.7671 - val_acc: 0.2050
Epoch 19/100
13/12 [===============================] - 107s 8s/step - loss: 1.4985 - acc: 0.3843 - val_loss: 1.7367 - val_acc: 0.2150
Epoch 20/100
13/12 [===============================] - 107s 8s/step - loss: 1.4073 - acc: 0.4180 - val_loss: 1.8292 - val_acc: 0.1700
Epoch 21/100
13/12 [===============================] - 111s 9s/step - loss: 1.4495 - acc: 0.3743 - val_loss: 1.8178 - val_acc: 0.2050
Epoch 22/100
13/12 [===============================] - 108s 8s/step - loss: 1.3810 - acc: 0.4704 - val_loss: 1.8049 - val_acc: 0.2000
Epoch 23/100
13/12 [===============================] - 105s 8s/step - loss: 1.3556 - acc: 0.4366 - val_loss: 1.7813 - val_acc: 0.2050
Epoch 24/100
13/12 [===============================] - 111s 9s/step - loss: 1.3139 - acc: 0.4614 - val_loss: 1.8184 - val_acc: 0.2000
Epoch 25/100
13/12 [===============================] - 111s 9s/step - loss: 1.4152 - acc: 0.4421 - val_loss: 1.8859 - val_acc: 0.1300
Epoch 26/100
13/12 [===============================] - 110s 8s/step - loss: 1.3630 - acc: 0.4577 - val_loss: 1.7652 - val_acc: 0.2250
Epoch 27/100
13/12 [===============================] - 110s 8s/step - loss: 1.3347 - acc: 0.4521 - val_loss: 1.7304 - val_acc: 0.2200
Epoch 28/100
13/12 [===============================] - 107s 8s/step - loss: 1.2981 - acc: 0.5048 - val_loss: 1.8108 - val_acc: 0.2200
Epoch 29/100
2/12 [===>..........................] - ETA: 52s - loss: 1.5823 - acc: 0.3125