2019-04-28 21:37:16 cjm083121 阅读数 216
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    39700 人正在学习 去看看 唐宇迪

一、名词解释

激活函数:用于计算隐藏层值的非线性函数
在这里插入图片描述

二、整流线性单元

整流线性单元是隐藏单元极好的默认选择
整流线性单元使用激活函数g(z)=max{0,z}
在这里插入图片描述
整流线性单元的一个缺陷是它们不能通过基于梯度的方法学习那些使它们激活为零的样本。整流线性单元的各种扩展保证了它们能在各个位置都接收到梯度。
整流线性单元的扩展基于当zi < 0 时使用一个非零的斜率αi:
在这里插入图片描述

三、maxout单元

maxout 单元(maxout unit)(Goodfellow et al., 2013a) 进一步扩展了整流线性单元。maxout 单元将z划分为每组具有k个值的组,每个maxout 单元则输出每组中的最大元素:
在这里插入图片描述
maxout单元可以学习具有多达k段的分段线性的凸函数。maxout 单元因此可以视为学习激活函数本身。使用足够大的k,maxout单元可以以任意的精确度来近似任何凸函数。
整流线性单元和它的扩展都是基于一个原则,那就是如果它们的行为更接近线性,那么模型更容易优化。

三、其它

在引入整流线性单元之前,大多数神经网络使用logistic sigmoid 激活函数或者是双曲正切激活函数。
sigmoid单元在其大部分定义域内都饱和。sigmoid 单元的广泛饱和性会使得基于梯度的学习变得非常困难。因为这个原因,现在不鼓励将它们用作前馈网络中的隐藏单元。logistic sigmoid激活函数如下图所示:
在这里插入图片描述
当必须要使用sigmoid激活函数时,双曲正切激活函数通常要比logistic sigmoid 函数表现更好,因为它更像是单位函数,训练起来更容易。双曲正切激活函数如下图所示:
在这里插入图片描述
sigmoid激活函数在除了前馈网络以外的情景中更为常见。

2019-07-05 14:47:37 qq_43270687 阅读数 72
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    39700 人正在学习 去看看 唐宇迪

解决欠拟合

在这里插入图片描述
1.L1正则(岭回归)
回归容易产生稀疏矩阵(有数值会落在坐标轴上)
在这里插入图片描述
在这里插入图片描述
2.L2正则(lasso回归)
在这里插入图片描述
在这里插入图片描述

解决过拟合

Njg3,size_16,color_FFFFFF,t_70)

模型的损失函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

特征工程

在这里插入图片描述标准化:(X-μ)/σ
区间缩放法:(X-Xmin)/(Xmax-Xmin)

KNN

在这里插入图片描述

决策树

在这里插入图片描述

集成学习

在这里插入图片描述在这里插入图片描述

聚类

在这里插入图片描述

SVM

在这里插入图片描述
在这里插入图片描述

2017-03-07 10:45:47 u010555688 阅读数 680
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    39700 人正在学习 去看看 唐宇迪

注:本文是在阅读新智元的文章后总结,文中不少语句参考了原文作者,请知晓。


1、shuffle:在框架允许的前提下,每个epoch要shuffle一次;

2、扩展数据集:小数据集容易使得模型过拟合,但过分扩展会使得大都相同的数据,需采取一定的方法,避免出现相同的样本(尝试中);

3、在非常小的子数据集上训练进行过拟合,再在整个数据集上训练:以确定网络可以收敛;

4、始终是用dropout将过拟合的几率最小化:当神经元节点超过256时,就要使用dropout,Dropout as a Bayesian Approximation: Representing Model Uncertainty in Deep Learning [Gal Yarin & Zoubin Ghahramani,2015].

5、MAX pooling会更快,避免使用LRN pooling

6、避免使用sigmoid/tanh:代价昂贵,容易饱和,网络越深,越容易停止反向传播;而更简单有效的ReLU和PreLU能够促进稀疏性,其反向传播也更加鲁棒,Deep Sparse Rectifier Neural Networks

7、在max pooling之前不要使用ReLU和PreLU,在保持计算之后再使用;

8、不要使用ReLU:虽然它们是很好的非线性函数,但是在微调模型时会阻碍反向传播,在初始化阶段被卡住,无法得到任何微调效果;可以使用PreLU以及一个很小的乘数(通常是0.1),收敛更快;

9、经常使用批标准化(Batch Normalization):可以允许更快的收敛以及更小的数据集,节省时间以及资源,Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift [Sergey Ioffe & Christian Szegedy,2015]。

10、相对于减去平均值,更倾向于将数据压缩到[-1, +1]:针对训练和部署的技巧,而非提升性能;

11、小型化模型,并尝试 ensemble以方便用户及服务,并提升准确度

12、尽可能使用 xavier 初始化:可在较大的全连接层上使用,避免在CNN层使用,An Explanation of Xavier Initialization(by Andy Jones)

13、如果输入数据有空间参数,可以尝试端到端CNNSqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size [Forrest N. Iandola et. al. 2016];

14、修改模型,只要可能就使用 1x1 的 CNN 层,它的位置对提高性能很有帮助。

15、假如你要利用模型或你自己的层来制作模板,记得把所有东西参数化,否则你得重建所有二进制文件。

16、了解正在着手的任务及使用的结构,莫要盲目地复制模型;


参考资料:

1、 Ian Goodfellow , Yoshua Bengio 和 Aaron Courville 合著的经典教材《深度学习》(数学理论丰富)

2、邓力和俞栋合著的《深度学习:方法及应用》(关于历史与介绍)

3、Timothy Masters 写的 Deep Belief Nets in C++ and CUDA C, Vol. 1: Restricted Boltzmann Machines and Supervised Feedforward Networks(实现算法)

2018-01-24 22:04:13 huanhuan_Coder 阅读数 1521
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    39700 人正在学习 去看看 唐宇迪
  • 在深度学习领域,用for循环易造成效率低下,加速运算用vectorization向量化可以摆脱for循环。

  • 下面我们通过一个图来比较一下向量化和非向量化的区别
    m个样本的逻辑回归的向量化与非向量化

  • 上图是m个样本的逻辑回归的向量化和非向量化,单单从代码量和简洁程度上来看,向量化做的要比非向量化好得多,而且在执行效率上向量化要更高。这一切都要归功于python中的numpy。

  • numPy系统是Python的一种开源的数值计算扩展,这种工具可用来存储和处理大型矩阵,由于numpy可以利用并行化技术直接进行矩阵运算,所以避免了for循环带来的效率低下。

  • np.dot(w.T,x)是w的转置、x两个矩阵相乘,只用这一句话就代替了m次的计算,np.sum(z)是将z中各个元素加起来,A-Y得到的是矩阵A和矩阵Y相减后的矩阵。

2019-03-14 19:19:27 qq_24946843 阅读数 422
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    39700 人正在学习 去看看 唐宇迪

GAN的全称为Generative Adversarial Networks,意为对抗生成网络。原始的GAN是一种无监督学习方法,它巧妙地利用“对抗”的思想来学习生成式模型,一旦训练完成后可以生成全新的数据样本。DCGAN将GAN的概念扩展到卷积神经网络中,可以生成质量较高的图片样本。GAN和DCGAN在各个领域都有广泛的应用,这篇文章首先会介绍他们的原理,再介绍如何在TensorFlow中使用DCGAN生成图像,关于GAN和DCGAN的更多项目会在接下来的章节中进行介绍。

GAN的原理

GAN的原理其实非常简单。可以把GAN看成数据生成工具,这里以生成图片数据为例进行讲解,实际GAN可以应用到任何类型的数据。

假设有两个网络,生成网络G(Generator)和判别网络D(Discriminator) 
他们的功能分别是:

  • G负责生成图片,它接收一个随机的噪声z,通过该噪声生成图片,将生成的图片记为G(z)。
  • D负责判别一张图片是不是“真实的”。它的输入是x,x代表一张图片,输出D(x)表示x为真实图片的概率,如果为1,代表真实图片的概率为100%,而输出为0,代表不可能是真实的图片。

在训练过程中,生成网络G的目标是尽量生成真实的图片去欺骗判别网络D,而D的目标是尽量把生成的图片和真实的图片区分开来。这样,G和D构成了一个动态的“博弈”,这就是GAN的基本思想。

最后博弈的结果是什么?在理想的状态下,G可以生成足以"以假乱真"的图片G(z)。对于D来说,他难以判定G生成的图片究竟是不是真实的,因此D(G(z))=0.5。此时得到了一个生成式的模型G,他可以用来生成图片。 

 在上面的步骤中,每对D的参数更新一次,便接着更新一次G的参数。有时还可以对D的参数更新k次后再更新一次G的参数,这些要根据训练的实际情况进行调整。另外,要注意的是,由于D是希望损失越大越好,G是希望损失损失越小越好,所以他们是一个加上梯度,一个是减去梯度。

当训练完成后,可以从Pz(z)随机取出一个噪声,经过G运算后可以生成符合Pdata(x)的新样本。

2 DCGAN的原理

DCGAN的全称是Deep Convolutional Generative Adversarial Networks , 意即深度卷积对抗生成网络,它是由Alec Radford在论文Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks中提出的。从名字上来看,它是在GAN的基础上增加深度卷积网 络结构,专门生成图像样本。下面一起来学习DCGAN的原理。

上一节详细介绍了D 、G 的输入输出和损失的走义,但关于D 、G 本身的结构并没高做过多的介绍。事实上, GAN 并没再对D 、G 的具体结构做出任何限制。DCGAN中的D 、G 的含义以及损失都和原始GAN中完全一致,但是它在D和G中采用了较为特殊的结构,以便对图片进行有效建模。

对于判别器D,它的输入是一张图像,输出是这张图像为真实图像的概率。在DCGAN中,判别器D的结构是一个卷积神经网络,输入的图像经过若干层卷积后得到一个卷积特征,将得到的特征送入Logistic函数,输出可以看作是概率。

对于生成器G ,它的网络结构如下图所示。

G的输入时一个100维的向量z。它是之前所说的噪声向量。G网络的第一层实际是一个全连接层,将100维的向量变成一个4x4x1024维的向量,再reshape。

从第二层开始,使用转置卷积做上采样(反卷积),逐渐减少通道数,最后得到的输出为64x64x3,即输出一个三通道的宽和高都为64的图像。

反卷积(可参考这篇博客

下图表示的是参数为( i′=2,k′=3,s′=1,p′=2)的反卷积操作,其对应的卷积操作参数为 (i=4,k=3,s=1,p=0)。我们可以发现对应的卷积和非卷积操作其 (k=k′,s=s′),但是反卷积却多了p′=2。通过对比我们可以发现卷积层中左上角的输入只对左上角的输出有贡献,所以反卷积层会出现 p′=k−p−1=2。通过示意图,我们可以发现,反卷积层的输入输出在 s=s′=1 的情况下关系为:

Hout = (Hin-1)*stride -2*padding + kernel_size(卷积的输入即可反卷积的输出)

此外,G、D还有一些其他的实现细节:

  • 不采用任何池化层( Pooling Layer ),在判别器D 中,用带有步长( Stride)的卷积来代替池化层。
  • 在G 、D 中均使用Batch Normalization帮助模型收敛。
  • 在G中,激活函数除了最后一层都使用ReLU 函数,而最后一层使用tanh函数。使用tanh函数的原因在于最后一层要输出图像,而图像的像素值是有一个取值范围的,如0~255 。ReLU函数的输出可能会很大,而tanh函数的输出是在-1~1之间的,只要将tanh函数的输出加1再乘以127.5可以得到0~255 的像素值。
  • 在D 中,激活函数都使用Leaky ReLU作为激活函数。

以上是DCGAN中D和G的结构,损失的定义以及训练的方法和第1节中描述的完全一致。Alec Radford使用DCGAN在LSUN数据集上进行无监督学习, LSUN是一个场景理解图像数据集,主要包含了卧室、固房、客厅、教室等场景图像。在LSUN的卧室数据集上,DCGAN生成的图像如图8-2所示。 

这里写图片描述

 除了使用G生成图像之外,还可以将G的输入信号z看作生成图像的一种表示。假设图片A对应的输入为zA,图片B对应的输入为zB,可以在zA和zB之间做插值,并使用G生成每一个插值对应的图片,对应的结果如图8-3所示。每一行的最左边可以看做图片A,而每一行的最右边可以看做是图片B,DCGAN可以让生成的图像以比较自然的方式从A过渡到B,并保证每一张过渡图片都是卧室的图片。如图8-3所示的第六行中,一间没有窗户的卧室逐渐变化成了一间有窗户的卧室,在第四行中,一间有电视的卧室逐渐变化成了一间没有电视的卧室,原来电视的位置被窗帘取代,所有这些图片都是机器自动生成的。

这里写图片描述

 实验证明,不仅可以对输入信号z进行过渡插值,还可以对它进行复杂运算。如图8-4所示,用代表“露出笑容的女性”的zz,减去“女性”,再加上“男性”,最后得到了“露出笑容的男性”。

这里写图片描述

 

3 在TensorFlow中用DCGAN生成图像

本节会以GitHub上的一个DCGAN项目介绍TensorFlow中的DCGAN实现。利用该代码主要去完成两件事,一是生成MNIST手写数字,二是在自己的数据集上训练。还会穿插讲解该项目的数据读入方法、数据可视化方法。

3.1 生成MNIST图像

先做一个简单的小实验:生成MNIST手写数字。 
运行如下代码会下载MNIST数据集到data/mnist文件夹中。

run download.py mnist

download.py 依赖一个名为tqdm的库,如果运行报错,可以先使用pip install tqdm安装该库。

注意:当下载数据集时,如果出现网络问题导致下载中断, 在再次下载时必须先删除data/mnist 文件夹,否则download.py 会自动跳过下载。

下载完成后,使用下面的命令即可开始训练:

run main.py --dataset mnist --input_height=28 --output_height=28 --train

参数的含义会在下面的小节中进行详细的介绍,先来关注运行该命令后屏幕显示的信息:

Epoch:[1/25][162/1093]表示当前为第1个epoch,每个epoch内有1093步,当前为第162步。默认会在MNIST数据集运行25个epoch。每隔一段时间,程序会把生成的模型保存在checkpoint/mnist_64_28_28、文件夹中。此外,每隔100步,程序都会使用当前的G生成图像样本,并将图像保存在samples文件夹中。这些自动生成的图像以train开头,如train_20_0299.png表示是第20个epoch第299步生成的图像。根据这些图像,可以得知当前生成G的性能,从而决定是否可以停止训练。

运行到不同epoch时,生成的效果如图8-5所示。

0epoch199步​​​​
0epoch999步

 

2epoch1013步
3epoch720步

 

3.2 使用自己的数据集训练

本节介绍如何使用自己的图片数据集进行训练。首先需要准备好图片数据将它们裁剪到统一大小。在我的网盘中已经准备好了一个动漫人物头像数据集faces.zip 。链接:https://pan.baidu.com/s/1SlCM2hxluA1yZuwMh0dldQ 提取码:ws8g 
在源代码的data目录中新建一个anime目录(如果没有data目录可以自行新建) ,并将faces.zip中所有的图像文件解压到anime目录中。最后形成的项目结构为: 

这里写图片描述

在项目根目录中运行下面的命令即可开始训练:

run main.py --input_height 96 --input_width 96 \
    --output_height 48 --output_width 48 \
    --dataset anime --crop --train \
    --epoch 300 --input_fname_pattern ".jpg"

这里将参数设置为一共会训练300个epoch,实际可能并不需要那么多,读者同样可以观察samples文件夹下生成的样本图像来决定应该训练多少个 epoch 。在训练1个epoch后,产生的样本图像如图8-6所示,此时只有模糊的边框(产生的图片在samples文件夹中)。 

这里写图片描述

 在训练5个epoch后,产生的样本如图8-7所示。 

这里写图片描述

 在训练50个epoch 后,产生的样本如图8-8所示,此时模型已经基本收敛了。

这里写图片描述

 使用已经训练好的模型进行测试的对应命令为:

run main.py --input_height 96 --input_width 96 \
    --output_height 48 --output_width 48 \
    --dataset anime --crop

3.3 程序结构分析:如何将图像读入模型

如果对第3.1、3.2节中的命令仍有所疑惑,本节会结合程序源码,对这些输入参数进行详细的分析。项目所有的功能入口为文件main.py,因此,先来看下main.py的大体结构。在这个文件中,首先定义了一些参数,然后将参数统一保存到变量FLAGS中,接着根据这些参数调用DCGAN(),新建一个模型,并保存到变量dcgan中。接下来的代码为:

# 如果参数中指定为train,那么调用train方法进行训练
if FLAGS.train:
  dcgan.train(FLAGS)
else:
    # 如果不需训练,直接去载入已经训练好的模型
  if not dcgan.load(FLAGS.checkpoint_dir)[0]:
    raise Exception("[!] Train a model first, then run test mode")

# Below is codes for visualization
# 无论是进行训练还是直接执行,都会调用visualize方法进行可视化
OPTION = 2
visualize(sess, dcgan, FLAGS, OPTION)

根据这段代码,在输入命令时,如果指定了–train,会进行训练,如果不指定–train,会载入己保存的模型,无论是进行训练还是不进行训练,都会调用visualize方法进行可视化。

以上是该项目的整体逻辑。下面介绍输入的命令行和输入图像有关的参数处理。–input_height、–input_width、–output_height、–output_width 、–dataset、–crop、–input_fname_pattern 这些参数。

首先–dataset、–input_fname_pattern 两个参数。在model.py中,找到下列代码:

# mnist单独处理
if self.dataset_name == 'mnist':
  self.data_X, self.data_y = self.load_mnist()
  self.c_dim = self.data_X[0].shape[-1]
else:
  # 在训练时,使用self.data中的数据
  # 是data、dataset_name、self.input_fname_pattern
  self.data = glob(os.path.join("E:\datasets", self.dataset_name, self.input_fname_pattern))
  # 检查图片的通道数。一般是3通道彩色图
  imreadImg = imread(self.data[0]);
  if len(imreadImg.shape) >= 3: #check if image is a non-grayscale image by checking channel number
    self.c_dim = imread(self.data[0]).shape[-1]
  else:
    self.c_dim = 1

对于MNIST数据,程序是使用一个load_mnist()函数单独处理的。而对 于自己的数据集, 程序会在data 文件夹下根据dataset和input_fname pattern两个变量找图像文件。这里的self.dataset_name是输入参数dataset, self.input_fname_pattern是输入参数input_fname pattern 。如输入dataset 为anime 、input_fname_pattern 为.jpg ,程序会自动寻找路径为data/anime/ .jpg的所有图片,即data/anime目录下的所有jpg图像。

读入所高图片的文件名后,又会做哪些操作呢?这涉及–input_height 、–input_width 、–crop 、–output_height 、–output_width五个参数。首先要说明的一点是,如果输入时不指定–input_width,那么它的值会和–input_height的值相同;同样,如果不指定–output_width,那么它的值会和–output_height相同。即main.py中的:

if FLAGS.input_width is None:
  FLAGS.input_width = FLAGS.input_height
if FLAGS.output_width is None:
  FLAGS.output_width = FLAGS.output_height

读入的图片文件名首先经过以下操作(该部分代码在model.py 中):

# mnist单独操作
if config.dataset == 'mnist':
batch_images = self.data_X[idx*config.batch_size:(idx+1)*config.batch_size]
batch_labels = self.data_y[idx*config.batch_size:(idx+1)*config.batch_size]
else:
# self.data是所有图像文件名,batch_files是取出一个batch_size文件的文件名
batch_files = self.data[idx*config.batch_size:(idx+1)*config.batch_size]
# 调用get_image函数对每个图像进行处理
batch = [
    get_image(batch_file,
              input_height=self.input_height,
              input_width=self.input_width,
              resize_height=self.output_height,
              resize_width=self.output_width,
              crop=self.crop,
              grayscale=self.grayscale) for batch_file in batch_files]
# 区分灰度图和彩色图
if self.grayscale:
  batch_images = np.array(batch).astype(np.float32)[:, :, :, None]
else:
  batch_images = np.array(batch).astype(np.float32)

self.data是之前说的存放所有图像文件路径的列表,每次都从该列表中取出batch_size大小的子集batch_files,对于batch_files中的每一个文件路径,调用get_image函数进行处理。

get_image函数在utils.py中,在此直接列出所有用到的函数:

# get_image读入图像后直接使用transform函数
def get_image(image_path, input_height, input_width,
              resize_height=64, resize_width=64,
              crop=True, grayscale=False):
  image = imread(image_path, grayscale)
  return transform(image, input_height, input_width,
                   resize_height, resize_width, crop)


# transform函数
def transform(image, input_height, input_width, 
              resize_height=64, resize_width=64, crop=True):
  if crop:
  # 中心crop之后resize
    cropped_image = center_crop(
      image, input_height, input_width, 
      resize_height, resize_width)
  else:
  # 直接resize
    cropped_image = scipy.misc.imresize(image, [resize_height, resize_width])
    # 标准化处理
  return np.array(cropped_image)/127.5 - 1.

# 中心crop,再进行缩放
def center_crop(x, crop_h, crop_w,
                resize_h=64, resize_w=64):
  if crop_w is None:
    crop_w = crop_h
  h, w = x.shape[:2]
  j = int(round((h - crop_h)/2.))
  i = int(round((w - crop_w)/2.))
  return scipy.misc.imresize(
      x[j:j+crop_h, i:i+crop_w], [resize_h, resize_w])

get_image函数实际调用了transform 函数。transform 函数又使用了 center_crop函数。而center_crop函数的功能是:在图片中心截取高为crop_h像素,宽为crop_w像素的图片,再缩放为resize_h乘resize_w的大小。再看transform函数,对输入图像的处理有两种方法。当指定–crop后,会调用center_crop函数。根据调用关系,这里的input_height和input_width是输入的–input_height和–input_ width参数,而resize_height和resize_width是输入的–output_height和–output_width参数。因此,实际是在图像中心截 取高为input_height乘以input_width的小块,并放缩到output_ height乘以 output_width的大小。此外,如果不指定参数--crop,不去截取图像,而是直接缩放到output_height乘output_width 。

这样的话,之前的执行指令非常好理解了,下面的命令:

run main.py --input_height 96 --input_width 96 \
    --output_height 48 --output_width 48 \
    --dataset anime --crop --train --epoch 300 --input_fname_pattern "*.jpg"

对应的含义是:

  • 找出data/anime/下所有jpg格式的图像。
  • 将这些图像中心截取96x96的小块,并缩放到48 ×48像素。
  • 因为有–train参数, 所以执行训练。

最后还有一个参数–epoch没解释,这个参数含义很好理解,代表执行的epoch数目。

3.4 程序结构分析:可视化方法

在训练好模型或者载入已有模型后,都会调用visualize方法进行可视化,即main.py中的如下代码:

OPTION = 0
visualize(sess, dcgan, FLAGS, OPTION)

visualize函数在utils.py中。简单查看后可以发现该函数的输入参数option支持0、1、2、3、4一共5个值。在main. py 中直接更改OPTION的值可以使用不同的可视化方法。这里以option=0和option=1为例进行介绍。option=0的可视化方法:

# image_fname_dim是batch_size开方之后向上取整的值
image_frame_dim = int(math.ceil(config.batch_size**.5))
if option == 0:
  # 生成batch_size个z噪声
  z_sample = np.random.uniform(-0.5, 0.5, size=(config.batch_size, dcgan.z_dim))
  # 根据batch_size个z噪声生成batch_size张图片
  samples = sess.run(dcgan.sampler, feed_dict={dcgan.z: z_sample})
  # 将所有图片拼合成一张图片
  # 这一张图片的格式为image_frame_dim乘以image_frame_dim
  save_images(samples, [image_frame_dim, image_frame_dim], './samples/test_%s.png' % strftime("%Y%m%d%H%M%S", gmtime()))

程序首先根据batch_size的值计算出一个image_frame_dim 。这个值实际上是batch_size开方后再向上取整的结果。如默认的batch_size为64, 那么对应的image_frame_dim值是8 。

接着随机生成一些躁声z并保存为变量z_sample,它的形状为( batch size,z dim ),后者z_dim是单个噪声本身具有的维度,默认为100,这也和原始论文中的网络结构保持一致。在默认情况下,将生成一个形状为( 64, 100)的z_sample,z_sample中的每个值都在-0.5~0.5 之间。将它送入网络中,可以得到64张图像并放在samples中,最后调用save_images函数将64张图像组合为一张8*8的图像,如图8-9所示。 

这里写图片描述

 再看option=1的可视化方法:

elif option == 1:
  # values是和batch_size等长的向量,从0~1递增
  values = np.arange(0, 1, 1./config.batch_size)
  # 会生成100张图片
  for idx in xrange(100):
    print(" [*] %d" % idx)
    # 这里的z_sample大多数都是0
    z_sample = np.zeros([config.batch_size, dcgan.z_dim])
    # 实际上是把z_sample的第idx列变成values
    for kdx, z in enumerate(z_sample):
      z[idx] = values[kdx]

    if config.dataset == "mnist":
      # 对mnist分开处理
      y = np.random.choice(10, config.batch_size)
      y_one_hot = np.zeros((config.batch_size, 10))
      y_one_hot[np.arange(config.batch_size), y] = 1

      samples = sess.run(dcgan.sampler, feed_dict={dcgan.z: z_sample, dcgan.y: y_one_hot})
    else:
      samples = sess.run(dcgan.sampler, feed_dict={dcgan.z: z_sample})

    save_images(samples, [image_frame_dim, image_frame_dim], './samples/test_arange_%s.png' % (idx))

option=1的可视化方法会生成100张和option=0中差不多的图片。每个z_sample中的数字大多数都是0,某中第idx( idx 从0~99)列变成一个事先定义好的向量values。因此每个z_sample中各个图片对应的改变很小。图 8-10展示了使用option=1进行可视化生成的图片(变化比较细微) 。

这里写图片描述

剩下的几种可视化方法我们可以自行参阅源码进行分析。注意option=2 、 3、4 的几种方法都依赖一个名为moviepy的库。可以使用pip install moviep y安装,并保证import moviepy.editor as mpy不会出错。

4 总结

本章首先讲解了GAN和DCGAN的原理,接着介绍了一个非常有趣的项目:在TensorFlow中利用DCGAN生成图片。最后,以输入图像和可视化方法两部分为例,分析了DCGAN 项目的源码。希望通过这篇文章的介绍,掌握GAN的思想以及DCGAN的使用方法。

参考文章:21个项目玩转深度学习

学习笔记:GAN和DCGAN入门

对抗生成网络(Generative Adversarial Net)

生成对抗网络GANs理解(附代码)

生成式对抗网络GAN研究进展(二)——原始GAN

Pytorch实战3:DCGAN深度卷积对抗生成网络生成动漫头像

没有更多推荐了,返回首页