无需数学背景!谷歌研究员为你解密生成式对抗网络
itomcoil 2025-06-24 14:24 2 浏览
原文来源:Towards Data Science
作者:Stefan Hosein
「雷克世界」编译:嗯~是阿童木呀、KABUDA
导语:大家都知道,自从生成式对抗网络(GAN)出现以来,便在图像处理方面有着广泛的应用。但还是有很多人对于GAN不是很了解,担心由于没有数学知识底蕴而学不会GAN。在本文中,谷歌研究员Stefan Hosein提供了一份初学者入门GAN的教程,在这份教程中,即使你没有拥有深厚的数学知识,你也能够了解什么是生成式对抗网络(GAN)。并且在阅读完这篇文章之后,你将学会如何编写一个可以创建数字的简单GAN!
类比
理解GAN的一个最为简单的方法是通过一个简单的比喻:
假设有一家商店,店主要从顾客那里购买某些种类的葡萄酒,然后再将这些葡萄酒销售出去。
然而,有些可恶的顾客为了赚取金钱而出售假酒。在这种情况下,店主必须能够区分假酒和正宗的葡萄酒。
你可以想象,在最初的时候,伪造者在试图出售假酒时可能会犯很多错误,并且店主很容易就会发现该酒不是正宗的葡萄酒。经历过这些失败之后,伪造者会继续尝试使用不同的技术来模拟真正的葡萄酒,而有些方法最终会取得成功。现在,伪造者知道某些技术已经能够躲过店主的检查,那么他就可以开始进一步对基于这些技术的假酒进行改善提升。
与此同时,店主可能会从其他店主或葡萄酒专家那里得到一些反馈,说明她所拥有的一些葡萄酒并不是原装的。这意味着店主必须改进她的判别方式,从而确定葡萄酒是伪造的还是正宗的。伪造者的目标是制造出与正宗葡萄酒无法区分的葡萄酒,而店主的目标是准确地分辨葡萄酒是否是正宗的。
可以这样说,这种循环往复的竞争正是GAN背后的主要思想。
生成式对抗网络的组成部分
通过上面的例子,我们可以提出一个GAN的体系结构。
GAN中有两个主要的组成部分:生成器和鉴别器。在上面我们所描述的例子中,店主被称为鉴别器网络,通常是一个卷积神经网络(因为GAN主要用于图像任务),主要是分配图像是真实的概率。
伪造者被称为生成式网络,并且通常也是一个卷积神经网络(具有解卷积层,deconvolution layers)。该网络接收一些噪声向量并输出一个图像。当对生成式网络进行训练时,它会学习可以对图像的哪些区域进行改进/更改,以便鉴别器将难以将其生成的图像与真实图像区分开来。
生成式网络不断地生成与真实图像更为接近的图像,而与此同时,鉴别式网络则试图确定真实图像和假图像之间的差异。最终的目标就是建立一个生成式网络,它可以生成与真实图像无法区分的图像。
用Keras编写一个简单的生成式对抗网络
现在,你已经了解什么是GAN,以及它们的主要组成部分,那么现在我们可以开始试着编写一个非常简单的代码。你可以使用Keras,如果你不熟悉这个Python库的话,则应在继续进行操作之前阅读本教程。本教程基于易于理解的GAN进行开发的。
首先,你需要做的第一件事是通过pip安装以下软件包:
- keras
- matplotlib
- tensorflow
- tqdm
你将使用matplotlib绘图,tensorflow作为Keras后端库和tqdm,以显示每个轮数(迭代)的花式进度条。
下一步是创建一个Python脚本,在这个脚本中,你首先需要导入你将要使用的所有模块和函数。在使用它们时将给出每个解释。
import
os
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
from keras.layers import Input
from keras.models import Model, Sequential
from keras.layers.core import Dense, Dropout
from keras.layers.advanced_activations import LeakyReLU
from keras.datasets import mnist
from keras.optimizers import Adam
from keras import initializers
你现在需要设置一些变量:
# Let Keras know that we are using tensorflow as our backend engine
os.environ["KERAS_BACKEND"] = "tensorflow"
# To make sure that we can reproduce the experiment and get the same results
np.random.seed(10)
# The dimension of our random noise vector.
random_dim = 100
在开始构建鉴别器和生成器之前,你首先应该收集数据,并对其进行预处理。你将会使用到常见的MNIST数据集,该数据集具有一组从0到9的单个数字图像。
MINST数字样本
def load_minst_data():
# load the data
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# normalize our inputs to be in the range[-1, 1]
x_train = (x_train.astype(np.float32) - 127.5)/127.5
# convert x_train with a shape of (60000, 28, 28) to (60000, 784) so we have
# 784 columns per row
x_train = x_train.reshape(60000, 784)
return (x_train, y_train, x_test, y_test)
需要注意的是,mnist.load_data()是Keras的一部分,这使得你可以轻松地将MNIST数据集导入至工作区域中。
现在,你可以开始创建你的生成器和鉴别器网络了。在这一过程中,你会使用到Adam优化器(
https://machinelearningmastery.com/adam-optimization-algorithm-for-deep-learning/)。此外,你还需要创建一个带有三个隐藏层的神经网络,其激活函数为Leaky Relu(
https://www.quora.com/What-are-the-advantages-of-using-Leaky-Rectified-Linear-Units-Leaky-ReLU-over-normal-ReLU-in-deep-learning)。对于鉴别器而言,你需要为其添加dropout层(dropout layers)(https://medium.com/@
amarbudhiraja/https-medium-com-amarbudhiraja-learning-less-to-learn-better-dropout-in-deep-machine-learning-74334da4bfc5),以提高对未知图像的鲁棒性。
def get_optimizer():
return Adam(lr=0.0002, beta_1=0.5)
def get_generator(optimizer):
generator = Sequential()
generator.add(Dense(256, input_dim=random_dim, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
generator.add(LeakyReLU(0.2))
generator.add(Dense(512))
generator.add(LeakyReLU(0.2))
generator.add(Dense(1024))
generator.add(LeakyReLU(0.2))
generator.add(Dense(784, activation='tanh'))
generator.compile(loss='binary_crossentropy', optimizer=optimizer)
return generator
def get_discriminator(optimizer):
discriminator = Sequential()
discriminator.add(Dense(1024, input_dim=784, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
discriminator.add(LeakyReLU(0.2))
discriminator.add(Dropout(0.3))
discriminator.add(Dense(512))
discriminator.add(LeakyReLU(0.2))
discriminator.add(Dropout(0.3))
discriminator.add(Dense(256))
discriminator.add(LeakyReLU(0.2))
discriminator.add(Dropout(0.3))
discriminator.add(Dense(1, activation='sigmoid'))
discriminator.compile(loss='binary_crossentropy', optimizer=optimizer)
return discriminator
接下来,则需要将发生器和鉴别器组合在一起!
def get_gan_network(discriminator, random_dim, generator, optimizer):
# We initially set trainable to False since we only want to train either the
# generator or discriminator at a time
discriminator.trainable = False
# gan input (noise) will be 100-dimensional vectors
gan_input = Input(shape=(random_dim,))
# the output of the generator (an image)
x = generator(gan_input)
# get the output of the discriminator (probability if the image is real or not)
gan_output = discriminator(x)
gan = Model(inputs=gan_input, outputs=gan_output)
gan.compile(loss='binary_crossentropy', optimizer=optimizer)
return gan
为了完整起见,你还可以创建一个函数,使其每训练20个轮数就对生成的图像进行1次保存。由于这不是本次课程的核心内容,因此你不必完全理解该函数。
def plot_generated_images(epoch, generator, examples=100, dim=(10, 10), figsize=(10, 10)):
noise = np.random.normal(0, 1, size=[examples, random_dim])
generated_images = generator.predict(noise)
generated_images = generated_images.reshape(examples, 28, 28)
plt.figure(figsize=figsize)
for i in range(generated_images.shape[0]):
plt.subplot(dim[0], dim[1], i+1)
plt.imshow(generated_images[i], interpolation='nearest', cmap='gray_r')
plt.axis('off')
plt.tight_layout()
plt.savefig('gan_generated_image_epoch_%d.png' % epoch)
你现在已经编码了大部分网络,剩下的就是训练这个网络,并查看你创建的图像。
def train(epochs=1, batch_size=128):
# Get the training and testing data
x_train, y_train, x_test, y_test = load_minst_data()
# Split the training data into batches of size 128
batch_count = x_train.shape[0] / batch_size
# Build our GAN netowrk
adam = get_optimizer()
generator = get_generator(adam)
discriminator = get_discriminator(adam)
gan = get_gan_network(discriminator, random_dim, generator, adam)
for e in xrange(1, epochs+1):
print '-'*15, 'Epoch %d' % e, '-'*15
for _ in tqdm(xrange(batch_count)):
# Get a random set of input noise and images
noise = np.random.normal(0, 1, size=[batch_size, random_dim])
image_batch = x_train[np.random.randint(0, x_train.shape[0], size=batch_size)]
# Generate fake MNIST images
generated_images = generator.predict(noise)
X = np.concatenate([image_batch, generated_images])
# Labels for generated and real data
y_dis = np.zeros(2*batch_size)
# One-sided label smoothing
y_dis[:batch_size] = 0.9
# Train discriminator
discriminator.trainable = True
discriminator.train_on_batch(X, y_dis)
# Train generator
noise = np.random.normal(0, 1, size=[batch_size, random_dim])
y_gen = np.ones(batch_size)
discriminator.trainable = False
gan.train_on_batch(noise, y_gen)
if e == 1 or e % 20 == 0:
plot_generated_images(e, generator)
if __name__ == '__main__':
train(400, 128)
在训练400个轮数后,你可以查看生成的图像。在查看经过1个轮数训练后而生成的图像时,你会发现它没有任何真实结构,在查看经过40个轮数训练后而生成的图像时,你会发现数字开始成形,最后,在查看经过400个轮数训练后而生成的图像时,你会发现,除了一组数字难以辨识外,其余大多数数字都清晰可见。
训练1个轮数后的结果(上)| 训练40个轮数后的结果(中) | 训练400个轮数后的结果(下)
此代码在CPU上运行一次大约需要2分钟,这也是我们选择该代码的主要原因。你可以尝试进行更多轮数的训练,并向生成器和鉴别器中添加更多数量(种类)的层。当然,在仅使用CPU的前提下,采用更复杂和更深层的体系结构时,相应的代码运行时间也会有所延长。但也不要因此放弃尝试。
至此,你已经完成了全部的学习任务,你以一种直观的方式学习了生成式对抗网络(GAN)的基础知识!并且,你还在Keras库的协助下实现了你的第一个模型。
原文链接:
https://towardsdatascience.com/demystifying-generative-adversarial-networks-c076d8db8f44
相关推荐
- Python Qt GUI设计:将UI文件转换Python文件三种妙招(基础篇—2)
-
在开始本文之前提醒各位朋友,Python记得安装PyQt5库文件,Python语言功能很强,但是Python自带的GUI开发库Tkinter功能很弱,难以开发出专业的GUI。好在Python语言的开放...
- Connect 2.0来了,还有Nuke和Maya新集成
-
ftrackConnect2.0现在可以下载了--重新设计的桌面应用程序,使用户能够将ftrackStudio与创意应用程序集成,发布资产等。这个新版本的发布中还有两个Nuke和Maya新集成,...
- Magicgui:不会GUI编程也能轻松构建Python GUI应用
-
什么是MagicguiMagicgui是一个Python库,它允许开发者仅凭简单的类型注解就能快速构建图形用户界面(GUI)应用程序。这个库基于Napari项目,利用了Python的强大类型系统,使得...
- Python入坑系列:桌面GUI开发之Pyside6
-
阅读本章之后,你可以掌握这些内容:Pyside6的SignalsandSlots、Envents的作用,如何使用?PySide6的Window、DialogsandAlerts、Widgets...
- Python入坑系列-一起认识Pyside6 designer可拖拽桌面GUI
-
通过本文章,你可以了解一下内容:如何安装和使用Pyside6designerdesigner有哪些的特性通过designer如何转成python代码以前以为Pyside6designer需要在下载...
- pyside2的基础界面(pyside2显示图片)
-
今天我们来学习pyside2的基础界面没有安装过pyside2的小伙伴可以看主页代码效果...
- Python GUI开发:打包PySide2应用(python 打包pyc)
-
之前的文章我们介绍了怎么使用PySide2来开发一个简单PythonGUI应用。这次我们来将上次完成的代码打包。我们使用pyinstaller。注意,pyinstaller默认会将所有安装的pack...
- 使用PySide2做窗体,到底是怎么个事?看这个能不能搞懂
-
PySide2是Qt框架的Python绑定,允许你使用Python创建功能强大的跨平台GUI应用程序。PySide2的基本使用方法:安装PySide2pipinstallPy...
- pycharm中conda解释器无法配置(pycharm安装的解释器不能用)
-
之前用的好好的pycharm正常配置解释器突然不能用了?可以显示有这个环境然后确认后可以conda正在配置解释器,但是进度条结束后还是不成功!!试过了pycharm重启,pycharm重装,anaco...
- Conda使用指南:从基础操作到Llama-Factory大模型微调环境搭建
-
Conda虚拟环境在Linux下的全面使用指南:从基础操作到Llama-Factory大模型微调环境搭建在当今的AI开发与数据分析领域,conda虚拟环境已成为Linux系统下管理项目依赖的标配工具。...
- Python操作系统资源管理与监控(python调用资源管理器)
-
在现代计算环境中,对操作系统资源的有效管理和监控是确保应用程序性能和系统稳定性的关键。Python凭借其丰富的标准库和第三方扩展,提供了强大的工具来实现这一目标。本文将探讨Python在操作系统资源管...
- 本地部署开源版Manus+DeepSeek创建自己的AI智能体
-
1、下载安装Anaconda,设置conda环境变量,并使用conda创建python3.12虚拟环境。2、从OpenManus仓库下载代码,并安装需要的依赖。3、使用Ollama加载本地DeepSe...
- 一文教会你,搭建AI模型训练与微调环境,包学会的!
-
一、硬件要求显卡配置:需要Nvidia显卡,至少配备8G显存,且专用显存与共享显存之和需大于20G。二、环境搭建步骤1.设置文件存储路径非系统盘存储:建议将非安装版的环境文件均存放在非系统盘(如E盘...
- 使用scikit-learn为PyTorch 模型进行超参数网格搜索
-
scikit-learn是Python中最好的机器学习库,而PyTorch又为我们构建模型提供了方便的操作,能否将它们的优点整合起来呢?在本文中,我们将介绍如何使用scikit-learn中的网格搜...
- 如何Keras自动编码器给极端罕见事件分类
-
全文共7940字,预计学习时长30分钟或更长本文将以一家造纸厂的生产为例,介绍如何使用自动编码器构建罕见事件分类器。现实生活中罕见事件的数据集:背景1.什么是极端罕见事件?在罕见事件问题中,数据集是...
- 一周热门
- 最近发表
-
- Python Qt GUI设计:将UI文件转换Python文件三种妙招(基础篇—2)
- Connect 2.0来了,还有Nuke和Maya新集成
- Magicgui:不会GUI编程也能轻松构建Python GUI应用
- Python入坑系列:桌面GUI开发之Pyside6
- Python入坑系列-一起认识Pyside6 designer可拖拽桌面GUI
- pyside2的基础界面(pyside2显示图片)
- Python GUI开发:打包PySide2应用(python 打包pyc)
- 使用PySide2做窗体,到底是怎么个事?看这个能不能搞懂
- pycharm中conda解释器无法配置(pycharm安装的解释器不能用)
- Conda使用指南:从基础操作到Llama-Factory大模型微调环境搭建
- 标签列表
-
- ps图案在哪里 (33)
- super().__init__ (33)
- python 获取日期 (34)
- 0xa (36)
- super().__init__()详解 (33)
- python安装包在哪里找 (33)
- linux查看python版本信息 (35)
- python怎么改成中文 (35)
- php文件怎么在浏览器运行 (33)
- eval在python中的意思 (33)
- python安装opencv库 (35)
- python div (34)
- sticky css (33)
- python中random.randint()函数 (34)
- python去掉字符串中的指定字符 (33)
- python入门经典100题 (34)
- anaconda安装路径 (34)
- yield和return的区别 (33)
- 1到10的阶乘之和是多少 (35)
- python安装sklearn库 (33)
- dom和bom区别 (33)
- js 替换指定位置的字符 (33)
- python判断元素是否存在 (33)
- sorted key (33)
- shutil.copy() (33)