这次的实践是基于很小的数据集,搭建的系统也比较粗糙,只是个toy implementation。主要用来练手和熟悉流程的。
1. 数据集准备
- 安装 dlib
用
pip install dlib
会提示安装失败,只能从dlib官网 下载whl文件,再用pip install dlib-18.17.100-cp35-none-win_amd64.whl
命令安装。 - 利用dlib截取自己的图片和别人的图片 参考写个神经网络,让她认得我(๑•ᴗ•๑),参考里面的代码截取了200张自己的图片和200张别人的图片,截取的图片宽高为64*64.
- 训练集和验证集划分
- 训练集:分别取自己和别人前160张图片作为训练集
- 验证集:分别取自己和别人后40张图片作为验证集
2. 数据预处理
- 转换图片形状 将输入的图片的形状转换为符合(None, width, height, channels)的形状,None是为batch_size预留的参数。不这么做的话,后面应用Keras写代码就会报错,因为Keras的CNN需要一个4D阵列(或者说张量)作为输入。 以下代码参考udacity深度学习项目二,不妥删。
from keras.preprocessing import image
from tqdm import tqdm # tqdm是显示进度条的包
def path_to_tensor(img_path):
# loads RGB image as PIL.Image.Image type
img = image.load_img(img_path, target_size=(64, 64))
# convert PIL.Image.Image type to 3D tensor with shape (64, 64, 3)
x = image.img_to_array(img)
# convert 3D tensor to 4D tensor with shape (1, 64, 64, 3) and return 4D tensor
return np.expand_dims(x, axis=0)
def paths_to_tensor(img_paths):
list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
return np.vstack(list_of_tensors)
- 添加标签 给训练集,验证集分别添加标签,0为自己的脸,1为别人的脸。
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
# load the train files
train_files = np.array(glob('faces/train/*/*'))
# set my face label is 0, the other face labels is 1
train_labels = np.array([0] * int(320/ 2) [1] *int(320/2))
# load the validation files
valid_files = np.array(glob('faces/validation/*/*'))
# set my face label is 0, the other face labels is 1
valid_labels = np.array([0] * int(80/ 2) [1] *int(80/2))
## load the test files
#test_files = np.array(glob('faces/test/*/*'))
#test_labels = np.array([0] * int(8/ 2) [1] *int(8/2))
# pre-process the data for Keras
train_data = paths_to_tensor(train_files).astype('float32')/64
valid_data = paths_to_tensor(valid_files).astype('float32')/64
#test_data = paths_to_tensor(test_files).astype('float32')/64
3. 搭建并训练CNN模型
代码语言:javascript复制from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense, Conv2D, MaxPooling2D
# bulid the CNN model
model = Sequential()
model.add(Conv2D(filters=16, kernel_size=2, padding='same', activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(filters=64, kernel_size=2, padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Flatten())
model.add(Dropout(0.5))
model.add(Dense(100, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
model.summary()
# compile the model
model.compile(optimizer='adam',
loss='binary_crossentropy', metrics=['accuracy'])
# fit the model
model.fit(train_data, train_labels,
epochs=10,
batch_size=320,
validation_data=(valid_data, valid_labels))
训练结果:
4. 测试模型
- 建立face_predict()用于测试
def face_predict(img_path):
image = path_to_tensor(img_path)
# 给出输入属于各个类别的概率,这里是二元分类,则该函数会给出输入图像属于0和1的概率各为多少
# result = model.predict(image)
# print('result:', result)
# 给出分类预测:0或者1
result = model.predict_classes(image)
print('result:', result)
# 返回分类预测结果
if result == 0:
return "Hi,cao!"
else:
return "Stranger !"
- 测试结果:
In [184]:
images = np.array(glob('E:/faces/test/*/*'))
face_predict(images[2]) # 测试自己的图片
result: [[0]]
Out[184]:
'Hi,cao!'
In [185]:
face_predict(images[5]) # 测试别人的图片
result: [[1]]
Out[185]:
'Stranger !'