Commit 3c62a25c authored by Yuxin Wu's avatar Yuxin Wu

deprecate more from symbolic_functions

parent fe5d4984
...@@ -2,10 +2,11 @@ Bug Reports/Feature Requests/Usage Questions Only: ...@@ -2,10 +2,11 @@ Bug Reports/Feature Requests/Usage Questions Only:
Any unexpected problems: PLEASE always include Any unexpected problems: PLEASE always include
1. What you did: 1. What you did:
+ Are you using any examples? + If you're using examples:
+ If yes, post the command you run and changes you made (if any). + What's the command you run:
+ Have you made and changes to code? Post them if any:
+ If not, describe what you did that may be relevant. + If not, describe what you did that may be relevant.
But we may not be able to resolve it if there is no reproducible code. But we may not be able to resolve it since there is no reproducible code.
2. What you observed, e.g. as much as logs possible. 2. What you observed, e.g. as much as logs possible.
3. What you expected, if not obvious. 3. What you expected, if not obvious.
4. Your environment (TF version, tensorpack version, cudnn version, number & type of GPUs), if it matters. 4. Your environment (TF version, tensorpack version, cudnn version, number & type of GPUs), if it matters.
......
...@@ -375,7 +375,7 @@ def autodoc_skip_member(app, what, name, obj, skip, options): ...@@ -375,7 +375,7 @@ def autodoc_skip_member(app, what, name, obj, skip, options):
'LeakyReLU', 'LeakyReLU',
'PrefetchOnGPUs', 'PrefetchOnGPUs',
'guided_relu', 'saliency_map', 'get_scalar_var', 'guided_relu', 'saliency_map', 'get_scalar_var', 'psnr',
'prediction_incorrect', 'huber_loss', 'prediction_incorrect', 'huber_loss',
]: ]:
return True return True
......
...@@ -71,14 +71,6 @@ tensorpack.tfutils.summary module ...@@ -71,14 +71,6 @@ tensorpack.tfutils.summary module
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
tensorpack.tfutils.symbolic_functions module
--------------------------------------------
.. automodule:: tensorpack.tfutils.symbolic_functions
:members:
:undoc-members:
:show-inheritance:
tensorpack.tfutils.varmanip module tensorpack.tfutils.varmanip module
---------------------------------- ----------------------------------
......
...@@ -229,9 +229,9 @@ Let me summarize what this DataFlow does: ...@@ -229,9 +229,9 @@ Let me summarize what this DataFlow does:
send them through ZMQ IPC pipe. send them through ZMQ IPC pipe.
3. The main process takes data from the pipe, makes batches. 3. The main process takes data from the pipe, makes batches.
The two DataFlow mentioned in this tutorial (both random read and sequential read) can run at a speed of 1k ~ 2k images per second if you have good CPUs, RAM, disks. The two DataFlow mentioned in this tutorial (both random read and sequential read) can run at a speed of 1k ~ 2.5k images per second if you have good CPUs, RAM, disks.
As a reference, tensorpack can train ResNet-18 at 1.2k images/s on 4 old TitanX. As a reference, tensorpack can train ResNet-18 at 1.2k images/s on 4 old TitanX.
A DGX-1 (8 P100) can train ResNet-50 at 1.7k images/s according to the [official benchmark](https://www.tensorflow.org/performance/benchmarks). A DGX-1 (8 P100s) can train ResNet-50 at 1.7k images/s according to the [official benchmark](https://www.tensorflow.org/performance/benchmarks).
So DataFlow will not be a serious bottleneck if configured properly. So DataFlow will not be a serious bottleneck if configured properly.
## Distributed DataFlow ## Distributed DataFlow
......
### Write a DataFlow ### Write a DataFlow
#### Write a Source DataFlow
There are several existing DataFlow, e.g. [ImageFromFile](../../modules/dataflow.html#tensorpack.dataflow.ImageFromFile), There are several existing DataFlow, e.g. [ImageFromFile](../../modules/dataflow.html#tensorpack.dataflow.ImageFromFile),
[DataFromList](../../modules/dataflow.html#tensorpack.dataflow.DataFromList), [DataFromList](../../modules/dataflow.html#tensorpack.dataflow.DataFromList),
which you can use if your data format is simple. which you can use if your data format is simple.
...@@ -23,14 +25,27 @@ Optionally, you can implement the following two methods: ...@@ -23,14 +25,27 @@ Optionally, you can implement the following two methods:
+ `reset_state()`. It is guaranteed that the actual process which runs a DataFlow will invoke this method before using it. + `reset_state()`. It is guaranteed that the actual process which runs a DataFlow will invoke this method before using it.
So if this DataFlow needs to do something after a `fork()`, you should put it here. So if this DataFlow needs to do something after a `fork()`, you should put it here.
The convention is that, `reset_state()` must be called once and usually only once for each DataFlow instance.
A typical situation is when your DataFlow uses random number generator (RNG). Then you would need to reset the RNG here. A typical situation is when your DataFlow uses random number generator (RNG). Then you would need to reset the RNG here.
Otherwise, child processes will have the same random seed. The `RNGDataFlow` base class does this for you. Otherwise, child processes will have the same random seed. The `RNGDataFlow` base class does this for you.
You can subclass `RNGDataFlow` to access `self.rng` whose seed has been taken care of. You can subclass `RNGDataFlow` to access `self.rng` whose seed has been taken care of.
The convention is that, `reset_state()` must be called once and usually only once for each DataFlow instance.
To reinitialize the dataflow (i.e. get a new iterator from the beginning), simply call `get_data()` again.
DataFlow implementations for several well-known datasets are provided in the DataFlow implementations for several well-known datasets are provided in the
[dataflow.dataset](../../modules/dataflow.dataset.html) [dataflow.dataset](../../modules/dataflow.dataset.html)
module, you can take them as a reference. module, you can take them as a reference.
#### More Data Processing
You can put any data processing you need in the source DataFlow, or write a new DataFlow for data
processing on top of the source DataFlow, e.g.:
```python
class ProcessingDataFlow(DataFlow):
def __init__(self, ds):
self.ds = ds
def get_data(self):
for datapoint in self.ds.get_data():
# do something
yield new_datapoint
```
...@@ -17,7 +17,6 @@ from six.moves import queue ...@@ -17,7 +17,6 @@ from six.moves import queue
from tensorpack import * from tensorpack import *
from tensorpack.utils.concurrency import ensure_proc_terminate, start_proc_mask_signal from tensorpack.utils.concurrency import ensure_proc_terminate, start_proc_mask_signal
from tensorpack.utils.serialize import dumps from tensorpack.utils.serialize import dumps
from tensorpack.tfutils import symbolic_functions as symbf
from tensorpack.tfutils.gradproc import MapGradient, SummaryGradient from tensorpack.tfutils.gradproc import MapGradient, SummaryGradient
from tensorpack.utils.gpu import get_nr_gpu from tensorpack.utils.gpu import get_nr_gpu
...@@ -117,7 +116,7 @@ class Model(ModelDesc): ...@@ -117,7 +116,7 @@ class Model(ModelDesc):
value_loss = tf.nn.l2_loss(value - futurereward, name='value_loss') value_loss = tf.nn.l2_loss(value - futurereward, name='value_loss')
pred_reward = tf.reduce_mean(value, name='predict_reward') pred_reward = tf.reduce_mean(value, name='predict_reward')
advantage = symbf.rms(advantage, name='rms_advantage') advantage = tf.sqrt(tf.reduce_mean(tf.square(advantage)), name='rms_advantage')
entropy_beta = tf.get_variable('entropy_beta', shape=[], entropy_beta = tf.get_variable('entropy_beta', shape=[],
initializer=tf.constant_initializer(0.01), trainable=False) initializer=tf.constant_initializer(0.01), trainable=False)
self.cost = tf.add_n([policy_loss, xentropy_loss * entropy_beta, value_loss]) self.cost = tf.add_n([policy_loss, xentropy_loss * entropy_beta, value_loss])
......
...@@ -14,7 +14,7 @@ from six.moves import range ...@@ -14,7 +14,7 @@ from six.moves import range
from tensorpack import * from tensorpack import *
from tensorpack.tfutils import symbolic_functions, summary, optimizer from tensorpack.tfutils import summary, optimizer
from tensorpack.tfutils.gradproc import GlobalNormClip from tensorpack.tfutils.gradproc import GlobalNormClip
from tensorpack.utils.globvars import globalns as param from tensorpack.utils.globvars import globalns as param
...@@ -80,7 +80,7 @@ class Model(ModelDesc): ...@@ -80,7 +80,7 @@ class Model(ModelDesc):
ret = tf.get_variable(n + '_unused', [param.batch_size, param.rnn_size], ret = tf.get_variable(n + '_unused', [param.batch_size, param.rnn_size],
trainable=False, trainable=False,
initializer=tf.constant_initializer()) initializer=tf.constant_initializer())
ret = symbolic_functions.shapeless_placeholder(ret, 0, name=n) ret = tf.placeholder_with_default(ret, shape=[None, param.rnn_size], name=n)
return ret return ret
initial = (rnn.LSTMStateTuple(get_v('c0'), get_v('h0')), initial = (rnn.LSTMStateTuple(get_v('c0'), get_v('h0')),
rnn.LSTMStateTuple(get_v('c1'), get_v('h1'))) rnn.LSTMStateTuple(get_v('c1'), get_v('h1')))
......
...@@ -12,7 +12,6 @@ import argparse ...@@ -12,7 +12,6 @@ import argparse
from tensorpack import * from tensorpack import *
from tensorpack.utils.viz import interactive_imshow, stack_patches from tensorpack.utils.viz import interactive_imshow, stack_patches
import tensorpack.tfutils.symbolic_functions as symbf
from tensorpack.tfutils.scope_utils import auto_reuse_variable_scope from tensorpack.tfutils.scope_utils import auto_reuse_variable_scope
from tensorpack.dataflow import dataset from tensorpack.dataflow import dataset
from GAN import GANTrainer, RandomZData, GANModelDesc from GAN import GANTrainer, RandomZData, GANModelDesc
...@@ -30,6 +29,16 @@ A pretrained model is at http://models.tensorpack.com/GAN/ ...@@ -30,6 +29,16 @@ A pretrained model is at http://models.tensorpack.com/GAN/
BATCH = 128 BATCH = 128
def batch_flatten(x):
"""
Flatten the tensor except the first dimension.
"""
shape = x.get_shape().as_list()[1:]
if None not in shape:
return tf.reshape(x, [-1, int(np.prod(shape))])
return tf.reshape(x, tf.stack([tf.shape(x)[0], -1]))
class Model(GANModelDesc): class Model(GANModelDesc):
def _get_inputs(self): def _get_inputs(self):
return [InputDesc(tf.float32, (None, 28, 28), 'input'), return [InputDesc(tf.float32, (None, 28, 28), 'input'),
...@@ -65,7 +74,7 @@ class Model(GANModelDesc): ...@@ -65,7 +74,7 @@ class Model(GANModelDesc):
.BatchNorm('bn1') .BatchNorm('bn1')
.tf.nn.leaky_relu() .tf.nn.leaky_relu()
.apply(symbf.batch_flatten) .apply(batch_flatten)
.ConcatWith(yv, 1) .ConcatWith(yv, 1)
.FullyConnected('fc1', 1024, nl=tf.identity) .FullyConnected('fc1', 1024, nl=tf.identity)
.BatchNorm('bn2') .BatchNorm('bn2')
...@@ -81,7 +90,7 @@ class Model(GANModelDesc): ...@@ -81,7 +90,7 @@ class Model(GANModelDesc):
y = tf.one_hot(y, 10, name='label_onehot') y = tf.one_hot(y, 10, name='label_onehot')
z = tf.random_uniform([BATCH, 100], -1, 1, name='z_train') z = tf.random_uniform([BATCH, 100], -1, 1, name='z_train')
z = symbf.shapeless_placeholder(z, [0], name='z') z = tf.placeholder_with_default(z, [None, 100], name='z') # clear the static shape
with argscope([Conv2D, Deconv2D, FullyConnected], with argscope([Conv2D, Deconv2D, FullyConnected],
W_init=tf.truncated_normal_initializer(stddev=0.02)): W_init=tf.truncated_normal_initializer(stddev=0.02)):
......
...@@ -14,7 +14,6 @@ from tensorpack import * ...@@ -14,7 +14,6 @@ from tensorpack import *
from tensorpack.utils import viz from tensorpack.utils import viz
from tensorpack.tfutils.scope_utils import auto_reuse_variable_scope, under_name_scope from tensorpack.tfutils.scope_utils import auto_reuse_variable_scope, under_name_scope
from tensorpack.tfutils import optimizer, summary from tensorpack.tfutils import optimizer, summary
import tensorpack.tfutils.symbolic_functions as symbf
from tensorpack.dataflow import dataset from tensorpack.dataflow import dataset
from GAN import GANTrainer, GANModelDesc from GAN import GANTrainer, GANModelDesc
...@@ -38,6 +37,35 @@ NOISE_DIM = 62 ...@@ -38,6 +37,35 @@ NOISE_DIM = 62
DIST_PRIOR_PARAM = [1.] * NUM_CLASS + [0.] * NUM_UNIFORM DIST_PRIOR_PARAM = [1.] * NUM_CLASS + [0.] * NUM_UNIFORM
def shapeless_placeholder(x, axis, name):
"""
Make the static shape of a tensor less specific.
If you want to feed to a tensor, the shape of the feed value must match
the tensor's static shape. This function creates a placeholder which
defaults to x if not fed, but has a less specific static shape than x.
See also `tensorflow#5680 <https://github.com/tensorflow/tensorflow/issues/5680>`_.
Args:
x: a tensor
axis(int or list of ints): these axes of ``x.get_shape()`` will become
None in the output.
name(str): name of the output tensor
Returns:
a tensor equal to x, but shape information is partially cleared.
"""
shp = x.get_shape().as_list()
if not isinstance(axis, list):
axis = [axis]
for a in axis:
if shp[a] is None:
raise ValueError("Axis {} of shape {} is already unknown!".format(a, shp))
shp[a] = None
x = tf.placeholder_with_default(x, shape=shp, name=name)
return x
def get_distributions(vec_cat, vec_uniform): def get_distributions(vec_cat, vec_uniform):
cat = tf.distributions.Categorical(logits=vec_cat, validate_args=True, name='cat') cat = tf.distributions.Categorical(logits=vec_cat, validate_args=True, name='cat')
uni = tf.distributions.Normal(vec_uniform, scale=1., validate_args=True, allow_nan_stats=False, name='uni_a') uni = tf.distributions.Normal(vec_uniform, scale=1., validate_args=True, allow_nan_stats=False, name='uni_a')
...@@ -115,8 +143,8 @@ class Model(GANModelDesc): ...@@ -115,8 +143,8 @@ class Model(GANModelDesc):
real_sample = tf.expand_dims(real_sample, -1) real_sample = tf.expand_dims(real_sample, -1)
# sample the latent code: # sample the latent code:
zc = symbf.shapeless_placeholder(sample_prior(BATCH), 0, name='z_code') zc = shapeless_placeholder(sample_prior(BATCH), 0, name='z_code')
z_noise = symbf.shapeless_placeholder( z_noise = shapeless_placeholder(
tf.random_uniform([BATCH, NOISE_DIM], -1, 1), 0, name='z_noise') tf.random_uniform([BATCH, NOISE_DIM], -1, 1), 0, name='z_noise')
z = tf.concat([zc, z_noise], 1, name='z') z = tf.concat([zc, z_noise], 1, name='z')
......
...@@ -17,6 +17,7 @@ from tensorpack.predict import PredictConfig, SimpleDatasetPredictor ...@@ -17,6 +17,7 @@ from tensorpack.predict import PredictConfig, SimpleDatasetPredictor
from tensorpack.utils.stats import RatioCounter from tensorpack.utils.stats import RatioCounter
from tensorpack.models import regularize_cost from tensorpack.models import regularize_cost
from tensorpack.tfutils.summary import add_moving_summary from tensorpack.tfutils.summary import add_moving_summary
from tensorpack.utils import logger
class GoogleNetResize(imgaug.ImageAugmentor): class GoogleNetResize(imgaug.ImageAugmentor):
...@@ -97,6 +98,8 @@ def get_imagenet_dataflow( ...@@ -97,6 +98,8 @@ def get_imagenet_dataflow(
if isTrain: if isTrain:
ds = dataset.ILSVRC12(datadir, name, shuffle=True) ds = dataset.ILSVRC12(datadir, name, shuffle=True)
ds = AugmentImageComponent(ds, augmentors, copy=False) ds = AugmentImageComponent(ds, augmentors, copy=False)
if parallel < 16:
logger.warn("DataFlow may become the bottleneck when too few processes are used.")
ds = PrefetchDataZMQ(ds, parallel) ds = PrefetchDataZMQ(ds, parallel)
ds = BatchData(ds, batch_size, remainder=False) ds = BatchData(ds, batch_size, remainder=False)
else: else:
......
...@@ -38,6 +38,21 @@ def guided_relu(): ...@@ -38,6 +38,21 @@ def guided_relu():
yield yield
def saliency_map(output, input, name="saliency_map"):
"""
Produce a saliency map as described in the paper:
`Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps
<https://arxiv.org/abs/1312.6034>`_.
The saliency map is the gradient of the max element in output w.r.t input.
Returns:
tf.Tensor: the saliency map. Has the same shape as input.
"""
max_outp = tf.reduce_max(output, 1)
saliency_op = tf.gradients(max_outp, input)[:][0]
return tf.identity(saliency_op, name=name)
class Model(tp.ModelDesc): class Model(tp.ModelDesc):
def _get_inputs(self): def _get_inputs(self):
return [tp.InputDesc(tf.float32, (IMAGE_SIZE, IMAGE_SIZE, 3), 'image')] return [tp.InputDesc(tf.float32, (IMAGE_SIZE, IMAGE_SIZE, 3), 'image')]
...@@ -49,7 +64,7 @@ class Model(tp.ModelDesc): ...@@ -49,7 +64,7 @@ class Model(tp.ModelDesc):
with slim.arg_scope(resnet_v1.resnet_arg_scope(is_training=False)): with slim.arg_scope(resnet_v1.resnet_arg_scope(is_training=False)):
image = tf.expand_dims(orig_image - mean, 0) image = tf.expand_dims(orig_image - mean, 0)
logits, _ = resnet_v1.resnet_v1_50(image, 1000) logits, _ = resnet_v1.resnet_v1_50(image, 1000)
tp.symbolic_functions.saliency_map(logits, orig_image, name="saliency") saliency_map(logits, orig_image, name="saliency")
def run(model_path, image_path): def run(model_path, image_path):
......
...@@ -84,6 +84,7 @@ class BatchData(ProxyDataFlow): ...@@ -84,6 +84,7 @@ class BatchData(ProxyDataFlow):
enough to form a batch, whether or not to also produce the remaining enough to form a batch, whether or not to also produce the remaining
data as a smaller batch. data as a smaller batch.
If set to False, all produced datapoints are guranteed to have the same batch size. If set to False, all produced datapoints are guranteed to have the same batch size.
If set to True, `ds.size()` must be accurate.
use_list (bool): if True, each component will contain a list use_list (bool): if True, each component will contain a list
of datapoints instead of an numpy array of an extra dimension. of datapoints instead of an numpy array of an extra dimension.
""" """
......
...@@ -171,6 +171,7 @@ def get_scalar_var(name, init_value, summary=False, trainable=False): ...@@ -171,6 +171,7 @@ def get_scalar_var(name, init_value, summary=False, trainable=False):
return ret return ret
@deprecated("Please implement it by yourself.", "2018-04-28")
def psnr(prediction, ground_truth, maxp=None, name='psnr'): def psnr(prediction, ground_truth, maxp=None, name='psnr'):
"""`Peek Signal to Noise Ratio <https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio>`_. """`Peek Signal to Noise Ratio <https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio>`_.
...@@ -228,6 +229,7 @@ def guided_relu(): ...@@ -228,6 +229,7 @@ def guided_relu():
yield yield
@deprecated("Please implement it by yourself.", "2018-04-28")
def saliency_map(output, input, name="saliency_map"): def saliency_map(output, input, name="saliency_map"):
""" """
Produce a saliency map as described in the paper: Produce a saliency map as described in the paper:
...@@ -244,6 +246,7 @@ def saliency_map(output, input, name="saliency_map"): ...@@ -244,6 +246,7 @@ def saliency_map(output, input, name="saliency_map"):
return saliency_op return saliency_op
@deprecated("Please implement it by yourself.", "2018-04-28")
def shapeless_placeholder(x, axis, name): def shapeless_placeholder(x, axis, name):
""" """
Make the static shape of a tensor less specific. Make the static shape of a tensor less specific.
......
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