从零开始深度学习论文系列是本人精选从Alexnet开始到现在数十篇深度学习论文,讲解,并加以自己理解,并附上paddlepaddle工具编写的源码,希望大家喜欢。
Alexnet是深度学习的开山之作,从Alexnet开始人工智能正式进入深度学习时代,纵观Alexnet之前,其底层算法卷积神经网络并非什么新的名词,实际上卷积神经网络上世纪80年代就已经诞生了。到Alexnet的诞生中的20多年里,也有不少在卷积神经网络上研究的论文。
那为什么只有Alexnet成功开创深度学习呢?究其原因有以下几点:
1.算力的发展,摩尔定律在20多年的发展,硬件上的计算能力支撑了深度学习的出现,可以使用更大参数量的模型,更深层次的神经网络。
2.大数据的出现,其本质也是硬件上的存储能力,使得更多的数据存储在了云端,也有了更多的数据集可以用于挖掘,训练。
3.论文本身创新,过拟合一直是卷积神经网络让人诟病的问题,过于容易过拟合,以至于在alexnet过去的几十年中,很多人的论文方向都集中在树模型、集成学习方面研究,而alexnet里开创性的引出dropout,maxpooling,LRN等概念,并成功使用Relu作为神经网络的激活函数,并且充分利用了GPU的计算性能。
Alexnet论文地址:Alexnet论文传送门
Alexnet使用的数据是ImageNet的图片,其中LSVRC-2010数据集有120万图片,1000个分类,5万验证集,15万测试集。
ImageNet地址:ImageNet官网
上图为Alexnet的结构图,input为size(224,224,3)的图片大小,而中间结构为:
1111 conv->55 conv-> max_pooling -> 33 conv -> max_pooling -> 33 conv -> 33 conv ->max_pooling->2048 fc-> 2048 fc->1000 fc
可以看到整个Alexnet网络结构里主要包含卷积层,池化层以及全连接层,通过不断地提炼特征,在进全连接层前将原本的224224大小降低到1313的大小,经过几个全连接层到1000的全连接对应1000个分类。
而一上来的1111的卷积层,明显是想一次性学到更多的局部信息,但后来的vgg证明多用33的卷积层堆叠可以在更少的参数量,达到更深的层次,以及更多的非线性从而比单用1111的卷积层更好的效果。
除本身结构外,Alexnet主要创新点在:
1.dropout使用,训练时对一些神经元随机的忽略,不计算,这样的方式有效的在层次深的情况下避免了过拟合。
2.Relu使用,relu的公式很简单,max(0,x),这种激活函数在深层次的网络相较于之前惯用的sigmoid解决了梯度弥散的问题。
3.最大池化使用,相较于平均池化,其效果会更能捕捉局部信息,不会模糊化信息,并且stride小于池化核大小也有利于重叠池化后的feature map。
4.LRN,Local Response Normalization 虽然在后面的论文很难看到使用,之后基本都是使用的BN(batch normalization),但其通过对局部神经元的活动创建竞争机制,使响应比较大的值变得相对更大,抑制其他反馈较小的神经元的思想是可以借鉴的。
第一步,引入paddlepaddle依赖库。
import paddlepaddle
第二步,加入数据集,在这里我们使用paddle自带的cifar-10数据集,并将3232的图片转换为224224大小。
from paddle.vision.transforms import Resize,Normalize,Compose,Transpose
transform = Compose([Resize(224),Normalize(mean=[127.5, 127.5, 127.5], std=[127.5, 127.5, 127.5], data_format='HWC'),Transpose()])
train_dataset = paddle.vision.datasets.Cifar10(mode='train',transform=transform,backend='cv2')
test_dataset = paddle.vision.datasets.Cifar10(mode='test',transform=transform,backend='cv2')
第三步,初始化alexnet模型。
alexnet = paddle.vision.models.vgg11(batch_norm=True,num_classes=10)
model = paddle.Model(alexnet)
第四步,配置损失函数,优化器等,开始训练。
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy())
model.fit(train_dataset, epochs=50, batch_size=128, verbose=1)
废话不多说,直接放出模型源码。
import paddle
from paddle import nn
model = nn.Sequential(
nn.Conv2D(3,96,11,stride=4,padding=2),
nn.ReLU(),
nn.MaxPool2D(kernel_size=3, stride=2, padding=0),
nn.Conv2D(96,256,5,stride=1,padding=2),
nn.ReLU(),
nn.MaxPool2D(kernel_size=3, stride=2, padding=0),
nn.Conv2D(256,384,3,stride=1,padding=1),
nn.Conv2D(384,256,3,stride=1,padding=1),
nn.Conv2D(256,256,3,stride=1,padding=1),
nn.ReLU(),
nn.MaxPool2D(kernel_size=3, stride=2, padding=0),
nn.Flatten(),
nn.Dropout(0.5),
nn.Linear(256*6*6,4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096,4096),
nn.ReLU(),
nn.Linear(4096,10)
)
paddle.summary(model,(16,3,224,224))
执行该模型代码最终打印出的结构如下:
最终的模型结构如上,与论文上alexnet的模型结构基本一致,参数量在那个年代其实也不算小。
Alexnet是深度学习的开始,虽然从现在看来,整个模型结构还有不成熟的地方,但是其上的很多使用的方法和思想如dropout,relu也仍然沿用至今,在Alexnet里也提到了数据增强的方法,虽然在本文并未体现,但也是模型效果成功的关键。