<> What is? GAN

GAN(Generative Adversarial
Network), The Internet is just like his name , Generated , There is confrontation , Two networks play games with each other . Let's name the two networks , The first network used to generate data is named generator (generator)
, Another network is used to identify the data generated by the generator, which we call discriminator (discriminator).

<>GAN Training of

standard GAN There are three steps in training :

* Training discriminator with real training data
* Train the discriminator with the generated data
* Training generator generates data , And make the discriminator think it is real data
<> data set

classic mnist data set , Classic in classic , No , Many online .

<> code

Code from 《Pytorch Generation countermeasure network programming 》 People's Posts and Telecommunications Publishing House
It's not very good , It makes the training very slow , The refactored code follows , It's much faster
I'm not used to the methods in some books , Also refactored a lot , The final effect is almost the same .
Fixed issues such as mode corruption
import torch import torch.nn as nn from torch.utils.data import Dataset import
torch.utils.data as Data from sklearn.preprocessing import OneHotEncoder import
scipy.io as scio import numpy as np import pandas as pd import random import
matplotlib.pyplot as plt mnist_dataset = pd.read_csv('mnist_train.csv', header=
None).values label = mnist_dataset[:, 0] image_values = mnist_dataset[:, 1:] /
255.0 encoder = OneHotEncoder(sparse=False) # sparse Default to True, Return sparse matrix label =
encoder.fit_transform(label.reshape(-1, 1)) train_t = torch.from_numpy(
image_values.astype(np.float32)) label = torch.from_numpy(label.astype(np.
float32)) train_data = Data.TensorDataset(train_t, label) train_loader = Data.
DataLoader(dataset=train_data, batch_size=1, shuffle=True) def plot_num_image(
index): plt.imshow(image_values[index].reshape(28, 28), cmap='gray') plt.title(
'label=' + str(label[index])) plt.show() def generate_random(size): random_data
= torch.rand(size) return random_data def generate_random_seed(size):
random_data= torch.randn(size) return random_data # Build classifier class Discriminator(nn
.Module): def __init__(self): # Initialize parent class super(Discriminator, self).__init__() self
.model = nn.Sequential( nn.Linear(784, 300), nn.LeakyReLU(0.02), nn.LayerNorm(
300), nn.Linear(300, 30), nn.LeakyReLU(0.02), nn.LayerNorm(30), nn.Linear(30, 1)
, nn.Sigmoid(), ) self.loss_function = nn.BCELoss() # Create optimizer self.optimiser =
torch.optim.Adam(self.parameters(), lr=0.01) self.counter = 0 self.progress = []
def forward(self, inputs): return self.model(inputs) def train(self, inputs,
targets): outputs = self.forward(inputs) loss = self.loss_function(outputs,
targets) # Every training 10 This increment counter self.counter += 1 if self.counter % 10 == 0: self.
progress.append(loss.item()) if self.counter % 10000 == 0: print("counter = ",
self.counter) # Clear gradient , Back propagation , Update weight self.optimiser.zero_grad() loss.backward() self.
optimiser.step() # Build generator class Generator(nn.Module): def __init__(self): super(
Generator, self).__init__() self.model = nn.Sequential( nn.Linear(100, 300), nn.
LeakyReLU(0.02), nn.LayerNorm(300), nn.Linear(300, 784), nn.Sigmoid(), ) # Create optimizer
self.optimiser = torch.optim.Adam(self.parameters(), lr=0.01) self.counter = 0
self.progress = [] def forward(self, inputs): return self.model(inputs) def
train(self, D, inputs, targets): # The loss of classifier is used to train generation g_output = self.forward(inputs)
# generator generator Output of d_output = D.forward(g_output) # classifier discriminator Output of loss = D.
loss_function(d_output, targets) self.counter += 1 if self.counter % 10 == 0:
self.progress.append(loss.item()) self.optimiser.zero_grad() loss.backward()
self.optimiser.step() D = Discriminator() G = Generator() ''' for step, (b_x,
b_y) in enumerate(train_loader): # Real data D.train(b_x[0],
torch.FloatTensor([1.0])) # Generate data D.train(generate_random(784),
torch.FloatTensor([0.0])) plt.plot(D.progress) # loss I'll be back soon 0 Yes plt.show() #
Output a real data and generate data print('real_num:', D.forward(b_x[0]).item())
print('generate-num:', D.forward(generate_random(784)).item()) #
So far, our discriminator has learned to classify real data and randomly generated data # Let the generator randomly generate an image. Let's see output =
G.forward(generate_random(1)) img = output.detach().numpy().reshape(28, 28)
plt.imshow(img, interpolation='none', cmap='gray') # interpolation Difference method
plt.show() ''' for epoch in range(10): for step, (b_x, b_y) in enumerate(
train_loader): # Real data D.train(b_x[0], torch.FloatTensor([1.0])) D.train(G.
forward(generate_random_seed(100)).detach(), torch.FloatTensor([0.0])) G.train(D
, generate_random_seed(100), torch.FloatTensor([1.0])) print(' complete ',epoch+1,
'epoch','*************'*3) # Let's take a look at the of the generator and discriminator loss plt.plot(D.progress, c='b', label
='D-loss') plt.plot(G.progress, c='r', label='G-loss') plt.legend() plt.savefig(
'loss.jpg') plt.show() # The generator has been trained at this time , Let's generate a few more to see for i in range(6): output = G.
forward(generate_random_seed(100)) img = output.detach().numpy().reshape(28, 28)
plt.subplot(2, 3, i+1) plt.imshow(img,cmap='gray') plt.show()
Let's generate some images to see :
for i in range(6): output = G.forward(generate_random_seed(100)) img = output.
detach().numpy().reshape(28, 28) plt.subplot(2, 3, i+1) plt.imshow(img, cmap=
'gray') plt.show()

Looks like 000038, Very good , The generator has never seen what numbers look like , But he learned how to write ( generate ) Similar images .
Just started learning GAN Soon , So far, our generator can only generate images randomly , Unable to generate a specific number . I haven't figured out how to solve it yet .( Use conditions GAN)

After reconstruction :
import torch import torch.nn as nn import torch.nn.functional as F import torch
.optim as optim import numpy as np import matplotlib.pyplot as plt import
torchvisionfrom torchvision import transforms # data normalization (-1,1) transform =
transforms.Compose([ transforms.ToTensor(), # 0-1 transforms.Normalize(0.5, 0.5)
# mean value 0.5 variance 0.5 ]) # Load built-in dataset train_ds = torchvision.datasets.MNIST('data', train=
True, transform=transform, download=True) dataloader = torch.utils.data.
DataLoader(train_ds, batch_size=64, shuffle=True) # Returns the data of a batch imgs, _ = next(
iter(dataloader)) # generator , input 100 Noise output (1,28,28) class Generator(nn.Module): def
__init__(self): super(Generator, self).__init__() self.linear = nn.Sequential(
nn.Linear(100, 256), nn.Tanh(), nn.Linear(256, 512), nn.Tanh(), nn.Linear(512,
28*28), nn.Tanh() ) def forward(self, x): x = self.linear(x) x = x.view(-1, 28,
28) return x # Discriminator , input (1,28,28), Output true and false , Recommended use LeakRelu class Discriminator(nn.Module):
def __init__(self): super(Discriminator, self).__init__() self.linear = nn.
Sequential( nn.Linear(28*28, 512), nn.LeakyReLU(), nn.Linear(512, 256), nn.
LeakyReLU(), nn.Linear(256, 1), nn.Sigmoid() ) def forward(self, x): x = x.view(
-1, 28*28) x = self.linear(x) return x device = 'cuda' if torch.cuda.
is_available() else 'cpu' if device == 'cuda': print('using cuda:', torch.cuda.
get_device_name(0)) Gen = Generator().to(device) Dis = Discriminator().to(device
) d_optim = torch.optim.Adam(Dis.parameters(), lr=0.001) g_optim = torch.optim.
Adam(Gen.parameters(), lr=0.001) # BCEWithLogisticLoss Inactive output loss_function =
torch.nn.BCELoss() def gen_img_plot(model, test_input): # squeeze Delete single dimension
prediction= np.squeeze(model(test_input).detach().cpu().numpy()) fig = plt.
figure(figsize=(4, 4)) for i in range(prediction.shape[0]): plt.subplot(4, 4, i+
1) plt.imshow((prediction[i]+1) / 2) # generate -1,1, Restore to 0,1 plt.axis('off') plt.show()
test_input= torch.randn(16, 100, device=device) D_loss = [] G_loss = [] for
epochin range(20): d_epoch_loss = 0 g_epoch_loss = 0 count = len(dataloader) for
step, (img, _) in enumerate(dataloader): img = img.to(device) size = img.size(0
) random_noise = torch.randn(size, 100, device=device) d_optim.zero_grad()
real_output= Dis(img) # Discriminator input real picture # Loss of discriminator on real image d_real_loss = loss_function(
real_output, torch.ones_like(real_output) ) d_real_loss.backward() gen_img = Gen
(random_noise) fake_output = Dis(gen_img.detach()) #
Discriminator input generates picture ,fake_output Prediction of generated pictures # gen_img It's from the generator , But now we only update the discriminator , So cut off the pair Gen Update of #
detach() We get a solution without gradient tensor, The derivation stops here ,backward You won't find the derivative when Gen Yes d_fake_loss =
loss_function(fake_output, torch.zeros_like(fake_output) ) d_fake_loss.backward(
) d_loss = d_real_loss + d_fake_loss d_optim.step() # Update generator g_optim.zero_grad()
fake_output= Dis(gen_img) g_loss = loss_function(fake_output, torch.ones_like(
fake_output)) g_loss.backward() g_optim.step() with torch.no_grad():
d_epoch_loss+= d_loss g_epoch_loss += g_loss with torch.no_grad(): #
The gradient is not calculated for the following contents ( Construction of graph ) d_epoch_loss /= count g_epoch_loss /= count D_loss.append(
d_epoch_loss) G_loss.append(g_epoch_loss) print('Epoch:', epoch+1) gen_img_plot(
Gen, test_input)
train 20 After wheel :

Of course, we can also use the network structure DCGAN:
import torch import torch.nn as nn import torch.nn.functional as F import torch
.optim as optim import numpy as np import matplotlib.pyplot as plt import
torchvisionfrom torchvision import transforms # data normalization (-1,1) transform =
transforms.Compose([ transforms.ToTensor(), # 0-1 transforms.Normalize(0.5, 0.5)
# mean value 0.5 variance 0.5 ]) # Load built-in dataset train_ds = torchvision.datasets.MNIST('data', train=
True, transform=transform, download=True) dataloader = torch.utils.data.
DataLoader(train_ds, batch_size=64, shuffle=True) # Definition generator , Still enter the length 100 Noise class
Generator(nn.Module): def __init__(self): super(Generator, self).__init__() self
.linear1 = nn.Linear(100, 256*7*7) self.bn1 = nn.BatchNorm1d(256*7*7) self.
deconv1= nn.ConvTranspose2d(256, 128, kernel_size=(3, 3), stride=1, padding=1 )
self.bn2 = nn.BatchNorm2d(128) self.deconv2 = nn.ConvTranspose2d(128, 64,
kernel_size=(4, 4), stride=2, padding=1 ) self.bn3 = nn.BatchNorm2d(64) self.
deconv3= nn.ConvTranspose2d(64, 1, kernel_size=(4, 4), stride=2, padding=1 ) def
forward(self, x): x = F.relu(self.linear1(x)) x = self.bn1(x) x = x.view(-1, 256
, 7, 7) x = F.relu(self.deconv1(x)) x = self.bn2(x) x = F.relu(self.deconv2(x))
x= self.bn3(x) x = torch.tanh(self.deconv3(x)) return x # Discriminator , input (28,28) picture class
Discriminator(nn.Module): def __init__(self): super(Discriminator, self).
__init__() self.conv1 = nn.Conv2d(1, 64, kernel_size=3, stride=2) self.conv2 =
nn.Conv2d(64, 128, 3, 2) self.bn = nn.BatchNorm2d(128) self.fc = nn.Linear(128*6
*6, 1) def forward(self, x): x = F.dropout2d(F.leaky_relu(self.conv1(x)), p=0.3)
x= F.dropout2d(F.leaky_relu(self.conv2(x)), p=0.3) x = self.bn(x) x = x.view(-1
, 128*6*6) x = torch.sigmoid(self.fc(x)) return x device = 'cuda' if torch.cuda.
is_available() else 'cpu' if device == 'cuda': print('using cuda:', torch.cuda.
get_device_name(0)) Gen = Generator().to(device) Dis = Discriminator().to(device
) loss_fun = nn.BCELoss() d_optimizer = torch.optim.Adam(Dis.parameters(), lr=
1e-5) # antic g_optimizer = torch.optim.Adam(Gen.parameters(), lr=1e-4) def
generate_and_save_image(model, test_input): predictions = np.squeeze(model(
test_input).cpu().numpy()) fig = plt.figure(figsize=(4, 4)) for i in range(
predictions.shape[0]): plt.subplot(4, 4, i+1) plt.imshow((predictions[i]+1) / 2,
cmap='gray') plt.axis('off') plt.show() test_input = torch.randn(16, 100,
device=device) D_loss = [] G_loss = [] for epoch in range(30): d_epoch_loss = 0
g_epoch_loss= 0 count = len(dataloader.dataset) for step, (img, _) in enumerate(
dataloader): img = img.to(device) size = img.size(0) random_noise = torch.randn(
size, 100, device=device) d_optimizer.zero_grad() real_output = Dis(img) #
Discriminator input real picture # Loss of discriminator on real image d_real_loss = loss_fun(real_output, torch.ones_like(
real_output) ) d_real_loss.backward() gen_img = Gen(random_noise) fake_output =
Dis(gen_img.detach()) # Discriminator input generates picture ,fake_output Prediction of generated pictures #
gen_img It's from the generator , But now we only update the discriminator , So cut off the pair Gen Update of #
detach() We get a solution without gradient tensor, The derivation stops here ,backward You won't find the derivative when Gen Yes d_fake_loss = loss_fun(
fake_output, torch.zeros_like(fake_output) ) d_fake_loss.backward() d_loss =
d_real_loss+ d_fake_loss d_optimizer.step() # Update generator g_optimizer.zero_grad()
fake_output= Dis(gen_img) g_loss = loss_fun(fake_output, torch.ones_like(
fake_output)) g_loss.backward() g_optimizer.step() with torch.no_grad():
d_epoch_loss+= d_loss.item() g_epoch_loss += g_loss.item() with torch.no_grad():
# The gradient is not calculated for the following contents ( Construction of graph ) d_epoch_loss /= count g_epoch_loss /= count D_loss.append(
d_epoch_loss) G_loss.append(g_epoch_loss) print('Epoch:', epoch+1)
generate_and_save_image(model=Gen, test_input=test_input) plt.plot(D_loss, label
='D_loss') plt.plot(G_loss, label='G_loss') plt.legend() plt.show()

30 Wheel effect

Technology
©2019-2020 Toolsou All rights reserved,
C++ of string of compare usage Python Study notes ( one )evo Tool usage problems ——Degenerate covariance rank, Umeyama alignment is not possibleRISC-V_GD32VF103-TIMER0 timer interrupt java Array subscript variable _Java Basic grammar : array be based on stm32 Control four-wheel trolley motor drive ( one ) be based on redis Design of liking function Software engineering career planning mysql Query random data by conditions _MySQL Random query of several qualified records centos7 install RabbitMq