传统的机器学习,自行设计特征提取函数,对图像的特征进行提取,再以特征作为输入,训练模型。这样导致了使用较干净的数据集和较有效的特征有时甚至比机器学习的模型的选择对分类结果的影响更大。
而现在使用的深度学习,则省去了设计特征提取函数这一步骤,图像直接作为输入,训练模型。在训练模型的过程中,卷积层相当于是一个特征提取函数,多层卷积提取的是图像的高维特征,而卷积层的参数也是通过训练学习而来的。
这一个改变让深度学习变成了一个由端到端(end-to-end)的模型,省去了对数据手动进行特征提取的过程。这就使得深度学习对比机器学习能将重心转移到数据和模型的结构上去。
数据和硬件性能是阻碍深度学习发展的一个很大的因素,因此直到近年来这两个条件都具备了,深度学习才有了突破性的进展。
AlexNet
AlexNet是来源于该论文的第一作者,Alex Krizhevsky。赢得了ImageNet2012图像识别挑战赛,首次证明了学习到的特征可以超越手工设计的特征,从而一举打破计算机视觉研究的前状。
相对与LeNet,AlexNet:
1.较多的层数,即更深的网络;
2.将sigmoid激活函数改成了更加简单的ReLU激活函数,使模型更加容易训练,并且sigmoid在输出非常接近0或1时,这些区域的梯度几乎为0,而ReLU函数则不会这样;
3.AlexNet通过丢弃法控制全连接层的复杂度
4.引入了图像增广,进一步的扩大数据集,防止了过拟合。
以下为稍微简化过的AlexNet代码:
import d2lzh as d2l
from mxnet import gluon, init, nd
from mxnet.gluon import data as gdata, nn
import os
import sys
net = nn.Sequential()
# 使用较大的11 x 11窗口来捕获物体。同时使用步幅4来较大幅度减小输出高和宽。这里使用的输出通
# 道数比LeNet中的也要大很多
net.add(nn.Conv2D(96, kernel_size=11, strides=4, activation='relu'),
nn.MaxPool2D(pool_size=3, strides=2),
# 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
nn.Conv2D(256, kernel_size=5, padding=2, activation='relu'),
nn.MaxPool2D(pool_size=3, strides=2),
# 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。
# 前两个卷积层后不使用池化层来减小输入的高和宽
nn.Conv2D(384, kernel_size=3, padding=1, activation='relu'),
nn.Conv2D(384, kernel_size=3, padding=1, activation='relu'),
nn.Conv2D(256, kernel_size=3, padding=1, activation='relu'),
nn.MaxPool2D(pool_size=3, strides=2),
# 这里全连接层的输出个数比LeNet中的大数倍。使用丢弃层来缓解过拟合
nn.Dense(4096, activation="relu"), nn.Dropout(0.5),
nn.Dense(4096, activation="relu"), nn.Dropout(0.5),
# 输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000
nn.Dense(10))
读取数据集:
# 本函数已保存在d2lzh包中方便以后使用
def load_data_fashion_mnist(batch_size, resize=None, root=os.path.join(
'~', '.mxnet', 'datasets', 'fashion-mnist')):
root = os.path.expanduser(root) # 展开用户路径'~'
transformer = []
if resize:
transformer += [gdata.vision.transforms.Resize(resize)]
transformer += [gdata.vision.transforms.ToTensor()]
transformer = gdata.vision.transforms.Compose(transformer)
mnist_train = gdata.vision.FashionMNIST(root=root, train=True)
mnist_test = gdata.vision.FashionMNIST(root=root, train=False)
num_workers = 0 if sys.platform.startswith('win32') else 4
train_iter = gdata.DataLoader(
mnist_train.transform_first(transformer), batch_size, shuffle=True,
num_workers=num_workers)
test_iter = gdata.DataLoader(
mnist_test.transform_first(transformer), batch_size, shuffle=False,
num_workers=num_workers)
return train_iter, test_iter
batch_size = 8 #batch_size都这么小了还不行,渣GPU还是跑不动,哭辽
# 如出现“out of memory”的报错信息,可减小batch_size或resize
train_iter, test_iter = load_data_fashion_mnist(batch_size, resize=224)
训练模型:
lr, num_epochs, ctx = 0.01, 5, d2l.try_gpu()
net.initialize(force_reinit=True, ctx=ctx, init=init.Xavier())
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': lr})
d2l.train_ch5(net, train_iter, test_iter, batch_size, trainer, ctx, num_epochs)
参考文献:
动手学深度学习——阿斯顿张、李沐