Commit 9cf69179 authored by Jacky Lin's avatar Jacky Lin
Browse files

add model saver

parent bf034f91
......@@ -677,6 +677,37 @@
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Save/Load Model"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Save Model\n",
"torch.save(netG, \"saved_models/generator.pth\")\n",
"torch.save(netD, \"saved_models/discriminator.pth\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Load Model\n",
"netG = torch.load(\"saved_models/generator.pth\")\n",
"netD = torch.load(\"saved_models/discriminator.pth\")\n",
"netG.eval()\n",
"netD.eval()"
]
}
],
"metadata": {
This diff is collapsed.
......@@ -17,7 +17,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
......@@ -39,7 +39,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -55,7 +55,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
......@@ -78,13 +78,13 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e159505ae8b147fdab136d2c8e71539f",
"model_id": "66ab8e3d491f40b6a1eb73ad62c1ca3e",
"version_major": 2,
"version_minor": 0
},
......
......@@ -47,3 +47,4 @@ pip install pytorch numpy pandas sklearn torchvision matplotlib plotly PIL tqdm
4. [DCGAN](https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html)
5. [Context-Encoder GAN for Image Inpainting](https://www.kaggle.com/balraj98/context-encoder-gan-for-image-inpainting-pytorch/output)
6. [Tiny ImageNet Kaggle](https://www.kaggle.com/akash2sharma/tiny-imagenet)
7. [GANs-Application](https://github.com/nashory/gans-awesome-applications)
%% Cell type:markdown id: tags:
##### ref https://realpython.com/generative-adversarial-networks/#your-first-gan
%% Cell type:markdown id: tags:
## Simple GANs Example
%% Cell type:markdown id: tags:
#### Introduction
This project focuses on the exploration of generative adversarial network (GAN). A [generative adversarial network (GAN)](https://en.wikipedia.org/wiki/Generative_adversarial_network) is a class of machine learning frameworks designed by Ian Goodfellow and his colleagues in 2014. Two neural networks contest with each other in a game in the form of a zero-sum game, where one agent's gain is another agent's loss. In this project, we explore the basic concepts and structures behind the generative adversarial networks. We also perform this neural network on different datasets to learn some interesting application of this model. All the code we provided is written in python3 in jupyter notebook.
%% Cell type:markdown id: tags:
This notebook give an example of GANs where we train neural networks to generating a sine function $f(x) = sin(x)$ given a series of random number
%% Cell type:markdown id: tags:
### Import the essentail pacakge
First we import the essentail package, including:
### Import the essential pacakge
First we import the essential package, including:
1. pytorch which is the mainly package to build neural structure
2. matplotlib is used to visualize the data
%% Cell type:code id: tags:
``` python
import torch
from torch import nn
import math
import matplotlib.pyplot as plt
```
%% Cell type:markdown id: tags:
Set a random seed to reproduce the result
%% Cell type:code id: tags:
``` python
torch.manual_seed(111)
```
%%%% Output: execute_result
<torch._C.Generator at 0x7f912002f210>
%% Cell type:markdown id: tags:
#### Create dataset
%% Cell type:markdown id: tags:
Create the training set. The training set a series of point on sine function $f(x) = sin(x)$ where $x \in [0, 2\pi]$.
%% Cell type:code id: tags:
``` python
train_data_length = 1024
train_data = torch.zeros((train_data_length, 2))
train_data[:, 0] = 2 * math.pi * torch.rand(train_data_length)
train_data[:, 1] = torch.sin(train_data[:, 0])
train_labels = torch.zeros(train_data_length)
train_set = [(train_data[i], train_labels[i]) for i in range(train_data_length)]
```
%% Cell type:markdown id: tags:
Visualize the plot
%% Cell type:code id: tags:
``` python
plt.plot(train_data[:, 0], train_data[:, 1], ".")
```
%%%% Output: execute_result
[<matplotlib.lines.Line2D at 0x7f9093ee76d8>]
%%%% Output: display_data
![](data:image/png;base64,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)
%% Cell type:markdown id: tags:
#### Build the model
%% Cell type:markdown id: tags:
The GANs consists of two neural networks, one called Discriminator and the other called Generator. The role of the generator is to estimate the probability distribution of the real samples in order to provide generated samples resembling real data. The discriminator, in turn, is trained to estimate the probability that a given sample came from the real data rather than being provided by the generator.
![Struct](img/GANsStruct.jpg)
![s](./img/GANsStruct.jpg)
%% Cell type:code id: tags:
``` python
class Discriminator(nn.Module):
def __init__(self):
super().__init__()
self.model = nn.Sequential(
nn.Linear(2, 256),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(256, 128),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(128, 64),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(64, 1),
nn.Sigmoid(),
)
def forward(self, x):
output = self.model(x)
return output
```
%% Cell type:code id: tags:
``` python
class Generator(nn.Module):
def __init__(self):
super().__init__()
self.model = nn.Sequential(
nn.Linear(2, 16),
nn.ReLU(),
nn.Linear(16, 32),
nn.ReLU(),
nn.Linear(32, 2),
)
def forward(self, x):
output = self.model(x)
return output
```
%% Cell type:markdown id: tags:
Instantiation
%% Cell type:code id: tags:
``` python
discriminator = Discriminator()
generator = Generator()
```
%% Cell type:markdown id: tags:
#### Set hyperparameters
%% Cell type:code id: tags:
``` python
lr = 0.001
num_epochs = 300
loss_function = nn.BCELoss()
batch_size = 32
train_loader = torch.utils.data.DataLoader(
train_set, batch_size=batch_size, shuffle=True
)
```
%% Cell type:markdown id: tags:
#### Set the optimization object
What do optimizer do in neural network?
![op](img/optim.png)
`Adam` combines the best properties of the AdaGrad and RMSProp algorithms to provide an optimization algorithm that can handle sparse gradients on noisy problems.
%% Cell type:code id: tags:
``` python
optimizer_discriminator = torch.optim.Adam(discriminator.parameters(), lr=lr)
optimizer_generator = torch.optim.Adam(generator.parameters(), lr=lr)
```
%% Cell type:markdown id: tags:
Training process:
1. Train the discriminator using real(1) data and fake(0) data. The discriminator will need to distinguish between the fake and real data points
2. Train the generator using random numbers as input and let discriminator to do the classify output from generator. The loss is the difference of the classification result and true labels, all of which is of value 1
%% Cell type:code id: tags:
``` python
def train(generator, discriminator, num_epochs, batch_size, train_loader):
for epoch in range(num_epochs):
for n, (real_samples, _) in enumerate(train_loader):
# Data for training the discriminator
real_samples_labels = torch.ones((batch_size, 1))
latent_space_samples = torch.randn((batch_size, 2))
generated_samples = generator(latent_space_samples)
generated_samples_labels = torch.zeros((batch_size, 1))
all_samples = torch.cat((real_samples, generated_samples))
all_samples_labels = torch.cat(
(real_samples_labels, generated_samples_labels)
)
# Training the discriminator
discriminator.zero_grad()
output_discriminator = discriminator(all_samples)
loss_discriminator = loss_function(
output_discriminator, all_samples_labels)
loss_discriminator.backward()
optimizer_discriminator.step()
# Data for training the generator
latent_space_samples = torch.randn((batch_size, 2))
# Training the generator
generator.zero_grad()
generated_samples = generator(latent_space_samples)
output_discriminator_generated = discriminator(generated_samples)
loss_generator = loss_function(
output_discriminator_generated, real_samples_labels
)
loss_generator.backward()
optimizer_generator.step()
# Show loss
if epoch % 10 == 0 and n == batch_size - 1:
print(f"Epoch: {epoch} Loss D.: {loss_discriminator}")
print(f"Epoch: {epoch} Loss G.: {loss_generator}")
```
%% Cell type:code id: tags:
``` python
train(generator, discriminator, num_epochs, batch_size, train_loader)
```
%%%% Output: stream
Epoch: 0 Loss D.: 0.19172890484333038
Epoch: 0 Loss G.: 2.205277919769287
Epoch: 10 Loss D.: 0.6455698013305664
Epoch: 10 Loss G.: 0.8941397666931152
Epoch: 20 Loss D.: 0.643601655960083
Epoch: 20 Loss G.: 0.8925288915634155
Epoch: 30 Loss D.: 0.6730794906616211
Epoch: 30 Loss G.: 0.9668323993682861
Epoch: 40 Loss D.: 0.6405140161514282
Epoch: 40 Loss G.: 0.7298990488052368
Epoch: 50 Loss D.: 0.6809470057487488
Epoch: 50 Loss G.: 0.7750263214111328
Epoch: 60 Loss D.: 0.6326340436935425
Epoch: 60 Loss G.: 0.8059306144714355
Epoch: 70 Loss D.: 0.5179269313812256
Epoch: 70 Loss G.: 1.0993049144744873
Epoch: 80 Loss D.: 0.5927025675773621
Epoch: 80 Loss G.: 0.8768778443336487
Epoch: 90 Loss D.: 0.6255234479904175
Epoch: 90 Loss G.: 0.7707381248474121
Epoch: 100 Loss D.: 0.5345417857170105
Epoch: 100 Loss G.: 0.8872535228729248
Epoch: 110 Loss D.: 0.6842091083526611
Epoch: 110 Loss G.: 0.6737083196640015
Epoch: 120 Loss D.: 0.618989109992981
Epoch: 120 Loss G.: 1.0244462490081787
Epoch: 130 Loss D.: 0.651526689529419
Epoch: 130 Loss G.: 0.7835967540740967
Epoch: 140 Loss D.: 0.6564826965332031
Epoch: 140 Loss G.: 0.736600935459137
Epoch: 150 Loss D.: 0.7063291072845459
Epoch: 150 Loss G.: 0.8015179634094238
Epoch: 160 Loss D.: 0.7304964661598206
Epoch: 160 Loss G.: 0.6758403182029724
Epoch: 170 Loss D.: 0.6666960716247559
Epoch: 170 Loss G.: 0.7535879611968994
Epoch: 180 Loss D.: 0.6781765818595886
Epoch: 180 Loss G.: 0.7857789993286133
Epoch: 190 Loss D.: 0.6380088925361633
Epoch: 190 Loss G.: 0.7979979515075684
Epoch: 200 Loss D.: 0.6476839780807495
Epoch: 200 Loss G.: 0.7968341112136841
Epoch: 210 Loss D.: 0.6286032795906067
Epoch: 210 Loss G.: 1.0192309617996216
Epoch: 220 Loss D.: 0.6657217741012573
Epoch: 220 Loss G.: 0.7269636392593384
Epoch: 230 Loss D.: 0.7014310359954834
Epoch: 230 Loss G.: 0.7147063612937927
Epoch: 240 Loss D.: 0.7104332447052002
Epoch: 240 Loss G.: 0.7164992690086365
Epoch: 250 Loss D.: 0.7514128088951111
Epoch: 250 Loss G.: 1.0906519889831543
Epoch: 260 Loss D.: 0.5960716009140015
Epoch: 260 Loss G.: 1.1555901765823364
Epoch: 270 Loss D.: 0.6859428882598877
Epoch: 270 Loss G.: 0.682672917842865
Epoch: 280 Loss D.: 0.6769641041755676
Epoch: 280 Loss G.: 0.7675719857215881
Epoch: 290 Loss D.: 0.6696629524230957
Epoch: 290 Loss G.: 0.764472246170044
%% Cell type:markdown id: tags:
#### Prediction
%% Cell type:markdown id: tags:
Generate a series of random point and let the generator performs on these data poins and show the generated results
%% Cell type:code id: tags:
``` python
latent_space_samples = torch.randn(500, 2)
plt.plot(latent_space_samples[:, 0], latent_space_samples[:, 1], ".")
generated_samples = generator(latent_space_samples)
```
%%%% Output: display_data
![](data:image/png;base64,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)
%% Cell type:code id: tags:
``` python
generated_samples = generated_samples.detach()
plt.plot(generated_samples[:, 0], generated_samples[:, 1], ".")
```
%%%% Output: execute_result
[<matplotlib.lines.Line2D at 0x7f9069e33b70>]
%%%% Output: display_data
![](data:image/png;base64,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)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment