Commit 2d5707c0 authored by Yuxin Wu's avatar Yuxin Wu

remove keras-imagenet example

parent 22f37f9a
...@@ -68,7 +68,9 @@ Dependencies: ...@@ -68,7 +68,9 @@ Dependencies:
+ Python 3.3+. + Python 3.3+.
+ Python bindings for OpenCV. (Optional, but required by a lot of features) + Python bindings for OpenCV. (Optional, but required by a lot of features)
+ TensorFlow ≥ 1.5, < 2. (Not required if you only want to use `tensorpack.dataflow` alone as a data processing library) + TensorFlow ≥ 1.5, < 2
* TF is not not required if you only want to use `tensorpack.dataflow` alone as a data processing library
* TF2 is supported if used in graph mode (and use `tf.compat.v1` when needed)
``` ```
pip install --upgrade git+https://github.com/tensorpack/tensorpack.git pip install --upgrade git+https://github.com/tensorpack/tensorpack.git
# or add `--user` to install to user's local directories # or add `--user` to install to user's local directories
......
...@@ -25,7 +25,6 @@ These are the only toy examples in tensorpack. They are supposed to be just demo ...@@ -25,7 +25,6 @@ These are the only toy examples in tensorpack. They are supposed to be just demo
+ [An illustrative MNIST example with explanation of the framework](basics/mnist-convnet.py) + [An illustrative MNIST example with explanation of the framework](basics/mnist-convnet.py)
+ Tensorpack supports any symbolic libraries. See the same MNIST example written with [tf.layers](basics/mnist-tflayers.py), and [with weights visualizations](basics/mnist-visualizations.py) + Tensorpack supports any symbolic libraries. See the same MNIST example written with [tf.layers](basics/mnist-tflayers.py), and [with weights visualizations](basics/mnist-visualizations.py)
+ A tiny [Cifar ConvNet](basics/cifar-convnet.py) and [SVHN ConvNet](basics/svhn-digit-convnet.py) + A tiny [Cifar ConvNet](basics/cifar-convnet.py) and [SVHN ConvNet](basics/svhn-digit-convnet.py)
+ If you've used Keras, check out [Keras+Tensorpack examples](keras)
+ [A boilerplate file to start with, for your own tasks](boilerplate.py) + [A boilerplate file to start with, for your own tasks](boilerplate.py)
## Vision: ## Vision:
......
...@@ -29,7 +29,7 @@ baseline and they actually cannot beat this standard ResNet recipe. ...@@ -29,7 +29,7 @@ baseline and they actually cannot beat this standard ResNet recipe.
To reproduce training or evaluation in the above table, To reproduce training or evaluation in the above table,
first decompress ImageNet data into [this structure](http://tensorpack.readthedocs.io/modules/dataflow.dataset.html#tensorpack.dataflow.dataset.ILSVRC12), then: first decompress ImageNet data into [this structure](http://tensorpack.readthedocs.io/modules/dataflow.dataset.html#tensorpack.dataflow.dataset.ILSVRC12), then:
```bash ```bash
./imagenet-resnet.py --data /directory/of/ILSVRC -d 50 --batch 512 ./imagenet-resnet.py --data /directory/of/ILSVRC -d 50
./imagenet-resnet.py --data /directory/of/ILSVRC -d 50 --load ResNet50.npz --eval ./imagenet-resnet.py --data /directory/of/ILSVRC -d 50 --load ResNet50.npz --eval
# See ./imagenet-resnet.py -h for other options. # See ./imagenet-resnet.py -h for other options.
``` ```
......
...@@ -10,8 +10,6 @@ has mentioned some of it. ...@@ -10,8 +10,6 @@ has mentioned some of it.
Even on a single GPU, tensorpack can run [1.2~2x faster](https://github.com/tensorpack/benchmarks/tree/master/other-wrappers) Even on a single GPU, tensorpack can run [1.2~2x faster](https://github.com/tensorpack/benchmarks/tree/master/other-wrappers)
than the equivalent Keras code. The gap becomes larger when you scale to multiple GPUs. than the equivalent Keras code. The gap becomes larger when you scale to multiple GPUs.
Tensorpack and [horovod](https://github.com/uber/horovod/blob/master/examples/keras_imagenet_resnet50.py)
are the only two tools I know that can scale the training of a large Keras model.
### Simple Examples: ### Simple Examples:
...@@ -25,19 +23,6 @@ There are two flavors where you can use a Keras model inside tensorpack: ...@@ -25,19 +23,6 @@ There are two flavors where you can use a Keras model inside tensorpack:
2. The entire model to train is a Keras model (and there will be no `ModelDesc`, etc). 2. The entire model to train is a Keras model (and there will be no `ModelDesc`, etc).
See [mnist-keras-v2.py](mnist-keras-v2.py). See [mnist-keras-v2.py](mnist-keras-v2.py).
### ImageNet Example:
[imagenet-resnet-keras.py](imagenet-resnet-keras.py):
reproduce exactly the same setting of [tensorpack ResNet example](../ResNet) on ImageNet.
It has:
+ ResNet-50 model modified from [keras.applications](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/keras/_impl/keras/applications/resnet50.py).
(We put stride on 3x3 conv in each bottleneck, which is different from certain other implementations).
+ Multi-GPU data-parallel __training and validation__ which scales
+ Finished 100 epochs in 19 hours on 8 V100s, with >90% GPU utilization.
+ Still slightly slower than native tensorpack examples.
+ Good accuracy (same as [tensorpack ResNet example](../ResNet))
### Note: ### Note:
Keras does not respect variable scopes or variable Keras does not respect variable scopes or variable
...@@ -45,4 +30,4 @@ collections, which contradicts with tensorpack trainers. ...@@ -45,4 +30,4 @@ collections, which contradicts with tensorpack trainers.
Therefore Keras support is __experimental__ and __unofficial__. Therefore Keras support is __experimental__ and __unofficial__.
These simple examples can run within tensorpack smoothly, but note that a These simple examples can run within tensorpack smoothly, but note that a
complicated model or a future version of Keras may break them. complicated model or a future version of Keras may not work well.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: imagenet-resnet-keras.py
# Author: Yuxin Wu
import argparse
import numpy as np
import os
import tensorflow as tf
from tensorflow.python.keras.layers import *
from tensorpack import SyncMultiGPUTrainerReplicated
from tensorpack.callbacks import *
from tensorpack.contrib.keras import KerasModel
from tensorpack.dataflow import FakeData, MapDataComponent
from tensorpack.tfutils.common import get_tf_version_tuple
from tensorpack.utils import logger
from tensorpack.utils.gpu import get_num_gpu
from imagenet_utils import fbresnet_augmentor, get_imagenet_dataflow
TOTAL_BATCH_SIZE = 512
BASE_LR = 0.1 * (TOTAL_BATCH_SIZE // 256)
def bn(x, name, zero_init=False):
return BatchNormalization(
axis=1, name=name, fused=True,
momentum=0.9, epsilon=1e-5,
gamma_initializer='zeros' if zero_init else 'ones')(x)
def conv(x, filters, kernel, strides=1, name=None):
return Conv2D(filters, kernel, name=name,
strides=strides, use_bias=False, padding='same',
kernel_initializer=tf.keras.initializers.VarianceScaling(
scale=2.0, mode='fan_out',
distribution='untruncated_normal' if get_tf_version_tuple() >= (1, 12) else 'normal'),
kernel_regularizer=tf.keras.regularizers.l2(5e-5))(x)
def identity_block(input_tensor, kernel_size, filters, stage, block):
filters1, filters2, filters3 = filters
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
x = conv(input_tensor, filters1, 1, name=conv_name_base + '2a')
x = bn(x, name=bn_name_base + '2a')
x = Activation('relu')(x)
x = conv(x, filters2, kernel_size, name=conv_name_base + '2b')
x = bn(x, name=bn_name_base + '2b')
x = Activation('relu')(x)
x = conv(x, filters3, (1, 1), name=conv_name_base + '2c')
x = bn(x, name=bn_name_base + '2c', zero_init=True)
x = tf.keras.layers.add([x, input_tensor])
x = Activation('relu')(x)
return x
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
filters1, filters2, filters3 = filters
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
x = conv(input_tensor, filters1, (1, 1), name=conv_name_base + '2a')
x = bn(x, name=bn_name_base + '2a')
x = Activation('relu')(x)
x = conv(x, filters2, kernel_size, strides=strides, name=conv_name_base + '2b')
x = bn(x, name=bn_name_base + '2b')
x = Activation('relu')(x)
x = conv(x, filters3, (1, 1), name=conv_name_base + '2c')
x = bn(x, name=bn_name_base + '2c', zero_init=True)
shortcut = conv(
input_tensor,
filters3, (1, 1), strides=strides,
name=conv_name_base + '1')
shortcut = bn(shortcut, name=bn_name_base + '1')
x = tf.keras.layers.add([x, shortcut])
x = Activation('relu')(x)
return x
def resnet50(image):
input = Input(tensor=image)
def image_preprocess(image):
image = tf.cast(image, tf.float32)
image = image * (1.0 / 255)
mean = [0.485, 0.456, 0.406][::-1]
std = [0.229, 0.224, 0.225][::-1]
image = (image - tf.constant(mean, dtype=tf.float32)) / tf.constant(std, dtype=tf.float32)
image = tf.transpose(image, [0, 3, 1, 2])
return image
x = Lambda(image_preprocess)(input)
x = conv(x, 64, (7, 7), strides=(2, 2), name='conv0')
x = bn(x, name='bn_conv1')
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')
x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')
x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')
x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')
x = GlobalAveragePooling2D(name='avg_pool')(x)
x = Flatten()(x)
x = Dense(1000, activation='softmax', name='fc1000',
kernel_initializer=tf.keras.initializers.VarianceScaling(
scale=2.0, mode='fan_in'),
kernel_regularizer=tf.keras.regularizers.l2(5e-5))(x)
M = tf.keras.models.Model(input, x, name='resnet50')
return M
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--data', help='ILSVRC dataset dir')
parser.add_argument('--fake', help='use fakedata to test or benchmark this model', action='store_true')
args = parser.parse_args()
logger.set_logger_dir(os.path.join("train_log", "imagenet-resnet-keras"))
tf.keras.backend.set_image_data_format('channels_first')
num_gpu = get_num_gpu()
if args.fake:
df_train = FakeData([[32, 224, 224, 3], [32, 1000]], 5000, random=False, dtype='uint8')
df_val = FakeData([[32, 224, 224, 3], [32, 1000]], 5000, random=False)
else:
batch_size = TOTAL_BATCH_SIZE // num_gpu
assert args.data is not None
df_train = get_imagenet_dataflow(
args.data, 'train', batch_size, fbresnet_augmentor(True))
df_val = get_imagenet_dataflow(
args.data, 'val', batch_size, fbresnet_augmentor(False))
def one_hot(label):
return np.eye(1000)[label]
df_train = MapDataComponent(df_train, one_hot, 1)
df_val = MapDataComponent(df_val, one_hot, 1)
M = KerasModel(
resnet50,
input_signature=[tf.TensorSpec([None, 224, 224, 3], tf.uint8, 'images')],
target_signature=[tf.TensorSpec([None, 1000], tf.float32, 'labels')],
input=df_train,
trainer=SyncMultiGPUTrainerReplicated(num_gpu))
lr = tf.get_variable('learning_rate', initializer=0.1, trainable=False)
tf.summary.scalar('lr', lr)
M.compile(
optimizer=tf.train.MomentumOptimizer(lr, 0.9, use_nesterov=True),
loss='categorical_crossentropy',
metrics='categorical_accuracy'
)
callbacks = [
ModelSaver(),
ScheduledHyperParamSetter(
'learning_rate',
[(0, 0.1), (3, BASE_LR)], interp='linear'), # warmup
ScheduledHyperParamSetter(
'learning_rate',
[(30, BASE_LR * 0.1), (60, BASE_LR * 1e-2), (85, BASE_LR * 1e-3)]),
GPUUtilizationTracker()
]
if not args.fake:
callbacks.append(
DataParallelInferenceRunner(
df_val, ScalarStats(['categorical_accuracy']), num_gpu))
M.fit(
steps_per_epoch=100 if args.fake else 1281167 // TOTAL_BATCH_SIZE,
max_epoch=100,
callbacks=callbacks
)
../ResNet/imagenet_utils.py
\ No newline at end of file
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