利用Python通过强化CNN和Keras识别名人
当你在互联网上看到一张图片时,你有没有想过,这位名人是谁?我从一个类似的场景开始思考,想看看机器学习模型是否能帮助我们解决这个问题。
作为这个项目的一部分,我所做的就是看看机器学习模特是否能从一组照片中辨认出名人的名字。由于计算资源的限制,我将项目限制在三个不同的女明星。
1、采集训练数据,这个数据需要是图像格式,如果我们想要一个好的准确性,则必须是巨大的数量。如前所述,我选择了三位名人(Jennifer Lawrence,Ariel winter和Kaley Cuoco),并使用网络抓取来获取图像(https://celebmafia.com/)。
数据集中的图像计数如下:
2、下一步是从这个bucket列表中导入所有Python库。如果在此步骤中有任何导入错误,那么在继续进行任何操作之前,需要修复该特定库。下面是这些Python库的详尽列表
from __future__ import print_function, division import numpy as np import random import os import glob import cv2 import datetime import pandas as pd import time import h5py import csv from scipy.misc import imresize, imsave from sklearn.cross_validation import KFold, train_test_split from sklearn.metrics import log_loss, confusion_matrix from sklearn.utils import shuffle from PIL import Image, ImageChops, ImageOps import matplotlib.pyplot as plt from keras import backend as K from keras.callbacks import EarlyStopping, Callback from keras.utils import np_utils from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array from keras import optimizers from keras.models import Sequential, model_from_json from keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D, Activation, Dropout, Flatten, Dense from keras.models import Sequential from keras.layers import Conv2D from keras.layers import MaxPooling2D from keras.layers import Flatten from keras.layers import Dense import keras
3、下一步是生成图像数据,这些数据是对数据集中现有图像的一些修改。所谓修改,即同样的图像使用缩放、剪切和翻转,将为神经网络生成一个全新的数据点。我们在这些数据上训练我们的模型越多,我们的模型在识别测试数据中的细微变化时就会更加健壮。
这需要我们创建一个图像数据生成器,将其应用于我们在前一节中准备的目录。类模式将是分类的,并且需要softmax层。Python代码如下:
train_datagen = ImageDataGenerator(rescale = 1./255, shear_range = 0.2, zoom_range = 0.2, horizontal_flip = True) training_data = train_datagen.flow_from_directory(r'.', target_size = (224, 224), batch_size = 20, class_mode = 'categorical')
4、一旦完成上述步骤,我们将需要构建一个可以使用数据进行训练的机器学习模型。为此,我们将使用深度强化学习。VGG16符合我们的要求。我们在现有的VGG模型中添加了一个可训练的top模型。这将为我们提供最后一个具有三个可能输出的层。模型中的最后一步需要有损失、优化器和要进行训练的指标。Python实现如下:
model = applications.VGG16(weights='imagenet', include_top=False , input_shape=(224,224,3)) top_model = Sequential() top_model.add(Flatten(input_shape=model.output_shape[1:])) top_model.add(Dense(256, activation='relu',name='newlayer')) top_model.add(Dropout(0.5)) top_model.add(Dense(3, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer=optimizers.Adam(lr=0.0001), metrics=['accuracy'])
5、最后,我们通过传递steps_per_epoch、epochs数、训练集和验证集等参数来训练模型,这是我在系统上运行时收到的准确率和loss data。我们发现,目前的模型具有80%验证集精度的良好性能。
6、现在我们来看看我们的模型是如何工作的。为此,我创建了一个函数,它随机选取8张图像,将其输入到模型中以生成预测,然后用预测的名称对图像进行标签。我为模型设定了0.8的阈值,以便在图像上添加最终标签。
import numpy as np import matplotlib.pyplot as plt import matplotlib.image as mpimg w=10 h=10 fig=plt.figure(figsize=(16, 16)) columns = 4 rows = 5 ran=np.random.randint(low=1, high=60, size=9) shown = [] for i in range(1, len(ran)): k=ran[i] labelString = f"celeb/test/1 ({k}).jpg" shown.append(f"celeb/test/1 ({k}).jpg") img=mpimg.imread(f"celeb/test/1 ({k}).jpg") subp=fig.add_subplot(rows, columns, i) subp.set_title(predict(labelString)) plt.imshow(img) plt.show()
放置标签的函数如下
import numpy as np def predict(imagesToPredict): from keras.preprocessing import image test_image = image.load_img(imagesToPredict, target_size = (224, 224)) test_image = image.img_to_array(test_image) test_image = np.expand_dims(test_image, axis = 0) result = model.predict(test_image) prediction ="" print(str(result[0][0] ) +'##' + str(result[0][1] ) +'##' + str( result[0][2] )) # training_set.class_indices if result[0][0] > 0.8: prediction = 'Ariel Winter' elif(result[0][1] > 0.8): prediction = 'Jennifer Lawrence' elif(result[0][2] > 0.8): prediction = 'Kaley Cuoco' return ('Prediction: '+ prediction)
结果:我们发现在我们的测试集中,8个预测中有2个是错误的。这给出了75%的准确度(接近验证结果)