在过去的两个月里,我一直尝试使用Keras创建一个能够区分我自己和其他人的分类模型。我从狗与猫分类器开始,并替换了数据集。从那时起,我对网络和数据集进行了一些调整,并取得了一些成功。我还尝试了多种不同的数据增强组合(翻转、旋转、灰度化、调整亮度和暗度;我的增强方法可以将一张图片变成九张)。
在训练过程中,我使用笔记本电脑的摄像头从不同角度和方向捕捉我的面部,然后将其分为三份(1/3用于验证,2/3用于训练)。对于负面示例,我有另一组随机人的数据集,同样也按相同方式划分。
- 验证集:
- 本人:300
- 其他人:300
- 训练集:
- 本人:600
- 其他人:600
为了测试我的模型,我使用了一些家庭照片,达到了大约80%的准确率,但为此我只使用了60张照片,其中36张是我自己的照片。
img_width, img_height = 150, 150if K.image_data_format() == 'channels_first': input_shape = (3, img_width, img_height)else: input_shape = (img_width, img_height, 3)model = Sequential()model.add(Conv2D(32, (3, 3), input_shape=input_shape))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Conv2D(32, (3, 3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Conv2D(64, (3, 3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Flatten())model.add(Dense(64))model.add(Activation('relu'))model.add(Dropout(0.5))model.add(Dense(1))model.add(Activation('sigmoid'))model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])train_datagen = ImageDataGenerator( rescale=1. / 255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)test_datagen = ImageDataGenerator(rescale=1. / 255)train_generator = train_datagen.flow_from_directory( train_data_dir, target_size=(img_width, img_height), batch_size=batch_size, class_mode='binary')print(train_generator.class_indices)validation_generator = test_datagen.flow_from_directory( validation_data_dir, target_size=(img_width, img_height), batch_size=batch_size, class_mode='binary')print(validation_generator.class_indices)model.fit_generator( train_generator, steps_per_epoch=train_samples // batch_size, epochs=epochs, callbacks=[tensorboard], validation_data=validation_generator, validation_steps=validation_samples // batch_size)model.save('model.h5')
我所有的训练尝试都大致相同。前1-2个epoch的准确率和损失值接近,而后续的epoch准确率跳至0.9,损失降至0.1。
我的假设是问题出在数据集上。如何仅使用通过网络摄像头拍摄的照片来达到合理的准确度呢?
回答:
考虑到您的数据量,使用迁移学习而不是从头开始训练会是一个更好的方法。您可以从预训练的ImageNet模型如Resnet或Inception开始。但我认为在大型面部数据集上训练的模型可能会表现得更好。您可以查看这里的Facenet实现。您可以仅训练最后的全连接层权重,并“冻结”前面的层。如何使用Facenet进行分类可以参考这里。