Generative Adversarial Network 是深度学习中非常有趣的一种方法。GAN最早源自Ian Goodfellow的这篇论文。LeCun对GAN给出了极高的评价:

“There are many interesting recent development in deep learning…The most important one, in my opinion, is adversarial training (also called GAN for Generative Adversarial Networks). This, and the variations that are now being proposed is the most interesting idea in the last 10 years in ML, in my opinion.” – Yann LeCun

那么我们就看看GAN究竟是怎么回事吧:

如上图所示,GAN包含两个互相对抗的网络:G(Generator)和D(Discriminator)。正如它的名字所暗示的那样,它们的功能分别是:

Generator是一个生成器的网络,它接收一个随机的噪声,通过这个噪声生成图片,记做G(z)。
Discriminator是一个鉴别器网络,判别一张图片或者一个输入是不是“真实的”。它的输入x是数据或者图片,输出D(x)代表x为真实图片的概率,如果为1,就代表100%是真实的图片,而输出为0,就代表不可能是真实的图片。
在训练过程中,生成网络G的目标就是尽量生成真实的图片去欺骗判别网络D。而D的目标就是尽量把G生成的图片和真实的图片分别开来。这样,G和D构成了一个动态的“博弈过程”。在最理想的状态下,G可以生成足以“以假乱真”的图片G(z)。对于D来说,它难以判定G生成的图片究竟是不是真实的,因此D(G(z)) = 0.5。

最后,我们就可以使用生成器和随机输入来生成不同的数据或者图片了。

上面的描述大家可能都能理解,但是把它变成数学语言,可能你就蒙B了。

“GANçš„æ ¸å¿ƒåŽŸç†â€çš„å›¾ç‰‡æœç´¢ç»“æžœ

如上图所示,x是输入,z是随机噪声。D(x)是鉴别器的判定数据为真的概率,D(G(z))是判定生成数据为真的概率。生成器希望这个D(G(z))越大越好,这个时候整个表达式的值应该变小。而鉴别器的目的是能够有效区分真实数据和假数据,所以D(x)应该趋向于变大,D(G(z))趋向于变小,整个表达式就变大。也就是说训练过程,生成器和辨别器互相对抗,一个使上述表达式变小,另一个使其变大,最后训练趋向于平衡,而生成器这时候应该生成真假难辨的数据,这就是我们的最终目的。

上图是GAN算法训练的具体过程,这里我们不做过多的解释,直接运行一个例子。

“GAN”的图片搜索结果

我们用MINST数据集来看看如何使用TensorflowJS来训练一个GAN,模拟生成手写数字。

代码见我的codepen

function gen(xs) {
const l1 = tf.leakyRelu(xs.matMul(G1w).add(G1b));
const l2 = tf.leakyRelu(l1.matMul(G2w).add(G2b));
const l3 = tf.tanh(l2.matMul(G3w).add(G3b));
return l3;
}

function disReal(xs) {
const l1 = tf.leakyRelu(xs.matMul(D1w).add(D1b));
const l2 = tf.leakyRelu(l1.matMul(D2w).add(D2b));
const logits = l2.matMul(D3w).add(D3b);
const output = tf.sigmoid(logits);
return [logits, output];
}

function disFake(xs) {
return disReal(gen(xs));
}
GAN的两个网络分别用gen和disReal创建。gen是生成器网络,disReal是辨别器的网络。disFake是把生成数据用辨别器来辨别。这里的网络使用leakyrelu。使得输出在-inf到+inf,利用sigmoid映射到【0,1】,这是辨别器模型输出一个0-1之间的概率。

“leaky relu”的图片搜索结果

通常我们会创建一个比生成器更复杂的鉴别器网络使得鉴别器有足够的分辨能力。但在这个例子里,两个网络的复杂程度类似。

计算损失的函数使用 tf.sigmoidCrossEntropyWithLogits,值得注意的是,在最新的0.13版本中,这个交叉熵被移除了,你需要自己实现该方法。

训练过程如下:

async function trainBatch(realBatch, fakeBatch) {
const dcost = dOptimizer.minimize(
() => {
const [logitsReal, outputReal] = disReal(realBatch);
const [logitsFake, outputFake] = disFake(fakeBatch);

const lossReal = sigmoidCrossEntropyWithLogits(ONES_PRIME, logitsReal);
const lossFake = sigmoidCrossEntropyWithLogits(ZEROS, logitsFake);
return lossReal.add(lossFake).mean();
},
true,
[D1w, D1b, D2w, D2b, D3w, D3b]
);
await tf.nextFrame();
const gcost = gOptimizer.minimize(
() => {
const [logitsFake, outputFake] = disFake(fakeBatch);

const lossFake = sigmoidCrossEntropyWithLogits(ONES, logitsFake);
return lossFake.mean();
},
true,
[G1w, G1b, G2w, G2b, G3w, G3b]
);
await tf.nextFrame();

return [dcost, gcost];
}
训练使用了两个optimizer,

第一步,计算实际数据的辨别结果和1的交叉熵,以及生成器生成数据的辨别结果和0的交叉熵。也就是说,我们希望辨别器尽可能的判断出生成数据都是假的而实际数据都是真的。使得这两个交叉熵的均值最小。
第二步开始对抗,要让生成数据尽可能被判别为真。
下图是某个训练过程的损失:

这个是经过1000个迭代后的生成图:

大家可以尝试调整学习率,增加网络复杂度,加大迭代次数来获得更好的生成模型。

GAN的学习其实还是比较复杂的,参数和损失选择都不容易,好在有一些现成的工具可以使用,另外推荐大家去https://poloclub.github.io/ganlab/,提供了很直观的GAN学习的过程。这个也是用TensorflowJS来实现的。

参考:

https://www.msra.cn/zh-cn/news/features/gan-20170511
https://zhuanlan .www.michenggw.com zhihu.com/p/24767059
http://blog.aylien.com/introduction-www.mhylpt.com generative-adversarial-networks-code-tensorflow/
https://github.com/carpedm20/DCGAN-tensorflow
https://blog.openai.www.gcyl152.com com/generative-models/
https://zhuanlan.zhihu.com/p/45200767
https://blog.csdn.net/heyc861221/article/details/80127148

在浏览器中进行深度学习:TensorFlow.js (八)生成对抗网络 (GAN的更多相关文章

  1. 深度学习框架PyTorch一书的学习-第七章-生成对抗网络(GAN)

    参考:https://github.com/chenyuntc/pytorch-book/tree/v1.0/chapter7-GAN生成动漫头像 GAN解决了非监督学习中的著名问题:给定一批样本,训 ...

  2. 人工智能中小样本问题相关的系列模型演变及学习笔记(二):生成对抗网络 GAN

    [说在前面]本人博客新手一枚,象牙塔的老白,职业场的小白.以下内容仅为个人见解,欢迎批评指正,不喜勿喷![握手][握手] [再啰嗦一下]本文衔接上一个随笔:人工智能中小样本问题相关的系列模型演变及学习 ...

  3. TensorFlow从1到2(十二)生成对抗网络GAN和图片自动生成

    生成对抗网络的概念 上一篇中介绍的VAE自动编码器具备了一定程度的创造特征,能够"无中生有"的由一组随机数向量生成手写字符的图片. 这个"创造能力"我们在模型中 ...

  4. 深度学习-生成对抗网络GAN笔记

    生成对抗网络(GAN)由2个重要的部分构成: 生成器G(Generator):通过机器生成数据(大部分情况下是图像),目的是“骗过”判别器 判别器D(Discriminator):判断这张图像是真实的 ...

  5. 利用tensorflow训练简单的生成对抗网络GAN

    对抗网络是14年Goodfellow Ian在论文Generative Adversarial Nets中提出来的. 原理方面,对抗网络可以简单归纳为一个生成器(generator)和一个判断器(di ...

  6. CNCC2017中的深度学习与跨媒体智能

    CNCC2017中的深度学习与跨媒体智能 转载请注明作者:梦里茶 目录 机器学习与跨媒体智能 传统方法与深度学习 图像分割 小数据集下的深度学习 语音前沿技术 生成模型 基于贝叶斯的视觉信息编解码 珠 ...

  7. 深度学习-tensorflow学习笔记(1)-MNIST手写字体识别预备知识

    深度学习-tensorflow学习笔记(1)-MNIST手写字体识别预备知识 在tf第一个例子的时候需要很多预备知识. tf基本知识 香农熵 交叉熵代价函数cross-entropy 卷积神经网络 s ...

  8. 深度学习Tensorflow相关书籍推荐和PDF下载

    深度学习Tensorflow相关书籍推荐和PDF下载 baihualinxin关注 32018.03.28 10:46:16字数 481阅读 22,673 1.机器学习入门经典<统计学习方法&g ...

  9. Deep learning for visual understanding: A review 视觉理解中的深度学习:回顾 之一

    Deep learning for visual understanding: A review 视觉理解中的深度学习:回顾 ABSTRACT: Deep learning algorithms ar ...

随机推荐

  1. java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)

    今天开始就来总结一下Java多线程的基础知识点,下面是本篇的主要内容(大部分知识点参考java核心技术卷1): 1.什么是线程以及多线程与进程的区别 2.多线程的创建与启动 3.中断线程和守护线程以及 ...

  2. mysql 自增主键为什么不是连续的?

    由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧凑 MyISAM 引擎的自增值保存在数据文件中 nnoDB 引擎的自增值,其实是保存在了内存里,并且到了 MySQL 8.0 ...

  3. 文件权限管理命令chmod,chown与文本搜索命令grep

    1.复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限. [root@bogon home]# cp -r /etc/sk ...

  4. vue学习笔记-:class

    当items.state为true时使用class='rad2state',否则为rad2(默认).

  5. <Docker学习>2.Centos7安装docker

    Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10. CentOS 7 满足最低内核的要求,但由于内核版本比较低,部分功能(如 overlay2 存储层驱动)无 ...

  6. 学习python第十五天,面向对象

    Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的. 面向对象技术简介 类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了该集 ...

  7. PAT (Basic Level) Practice 1004 成绩排名

    个人练习 读入n名学生的姓名.学号.成绩,分别输出成绩最高和成绩最低学生的姓名和学号. 输入格式:每个测试输入包含1个测试用例,格式为\ 第1行:正整数n 第2行:第1个学生的姓名 学号 成绩 第3行 ...

  8. 14、函数之匿名函数(lambda)

    关键字lambda可以创建匿名函数,语法是:lambda 参数s :表达式.匿名函数与普通函数只有以下几点不同:①没有函数名:②只能有一个表达式:③一定会有返回值,返回值就是该表达式的结果. 另外,匿 ...

  9. spark的排序方法

    今天我们来介绍spark中排序的操作,spark的排序很简单,我们可以直接使用sortBy来进行,这个里面我们使用case clas,使用case class的好处是1.不用newjiukeyi 搞出 ...

  10. 10,before_request 和 after_request

    Flask我们已经学习很多基础知识了,现在有一个问题 我们现在有一个 Flask 程序其中有3个路由和视图函数,如下: from flask import Flask app = Flask(__na ...