Commit 425f9d27 authored by Yuxin Wu's avatar Yuxin Wu

tensorpack.tfv1

parent 8e6f930b
......@@ -4,7 +4,6 @@ API Documentation
.. toctree::
:maxdepth: 1
dataflow
dataflow.dataset
dataflow.imgaug
......@@ -17,3 +16,4 @@ API Documentation
tfutils
utils
contrib
tfv1
Moved to [../CaffeModels](../CaffeModels).
## DisturbLabel
I ran into the paper [DisturbLabel: Regularizing CNN on the Loss Layer](https://arxiv.org/abs/1605.00055) on CVPR16,
which basically said that noisy data gives you better performance.
As many, I didn't believe the method and the results. This code exists to
disprove the results in the paper.
This is a simple mnist training script with DisturbLabel. It uses the simple architecture in the paper, and
hyperparameters in my original [mnist example](../mnist-convnet.py).
The results surprised me, clean labels give the worst accuracy:
![mnist](mnist.png)
Experiements were repeated 15 times for p=0, 10 times for p=0.02 & 0.05, and 5 times for other values
of p. All experiements run for 100 epochs, with lr decay, which are enough for them to converge.
I suppose the disturb method works as a random noise that could prevent SGD from getting stuck, if
training data are too easy to fit or too few.
The method didn't work for slightly harder problems such as SVHN:
![svhn](svhn.png)
The SVHN experiements used the model & hyperparemeters as my original [svhn example](../svhn-digit-convnet.py).
Experiements were all repeated 10 times to get the error bar. It apparently does not work.
It will not work for ImageNet either. There is indeed a terribly weak
ImageNet experiment in this paper, and that's a CVPR paper.
# -*- coding: utf-8 -*-
# File: disturb.py
# Author: Yuxin Wu
from tensorpack.dataflow import ProxyDataFlow, RNGDataFlow
class DisturbLabel(ProxyDataFlow, RNGDataFlow):
def __init__(self, ds, prob):
super(DisturbLabel, self).__init__(ds)
self.prob = prob
def reset_state(self):
RNGDataFlow.reset_state(self)
ProxyDataFlow.reset_state(self)
def __iter__(self):
for dp in self.ds:
img, l = dp
if self.rng.rand() < self.prob:
l = self.rng.choice(10)
yield [img, l]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: mnist-disturb.py
import argparse
import imp
import os
import tensorflow as tf
from tensorpack import *
from tensorpack.dataflow import dataset
from tensorpack.utils import logger
from disturb import DisturbLabel
mnist_example = imp.load_source('mnist_example',
os.path.join(os.path.dirname(__file__), '..', 'basics', 'mnist-convnet.py'))
get_config = mnist_example.get_config
def get_data():
dataset_train = BatchData(DisturbLabel(dataset.Mnist('train'), args.prob), 128)
dataset_test = BatchData(dataset.Mnist('test'), 256, remainder=True)
return dataset_train, dataset_test
mnist_example.get_data = get_data
class Model(mnist_example.Model):
def build_graph(self, image, label):
image = tf.expand_dims(image, 3)
logits = (LinearWrap(image) # the starting brace is oactivationy for line-breaking
.Conv2D('conv0', 32, 5, padding='VALID', activation=tf.nn.relu)
.MaxPooling('pool0', 2)
.Conv2D('conv1', 64, 5, padding='VALID', activation=tf.nn.relu)
.MaxPooling('pool1', 2)
.FullyConnected('fc0', 512, activation=tf.nn.relu)
.FullyConnected('fc1', out_dim=10, activation=tf.identity)())
tf.nn.softmax(logits, name='prob')
wrong = tf.cast(tf.logical_not(tf.nn.in_top_k(logits, label, 1)), tf.float32, name='incorrect_vector')
add_moving_summary(tf.reduce_mean(wrong, name='train_error'))
cost = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=label)
cost = tf.reduce_mean(cost, name='cross_entropy_loss')
wd_cost = tf.multiply(1e-5, regularize_cost('fc.*/W', tf.nn.l2_loss),
name='regularize_loss')
return tf.add_n([wd_cost, cost], name='cost')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--gpu', help='comma separated list of GPU(s) to use.')
parser.add_argument('--prob', help='disturb prob', type=float, required=True)
args = parser.parse_args()
if args.gpu:
os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu
logger.auto_set_dir()
config = get_config()
launch_train_with_config(config, SimpleTrainer())
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: svhn-disturb.py
import argparse
import imp
import os
from tensorpack import *
from tensorpack.dataflow import dataset
from tensorpack.utils import logger
from disturb import DisturbLabel
svhn_example = imp.load_source('svhn_example',
os.path.join(os.path.dirname(__file__), '..',
'basics', 'svhn-digit-convnet.py'))
Model = svhn_example.Model
def get_data():
d1 = dataset.SVHNDigit('train')
d2 = dataset.SVHNDigit('extra')
data_train = RandomMixData([d1, d2])
data_train = DisturbLabel(data_train, args.prob)
data_test = dataset.SVHNDigit('test')
augmentors = [
imgaug.Resize((40, 40)),
imgaug.Brightness(30),
imgaug.Contrast((0.5, 1.5)),
]
data_train = AugmentImageComponent(data_train, augmentors)
data_train = BatchData(data_train, 128)
data_train = MultiProcessRunner(data_train, 5, 5)
augmentors = [imgaug.Resize((40, 40))]
data_test = AugmentImageComponent(data_test, augmentors)
data_test = BatchData(data_test, 128, remainder=True)
return data_train, data_test
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--prob', help='disturb prob', type=float, required=True)
args = parser.parse_args()
logger.auto_set_dir()
data_train, data_test = get_data()
config = TrainConfig(
model=Model(),
data=QueueInput(data_train),
callbacks=[
ModelSaver(),
InferenceRunner(data_test,
ScalarStats(['cost', 'accuracy']))
],
max_epoch=350,
)
launch_train_with_config(config, SimpleTrainer())
# -*- coding: utf-8 -*-
# File:
from tensorpack.compat import tfv1 as tf
from tensorpack import tfv1 as tf
from tensorpack import ModelDesc
from tensorpack.models import GlobalAvgPooling, l2_regularizer, regularize_cost
from tensorpack.tfutils import optimizer
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: alexnet.py
import argparse
import numpy as np
import os
import cv2
import tensorflow as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import imgaug
from tensorpack.tfutils import argscope
......
# -*- coding: utf-8 -*-
# File: imagenet_utils.py
import multiprocessing
import numpy as np
import os
from abc import abstractmethod
import cv2
import tensorflow as tf
import tqdm
from tensorpack import tfv1 as tf
from tensorpack import ModelDesc
from tensorpack.dataflow import (
AugmentImageComponent, BatchData, MultiThreadMapData,
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: inception-bn.py
# Author: Yuxin Wu
import argparse
import os
import tensorflow as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import dataset
......
......@@ -7,7 +7,7 @@ import math
import numpy as np
import os
import cv2
import tensorflow as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import imgaug
......
......@@ -4,7 +4,7 @@
import argparse
import os
import tensorflow as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.tfutils import argscope
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: mnist-addition.py
# Author: Yuxin Wu
......@@ -7,7 +6,7 @@ import argparse
import numpy as np
import os
import cv2
import tensorflow as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import dataset
......@@ -194,7 +193,10 @@ def get_data(isTrain):
ds = JoinData([ds, ds])
# stack the two digits into two channels, and label it with the sum
ds = MapData(ds, lambda dp: [np.stack([dp[0], dp[2]], axis=2), dp[1] + dp[3]])
def mapper(dp):
return [np.stack([dp[0], dp[2]], axis=2), dp[1] + dp[3]]
ds = MapData(ds, dp)
ds = BatchData(ds, 128)
return ds
......
......@@ -3,7 +3,7 @@
# Author: Yuxin Wu
import argparse
import os
from tensorpack.compat import tfv1 as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import dataset
......
......@@ -3,7 +3,7 @@
import argparse
import cv2
from tensorpack.compat import tfv1 as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.tfutils.export import ModelExporter
......
......@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
# File: mnist-convnet.py
from tensorpack.compat import tfv1 as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import dataset
from tensorpack.tfutils import summary
......
......@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
# File: mnist-tflayers.py
from tensorpack.compat import tfv1 as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import dataset
from tensorpack.tfutils import summary
......
......@@ -6,7 +6,7 @@
The same MNIST ConvNet example, but with weights/activations visualization.
"""
from tensorpack.compat import tfv1 as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import dataset
......
......@@ -3,7 +3,7 @@
import argparse
import os
from tensorpack.compat import tfv1 as tf
from tensorpack import tfv1 as tf
from tensorpack import *
from tensorpack.dataflow import dataset
from tensorpack.tfutils.summary import *
......
......@@ -21,3 +21,5 @@ if STATICA_HACK:
from tensorpack.train import *
from tensorpack.input_source import *
from tensorpack.predict import *
from tensorpack.compat import tfv1
import tensorflow as tf
def backport_tensor_spec():
def _backport_tensor_spec():
if hasattr(tf, 'TensorSpec'):
return tf.TensorSpec
try:
......@@ -19,6 +19,9 @@ def backport_tensor_spec():
def is_tfv2():
"""
Returns whether tensorflow is operating in V2 mode.
"""
try:
from tensorflow.python import tf2
return tf2.enabled()
......
......@@ -80,7 +80,7 @@ class Rotation(ImageAugmentor):
arr = cv2.warpAffine(arr, mat, arr.shape)
assert np.all(arr == orig)
"""
mat = cv2.getRotationMatrix2D(tuple(center - 0.5), deg, 1)
mat = cv2.getRotationMatrix2D(tuple(center - 0.5), float(deg), 1)
return WarpAffineTransform(
mat, img.shape[1::-1], interp=self.interp,
borderMode=self.border, borderValue=self.border_value)
......@@ -104,7 +104,7 @@ class RotationAndCropValid(ImageAugmentor):
deg = self._rand_range(-self.max_deg, self.max_deg)
if self.step_deg:
deg = deg // self.step_deg * self.step_deg
return deg
return float(deg)
def get_transform(self, img):
deg = self._get_deg(img)
......
......@@ -87,17 +87,17 @@ def Conv2D(
channel_axis = 3 if data_format == 'NHWC' else 1
in_channel = in_shape[channel_axis]
assert in_channel is not None, "[Conv2D] Input cannot have unknown channel!"
assert in_channel % split == 0
assert in_channel % split == 0, in_channel
assert kernel_regularizer is None and bias_regularizer is None and activity_regularizer is None, \
"Not supported by group conv or dilated conv!"
out_channel = filters
assert out_channel % split == 0
assert out_channel % split == 0, out_channel
assert dilation_rate == [1, 1] or get_tf_version_tuple() >= (1, 5), 'TF>=1.5 required for dilated conv.'
kernel_shape = shape2d(kernel_size)
filter_shape = kernel_shape + [in_channel / split, out_channel]
filter_shape = kernel_shape + [in_channel // split, out_channel]
stride = shape4d(strides, data_format=data_format)
kwargs = {"data_format": data_format}
......
......@@ -7,9 +7,9 @@ import tensorflow as tf
from ..utils.argtools import memoized_method
from ..tfutils.common import get_op_tensor_name
from ..tfutils.tower import get_current_tower_context
from ..compat import backport_tensor_spec, tfv1
from ..compat import _backport_tensor_spec, tfv1
TensorSpec = backport_tensor_spec()
TensorSpec = _backport_tensor_spec()
__all__ = ['ModelDesc', 'ModelDescBase']
......
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