GAN;DCGAN

目录
GAN
GAN
对于生成式网络来说,给定一个dataset,我们希望生成式网络可以在这个dataset基础上生成一些新的但是又不属于原始dataset的数据。
对于分类器网络来说,给定一个分类器,我们希望分类器可以成功将生成的数据与原始的dataset数据进行区分。
由此我们构成一个GAN(Generative Adversarial Networks)生成对抗网络。

对于分类器而言,我们希望它对于两种数据能够有很好的区分,记一个生成的数据(实际为假0)被判断为dataset中数据为1,被判断不是dataset中数据为0,判断成功即输入为假(0)输出为假(0),那么我们需要最小化分类器的loss函数。
对于生成器而言,我们希望它生成的数据能够最大程度地接近于dataset中的数据,记一个生成的数据(实际为假0)被判断为dataset中数据为1,被判断不是dataset中数据为0,生成成功即输入为假(0)输出为真(1),那么我们需要最大化生成器的loss函数。
所以整个生成对抗网络像是一个分类器与生成器之间的极小极大对抗。
GAN模型最好的应用是在image上。
————————————————
GAN:
1、传统NN:给定 x→y x \rightarrow yx→y,模型建立为P(y∣x) P(y|x)P(y∣x)
2、GAN:只有x xx,没有y yy,建模P(x) P(x)P(x),利用判别模型来得到更好的生成模型。
3、生成器Generator:产生和数据集真实图片越接近越好的图片,让分类器DIscriminator无法判别。

4、分类器Discriminator:用来区分真实图片与生成图片。利用最小化交叉熵损失:
minD{−ylogD(x)−(1−y)log(1−D(x))}, \min_D { - y \log D(\mathbf x) - (1-y)\log(1-D(\mathbf x)) },
D
min

{−ylogD(x)−(1−y)log(1−D(x))},

5、生成器的优化函数:

DCGAN
1、DCGAN结构有四层卷积的分类器和有四层“fractionally strided”卷积层的生成器
2、分类器有4层带批归一化的(除了输入层)的卷积以及采用Leaky-ReLU的激活函数。
3、转置卷积层使用 kh=kw=4 k_h = k_w = 4k


=4卷积核,sh=sw=2 s_h = s_w = 2s

=1作为padding。如果输入为 nh=nw=16 n_h = n_w = 16n
=16,生成器的尺寸计算如下:
n′h×n′w=[(nhkh−(nh−1)(kh−sh)−2ph]×[(nwkw−(nw−1)(kw−sw)−2pw]=[(kh+sh(nh−1)−2ph]×[(kw+sw(nw−1)−2pw]=[(4+2×(16−1)−2×1]×[(4+2×(16−1)−2×1]=32×32. \begin{aligned}n_h^{’} \times n_w^{’} &= [(n_h k_h - (n_h-1)(k_h-s_h)- 2p_h] \times [(n_w k_w - (n_w-1)(k_w-s_w)- 2p_w]\&= [(k_h + s_h (n_h-1)- 2p_h] \times [(k_w + s_w (n_w-1)- 2p_w]\&= [(4 + 2 \times (16-1)- 2 \times 1] \times [(4 + 2 \times (16-1)- 2 \times 1]\&= 32 \times 32 .\\end{aligned}
4、假设原有的参数范围是[0,1],执行transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))可以将参数范围调整为[-1,1],i,e: 0−0.50.5=−1 \frac {0-0.5}{0.5}=-1

5、除去使用leaky-ReLU作为激活函数以外,分类器和传统卷积网络没有区别。如果给定α∈[0,1] \alpha \in[0, 1]α∈[0,1],leaky-ReLU的定义如下:
leaky ReLU(x)={xαxif x>0otherwise. \textrm{leaky ReLU}(x) = \begin{cases}x & \text{if}\ x > 0\ \alpha x &\text{otherwise}\end{cases}.
leaky ReLU(x)={

常规的ReLU函数的α=0 \alpha=0α=0。对于α∈(0,1) \alpha \in (0, 1)α∈(0,1),leaky ReLU 对于负的输入有非零的输出。其目标是解决当神经元输出为负值的时候,常规ReLU的梯度为0所导致的“dying ReLU”问题。

import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
from torch import nn
import numpy as np
from torch.autograd import Variable
import torch
from torchvision.datasets import ImageFolder
from torchvision.transforms import transforms
import zipfile
cuda = True if torch.cuda.is_available() else False
print(cuda)
数据集下载地址:https://pokemondb.net/sprites

data_dir=’/home/kesci/input/pokemon8600/’
batch_size=256
transform=transforms.Compose([
transforms.Resize((64,64)),
transforms.ToTensor(),
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))
])
pokemon=ImageFolder(data_dir+‘pokemon’,transform)
data_iter=DataLoader(pokemon,batch_size=batch_size,shuffle=True)
#可视化前二十张照片
fig=plt.figure(figsize=(4,4))
imgs=data_iter.dataset.imgs
for i in range(20):
img = plt.imread(imgs[i*150][0])
plt.subplot(4,5,i+1)
plt.imshow(img)
plt.axis(‘off’)
plt.show()
成器模块设计

class G_block(nn.Module):
def init(self, in_channels, out_channels, kernel_size=4,strides=2, padding=1):
super(G_block,self).init()
self.conv2d_trans=nn.ConvTranspose2d(in_channels, out_channels, kernel_size=kernel_size,
stride=strides, padding=padding, bias=False)
self.batch_norm=nn.BatchNorm2d(out_channels,0.8)
self.activation=nn.ReLU()
def forward(self,x):
return self.activation(self.batch_norm(self.conv2d_trans(x)))

调用

Tensor=torch.cuda.FloatTensor
x=Variable(Tensor(np.zeros((2,3,16,16))))
g_blk=G_block(3,20)
g_blk.cuda()
print(g_blk(x).shape)

生成器设计

class net_G(nn.Module):
def init(self,in_channels):
super(net_G,self).init()

    n_G=64
    self.model=nn.Sequential(
        G_block(in_channels,n_G*8,strides=1,padding=0),
        G_block(n_G*8,n_G*4),
        G_block(n_G*4,n_G*2),
        G_block(n_G*2,n_G),
        nn.ConvTranspose2d(
            n_G,3,kernel_size=4,stride=2,padding=1,bias=False
        ),
        nn.Tanh()
    )
def forward(self,x):
    x=self.model(x)
    return x

def weights_init_normal(m):
classname = m.class.name
if classname.find(“Conv”) != -1:
torch.nn.init.normal_(m.weight.data, mean=0, std=0.02)
elif classname.find(“BatchNorm2d”) != -1:
torch.nn.init.normal_(m.weight.data, mean=1.0, std=0.02)
torch.nn.init.constant_(m.bias.data, 0.0)

调用

x=Variable(Tensor(np.zeros((1,100,1,1))))
generator=net_G(100)
generator.cuda()
generator.apply(weights_init_normal)
print(generator(x).shape)

LeakyReLU

alphas = [0, 0.2, 0.4, .6]
x = np.arange(-2, 1, 0.1)
Y = [nn.LeakyReLU(alpha)(Tensor(x)).cpu().numpy()for alpha in alphas]
plt.figure(figsize=(4,4))
for y in Y:
plt.plot(x,y)
plt.show()

分类器模块设计

class D_block(nn.Module):
def init(self,in_channels,out_channels,kernel_size=4,strides=2,
padding=1,alpha=0.2):
super(D_block,self).init()
self.conv2d=nn.Conv2d(in_channels,out_channels,kernel_size,strides,padding,bias=False)
self.batch_norm=nn.BatchNorm2d(out_channels,0.8)
self.activation=nn.LeakyReLU(alpha)
def forward(self,X):
return self.activation(self.batch_norm(self.conv2d(X)))

调用

x = Variable(Tensor(np.zeros((2, 3, 16, 16))))
d_blk = D_block(3,20)
d_blk.cuda()
print(d_blk(x).shape)

分类器设计

class net_D(nn.Module):
def init(self,in_channels):
super(net_D,self).init()
n_D=64
self.model=nn.Sequential(
D_block(in_channels,n_D),
D_block(n_D,n_D2),
D_block(n_D
2,n_D4),
D_block(n_D
4,n_D8)
)
self.conv=nn.Conv2d(n_D
8,1,kernel_size=4,bias=False)
self.activation=nn.Sigmoid()
# self._initialize_weights()
def forward(self,x):
x=self.model(x)
x=self.conv(x)
x=self.activation(x)
return x

x = Variable(Tensor(np.zeros((1, 3, 64, 64))))
discriminator=net_D(3)
discriminator.cuda()
discriminator.apply(weights_init_normal)
print(discriminator(x).shape)

模型的训练

def update_D(X,Z,net_D,net_G,loss,trainer_D):
batch_size=X.shape[0]
Tensor=torch.cuda.FloatTensor
ones=Variable(Tensor(np.ones(batch_size,)),requires_grad=False).view(batch_size,1)
zeros = Variable(Tensor(np.zeros(batch_size,)),requires_grad=False).view(batch_size,1)
real_Y=net_D(X).view(batch_size,-1)
fake_X=net_G(Z)
fake_Y=net_D(fake_X).view(batch_size,-1)
loss_D=(loss(real_Y,ones)+loss(fake_Y,zeros))/2
loss_D.backward()
trainer_D.step()
return float(loss_D.sum())

def update_G(Z,net_D,net_G,loss,trainer_G):
batch_size=Z.shape[0]
Tensor=torch.cuda.FloatTensor
ones=Variable(Tensor(np.ones((batch_size,))),requires_grad=False).view(batch_size,1)
fake_X=net_G(Z)
fake_Y=net_D(fake_X).view(batch_size,-1)
loss_G=loss(fake_Y,ones)
loss_G.backward()
trainer_G.step()
return float(loss_G.sum())

def train(net_D,net_G,data_iter,num_epochs,lr,latent_dim):
loss=nn.BCELoss()
Tensor=torch.cuda.FloatTensor
trainer_D=torch.optim.Adam(net_D.parameters(),lr=lr,betas=(0.5,0.999))
trainer_G=torch.optim.Adam(net_G.parameters(),lr=lr,betas=(0.5,0.999))
plt.figure(figsize=(7,4))
d_loss_point=[]
g_loss_point=[]
d_loss=0
g_loss=0
for epoch in range(1,num_epochs+1):
d_loss_sum=0
g_loss_sum=0
batch=0
for X in data_iter:
X=X[:][0]
batch+=1
X=Variable(X.type(Tensor))
batch_size=X.shape[0]
Z=Variable(Tensor(np.random.normal(0,1,(batch_size,latent_dim,1,1))))

        trainer_D.zero_grad()
        d_loss = update_D(X, Z, net_D, net_G, loss, trainer_D)
        d_loss_sum+=d_loss
        trainer_G.zero_grad()
        g_loss = update_G(Z, net_D, net_G, loss, trainer_G)
        g_loss_sum+=g_loss

    d_loss_point.append(d_loss_sum/batch)
    g_loss_point.append(g_loss_sum/batch)
    print(
        "[Epoch %d/%d]  [D loss: %f] [G loss: %f]"
        % (epoch, num_epochs,  d_loss_sum/batch_size,  g_loss_sum/batch_size)
    )


plt.ylabel('Loss', fontdict={ 'size': 14})
plt.xlabel('epoch', fontdict={ 'size': 14})
plt.xticks(range(0,num_epochs+1,3))
plt.plot(range(1,num_epochs+1),d_loss_point,color='orange',label='discriminator')
plt.plot(range(1,num_epochs+1),g_loss_point,color='blue',label='generator')
plt.legend()
plt.show()
print(d_loss,g_loss)

Z = Variable(Tensor(np.random.normal(0, 1, size=(21, latent_dim, 1, 1))),requires_grad=False)
fake_x = generator(Z)
fake_x=fake_x.cpu().detach().numpy()
plt.figure(figsize=(14,6))
for i in range(21):
    im=np.transpose(fake_x[i])
    plt.subplot(3,7,i+1)
    plt.imshow(im)
plt.show()

if name == ‘main’:
lr,latent_dim,num_epochs=0.005,100,50
train(discriminator,generator,data_iter,num_epochs,lr,latent_dim)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值