Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add dataflow module #1028

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ venv_py2/

# TensorLayer Directories
checkpoints
data/
raw_data/
lib_win/

# Custom Scripts
Expand Down
172 changes: 172 additions & 0 deletions examples/basic_tutorials/tutorial_cifar10_cnn_static_dataloader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import multiprocessing
import time

import numpy as np

import tensorflow as tf
import tensorlayer as tl
from tensorlayer.layers import (BatchNorm, Conv2d, Dense, Flatten, Input, LocalResponseNorm, MaxPool2d)
from tensorlayer.models import Model

# enable debug logging
tl.logging.set_verbosity(tl.logging.DEBUG)
tl.logging.set_verbosity(tl.logging.DEBUG)


# define the network
def get_model(inputs_shape):
# self defined initialization
W_init = tl.initializers.truncated_normal(stddev=5e-2)
W_init2 = tl.initializers.truncated_normal(stddev=0.04)
b_init2 = tl.initializers.constant(value=0.1)

# build network
ni = Input(inputs_shape)
nn = Conv2d(64, (5, 5), (1, 1), padding='SAME', act=tf.nn.relu, W_init=W_init, b_init=None, name='conv1')(ni)
nn = MaxPool2d((3, 3), (2, 2), padding='SAME', name='pool1')(nn)
nn = LocalResponseNorm(depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name="norm1")(nn)

nn = Conv2d(64, (5, 5), (1, 1), padding='SAME', act=tf.nn.relu, W_init=W_init, b_init=None, name='conv2')(nn)
nn = LocalResponseNorm(depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name="norm2")(nn)
nn = MaxPool2d((3, 3), (2, 2), padding='SAME', name='pool2')(nn)

nn = Flatten(name='flatten')(nn)
nn = Dense(384, act=tf.nn.relu, W_init=W_init2, b_init=b_init2, name='dense1relu')(nn)
nn = Dense(192, act=tf.nn.relu, W_init=W_init2, b_init=b_init2, name='dense2relu')(nn)
nn = Dense(10, act=None, W_init=W_init2, name='output')(nn)

M = Model(inputs=ni, outputs=nn, name='cnn')
return M


def get_model_batchnorm(inputs_shape):
# self defined initialization
W_init = tl.initializers.truncated_normal(stddev=5e-2)
W_init2 = tl.initializers.truncated_normal(stddev=0.04)
b_init2 = tl.initializers.constant(value=0.1)

# build network
ni = Input(inputs_shape)
nn = Conv2d(64, (5, 5), (1, 1), padding='SAME', W_init=W_init, b_init=None, name='conv1')(ni)
nn = BatchNorm(decay=0.99, act=tf.nn.relu, name='batch1')(nn)
nn = MaxPool2d((3, 3), (2, 2), padding='SAME', name='pool1')(nn)

nn = Conv2d(64, (5, 5), (1, 1), padding='SAME', W_init=W_init, b_init=None, name='conv2')(nn)
nn = BatchNorm(decay=0.99, act=tf.nn.relu, name='batch2')(nn)
nn = MaxPool2d((3, 3), (2, 2), padding='SAME', name='pool2')(nn)

nn = Flatten(name='flatten')(nn)
nn = Dense(384, act=tf.nn.relu, W_init=W_init2, b_init=b_init2, name='dense1relu')(nn)
nn = Dense(192, act=tf.nn.relu, W_init=W_init2, b_init=b_init2, name='dense2relu')(nn)
nn = Dense(10, act=None, W_init=W_init2, name='output')(nn)

M = Model(inputs=ni, outputs=nn, name='cnn')
return M


# get the network
net = get_model([None, 24, 24, 3])

# training settings
batch_size = 128
n_epoch = 50000
learning_rate = 0.0001
print_freq = 5
# init_learning_rate = 0.1
# learning_rate_decay_factor = 0.1
# num_epoch_decay = 350

train_weights = net.trainable_weights
# learning_rate = tf.Variable(init_learning_rate)
optimizer = tf.optimizers.Adam(learning_rate)


def _fn_train(img, target):
# 1. Randomly crop a [height, width] section of the image.
img = tl.prepro.crop(img, 24, 24, False)
# 2. Randomly flip the image horizontally.
img = tl.prepro.flip_axis(img, is_random=True)
# 3. Subtract off the mean and divide by the variance of the pixels.
img = tl.prepro.samplewise_norm(img)
target = np.reshape(target, ())
return img, target


def _fn_test(img, target):
# 1. Crop the central [height, width] of the image.
img = tl.prepro.crop(img, 24, 24)
# 2. Subtract off the mean and divide by the variance of the pixels.
img = tl.prepro.samplewise_norm(img)
img = np.reshape(img, (24, 24, 3))
target = np.reshape(target, ())
return img, target


# dataset API and augmentation
train_ds = tl.data.CIFAR10(train_or_test='train', shape=(-1, 32, 32, 3))
train_dl = tl.data.Dataloader(train_ds, transforms=[_fn_train], shuffle=True,
batch_size=batch_size, output_types=(np.float32, np.int32))
test_ds = tl.data.CIFAR10(train_or_test='test', shape=(-1, 32, 32, 3))
test_dl = tl.data.Dataloader(test_ds, transforms=[_fn_test], batch_size=batch_size)

for epoch in range(n_epoch):
start_time = time.time()

train_loss, train_acc, n_iter = 0, 0, 0
for X_batch, y_batch in train_dl:
net.train()

with tf.GradientTape() as tape:
# compute outputs
_logits = net(X_batch)
# compute loss and update model
_loss_ce = tl.cost.cross_entropy(_logits, y_batch, name='train_loss')
_loss_L2 = 0
# for p in tl.layers.get_variables_with_name('relu/W', True, True):
# _loss_L2 += tl.cost.lo_regularizer(1.0)(p)
_loss = _loss_ce + _loss_L2
# print(_loss)

grad = tape.gradient(_loss, train_weights)
optimizer.apply_gradients(zip(grad, train_weights))

train_loss += _loss
train_acc += np.mean(np.equal(np.argmax(_logits, 1), y_batch))
n_iter += 1

# use training and evaluation sets to evaluate the model every print_freq epoch
if epoch + 1 == 1 or (epoch + 1) % print_freq == 0:

print("Epoch {} of {} took {}".format(epoch + 1, n_epoch, time.time() - start_time))

print(" train loss: {}".format(train_loss / n_iter))
print(" train acc: {}".format(train_acc / n_iter))

net.eval()

val_loss, val_acc, n_iter = 0, 0, 0
for X_batch, y_batch in test_dl:
_logits = net(X_batch) # is_train=False, disable dropout
val_loss += tl.cost.cross_entropy(_logits, y_batch, name='eval_loss')
val_acc += np.mean(np.equal(np.argmax(_logits, 1), y_batch))
n_iter += 1
print(" val loss: {}".format(val_loss / n_iter))
print(" val acc: {}".format(val_acc / n_iter))

# FIXME : how to apply lr decay in eager mode?
# learning_rate.assign(tf.train.exponential_decay(init_learning_rate, epoch, num_epoch_decay,
# learning_rate_decay_factor))

# use testing data to evaluate the model
net.eval()
test_loss, test_acc, n_iter = 0, 0, 0
for X_batch, y_batch in test_dl:
_logits = net(X_batch)
test_loss += tl.cost.cross_entropy(_logits, y_batch, name='test_loss')
test_acc += np.mean(np.equal(np.argmax(_logits, 1), y_batch))
n_iter += 1
print(" test loss: {}".format(test_loss / n_iter))
print(" test acc: {}".format(test_acc / n_iter))
2 changes: 2 additions & 0 deletions tensorlayer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from tensorlayer import optimizers
from tensorlayer import rein
from tensorlayer import utils
from tensorlayer import data

from tensorlayer.lazy_imports import LazyImport

Expand All @@ -54,6 +55,7 @@
prepro = LazyImport("tensorlayer.prepro")
utils = LazyImport("tensorlayer.utils")
visualize = LazyImport("tensorlayer.visualize")
data = LazyImport("tensorlayer.data")

# alias
act = activation
Expand Down
3 changes: 3 additions & 0 deletions tensorlayer/data/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .base import Dataset
from .common import Dataloader
from .dataset import *
65 changes: 65 additions & 0 deletions tensorlayer/data/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
class Dataset(object):

def __getitem__(self, index):
raise NotImplementedError("A Dataset must implement __getitem__(index) method.")

def __len__(self):
raise NotImplementedError("A Dataset must implement __len__() method.")

def __iter__(self):
for i in range(self.__len__()):
yield self.__getitem__(i)

def __call__(self, *args, **kwargs):
return self.__iter__()


class DatasetWrapper(object):
def __init__(self, ds):
self.ds = ds
self.ds_len = len(ds)

def __len__(self):
return len(self.ds)

def __iter__(self):
for dp in self.ds:
yield dp

def __call__(self, *args, **kwargs):
return self.__iter__()


class IndexableDatasetWrapper(object):
def __init__(self, ds):
self.ds = ds
self.ds_len = len(ds)

def __getitem__(self, index):
return self.ds.__getitem__(index)

def __len__(self):
return len(self.ds)

def __call__(self, *args, **kwargs):
return self


class Transform(object):
def __call__(self, *args, **kwargs):
raise NotImplementedError("Transform must implement __call__() method.")


class _Transforms_for_tf_dataset(object):
"""
This class aggregate Transforms into one object in order to use tf.data.Dataset.map API
"""

def __init__(self, transforms):
self.transforms = transforms

def __call__(self, *args):
data_list = list(args)
for transform in self.transforms:
data_list = transform(*data_list)
return data_list
Loading