使用CNN(convolutional neural nets)检测脸部关键点教程(二):浅层网络训练和测试

第三部分 第一个模型:一个隐层结构的传统神经网络

这一部分让我们从代码开始:

# add to kfkd.py
from lasagne import layers
from lasagne.updates import nesterov_momentum
from nolearn.lasagne import NeuralNet

net1 = NeuralNet(
layers=[  # three layers: one hidden layer
    (‘input‘, layers.InputLayer),
    (‘hidden‘, layers.DenseLayer),
    (‘output‘, layers.DenseLayer),
    ],
# layer parameters:
input_shape=(None, 9216),  # 96x96 input pixels per batch
hidden_num_units=100,  # number of units in hidden layer
output_nonlinearity=None,  # output layer uses identity function
output_num_units=30,  # 30 target values

# optimization method:
update=nesterov_momentum,
update_learning_rate=0.01,
update_momentum=0.9,

regression=True,  # flag to indicate we‘re dealing with regression problem
max_epochs=400,  # we want to train this many epochs
verbose=1,
)

X, y = load()
net1.fit(X, y)

在这个网络中,我们使用了一些参数来初始化,让我们从头梳理:

layers=[  # three layers: one hidden layer
    (‘input‘, layers.InputLayer),
    (‘hidden‘, layers.DenseLayer),
    (‘output‘, layers.DenseLayer),
    ],
# layer parameters:
input_shape=(None, 9216),  # 96x96 input pixels per batch
hidden_num_units=100,  # number of units in hidden layer
output_nonlinearity=None,  # output layer uses identity function
output_num_units=30,  # 30 target values

这里我们定义了input层,hidden层,还有output层。在layers参数下,我们定义了每一层的类型,以及层与层之间的顺序。input_shape , hidden_num_units ,output_nonlinearity ,output_num_units 分别指定了每一层的参数,这些参数通过前缀指定相应的层,如input_shape制定了input层。之所以采用这种稍显奇怪的方式来制定参数,是为了更好的兼容scikit-learn从而更好的利用其优势。

我们将输入的第一个维度设置为None,相当于设定了可变的batch size。

将输出层非线性显示的设置为None。也就是,输出层单元的激活方式是线性的,即隐藏层激活值的线性组合。

Denselayer的默认非线性特性曲线是rectifier,即max(0,x),当先最流行的激活方程。通过不明确的制定隐藏层的激活方程,也就制定了rectifier作为隐层的激活方程。

神经网络的权重初始化为某一个区间的均匀分布值,Lasagne已经选好了这个区间。【区间选取参考

还有一些没有介绍的参数,这些参数都以update开头用来表示更新方程(或最优化方法)的参数。更新方程将会在每个batch后更新神经网络的权重。我们使用nesterov_momentum梯度下降这种最优化方法来完成这个工作。Lasagne还为我们实现了一些

其他的方法诸如adagrad和rmsprop。我们选择nesterov_momentum是因为这种方法已经在大量的问题上被证明有效。

# optimization method:
update=nesterov_momentum,
update_learning_rate=0.01,
update_momentum=0.9,

update_learning_rate定义了梯度下降更新权重的步长。我们稍后讨论学习率和momentum参数,现在的话,这种健全的默认值已经足够了。

上图是不同的最优化方法的对比(animation by Alec Radford)。星标位置为全局最优值。注意不添加“势”的随机梯度下降是收敛最慢的,我们在教程中从头到尾都是用Nesterov加速过的梯度下降。

最后两行加载了数据,然后用数据训练了我们的第一个神经网络。

X, y = load()
net1.fit(X, y)

运行这两行会输出一个表格,每次完成一个epoch就输出一行。每一行里,我们可以看到当前的训练损失和验证损失(最小二乘损失),以及两者的比率。NeuroNet将会自动把输入数据X分成训练集和测试集,用20%的数据作验证。(比率可以通过参数eval_size=0.2调整)

$ python kfkd.py
...
  InputLayer          (None, 9216)            produces    9216 outputs
  DenseLayer          (None, 100)             produces     100 outputs
  DenseLayer          (None, 30)              produces      30 outputs

     Epoch  |  Train loss  |  Valid loss  |  Train / Val
    --------|--------------|--------------|----------------
     1  |    0.105418  |    0.031085  |     3.391261
     2  |    0.020353  |    0.019294  |     1.054894
     3  |    0.016118  |    0.016918  |     0.952734
     4  |    0.014187  |    0.015550  |     0.912363
     5  |    0.013329  |    0.014791  |     0.901199
    ...
   200  |    0.003250  |    0.004150  |     0.783282
   201  |    0.003242  |    0.004141  |     0.782850
   202  |    0.003234  |    0.004133  |     0.782305
   203  |    0.003225  |    0.004126  |     0.781746
   204  |    0.003217  |    0.004118  |     0.781239
   205  |    0.003209  |    0.004110  |     0.780738
    ...
   395  |    0.002259  |    0.003269  |     0.690925
   396  |    0.002256  |    0.003264  |     0.691164
   397  |    0.002254  |    0.003264  |     0.690485
   398  |    0.002249  |    0.003259  |     0.690303
   399  |    0.002247  |    0.003260  |     0.689252
   400  |    0.002244  |    0.003255  |     0.689606

在相对较快的GPU上训练,我们能够在1分钟之内完成400个epoch的训练。注意测试损失会一直减小。

现在我们有了一个很好的结果了么?我们看到测试误差是0.0032,和竞赛基准比试一下。注意我们将目标除以了48以将其缩放到-1到1之间,也就是说,要是想计算均方误差和排行榜的结果比较,必须把我们上面得到的0.003255还原到原来的尺度。

>>> import numpy as np
>>> np.sqrt(0.003255) * 48
2.7385251505144153

这个值应该可以代表我们的成绩了。当然,这得假设测试集合的数据和训练集合的数据符合相同的分布,但事实却并非如此。

第四部分 测试刚刚的网络

我们刚刚训练的net1对象已经保存了训练时打印在控制台桌面中的记录,我们可以获取这个记录通过train_history_相关属性,让我们画出这两个曲线。

train_loss = np.array([i["train_loss"] for i in net1.train_history_])
valid_loss = np.array([i["valid_loss"] for i in net1.train_history_])
pyplot.plot(train_loss, linewidth=3, label="train")
pyplot.plot(valid_loss, linewidth=3, label="valid")
pyplot.grid()
pyplot.legend()
pyplot.xlabel("epoch")
pyplot.ylabel("loss")
pyplot.ylim(1e-3, 1e-2)
pyplot.yscale("log")
pyplot.show()

我们能够看到我们的网络过拟合了,但是结果还不赖。事实上,我们找不到验证错误开始上升的点,所以那种通常用来避免过拟合的early stopping方法在现在还没有什么用处。注意我们没有采用任何正则化手段,除了选择节点比较少的隐层——这可以让过拟合保持在可控范围内。

那么网络的预测结果是什么样的呢?让我们选择一些样例来看一看。

def plot_sample(x, y, axis):
    img = x.reshape(96, 96)
    axis.imshow(img, cmap=‘gray‘)
    axis.scatter(y[0::2] * 48 + 48, y[1::2] * 48 + 48, marker=‘x‘, s=10)

X, _ = load(test=True)
y_pred = net1.predict(X)

fig = pyplot.figure(figsize=(6, 6))
fig.subplots_adjust(
    left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)

for i in range(16):
    ax = fig.add_subplot(4, 4, i + 1, xticks=[], yticks=[])
    plot_sample(X[i], y_pred[i], ax)

pyplot.show()

第一个模型预测的结果(从测试集抽出了16个样例)

预测结果看起来还不错,但是有点时候还是有一点偏。让我们试着做的更好一些。

To be continue…

时间: 2024-11-08 11:17:10

使用CNN(convolutional neural nets)检测脸部关键点教程(二):浅层网络训练和测试的相关文章

使用CNN(convolutional neural nets)检测脸部关键点教程(三):卷积神经网络训练和数据扩充

第五部分 第二个模型:卷积神经网络 上图演示了卷积操作 LeNet-5式的卷积神经网络,是计算机视觉领域近期取得的巨大突破的核心.卷积层和之前的全连接层不同,采用了一些技巧来避免过多的参数个数,但保持了模型的描述能力.这些技巧是: 1, 局部联结:神经元仅仅联结前一层神经元的一小部分. 2, 权重共享:在卷积层,神经元子集之间的权重是共享的.(这些神经元的形式被称为特征图[feature map]) 3, 池化:对输入进行静态的子采样. 局部性和权重共享的图示 卷积层的单元实际上连接了前一层神经

使用CNN(convolutional neural nets)检测脸部关键点教程(一)

本教程使用Lasagne(一个基于Theano可以快速构建神经网络的工具): 1,实现几种神经网络的搭建 2,讨论数据扩充(data augmentation)方法 3,讨论 学习"势" 的重要性 4,讨论 前训练(pre-training) 以上方法,将有利于改进我们的结果. 本教程基于你已经对神经网络有过一定的了解,因为在这里不再讨论神经网络的工作原理.但是这里有一些好的资料: 1, 一本deeplearning的在线书籍 2, Alec.Radford的视频教程"使用p

使用CNN(convolutional neural nets)检测脸部关键点教程(五):通过前训练(pre-train)训练专项网络

第九部分 训练专项网络 还记得在刚开始的时候我们丢掉的70%的训练数据吗?如果我们想要得到一个在Kaggle排行榜上有竞争力的成绩,那不是一个好主意.在70%的数据中,还有相当多的特征我们没有看到. 所以改变之前只训练一个模型的方式,我们训练几个专项网络,每一个都可以预测不同的目标集合.我们训练一个模型预测left_eye_center和right_eye_center,另一个模型预测nose_tip--:最终,我们有6个模型,使得我们可以完全利用训练数据,希望能够得到更好的预测效果. 这6个专

CNN(Convolutional Neural Network)

CNN(Convolutional Neural Network) 卷积神经网络(简称CNN)最早可以追溯到20世纪60年代,Hubel等人通过对猫视觉皮层细胞的研究表明,大脑对外界获取的信息由多层的感受野(Receptive Field)激发完成的.在感受野的基础上,1980年Fukushima提出了一个理论模型Neocognitron是感受野在人工神经网络领域的首次应用.1998年,Lecun等人提出的LeNet-5模型在手写字符识别上取得了成功,引起了学术界对卷积神经网络的关注.2012年

【网络结构】MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications论文解析

0. Paper link MobileNets 1. Overview ??MobileNets是一种基于深度可分割卷积的轻量流线型结构,引进了两个简单的全局超参数在延迟与准确率之间达到了平衡,并且超参数让model builder可以按照不同的应用场景的限制去选择合适大小的模型,网络的主要贡献是把传统的卷积拆成了"deepwise convolution"与"pointwise convolution"来减少卷积过程的计算量与参数数量,同时利用了两个超参数来改变

卷积神经网络(Convolutional Neural Network,CNN)

全连接神经网络(Fully connected neural network)处理图像最大的问题在于全连接层的参数太多.参数增多除了导致计算速度减慢,还很容易导致过拟合问题.所以需要一个更合理的神经网络结构来有效地减少神经网络中参数的数目.而卷积神经网络(Convolutional Neural Network,CNN)可以做到. 1. 卷积神经网络构成 图 1:卷积神经网络 输入层 整个网络的输入,一般代表了一张图片的像素矩阵.图 1中最左侧三维矩阵代表一张输入的图片,三维矩阵的长.宽代表了图

Convolutional neural network (CNN) - Pytorch版

import torch import torch.nn as nn import torchvision import torchvision.transforms as transforms # 配置GPU或CPU设置 device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') # 超参数设置 num_epochs = 5 num_classes = 10 batch_size = 100 learning_

pytorch -- CNN 文本分类 -- 《 Convolutional Neural Networks for Sentence Classification》

论文  < Convolutional Neural Networks for Sentence Classification>通过CNN实现了文本分类. 论文地址: 666666 模型图: 模型解释可以看论文,给出code and comment: 1 # -*- coding: utf-8 -*- 2 # @time : 2019/11/9 13:55 3 4 import numpy as np 5 import torch 6 import torch.nn as nn 7 impor

(转)A Beginner&#39;s Guide To Understanding Convolutional Neural Networks

Adit Deshpande CS Undergrad at UCLA ('19) Blog About A Beginner's Guide To Understanding Convolutional Neural Networks Introduction Convolutional neural networks. Sounds like a weird combination of biology and math with a little CS sprinkled in, but