提交 eeb4d934 编写于 作者: Y Yu Yang 提交者: GitHub

Merge pull request #182 from reyoung/feature/refine_frontpage

Feature/refine frontpage
......@@ -2,3 +2,5 @@ deprecated
*~
pandoc.template
.DS_Store
.idea
py_env*
......@@ -31,12 +31,10 @@
description: Convert README.md into index.html and README.en.md into index.en.html
entry: python pre-commit-hooks/convert_markdown_into_html.py
language: system
files: \.md$
- repo: local
hooks:
files: .+README(\.en)?\.md$
- id: convert-markdown-into-ipynb
name: convert-markdown-into-ipynb
description: Convert README.md into README.ipynb and README.en.md into README.en.ipynb
entry: ./pre-commit-hooks/convert_markdown_into_ipynb.sh
language: system
files: \.md$
files: .+README(\.en)?\.md$
......@@ -188,7 +188,7 @@
}
.markdown-body a {
color: #4078c0;
color: #597cf1;
text-decoration: none;
}
......
......@@ -16,7 +16,7 @@ addons:
- python2.7-dev
- golang
before_install:
- pip install virtualenv pre-commit
- pip install -U virtualenv pre-commit pip
- GOPATH=/tmp/go go get -u github.com/wangkuiyi/ipynb/markdown-to-ipynb
script:
- travis/precommit.sh
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 图像分类\n",
"\n",
"本教程源代码目录在[book/image_classification](https://github.com/PaddlePaddle/book/tree/develop/image_classification), 初次使用请参考PaddlePaddle[安装教程](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/getstarted/build_and_install/docker_install_cn.rst)。\n",
"\n",
"## 背景介绍\n",
"\n",
"图像相比文字能够提供更加生动、容易理解及更具艺术感的信息,是人们转递与交换信息的重要来源。在本教程中,我们专注于图像识别领域的一个重要问题,即图像分类。\n",
"\n",
"图像分类是根据图像的语义信息将不同类别图像区分开来,是计算机视觉中重要的基本问题,也是图像检测、图像分割、物体跟踪、行为分析等其他高层视觉任务的基础。图像分类在很多领域有广泛应用,包括安防领域的人脸识别和智能视频分析等,交通领域的交通场景识别,互联网领域基于内容的图像检索和相册自动归类,医学领域的图像识别等。\n",
"\n",
"\n",
"一般来说,图像分类通过手工特征或特征学习方法对整个图像进行全部描述,然后使用分类器判别物体类别,因此如何提取图像的特征至关重要。在深度学习算法之前使用较多的是基于词袋(Bag of Words)模型的物体分类方法。词袋方法从自然语言处理中引入,即一句话可以用一个装了词的袋子表示其特征,袋子中的词为句子中的单词、短语或字。对于图像而言,词袋方法需要构建字典。最简单的词袋模型框架可以设计为**底层特征抽取**、**特征编码**、**分类器设计**三个过程。\n",
"\n",
"而基于深度学习的图像分类方法,可以通过有监督或无监督的方式**学习**层次化的特征描述,从而取代了手工设计或选择图像特征的工作。深度学习模型中的卷积神经网络(Convolution Neural Network, CNN)近年来在图像领域取得了惊人的成绩,CNN直接利用图像像素信息作为输入,最大程度上保留了输入图像的所有信息,通过卷积操作进行特征的提取和高层抽象,模型输出直接是图像识别的结果。这种基于\"输入-输出\"直接端到端的学习方法取得了非常好的效果,得到了广泛的应用。\n",
"\n",
"本教程主要介绍图像分类的深度学习模型,以及如何使用PaddlePaddle训练CNN模型。\n",
"\n",
"## 效果展示\n",
"\n",
"图像分类包括通用图像分类、细粒度图像分类等。图1展示了通用图像分类效果,即模型可以正确识别图像上的主要物体。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/dog_cat.png \" width=\"350\" \u003e\u003cbr/\u003e\n",
"图1. 通用图像分类展示\n",
"\u003c/p\u003e\n",
"\n",
"\n",
"图2展示了细粒度图像分类-花卉识别的效果,要求模型可以正确识别花的类别。\n",
"\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/flowers.png\" width=\"400\" \u003e\u003cbr/\u003e\n",
"图2. 细粒度图像分类展示\n",
"\u003c/p\u003e\n",
"\n",
"\n",
"一个好的模型既要对不同类别识别正确,同时也应该能够对不同视角、光照、背景、变形或部分遮挡的图像正确识别(这里我们统一称作图像扰动)。图3展示了一些图像的扰动,较好的模型会像聪明的人类一样能够正确识别。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/variations.png\" width=\"550\" \u003e\u003cbr/\u003e\n",
"图3. 扰动图片展示[22]\n",
"\u003c/p\u003e\n",
"\n",
"## 模型概览\n",
"\n",
"图像识别领域大量的研究成果都是建立在[PASCAL VOC](http://host.robots.ox.ac.uk/pascal/VOC/)、[ImageNet](http://image-net.org/)等公开的数据集上,很多图像识别算法通常在这些数据集上进行测试和比较。PASCAL VOC是2005年发起的一个视觉挑战赛,ImageNet是2010年发起的大规模视觉识别竞赛(ILSVRC)的数据集,在本章中我们基于这些竞赛的一些论文介绍图像分类模型。\n",
"\n",
"在2012年之前的传统图像分类方法可以用背景描述中提到的三步完成,但通常完整建立图像识别模型一般包括底层特征学习、特征编码、空间约束、分类器设计、模型融合等几个阶段。\n",
" 1). **底层特征提取**: 通常从图像中按照固定步长、尺度提取大量局部特征描述。常用的局部特征包括SIFT(Scale-Invariant Feature Transform, 尺度不变特征转换) \\[[1](#参考文献)\\]、HOG(Histogram of Oriented Gradient, 方向梯度直方图) \\[[2](#参考文献)\\]、LBP(Local Bianray Pattern, 局部二值模式) \\[[3](#参考文献)\\] 等,一般也采用多种特征描述子,防止丢失过多的有用信息。\n",
" 2). **特征编码**: 底层特征中包含了大量冗余与噪声,为了提高特征表达的鲁棒性,需要使用一种特征变换算法对底层特征进行编码,称作特征编码。常用的特征编码包括向量量化编码 \\[[4](#参考文献)\\]、稀疏编码 \\[[5](#参考文献)\\]、局部线性约束编码 \\[[6](#参考文献)\\]、Fisher向量编码 \\[[7](#参考文献)\\] 等。\n",
" 3). **空间特征约束**: 特征编码之后一般会经过空间特征约束,也称作**特征汇聚**。特征汇聚是指在一个空间范围内,对每一维特征取最大值或者平均值,可以获得一定特征不变形的特征表达。金字塔特征匹配是一种常用的特征聚会方法,这种方法提出将图像均匀分块,在分块内做特征汇聚。\n",
" 4). **通过分类器分类**: 经过前面步骤之后一张图像可以用一个固定维度的向量进行描述,接下来就是经过分类器对图像进行分类。通常使用的分类器包括SVM(Support Vector Machine, 支持向量机)、随机森林等。而使用核方法的SVM是最为广泛的分类器,在传统图像分类任务上性能很好。\n",
"\n",
"这种方法在PASCAL VOC竞赛中的图像分类算法中被广泛使用 \\[[18](#参考文献)\\]。[NEC实验室](http://www.nec-labs.com/)在ILSVRC2010中采用SIFT和LBP特征,两个非线性编码器以及SVM分类器获得图像分类的冠军 \\[[8](#参考文献)\\]。\n",
"\n",
"Alex Krizhevsky在2012年ILSVRC提出的CNN模型 \\[[9](#参考文献)\\] 取得了历史性的突破,效果大幅度超越传统方法,获得了ILSVRC2012冠军,该模型被称作AlexNet。这也是首次将深度学习用于大规模图像分类中。从AlexNet之后,涌现了一系列CNN模型,不断地在ImageNet上刷新成绩,如图4展示。随着模型变得越来越深以及精妙的结构设计,Top-5的错误率也越来越低,降到了3.5%附近。而在同样的ImageNet数据集上,人眼的辨识错误率大概在5.1%,也就是目前的深度学习模型的识别能力已经超过了人眼。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/ilsvrc.png\" width=\"500\" \u003e\u003cbr/\u003e\n",
"图4. ILSVRC图像分类Top-5错误率\n",
"\u003c/p\u003e\n",
"\n",
"### CNN\n",
"\n",
"传统CNN包含卷积层、全连接层等组件,并采用softmax多类别分类器和多类交叉熵损失函数,一个典型的卷积神经网络如图5所示,我们先介绍用来构造CNN的常见组件。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/lenet.png\"\u003e\u003cbr/\u003e\n",
"图5. CNN网络示例[20]\n",
"\u003c/p\u003e\n",
"\n",
"- 卷积层(convolution layer): 执行卷积操作提取底层到高层的特征,发掘出图片局部关联性质和空间不变性质。\n",
"- 池化层(pooling layer): 执行降采样操作。通过取卷积输出特征图中局部区块的最大值(max-pooling)或者均值(avg-pooling)。降采样也是图像处理中常见的一种操作,可以过滤掉一些不重要的高频信息。\n",
"- 全连接层(fully-connected layer,或者fc layer): 输入层到隐藏层的神经元是全部连接的。\n",
"- 非线性变化: 卷积层、全连接层后面一般都会接非线性变化层,例如Sigmoid、Tanh、ReLu等来增强网络的表达能力,在CNN里最常使用的为ReLu激活函数。\n",
"- Dropout \\[[10](#参考文献)\\] : 在模型训练阶段随机让一些隐层节点权重不工作,提高网络的泛化能力,一定程度上防止过拟合。\n",
"\n",
"另外,在训练过程中由于每层参数不断更新,会导致下一次输入分布发生变化,这样导致训练过程需要精心设计超参数。如2015年Sergey Ioffe和Christian Szegedy提出了Batch Normalization (BN)算法 \\[[14](#参考文献)\\] 中,每个batch对网络中的每一层特征都做归一化,使得每层分布相对稳定。BN算法不仅起到一定的正则作用,而且弱化了一些超参数的设计。经过实验证明,BN算法加速了模型收敛过程,在后来较深的模型中被广泛使用。\n",
"\n",
"接下来我们主要介绍VGG,GoogleNet和ResNet网络结构。\n",
"\n",
"### VGG\n",
"\n",
"牛津大学VGG(Visual Geometry Group)组在2014年ILSVRC提出的模型被称作VGG模型 \\[[11](#参考文献)\\] 。该模型相比以往模型进一步加宽和加深了网络结构,它的核心是五组卷积操作,每两组之间做Max-Pooling空间降维。同一组内采用多次连续的3X3卷积,卷积核的数目由较浅组的64增多到最深组的512,同一组内的卷积核数目是一样的。卷积之后接两层全连接层,之后是分类层。由于每组内卷积层的不同,有11、13、16、19层这几种模型,下图展示一个16层的网络结构。VGG模型结构相对简洁,提出之后也有很多文章基于此模型进行研究,如在ImageNet上首次公开超过人眼识别的模型\\[[19](#参考文献)\\]就是借鉴VGG模型的结构。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/vgg16.png\" width=\"750\" \u003e\u003cbr/\u003e\n",
"图6. 基于ImageNet的VGG16模型\n",
"\u003c/p\u003e\n",
"\n",
"### GoogleNet\n",
"\n",
"GoogleNet \\[[12](#参考文献)\\] 在2014年ILSVRC的获得了冠军,在介绍该模型之前我们先来了解NIN(Network in Network)模型 \\[[13](#参考文献)\\] 和Inception模块,因为GoogleNet模型由多组Inception模块组成,模型设计借鉴了NIN的一些思想。\n",
"\n",
"NIN模型主要有两个特点:1) 引入了多层感知卷积网络(Multi-Layer Perceptron Convolution, MLPconv)代替一层线性卷积网络。MLPconv是一个微小的多层卷积网络,即在线性卷积后面增加若干层1x1的卷积,这样可以提取出高度非线性特征。2) 传统的CNN最后几层一般都是全连接层,参数较多。而NIN模型设计最后一层卷积层包含类别维度大小的特征图,然后采用全局均值池化(Avg-Pooling)替代全连接层,得到类别维度大小的向量,再进行分类。这种替代全连接层的方式有利于减少参数。\n",
"\n",
"Inception模块如下图7所示,图(a)是最简单的设计,输出是3个卷积层和一个池化层的特征拼接。这种设计的缺点是池化层不会改变特征通道数,拼接后会导致特征的通道数较大,经过几层这样的模块堆积后,通道数会越来越大,导致参数和计算量也随之增大。为了改善这个缺点,图(b)引入3个1x1卷积层进行降维,所谓的降维就是减少通道数,同时如NIN模型中提到的1x1卷积也可以修正线性特征。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/inception.png\" width=\"800\" \u003e\u003cbr/\u003e\n",
"图7. Inception模块\n",
"\u003c/p\u003e\n",
"\n",
"GoogleNet由多组Inception模块堆积而成。另外,在网络最后也没有采用传统的多层全连接层,而是像NIN网络一样采用了均值池化层;但与NIN不同的是,池化层后面接了一层到类别数映射的全连接层。除了这两个特点之外,由于网络中间层特征也很有判别性,GoogleNet在中间层添加了两个辅助分类器,在后向传播中增强梯度并且增强正则化,而整个网络的损失函数是这个三个分类器的损失加权求和。\n",
"\n",
"GoogleNet整体网络结构如图8所示,总共22层网络:开始由3层普通的卷积组成;接下来由三组子网络组成,第一组子网络包含2个Inception模块,第二组包含5个Inception模块,第三组包含2个Inception模块;然后接均值池化层、全连接层。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/googlenet.jpeg\" \u003e\u003cbr/\u003e\n",
"图8. GoogleNet[12]\n",
"\u003c/p\u003e\n",
"\n",
"\n",
"上面介绍的是GoogleNet第一版模型(称作GoogleNet-v1)。GoogleNet-v2 \\[[14](#参考文献)\\] 引入BN层;GoogleNet-v3 \\[[16](#参考文献)\\] 对一些卷积层做了分解,进一步提高网络非线性能力和加深网络;GoogleNet-v4 \\[[17](#参考文献)\\] 引入下面要讲的ResNet设计思路。从v1到v4每一版的改进都会带来准确度的提升,介于篇幅,这里不再详细介绍v2到v4的结构。\n",
"\n",
"\n",
"### ResNet\n",
"\n",
"ResNet(Residual Network) \\[[15](#参考文献)\\] 是2015年ImageNet图像分类、图像物体定位和图像物体检测比赛的冠军。针对训练卷积神经网络时加深网络导致准确度下降的问题,ResNet提出了采用残差学习。在已有设计思路(BN, 小卷积核,全卷积网络)的基础上,引入了残差模块。每个残差模块包含两条路径,其中一条路径是输入特征的直连通路,另一条路径对该特征做两到三次卷积操作得到该特征的残差,最后再将两条路径上的特征相加。\n",
"\n",
"残差模块如图9所示,左边是基本模块连接方式,由两个输出通道数相同的3x3卷积组成。右边是瓶颈模块(Bottleneck)连接方式,之所以称为瓶颈,是因为上面的1x1卷积用来降维(图示例即256-\u003e64),下面的1x1卷积用来升维(图示例即64-\u003e256),这样中间3x3卷积的输入和输出通道数都较小(图示例即64-\u003e64)。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/resnet_block.jpg\" width=\"400\"\u003e\u003cbr/\u003e\n",
"图9. 残差模块\n",
"\u003c/p\u003e\n",
"\n",
"图10展示了50、101、152层网络连接示意图,使用的是瓶颈模块。这三个模型的区别在于每组中残差模块的重复次数不同(见图右上角)。ResNet训练收敛较快,成功的训练了上百乃至近千层的卷积神经网络。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/resnet.png\"\u003e\u003cbr/\u003e\n",
"图10. 基于ImageNet的ResNet模型\n",
"\u003c/p\u003e\n",
"\n",
"\n",
"## 数据准备\n",
"\n",
"通用图像分类公开的标准数据集常用的有[CIFAR](\u003chttps://www.cs.toronto.edu/~kriz/cifar.html)、[ImageNet](http://image-net.org/)、[COCO](http://mscoco.org/)等,常用的细粒度图像分类数据集包括[CUB-200-2011](http://www.vision.caltech.edu/visipedia/CUB-200-2011.html)、[Stanford Dog](http://vision.stanford.edu/aditya86/ImageNetDogs/)、[Oxford-flowers](http://www.robots.ox.ac.uk/~vgg/data/flowers/)等。其中ImageNet数据集规模相对较大,如[模型概览](#模型概览)一章所讲,大量研究成果基于ImageNet。ImageNet数据从2010年来稍有变化,常用的是ImageNet-2012数据集,该数据集包含1000个类别:训练集包含1,281,167张图片,每个类别数据732至1300张不等,验证集包含50,000张图片,平均每个类别50张图片。\n",
"\n",
"由于ImageNet数据集较大,下载和训练较慢,为了方便大家学习,我们使用[CIFAR10](\u003chttps://www.cs.toronto.edu/~kriz/cifar.html\u003e)数据集。CIFAR10数据集包含60,000张32x32的彩色图片,10个类别,每个类包含6,000张。其中50,000张图片作为训练集,10000张作为测试集。图11从每个类别中随机抽取了10张图片,展示了所有的类别。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/cifar.png\" width=\"350\"\u003e\u003cbr/\u003e\n",
"图11. CIFAR10数据集[21]\n",
"\u003c/p\u003e\n",
"\n",
"Paddle API提供了自动加载cifar数据集模块 `paddle.dataset.cifar`。\n",
"\n",
"通过输入`python train.py`,就可以开始训练模型了,以下小节将详细介绍`train.py`的相关内容。\n",
"\n",
"### 模型结构\n",
"\n",
"#### Paddle 初始化\n",
"\n",
"通过 `paddle.init`,初始化Paddle是否使用GPU,trainer的数目等等。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"import sys\n",
"import paddle.v2 as paddle\n",
"from vgg import vgg_bn_drop\n",
"from resnet import resnet_cifar10\n",
"\n",
"# PaddlePaddle init\n",
"paddle.init(use_gpu=False, trainer_count=1)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"本教程中我们提供了VGG和ResNet两个模型的配置。\n",
"\n",
"#### VGG\n",
"\n",
"首先介绍VGG模型结构,由于CIFAR10图片大小和数量相比ImageNet数据小很多,因此这里的模型针对CIFAR10数据做了一定的适配。卷积部分引入了BN和Dropout操作。\n",
"\n",
"1. 定义数据输入及其维度\n",
"\n",
" 网络输入定义为 `data_layer` (数据层),在图像分类中即为图像像素信息。CIFRAR10是RGB 3通道32x32大小的彩色图,因此输入数据大小为3072(3x32x32),类别大小为10,即10分类。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
" datadim = 3 * 32 * 32\n",
" classdim = 10\n",
"\n",
" image = paddle.layer.data(\n",
" name=\"image\", type=paddle.data_type.dense_vector(datadim))\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"2. 定义VGG网络核心模块\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
" net = vgg_bn_drop(image)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" VGG核心模块的输入是数据层,`vgg_bn_drop` 定义了16层VGG结构,每层卷积后面引入BN层和Dropout层,详细的定义如下:\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
" def vgg_bn_drop(input):\n",
" def conv_block(ipt, num_filter, groups, dropouts, num_channels=None):\n",
" return paddle.networks.img_conv_group(\n",
" input=ipt,\n",
" num_channels=num_channels,\n",
" pool_size=2,\n",
" pool_stride=2,\n",
" conv_num_filter=[num_filter] * groups,\n",
" conv_filter_size=3,\n",
" conv_act=paddle.activation.Relu(),\n",
" conv_with_batchnorm=True,\n",
" conv_batchnorm_drop_rate=dropouts,\n",
" pool_type=paddle.pooling.Max())\n",
"\n",
" conv1 = conv_block(input, 64, 2, [0.3, 0], 3)\n",
" conv2 = conv_block(conv1, 128, 2, [0.4, 0])\n",
" conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])\n",
" conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])\n",
" conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])\n",
"\n",
" drop = paddle.layer.dropout(input=conv5, dropout_rate=0.5)\n",
" fc1 = paddle.layer.fc(input=drop, size=512, act=paddle.activation.Linear())\n",
" bn = paddle.layer.batch_norm(\n",
" input=fc1,\n",
" act=paddle.activation.Relu(),\n",
" layer_attr=paddle.attr.Extra(drop_rate=0.5))\n",
" fc2 = paddle.layer.fc(input=bn, size=512, act=paddle.activation.Linear())\n",
" return fc2\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
" 2.1. 首先定义了一组卷积网络,即conv_block。卷积核大小为3x3,池化窗口大小为2x2,窗口滑动大小为2,groups决定每组VGG模块是几次连续的卷积操作,dropouts指定Dropout操作的概率。所使用的`img_conv_group`是在`paddle.networks`中预定义的模块,由若干组 `Conv-\u003eBN-\u003eReLu-\u003eDropout` 和 一组 `Pooling` 组成,\n",
"\n",
" 2.2. 五组卷积操作,即 5个conv_block。 第一、二组采用两次连续的卷积操作。第三、四、五组采用三次连续的卷积操作。每组最后一个卷积后面Dropout概率为0,即不使用Dropout操作。\n",
"\n",
" 2.3. 最后接两层512维的全连接。\n",
"\n",
"3. 定义分类器\n",
"\n",
" 通过上面VGG网络提取高层特征,然后经过全连接层映射到类别维度大小的向量,再通过Softmax归一化得到每个类别的概率,也可称作分类器。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
" out = paddle.layer.fc(input=net,\n",
" size=classdim,\n",
" act=paddle.activation.Softmax())\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"4. 定义损失函数和网络输出\n",
"\n",
" 在有监督训练中需要输入图像对应的类别信息,同样通过`paddle.layer.data`来定义。训练中采用多类交叉熵作为损失函数,并作为网络的输出,预测阶段定义网络的输出为分类器得到的概率信息。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
" lbl = paddle.layer.data(\n",
" name=\"label\", type=paddle.data_type.integer_value(classdim))\n",
" cost = paddle.layer.classification_cost(input=out, label=lbl)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"### ResNet\n",
"\n",
"ResNet模型的第1、3、4步和VGG模型相同,这里不再介绍。主要介绍第2步即CIFAR10数据集上ResNet核心模块。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"net = resnet_cifar10(image, depth=56)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"先介绍`resnet_cifar10`中的一些基本函数,再介绍网络连接过程。\n",
"\n",
" - `conv_bn_layer` : 带BN的卷积层。\n",
" - `shortcut` : 残差模块的\"直连\"路径,\"直连\"实际分两种形式:残差模块输入和输出特征通道数不等时,采用1x1卷积的升维操作;残差模块输入和输出通道相等时,采用直连操作。\n",
" - `basicblock` : 一个基础残差模块,即图9左边所示,由两组3x3卷积组成的路径和一条\"直连\"路径组成。\n",
" - `bottleneck` : 一个瓶颈残差模块,即图9右边所示,由上下1x1卷积和中间3x3卷积组成的路径和一条\"直连\"路径组成。\n",
" - `layer_warp` : 一组残差模块,由若干个残差模块堆积而成。每组中第一个残差模块滑动窗口大小与其他可以不同,以用来减少特征图在垂直和水平方向的大小。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"def conv_bn_layer(input,\n",
" ch_out,\n",
" filter_size,\n",
" stride,\n",
" padding,\n",
" active_type=paddle.activation.Relu(),\n",
" ch_in=None):\n",
" tmp = paddle.layer.img_conv(\n",
" input=input,\n",
" filter_size=filter_size,\n",
" num_channels=ch_in,\n",
" num_filters=ch_out,\n",
" stride=stride,\n",
" padding=padding,\n",
" act=paddle.activation.Linear(),\n",
" bias_attr=False)\n",
" return paddle.layer.batch_norm(input=tmp, act=active_type)\n",
"\n",
"def shortcut(ipt, n_in, n_out, stride):\n",
" if n_in != n_out:\n",
" return conv_bn_layer(ipt, n_out, 1, stride, 0,\n",
" paddle.activation.Linear())\n",
" else:\n",
" return ipt\n",
"\n",
"def basicblock(ipt, ch_out, stride):\n",
" ch_in = ch_out * 2\n",
" tmp = conv_bn_layer(ipt, ch_out, 3, stride, 1)\n",
" tmp = conv_bn_layer(tmp, ch_out, 3, 1, 1, paddle.activation.Linear())\n",
" short = shortcut(ipt, ch_in, ch_out, stride)\n",
" return paddle.layer.addto(input=[tmp, short], act=paddle.activation.Relu())\n",
"\n",
"def layer_warp(block_func, ipt, features, count, stride):\n",
" tmp = block_func(ipt, features, stride)\n",
" for i in range(1, count):\n",
" tmp = block_func(tmp, features, 1)\n",
" return tmp\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"`resnet_cifar10` 的连接结构主要有以下几个过程。\n",
"\n",
"1. 底层输入连接一层 `conv_bn_layer`,即带BN的卷积层。\n",
"2. 然后连接3组残差模块即下面配置3组 `layer_warp` ,每组采用图 10 左边残差模块组成。\n",
"3. 最后对网络做均值池化并返回该层。\n",
"\n",
"注意:除过第一层卷积层和最后一层全连接层之外,要求三组 `layer_warp` 总的含参层数能够被6整除,即 `resnet_cifar10` 的 depth 要满足 $(depth - 2) % 6 == 0$ 。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"def resnet_cifar10(ipt, depth=32):\n",
" # depth should be one of 20, 32, 44, 56, 110, 1202\n",
" assert (depth - 2) % 6 == 0\n",
" n = (depth - 2) / 6\n",
" nStages = {16, 64, 128}\n",
" conv1 = conv_bn_layer(\n",
" ipt, ch_in=3, ch_out=16, filter_size=3, stride=1, padding=1)\n",
" res1 = layer_warp(basicblock, conv1, 16, n, 1)\n",
" res2 = layer_warp(basicblock, res1, 32, n, 2)\n",
" res3 = layer_warp(basicblock, res2, 64, n, 2)\n",
" pool = paddle.layer.img_pool(\n",
" input=res3, pool_size=8, stride=1, pool_type=paddle.pooling.Avg())\n",
" return pool\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## 训练模型\n",
"\n",
"### 定义参数\n",
"\n",
"首先依据模型配置的`cost`定义模型参数。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"# Create parameters\n",
"parameters = paddle.parameters.create(cost)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"可以打印参数名字,如果在网络配置中没有指定名字,则默认生成。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"print parameters.keys()\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"### 构造训练(Trainer)\n",
"\n",
"根据网络拓扑结构和模型参数来构造出trainer用来训练,在构造时还需指定优化方法,这里使用最基本的Momentum方法,同时设定了学习率、正则等。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"# Create optimizer\n",
"momentum_optimizer = paddle.optimizer.Momentum(\n",
" momentum=0.9,\n",
" regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),\n",
" learning_rate=0.1 / 128.0,\n",
" learning_rate_decay_a=0.1,\n",
" learning_rate_decay_b=50000 * 100,\n",
" learning_rate_schedule='discexp',\n",
" batch_size=128)\n",
"\n",
"# Create trainer\n",
"trainer = paddle.trainer.SGD(cost=cost,\n",
" parameters=parameters,\n",
" update_equation=momentum_optimizer)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"通过 `learning_rate_decay_a` (简写$a$) 、`learning_rate_decay_b` (简写$b$) 和 `learning_rate_schedule` 指定学习率调整策略,这里采用离散指数的方式调节学习率,计算公式如下, $n$ 代表已经处理过的累计总样本数,$lr_{0}$ 即为 `settings` 里设置的 `learning_rate`。\n",
"\n",
"$$ lr = lr_{0} * a^ {\\lfloor \\frac{n}{ b}\\rfloor} $$\n",
"\n",
"\n",
"### 训练\n",
"\n",
"cifar.train10()每次产生一条样本,在完成shuffle和batch之后,作为训练的输入。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"reader=paddle.batch(\n",
" paddle.reader.shuffle(\n",
" paddle.dataset.cifar.train10(), buf_size=50000),\n",
" batch_size=128)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"通过`feeding`来指定每一个数据和`paddle.layer.data`的对应关系。例如: `cifar.train10()`产生数据的第0列对应image层的特征。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"feeding={'image': 0,\n",
" 'label': 1}\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"可以使用`event_handler`回调函数来观察训练过程,或进行测试等, 该回调函数是`trainer.train`函数里设定。\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"# End batch and end pass event handler\n",
"def event_handler(event):\n",
" if isinstance(event, paddle.event.EndIteration):\n",
" if event.batch_id % 100 == 0:\n",
" print \"\\nPass %d, Batch %d, Cost %f, %s\" % (\n",
" event.pass_id, event.batch_id, event.cost, event.metrics)\n",
" else:\n",
" sys.stdout.write('.')\n",
" sys.stdout.flush()\n",
" if isinstance(event, paddle.event.EndPass):\n",
" result = trainer.test(\n",
" reader=paddle.batch(\n",
" paddle.dataset.cifar.test10(), batch_size=128),\n",
" feeding=feeding)\n",
" print \"\\nTest with Pass %d, %s\" % (event.pass_id, result.metrics)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"通过`trainer.train`函数训练:\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"editable": true
},
"source": [
"trainer.train(\n",
" reader=reader,\n",
" num_passes=200,\n",
" event_handler=event_handler,\n",
" feeding=feeding)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"一轮训练log示例如下所示,经过1个pass, 训练集上平均error为0.6875 ,测试集上平均error为0.8852 。\n",
"\n",
"```text\n",
"Pass 0, Batch 0, Cost 2.473182, {'classification_error_evaluator': 0.9140625}\n",
"...................................................................................................\n",
"Pass 0, Batch 100, Cost 1.913076, {'classification_error_evaluator': 0.78125}\n",
"...................................................................................................\n",
"Pass 0, Batch 200, Cost 1.783041, {'classification_error_evaluator': 0.7421875}\n",
"...................................................................................................\n",
"Pass 0, Batch 300, Cost 1.668833, {'classification_error_evaluator': 0.6875}\n",
"..........................................................................................\n",
"Test with Pass 0, {'classification_error_evaluator': 0.885200023651123}\n",
"```\n",
"\n",
"图12是训练的分类错误率曲线图,运行到第200个pass后基本收敛,最终得到测试集上分类错误率为8.54%。\n",
"\n",
"\u003cp align=\"center\"\u003e\n",
"\u003cimg src=\"image/plot.png\" width=\"400\" \u003e\u003cbr/\u003e\n",
"图12. CIFAR10数据集上VGG模型的分类错误率\n",
"\u003c/p\u003e\n",
"\n",
"\n",
"## 总结\n",
"\n",
"传统图像分类方法由多个阶段构成,框架较为复杂,而端到端的CNN模型结构可一步到位,而且大幅度提升了分类准确率。本文我们首先介绍VGG、GoogleNet、ResNet三个经典的模型;然后基于CIFAR10数据集,介绍如何使用PaddlePaddle配置和训练CNN模型,尤其是VGG和ResNet模型;最后介绍如何使用PaddlePaddle的API接口对图片进行预测和特征提取。对于其他数据集比如ImageNet,配置和训练流程是同样的,大家可以自行进行实验。\n",
"\n",
"\n",
"## 参考文献\n",
"\n",
"[1] D. G. Lowe, [Distinctive image features from scale-invariant keypoints](http://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf). IJCV, 60(2):91-110, 2004.\n",
"\n",
"[2] N. Dalal, B. Triggs, [Histograms of Oriented Gradients for Human Detection](http://vision.stanford.edu/teaching/cs231b_spring1213/papers/CVPR05_DalalTriggs.pdf), Proc. IEEE Conf. Computer Vision and Pattern Recognition, 2005.\n",
"\n",
"[3] Ahonen, T., Hadid, A., and Pietikinen, M. (2006). [Face description with local binary patterns: Application to face recognition](http://ieeexplore.ieee.org/document/1717463/). PAMI, 28.\n",
"\n",
"[4] J. Sivic, A. Zisserman, [Video Google: A Text Retrieval Approach to Object Matching in Videos](http://www.robots.ox.ac.uk/~vgg/publications/papers/sivic03.pdf), Proc. Ninth Int'l Conf. Computer Vision, pp. 1470-1478, 2003.\n",
"\n",
"[5] B. Olshausen, D. Field, [Sparse Coding with an Overcomplete Basis Set: A Strategy Employed by V1?](http://redwood.psych.cornell.edu/papers/olshausen_field_1997.pdf), Vision Research, vol. 37, pp. 3311-3325, 1997.\n",
"\n",
"[6] Wang, J., Yang, J., Yu, K., Lv, F., Huang, T., and Gong, Y. (2010). [Locality-constrained Linear Coding for image classification](http://ieeexplore.ieee.org/abstract/document/5540018/). In CVPR.\n",
"\n",
"[7] Perronnin, F., Sánchez, J., \u0026 Mensink, T. (2010). [Improving the fisher kernel for large-scale image classification](http://dl.acm.org/citation.cfm?id=1888101). In ECCV (4).\n",
"\n",
"[8] Lin, Y., Lv, F., Cao, L., Zhu, S., Yang, M., Cour, T., Yu, K., and Huang, T. (2011). [Large-scale image clas- sification: Fast feature extraction and SVM training](http://ieeexplore.ieee.org/document/5995477/). In CVPR.\n",
"\n",
"[9] Krizhevsky, A., Sutskever, I., and Hinton, G. (2012). [ImageNet classification with deep convolutional neu- ral networks](http://www.cs.toronto.edu/~kriz/imagenet_classification_with_deep_convolutional.pdf). In NIPS.\n",
"\n",
"[10] G.E. Hinton, N. Srivastava, A. Krizhevsky, I. Sutskever, and R.R. Salakhutdinov. [Improving neural networks by preventing co-adaptation of feature detectors](https://arxiv.org/abs/1207.0580). arXiv preprint arXiv:1207.0580, 2012.\n",
"\n",
"[11] K. Chatfield, K. Simonyan, A. Vedaldi, A. Zisserman. [Return of the Devil in the Details: Delving Deep into Convolutional Nets](https://arxiv.org/abs/1405.3531). BMVC, 2014。\n",
"\n",
"[12] Szegedy, C., Liu, W., Jia, Y., Sermanet, P., Reed, S., Anguelov, D., Erhan, D., Vanhoucke, V., Rabinovich, A., [Going deeper with convolutions](https://arxiv.org/abs/1409.4842). In: CVPR. (2015)\n",
"\n",
"[13] Lin, M., Chen, Q., and Yan, S. [Network in network](https://arxiv.org/abs/1312.4400). In Proc. ICLR, 2014.\n",
"\n",
"[14] S. Ioffe and C. Szegedy. [Batch normalization: Accelerating deep network training by reducing internal covariate shift](https://arxiv.org/abs/1502.03167). In ICML, 2015.\n",
"\n",
"[15] K. He, X. Zhang, S. Ren, J. Sun. [Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385). CVPR 2016.\n",
"\n",
"[16] Szegedy, C., Vanhoucke, V., Ioffe, S., Shlens, J., Wojna, Z. [Rethinking the incep-tion architecture for computer vision](https://arxiv.org/abs/1512.00567). In: CVPR. (2016).\n",
"\n",
"[17] Szegedy, C., Ioffe, S., Vanhoucke, V. [Inception-v4, inception-resnet and the impact of residual connections on learning](https://arxiv.org/abs/1602.07261). arXiv:1602.07261 (2016).\n",
"\n",
"[18] Everingham, M., Eslami, S. M. A., Van Gool, L., Williams, C. K. I., Winn, J. and Zisserman, A. [The Pascal Visual Object Classes Challenge: A Retrospective]((http://link.springer.com/article/10.1007/s11263-014-0733-5)). International Journal of Computer Vision, 111(1), 98-136, 2015.\n",
"\n",
"[19] He, K., Zhang, X., Ren, S., and Sun, J. [Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification](https://arxiv.org/abs/1502.01852). ArXiv e-prints, February 2015.\n",
"\n",
"[20] http://deeplearning.net/tutorial/lenet.html\n",
"\n",
"[21] https://www.cs.toronto.edu/~kriz/cifar.html\n",
"\n",
"[22] http://cs231n.github.io/classification/\n",
"\n",
"\u003cbr/\u003e\n",
"\u003ca rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\"\u003e\u003cimg alt=\"知识共享许可协议\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" /\u003e\u003c/a\u003e\u003cbr /\u003e\u003cspan xmlns:dct=\"http://purl.org/dc/terms/\" href=\"http://purl.org/dc/dcmitype/Text\" property=\"dct:title\" rel=\"dct:type\"\u003e本教程\u003c/span\u003e 由 \u003ca xmlns:cc=\"http://creativecommons.org/ns#\" href=\"http://book.paddlepaddle.org\" property=\"cc:attributionName\" rel=\"cc:attributionURL\"\u003ePaddlePaddle\u003c/a\u003e 创作,采用 \u003ca rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\"\u003e知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议\u003c/a\u003e进行许可。\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
图像分类
=======
# 图像分类
本教程源代码目录在[book/image_classification](https://github.com/PaddlePaddle/book/tree/develop/image_classification), 初次使用请参考PaddlePaddle[安装教程](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/getstarted/build_and_install/docker_install_cn.rst)
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,13 +35,12 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
<div id="markdown" style='display:none'>
图像分类
=======
# 图像分类
本教程源代码目录在[book/image_classification](https://github.com/PaddlePaddle/book/tree/develop/image_classification), 初次使用请参考PaddlePaddle[安装教程](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/getstarted/build_and_install/docker_install_cn.rst)。
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
<html>
<head>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
extensions: ["tex2jax.js", "TeX/AMSsymbols.js", "TeX/AMSmath.js"],
jax: ["input/TeX", "output/HTML-CSS"],
tex2jax: {
inlineMath: [ ['$','$'] ],
displayMath: [ ['$$','$$'] ],
processEscapes: true
},
"HTML-CSS": { availableFonts: ["TeX"] }
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js" async></script>
<script type="text/javascript" src="../.tmpl/marked.js">
</script>
<link href="http://cdn.bootcss.com/highlight.js/9.9.0/styles/darcula.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/highlight.js/9.9.0/highlight.min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/perfect-scrollbar/0.6.14/css/perfect-scrollbar.min.css" rel="stylesheet">
<link href="../.tmpl/github-markdown.css" rel='stylesheet'>
</head>
<style type="text/css" >
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
</style>
<body>
<div id="context" class="container markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
<div id="markdown" style='display:none'>
# Deep Learning with PaddlePaddle
1. [Fit a Line](http://book.paddlepaddle.org/fit_a_line/index.en.html)
1. [Recognize Digits](http://book.paddlepaddle.org/recognize_digits/index.en.html)
1. [Image Classification](http://book.paddlepaddle.org/image_classification/index.en.html)
1. [Word to Vector](http://book.paddlepaddle.org/word2vec/index.en.html)
1. [Understand Sentiment](http://book.paddlepaddle.org/understand_sentiment/index.en.html)
1. [Label Semantic Roles](http://book.paddlepaddle.org/label_semantic_roles/index.en.html)
1. [Machine Translation](http://book.paddlepaddle.org/machine_translation/index.en.html)
1. [Recommender System](http://book.paddlepaddle.org/recommender_system/index.en.html)
This tutorial is contributed by <a xmlns:cc="http://creativecommons.org/ns#" href="http://book.paddlepaddle.org" property="cc:attributionName" rel="cc:attributionURL">PaddlePaddle</a>, and licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.
</div>
<!-- You can change the lines below now. -->
<script type="text/javascript">
marked.setOptions({
renderer: new marked.Renderer(),
gfm: true,
breaks: false,
smartypants: true,
highlight: function(code, lang) {
code = code.replace(/&amp;/g, "&")
code = code.replace(/&gt;/g, ">")
code = code.replace(/&lt;/g, "<")
code = code.replace(/&nbsp;/g, " ")
return hljs.highlightAuto(code, [lang]).value;
}
});
document.getElementById("context").innerHTML = marked(
document.getElementById("markdown").innerHTML)
</script>
</body>
{
"is_en": true,
"chapters": [
{
"name": "Linear Regression",
"link": "./fit_a_line/index.en.html"
},
{
"name": "Recognize Digits",
"link": "./recognize_digits/index.en.html"
},
{
"name": "Image Classification",
"link": "./image_classification/index.en.html"
},
{
"name": "Word2Vec",
"link": "./word2vec/index.en.html"
},
{
"name": "Sentiment Analysis",
"link": "./understand_sentiment/index.en.html"
},
{
"name": "Semantic Role Labeling",
"link": "./label_semantic_roles/index.en.html"
},
{
"name": "Machine Translation",
"link": "./machine_translation/index.en.html"
},
{
"name": "Personalized Recommendation",
"link": "./recommender_system/index.en.html"
}
]
}
index.html.tmpl
\ No newline at end of file
<html>
<head>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
extensions: ["tex2jax.js", "TeX/AMSsymbols.js", "TeX/AMSmath.js"],
jax: ["input/TeX", "output/HTML-CSS"],
tex2jax: {
inlineMath: [ ['$','$'] ],
displayMath: [ ['$$','$$'] ],
processEscapes: true
},
"HTML-CSS": { availableFonts: ["TeX"] }
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js" async></script>
<script type="text/javascript" src="../.tmpl/marked.js">
</script>
<link href="http://cdn.bootcss.com/highlight.js/9.9.0/styles/darcula.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/highlight.js/9.9.0/highlight.min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/perfect-scrollbar/0.6.14/css/perfect-scrollbar.min.css" rel="stylesheet">
<link href="../.tmpl/github-markdown.css" rel='stylesheet'>
</head>
<style type="text/css" >
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
</style>
<body>
<div id="context" class="container markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
<div id="markdown" style='display:none'>
# 深度学习入门
1. [新手入门](http://book.paddlepaddle.org/fit_a_line)
1. [识别数字](http://book.paddlepaddle.org/recognize_digits)
1. [图像分类](http://book.paddlepaddle.org/image_classification)
1. [词向量](http://book.paddlepaddle.org/word2vec)
1. [情感分析](http://book.paddlepaddle.org/understand_sentiment)
1. [语义角色标注](http://book.paddlepaddle.org/label_semantic_roles)
1. [机器翻译](http://book.paddlepaddle.org/machine_translation)
1. [个性化推荐](http://book.paddlepaddle.org/recommender_system)
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="知识共享许可协议" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/Text" property="dct:title" rel="dct:type">本教程</span><a xmlns:cc="http://creativecommons.org/ns#" href="http://book.paddlepaddle.org" property="cc:attributionName" rel="cc:attributionURL">PaddlePaddle</a> 创作,采用 <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议</a>进行许可。
</div>
<!-- You can change the lines below now. -->
<script type="text/javascript">
marked.setOptions({
renderer: new marked.Renderer(),
gfm: true,
breaks: false,
smartypants: true,
highlight: function(code, lang) {
code = code.replace(/&amp;/g, "&")
code = code.replace(/&gt;/g, ">")
code = code.replace(/&lt;/g, "<")
code = code.replace(/&nbsp;/g, " ")
return hljs.highlightAuto(code, [lang]).value;
}
});
document.getElementById("context").innerHTML = marked(
document.getElementById("markdown").innerHTML)
</script>
</body>
{
"is_en": false,
"chapters": [
{
"name": "新手入门",
"link": "./fit_a_line/index.html"
},
{
"name": "识别数字",
"link": "./recognize_digits/index.html"
},
{
"name": "图像分类",
"link": "./image_classification/index.html"
},
{
"name": "词向量",
"link": "./word2vec/index.html"
},
{
"name": "情感分析",
"link": "./understand_sentiment/index.html"
},
{
"name": "语义角色标注",
"link": "./label_semantic_roles/index.html"
},
{
"name": "机器翻译",
"link": "./machine_translation/index.html"
},
{
"name": "个性化推荐",
"link": "./recommender_system/index.html"
}
]
}
<!DOCTYPE html>
<html lang="{% if is_en %}en{%else%}zh-Hans{% endif %}">
<head>
<meta charset="UTF-8">
<title>{% if not is_en %}深度学习入门{%else%}Deep Learning 101{% endif %}</title>
<link href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/tether/1.4.0/js/tether.js"></script>
<script src="http://cdn.bootcss.com/jquery/3.1.0/jquery.slim.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<style>
* {
font-family:"Roboto","Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;
}
.left-panel {
background: #E5E6EA;
}
.left-panel .card-block a.click_active {
background-color: #597cf1;
color: #fff;
}
.left-panel .card-header {
background: #ecedee;
}
{% if not is_en %}
.left-panel .card-header a {
font-size: 14px;
}
{% endif %}
.left-panel .card-block a:not(.click_active) {
background: #e4e6e9;
}
.left-panel .card-block a {
border-radius: 0px;
font-size: 13px;
color: #2F323A;
padding-left: 40px;
border: 1px solid rgba(0,0,0,.125);
}
.left-panel .card-block a.active_color {
color: rgb(70, 74, 76);
font-weight: bolder;
}
.left-panel .list-group-item {
-moz-box-align: center;
align-items: center;
display: flex;
flex-flow: row wrap;
margin-bottom: -1px;
padding: 0.75rem 1.25rem;
position: relative;
color: #2f323a;
}
.navbar img {
height: 90%;
width: 90%;
}
</style>
</head>
<body>
<nav class="navbar navbar-toggleable-md navbar-inverse bg-inverse">
<a class="navbar-brand mr-auto" href="#">
<img alt="PaddlePaddle" src="./.theme/PP_w.png">
</a>
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" href="http://paddlepaddle.org">
{% if is_en %}Home{% else %}首页{% endif %}
</a>
</li>
<li class="nav-item {% if not is_en %}active{% endif %}">
<a class="nav-link" href="{% if is_en %}./index.html{% else %}#{%endif%}">
{% if is_en %}中文{% else %}深度学习入门{% endif %}
</a>
</li>
<li class="nav-item {% if is_en %}active{% endif %}">
<a class="nav-link" href="{% if is_en %}#{% else %}./index.en.html{% endif %}">
{% if is_en %}Deep Learning 101{% else %}English{% endif %}
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/PaddlePaddle/book/">Fork on Github</a>
</li>
</ul>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-3 pl-1 pr-1 left-panel">
<div id="accordion" role="tablist" aria-multiselectable="true">
<div class="card">
<div class="card-header" role="tab" id="headingOne">
<h5 class="mb-0">
<a aria-expanded="true" aria-controls="collapseOne">
{% if is_en %}Deep Learning 101<span class="sr-only">(current)</span>{% else %}深度学习入门{% endif %}
</a>
</h5>
</div>
<div id="collapseOne" class="rounded-0 collapse show" role="tabpanel" aria-labelledby="headingOne">
<div class="card-block pl-0 pr-0 pt-0 pb-0">
<div class="list-group ">
{% for chapter in chapters %}
<a href="{{ chapter.link }}" target="content_iframe" class="list-group-item list-group-item-action" style="border: 0px; border-bottom: 2px solid #dddfe3;">
{{ chapter.name }}
</a>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<iframe src="./fit_a_line/index{% if is_en %}.en{% endif %}.html" style="border: none; overflow-y : hidden" width="100%" height="100%" name="content_iframe" id="content_iframe">
</iframe>
</div>
</div>
</div>
<script>
$('#content_iframe').on('load', function(){
$("#content_iframe").height(200) // trick code to shrink iframe size
var body = $('#content_iframe').contents().find("body")
body.css("overflow-y", "hidden")
$("#content_iframe").height(body.height()+20)
var alllinks = $('#content_iframe').contents().find("a")
for (var i =0; i<alllinks.length; ++i) {
alllinks[i].setAttribute("target", "_blank")
}
});
$(".list-group a").click(function(){
$(".list-group a.click_active").removeClass("click_active");
$(this).addClass("click_active");
})
$($(".list-group a")[0]).addClass("click_active")
</script>
</body>
</html>
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -39,7 +39,7 @@ HEAD = """
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -13,7 +13,9 @@ export PATH=/usr/bin:$PATH
pre-commit install
if ! pre-commit run -a ; then
ls -lh
git diff --exit-code
exit 1
fi
trap : 0
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
......@@ -35,7 +35,7 @@
<body>
<div id="context" class="container markdown-body">
<div id="context" class="container-fluid markdown-body">
</div>
<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册