Skip to content

Commit

Permalink
Merge pull request PaddlePaddle#46 from qingqing01/cyclegan_mv
Browse files Browse the repository at this point in the history
Move cyclegan to examples and change train/test/eval to train_batch/test_batch/eval_batch.
  • Loading branch information
qingqing01 committed Apr 19, 2020
2 parents 33ece5d + b192a48 commit ed14907
Show file tree
Hide file tree
Showing 15 changed files with 59 additions and 61 deletions.
11 changes: 9 additions & 2 deletions cyclegan/README.md → examples/cyclegan/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,19 @@ data/cityscapes/testA/412_A.jpg

### 训练

在GPU单卡上训练:
在GPU单卡上静态图训练:

```
env CUDA_VISIBLE_DEVICES=0 python train.py
env CUDA_VISIBLE_DEVICES=0 python train.py --checkpoint_path=checkpoint_static
```

在GPU单卡上动态图训练:

```
env CUDA_VISIBLE_DEVICES=0 python train.py --dynamic --checkpoint_path=checkpoint_dynamic
```


执行`python train.py --help`可查看更多使用方式和参数详细说明。

图1为训练152轮的训练损失示意图,其中横坐标轴为训练轮数,纵轴为在训练集上的损失。其中,'g_loss','da_loss'和'db_loss'分别为生成器、判别器A和判别器B的训练损失。
Expand Down
File renamed without changes.
File renamed without changes.
5 changes: 3 additions & 2 deletions cyclegan/cyclegan.py → examples/cyclegan/cyclegan.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@

import numpy as np

from layers import ConvBN, DeConvBN
import paddle.fluid as fluid
from model import Model, Loss
from hapi.model import Model, Loss

from layers import ConvBN, DeConvBN


class ResnetBlock(fluid.dygraph.Layer):
Expand Down
4 changes: 2 additions & 2 deletions cyclegan/data.py → examples/cyclegan/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
import numpy as np
from PIL import Image, ImageOps

import paddle

DATASET = "cityscapes"
A_LIST_FILE = "./data/" + DATASET + "/trainA.txt"
B_LIST_FILE = "./data/" + DATASET + "/trainB.txt"
A_TEST_LIST_FILE = "./data/" + DATASET + "/testA.txt"
B_TEST_LIST_FILE = "./data/" + DATASET + "/testB.txt"
IMAGES_ROOT = "./data/" + DATASET + "/"

import paddle.fluid as fluid


class Cityscapes(paddle.io.Dataset):
def __init__(self, root_path, file_path, mode='train', return_name=False):
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
12 changes: 6 additions & 6 deletions cyclegan/infer.py → examples/cyclegan/infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
from scipy.misc import imsave

import paddle.fluid as fluid
from check import check_gpu, check_version
from hapi.model import Model, Input, set_device

from model import Model, Input, set_device
from check import check_gpu, check_version
from cyclegan import Generator, GeneratorCombine


Expand All @@ -43,7 +43,7 @@ def main():
im_shape = [-1, 3, 256, 256]
input_A = Input(im_shape, 'float32', 'input_A')
input_B = Input(im_shape, 'float32', 'input_B')
g.prepare(inputs=[input_A, input_B])
g.prepare(inputs=[input_A, input_B], device=FLAGS.device)
g.load(FLAGS.init_model, skip_mismatch=True, reset_optimizer=True)

out_path = FLAGS.output + "/single"
Expand All @@ -59,10 +59,10 @@ def main():
data = image.transpose([2, 0, 1])[np.newaxis, :]

if FLAGS.input_style == "A":
_, fake, _, _ = g.test([data, data])
_, fake, _, _ = g.test_batch([data, data])

if FLAGS.input_style == "B":
fake, _, _, _ = g.test([data, data])
fake, _, _, _ = g.test_batch([data, data])

fake = np.squeeze(fake[0]).transpose([1, 2, 0])

Expand All @@ -74,7 +74,7 @@ def main():
if __name__ == "__main__":
parser = argparse.ArgumentParser("CycleGAN inference")
parser.add_argument(
"-d", "--dynamic", action='store_false', help="Enable dygraph mode")
"-d", "--dynamic", action='store_true', help="Enable dygraph mode")
parser.add_argument(
"-p",
"--device",
Expand Down
File renamed without changes.
10 changes: 5 additions & 5 deletions cyclegan/test.py → examples/cyclegan/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
from scipy.misc import imsave

import paddle.fluid as fluid
from check import check_gpu, check_version
from hapi.model import Model, Input, set_device

from model import Model, Input, set_device
from check import check_gpu, check_version
from cyclegan import Generator, GeneratorCombine
import data as data

Expand All @@ -41,7 +41,7 @@ def main():
im_shape = [-1, 3, 256, 256]
input_A = Input(im_shape, 'float32', 'input_A')
input_B = Input(im_shape, 'float32', 'input_B')
g.prepare(inputs=[input_A, input_B])
g.prepare(inputs=[input_A, input_B], device=FLAGS.device)
g.load(FLAGS.init_model, skip_mismatch=True, reset_optimizer=True)

if not os.path.exists(FLAGS.output):
Expand All @@ -56,7 +56,7 @@ def main():
data_A = np.array(data_A).astype("float32")
data_B = np.array(data_B).astype("float32")

fake_A, fake_B, cyc_A, cyc_B = g.test([data_A, data_B])
fake_A, fake_B, cyc_A, cyc_B = g.test_batch([data_A, data_B])

datas = [fake_A, fake_B, cyc_A, cyc_B, data_A, data_B]
odatas = []
Expand All @@ -75,7 +75,7 @@ def main():
if __name__ == "__main__":
parser = argparse.ArgumentParser("CycleGAN test")
parser.add_argument(
"-d", "--dynamic", action='store_false', help="Enable dygraph mode")
"-d", "--dynamic", action='store_true', help="Enable dygraph mode")
parser.add_argument(
"-p",
"--device",
Expand Down
32 changes: 17 additions & 15 deletions cyclegan/train.py → examples/cyclegan/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@

import paddle
import paddle.fluid as fluid
from check import check_gpu, check_version

from model import Model, Input, set_device
from hapi.model import Model, Input, set_device

import data as data
from check import check_gpu, check_version
from cyclegan import Generator, Discriminator, GeneratorCombine, GLoss, DLoss
import data as data

step_per_epoch = 2974

Expand Down Expand Up @@ -76,12 +75,15 @@ def main():
fake_A = Input(im_shape, 'float32', 'fake_A')
fake_B = Input(im_shape, 'float32', 'fake_B')

g_AB.prepare(inputs=[input_A])
g_BA.prepare(inputs=[input_B])
g_AB.prepare(inputs=[input_A], device=FLAGS.device)
g_BA.prepare(inputs=[input_B], device=FLAGS.device)

g.prepare(g_optimizer, GLoss(), inputs=[input_A, input_B])
d_A.prepare(da_optimizer, DLoss(), inputs=[input_B, fake_B])
d_B.prepare(db_optimizer, DLoss(), inputs=[input_A, fake_A])
g.prepare(g_optimizer, GLoss(), inputs=[input_A, input_B],
device=FLAGS.device)
d_A.prepare(da_optimizer, DLoss(), inputs=[input_B, fake_B],
device=FLAGS.device)
d_B.prepare(db_optimizer, DLoss(), inputs=[input_A, fake_A],
device=FLAGS.device)

if FLAGS.resume:
g.load(FLAGS.resume)
Expand All @@ -108,14 +110,14 @@ def main():
data_B = data_B[0][0] if not FLAGS.dynamic else data_B[0]
start = time.time()

fake_B = g_AB.test(data_A)[0]
fake_A = g_BA.test(data_B)[0]
g_loss = g.train([data_A, data_B])[0]
fake_B = g_AB.test_batch(data_A)[0]
fake_A = g_BA.test_batch(data_B)[0]
g_loss = g.train_batch([data_A, data_B])[0]
fake_pb = B_pool.get(fake_B)
da_loss = d_A.train([data_B, fake_pb])[0]
da_loss = d_A.train_batch([data_B, fake_pb])[0]

fake_pa = A_pool.get(fake_A)
db_loss = d_B.train([data_A, fake_pa])[0]
db_loss = d_B.train_batch([data_A, fake_pa])[0]

t = time.time() - start
if i % 20 == 0:
Expand All @@ -128,7 +130,7 @@ def main():
if __name__ == "__main__":
parser = argparse.ArgumentParser("CycleGAN Training on Cityscapes")
parser.add_argument(
"-d", "--dynamic", action='store_false', help="Enable dygraph mode")
"-d", "--dynamic", action='store_true', help="Enable dygraph mode")
parser.add_argument(
"-p",
"--device",
Expand Down
46 changes: 17 additions & 29 deletions hapi/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,17 @@ def mode(self):
def mode(self, value):
self.model.mode = value

def train(self, inputs, labels=None):
def train_batch(self, inputs, labels=None):
assert self.model._optimizer, \
"model not ready, please call `model.prepare()` first"
self.mode = 'train'
return self._run(inputs, labels)

def eval(self, inputs, labels=None):
def eval_batch(self, inputs, labels=None):
self.mode = 'eval'
return self._run(inputs, labels)

def test(self, inputs):
def test_batch(self, inputs):
self.mode = 'test'
return self._run(inputs, None)

Expand Down Expand Up @@ -567,7 +567,7 @@ def mode(self, value):
self.model.mode = value

# TODO multi device in dygraph mode not implemented at present time
def train(self, inputs, labels=None):
def train_batch(self, inputs, labels=None):
assert self.model._optimizer, \
"model not ready, please call `model.prepare()` first"
super(Model, self.model).train()
Expand Down Expand Up @@ -600,7 +600,7 @@ def train(self, inputs, labels=None):
return ([to_numpy(l) for l in losses], metrics) \
if len(metrics) > 0 else [to_numpy(l) for l in losses]

def eval(self, inputs, labels=None):
def eval_batch(self, inputs, labels=None):
super(Model, self.model).eval()
self.mode = 'eval'
inputs = to_list(inputs)
Expand Down Expand Up @@ -642,7 +642,7 @@ def eval(self, inputs, labels=None):
return ([to_numpy(l) for l in losses], metrics) \
if len(metrics) > 0 else [to_numpy(l) for l in losses]

def test(self, inputs):
def test_batch(self, inputs):
super(Model, self.model).eval()
self.mode = 'test'
inputs = [to_variable(x) for x in to_list(inputs)]
Expand Down Expand Up @@ -741,14 +741,14 @@ def __init__(self):
else:
self._adapter = StaticGraphAdapter(self)

def train(self, *args, **kwargs):
return self._adapter.train(*args, **kwargs)
def train_batch(self, *args, **kwargs):
return self._adapter.train_batch(*args, **kwargs)

def eval(self, *args, **kwargs):
return self._adapter.eval(*args, **kwargs)
def eval_batch(self, *args, **kwargs):
return self._adapter.eval_batch(*args, **kwargs)

def test(self, *args, **kwargs):
return self._adapter.test(*args, **kwargs)
def test_batch(self, *args, **kwargs):
return self._adapter.test_batch(*args, **kwargs)

def save(self, *args, **kwargs):
if ParallelEnv().local_rank == 0:
Expand Down Expand Up @@ -1185,7 +1185,7 @@ def predict(self,
outputs = []
for data in tqdm.tqdm(loader):
data = flatten(data)
outputs.append(self.test(data[:len(self._inputs)]))
outputs.append(self.test_batch(data[:len(self._inputs)]))

# NOTE: for lod tensor output, we should not stack outputs
# for stacking may loss its detail info
Expand All @@ -1199,18 +1199,6 @@ def predict(self,
outputs = [o[:len(test_loader.dataset)] for o in outputs]
return outputs

def set_eval_data(self, eval_data):
"""
Args:
eval_data (Dataset|DataLoader|None): An iterable data loader is used for
eval. An instance of paddle.io.Dataset or
paddle.io.Dataloader is recomended.
"""
assert isinstance(
eval_data,
DataLoader), "eval_data must be a instance of Dataloader!"
self._test_dataloader = eval_data

def _run_one_epoch(self,
data_loader,
callbacks,
Expand Down Expand Up @@ -1247,11 +1235,11 @@ def _run_one_epoch(self,

callbacks.on_batch_begin(mode, step, logs)
if mode == 'train':
outs = self.train(data[:len(self._inputs)],
data[len(self._inputs):])
outs = self.train_batch(data[:len(self._inputs)],
data[len(self._inputs):])
else:
outs = self.eval(data[:len(self._inputs)],
data[len(self._inputs):])
outs = self.eval_batch(data[:len(self._inputs)],
data[len(self._inputs):])

# losses
loss = outs[0] if self._metrics else outs
Expand Down

0 comments on commit ed14907

Please sign in to comment.