**基于卷积神经网络的笑脸数据集(GENKI4K)训练**

基于卷积神经网络的笑脸数据集(GENKI4K)训练
一、人脸图像特征提取的方法
1.HOG 特征
方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图
像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度方向
直方图来构成特征。Hog 特征结合 SVM 分类器已经被广泛应用于图像识别中,尤其在
行人检测中获得了极大的成功。需要提醒的是,HOG+SVM 进行行人检测的方法是法国
研究人员 Dalal 在 2005 的 CVPR 上提出的,而如今虽然有很多行人检测算法不断提出,
但基本都是以 HOG+SVM 的思路为主。
(1)主要思想:
在一副图像中,局部目标的表象和形状(appearance and shape)能够被梯度或边缘的
方向密度分布很好地描述。(本质:梯度的统计信息,而梯度主要存在于边缘的地方)。
(2)具体的实现方法是:
首先将图像分成小的连通区域,我们把它叫细胞单元。然后采集细胞单元中各像素点的
梯度的或边缘的方向直方图。最后把这些直方图组合起来就可以构成特征描述器。
(3)提高性能:
把这些局部直方图在图像的更大的范围内(我们把它叫区间或 block)进行对比度归一
化(contrast-normalized),所采用的方法是:先计算各直方图在这个区间(block)中
的密度,然后根据这个密度对区间中的各个细胞单元做归一化。通过这个归一化后,能
对光照变化和阴影获得更好的效果。
(4)优点:
与其他的特征描述方法相比,HOG 有很多优点。首先,由于 HOG 是在图像的局部方格
单元上操作,所以它对图像几何的和光学的形变都能保持很好的不变性,这两种形变只
会出现在更大的空间领域上。其次,在粗的空域抽样、精细的方向抽样以及较强的局部
光学归一化等条件下,只要行人大体上能够保持直立的姿势,可以容许行人有一些细微
的肢体动作,这些细微的动作可以被忽略而不影响检测效果。因此 HOG 特征是特别适
合于做图像中的人体检测的。
HOG 特征提取方法就是将一个 image(你要检测的目标或者扫描窗口):
1)灰度化(将图像看做一个 x,y,z(灰度)的三维图像);
2)采用 Gamma 校正法对输入图像进行颜色空间的标准化(归一化);目的是调节图
像的对比度,降低图像局部的阴影和光照变化所造成的影响,同时可以抑制噪音的干扰;
3)计算图像每个像素的梯度(包括大小和方向);主要是为了捕获轮廓信息,同时进
一步弱化光照的干扰。
4)将图像划分成小 cells(例如 66 像素/cell);
5)统计每个 cell 的梯度直方图(不同梯度的个数),即可形成每个 cell 的 descriptor;
6)将每几个 cell 组成一个 block(例如 3
3 个 cell/block),一个 block 内所有 cell 的
特征 descriptor 串联起来便得到该 block 的 HOG 特征 descriptor。
7)将图像 image 内的所有 block 的 HOG 特征 descriptor 串联起来就可以得到该 image
(你要检测的目标)的 HOG 特征 descriptor 了。这个就是最终的可供分类使用的特征
向量了。
2.Dlib
Dlib 是一个包含机器学习算法的 C++开源工具包。Dlib 可以帮助您创建很多复杂的机器
学习方面的软件来帮助解决实际问题。目前 Dlib 已经被广泛的用在行业和学术领域,包
括机器人,嵌入式设备,移动电话和大型高性能计算环境。
Dlib 的主要特点:

  1. 文档齐全
    不像很多其他的开源库一样,Dlib 为每一个类和函数提供了完整的文档说明。同时,还提供了
    debug 模式;打开 debug 模式后,用户可以调试代码,查看变量和对象的值,快速定位错误点。
    另外,Dlib 还提供了大量的实例。
  2. 高质量的可移植代码
    Dlib 不依赖第三方库,无须安装和配置,这部分可参照(官网左侧树形目录的 how to compile
    的介绍)。Dlib 可用在 window、Mac OS、Linux 系统上。
  3. 提供大量的机器学习 / 图像处理算法
    深度学习
    基于 SVM 的分类和递归算法
    针对大规模分类和递归的降维方法
    相关向量机(relevance vector machine);是与支持向量机相同的函数形式稀疏概率模型,对未知函数进行
    预测或分类。其训练是在贝叶斯框架下进行的,与 SVM 相比,不需要估计正则化参数,其核函数也不需
    要满足 Mercer 条件,需要更少的相关向量,训练时间长,测试时间短。
    聚类: linear or kernel k-means, Chinese Whispers, and Newman clustering. Radial Basis Function Networks
    多层感知机
    3.卷积神经网络
    卷积神经网络(Convolutional Neural Networks)是一种深度学习模型或类似于人工神
    经网络的多层感知器,常用来分析视觉图像。卷积神经网络的创始人是着名的计算机科
    学家 Yann LeCun,目前在 Facebook 工作,他是第一个通过卷积神经网络在 MNIST 数
    据集上解决手写数字问题的人。
    卷积神经网络 CNN 主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。由于
    CNN 的特征检测层通过训练数据进行学习,所以在使用 CNN 时,避免了显式的特征抽
    取,而隐式地从训练数据中进行学习;再者由于同一特征映射面上的神经元权值相同,
    所以网络可以并行学习,这也是卷积网络相对于神经元彼此相连网络的一大优势。卷积
    神经网络以其局部权值共享的特殊结构在语音识别和图像处理方面有着独特的优越性,
    其布局更接近于实际的生物神经网络,权值共享降低了网络的复杂性,特别是多维输入
    向量的图像可以直接输入网络这一特点避免了特征提取和分类过程中数据重建的复杂
    度。
    卷积神经网络中,第一步一般用卷积核去提取特征,这些初始化的卷积核会在反向传播
    的过程中,在迭代中被一次又一次的更新,无限地逼近我们的真实解。其实本质没有对
    图像矩阵求解,而是初始化了一个符合某种分布的特征向量集,然后在反向传播中无限
    更新这个特征集,让它能无限逼近数学中的那个概念上的特征向量,以致于我们能用特
    征向量的数学方法对矩阵进行特征提取。
    二、笑脸数据集(GENKI4K)训练
    1.准备数据集
    (下载的数据集)
    2.导入 Keras 库,并划分数据集
    import keras
    keras.version
    import os, shutil #复制文件
    #原始目录所在的路径
    数据集未压缩
    original_dataset_dir0 = ‘D:\Workspaces\Jupyter-notebook\datasets\mldata
    \smile\train_folder\0’
    original_dataset_dir1 = ‘D:\Workspaces\Jupyter-notebook\datasets\mldata
    \smile\train_folder\1’
    我们将在其中的目录存储较小的数据集
    base_dir = 'D:\Workspaces\Jupyter-notebook\datasets\mldata\smile_small

    os.mkdir(base_dir)

训练、验证、测试数据集的目录

train_dir = os.path.join(base_dir, ‘train’)
os.mkdir(train_dir)
validation_dir = os.path.join(base_dir, ‘validation’)
os.mkdir(validation_dir)
test_dir = os.path.join(base_dir, ‘test’)
os.mkdir(test_dir)
#笑训练图片所在目录
train_smile_dir = os.path.join(train_dir, ‘smile’)
os.mkdir(train_smile_dir)
#不笑训练图片所在目录
train_unsmile_dir = os.path.join(train_dir, ‘unsmile’)
os.mkdir(train_unsmile_dir)
#笑验证图片所在目录
validation_smile_dir = os.path.join(validation_dir, ‘smile’)
os.mkdir(validation_smile_dir)
#不笑验证数据集所在目录
validation_unsmile_dir = os.path.join(validation_dir, ‘unsmile’)
os.mkdir(validation_unsmile_dir)
笑测试数据集所在目录
test_smile_dir = os.path.join(test_dir, ‘smile’)
os.mkdir(test_smile_dir)
不笑测试数据集所在目录
test_unsmile_dir = os.path.join(test_dir, ‘unsmile’)
os.mkdir(test_unsmile_dir)
#将前 1000 张笑图像复制到 train_smile_dir
fnames = [‘smile{}.jpg’.format(i) for i in range(1000)]
for fname in fnames:
src = os.path.join(original_dataset_dir1, fname)
dst = os.path.join(train_smile_dir, fname)
shutil.copyfile(src, dst)
将下 500 张笑图像复制到 validation_smile_dir
fnames = [‘smile{}.jpg’.format(i) for i in range(1000, 1500)]
for fname in fnames:
src = os.path.join(original_dataset_dir1, fname)
dst = os.path.join(validation_smile_dir, fname)
shutil.copyfile(src, dst)
#将下 500 张笑图像复制到 test_smile_dir
fnames = [‘smile{}.jpg’.format(i) for i in range(1000, 1500)]
for fname in fnames:
src = os.path.join(original_dataset_dir1, fname)
dst = os.path.join(test_smile_dir, fname)
shutil.copyfile(src, dst)
将前 1000 张不笑图像复制到 train_unsmile_dir
fnames = [‘unsmile{}.jpg’.format(i) for i in range(1000)]
for fname in fnames:
src = os.path.join(original_dataset_dir0, fname)
dst = os.path.join(train_unsmile_dir, fname)
shutil.copyfile(src, dst)
#将 500 张不笑图像复制到 validation_unsmile_dir
fnames = [‘unsmile{}.jpg’.format(i) for i in range(700, 1200)]
for fname in fnames:
src = os.path.join(original_dataset_dir0, fname)
dst = os.path.join(validation_unsmile_dir, fname)
shutil.copyfile(src, dst)
将 500 张不笑图像复制到 test_unsmile_dir
fnames = [‘unsmile{}.jpg’.format(i) for i in range(700, 1200)]
for fname in fnames:
src = os.path.join(original_dataset_dir0, fname)
dst = os.path.join(test_unsmile_dir, fname)
shutil.copyfile(src, dst)
作为健全性检查,让我们计算一下每个训练分组(训练/验证/测试)中有多少张图片:
print(‘total training cat images:’, len(os.listdir(train_smile_dir)))
print(‘total training dog images:’, len(os.listdir(train_unsmile_dir)))
print(‘total validation cat images:’, len(os.listdir(validation_smile_dir)))
print(‘total validation dog images:’, len(os.listdir(validation_unsmile_di
r)))
print(‘total test cat images:’, len(os.listdir(test_smile_dir)))
print(‘total test dog images:’, len(os.listdir(test_unsmile_dir)))

划分的图片数量与前面代码写的一致。

3.构建网络
from keras import layers
from keras import models
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation=‘relu’,
input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation=‘relu’))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation=‘relu’))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation=‘relu’))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(512, activation=‘relu’))
model.add(layers.Dense(1, activation=‘sigmoid’))
看一下特征贴图的尺寸如何随每个连续层变化:
model.summary()

4.数据预处理
from keras import optimizers
model.compile(loss=‘binary_crossentropy’,
optimizer=optimizers.RMSprop(lr=1e-4),
metrics=[‘acc’])
from keras.preprocessing.image import ImageDataGenerator
All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
This is the target directory
train_dir,
All images will be resized to 150x150
target_size=(150, 150),
batch_size=20,
Since we use binary_crossentropy loss, we need binary labels
class_mode=‘binary’)
validation_generator = test_datagen.flow_from_directory(
validation_dir,
target_size=(150, 150),
batch_size=20,
class_mode=‘binary’)
for data_batch, labels_batch in train_generator:
print(‘data batch shape:’, data_batch.shape)
print(‘labels batch shape:’, labels_batch.shape)
break
5.训练模型
history = model.fit_generator(
train_generator,
steps_per_epoch=100,
epochs=30,
validation_data=validation_generator,
validation_steps=50)
取部分训练轮数:

保存模型:
model.save(‘smile_and_unsmile_small_1.h5’)
在训练和验证数据上绘制模型的损失和准确性:
import matplotlib.pyplot as plt
acc = history.history[‘acc’]
val_acc = history.history[‘val_acc’]
loss = history.history[‘loss’]
val_loss = history.history[‘val_loss’]
epochs = range(len(acc))
plt.plot(epochs, acc, ‘bo’, label=‘Training acc’)
plt.plot(epochs, val_acc, ‘b’, label=‘Validation acc’)
plt.title(‘Training and validation accuracy’)
plt.legend()
plt.figure()
plt.plot(epochs, loss, ‘bo’, label=‘Training loss’)
plt.plot(epochs, val_loss, ‘b’, label=‘Validation loss’)
plt.title(‘Training and validation loss’)
plt.legend()
plt.show()
6.使用数据增强
数据增强采用了通过现有的训练样本生成更多训练数据的方法,方法是通过许多随机变
换来“增加”样本,以产生看起来可信的图像。目的是模型在训练时不会两次查看完全相
同的图像。这让模型能够观察到数据的更多内容,从而具有更好的泛化能力。
在 Keras 中,这可以通过配置要对 ImageDataGenerator 实例读取的图像执行的许多随 机转换来完成。让我们开始一个例子:
datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode=‘nearest’)
看一下我们的增强图像:
This is module with image preprocessing utilities
from keras.preprocessing import image
fnames = [os.path.join(train_smile_dir, fname) for fname in os.listdir(trai
n_smile_dir)]
We pick one image to “augment”
img_path = fnames[3]
Read the image and resize it
img = image.load_img(img_path, target_size=(150, 150))
Convert it to a Numpy array with shape (150, 150, 3)
x = image.img_to_array(img)
Reshape it to (1, 150, 150, 3)
x = x.reshape((1,) + x.shape)
The .flow() command below generates batches of randomly transformed image
s.
It will loop indefinitely, so we need to break the loop at some point!
i = 0
for batch in datagen.flow(x, batch_size=1):
plt.figure(i)
imgplot = plt.imshow(image.array_to_img(batch[0]))
i += 1
if i % 4 == 0:
break
plt.show()

在紧密连接的分类器之前为模型添加一个 Dropout 层:
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation=‘relu’,
input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation=‘relu’))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation&

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值