commit
67993f9674
@ -77,7 +77,7 @@ filegroup(
|
||||
"//tensorflow/contrib/ctc:all_files",
|
||||
"//tensorflow/contrib/distributions:all_files",
|
||||
"//tensorflow/contrib/ffmpeg:all_files",
|
||||
"//tensorflow/contrib/ffmpeg/kernels:all_files",
|
||||
"//tensorflow/contrib/ffmpeg/default:all_files",
|
||||
"//tensorflow/contrib/framework:all_files",
|
||||
"//tensorflow/contrib/layers:all_files",
|
||||
"//tensorflow/contrib/layers/kernels:all_files",
|
||||
|
@ -80,6 +80,49 @@ class ExponentialTest(tf.test.TestCase):
|
||||
self.assertEqual(exponential.entropy().get_shape(), (3,))
|
||||
self.assertAllClose(exponential.entropy().eval(), expected_entropy)
|
||||
|
||||
def testExponentialSample(self):
|
||||
with self.test_session():
|
||||
lam = tf.constant([3.0, 4.0])
|
||||
lam_v = [3.0, 4.0]
|
||||
n = tf.constant(100000)
|
||||
exponential = tf.contrib.distributions.Exponential(lam=lam)
|
||||
|
||||
samples = exponential.sample(n, seed=137)
|
||||
sample_values = samples.eval()
|
||||
self.assertEqual(sample_values.shape, (100000, 2))
|
||||
self.assertFalse(np.any(sample_values < 0.0))
|
||||
for i in range(2):
|
||||
self.assertLess(
|
||||
stats.kstest(
|
||||
sample_values[:, i], stats.expon(scale=1.0/lam_v[i]).cdf)[0],
|
||||
0.01)
|
||||
|
||||
def testExponentialSampleMultiDimensional(self):
|
||||
with self.test_session():
|
||||
batch_size = 2
|
||||
lam_v = [3.0, 22.0]
|
||||
lam = tf.constant([lam_v] * batch_size)
|
||||
|
||||
exponential = tf.contrib.distributions.Exponential(lam=lam)
|
||||
|
||||
n_v = 100000
|
||||
n = tf.constant(n_v)
|
||||
samples = exponential.sample(n, seed=138)
|
||||
self.assertEqual(samples.get_shape(), (n_v, batch_size, 2))
|
||||
|
||||
sample_values = samples.eval()
|
||||
|
||||
self.assertFalse(np.any(sample_values < 0.0))
|
||||
for i in range(2):
|
||||
self.assertLess(
|
||||
stats.kstest(
|
||||
sample_values[:, 0, i], stats.expon(scale=1.0/lam_v[i]).cdf)[0],
|
||||
0.01)
|
||||
self.assertLess(
|
||||
stats.kstest(
|
||||
sample_values[:, 1, i], stats.expon(scale=1.0/lam_v[i]).cdf)[0],
|
||||
0.01)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tf.test.main()
|
||||
|
@ -200,15 +200,26 @@ class ContinuousDistribution(BaseDistribution):
|
||||
"""Base class for continuous probability distributions.
|
||||
|
||||
`ContinuousDistribution` defines the API for the likelihood functions `pdf`
|
||||
and `log_pdf` of continuous probability distributions.
|
||||
and `log_pdf` of continuous probability distributions, and a property
|
||||
`is_reparameterized` (returning `True` or `False`) which describes
|
||||
whether the samples of this distribution are calculated in a differentiable
|
||||
way from a non-parameterized distribution. For example, the `Normal`
|
||||
distribution with parameters `mu` and `sigma` is reparameterized as
|
||||
|
||||
Subclasses must override both `pdf` and `log_pdf` but one can call this base
|
||||
class's implementation.
|
||||
```Normal(mu, sigma) = sigma * Normal(0, 1) + mu```
|
||||
|
||||
Subclasses must override `pdf` and `log_pdf` but one can call this base
|
||||
class's implementation. They must also override the `is_reparameterized`
|
||||
property.
|
||||
|
||||
See `BaseDistribution` for more information on the API for probability
|
||||
distributions.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def is_reparameterized(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def pdf(self, value, name="pdf"):
|
||||
"""Probability density function."""
|
||||
|
@ -20,7 +20,11 @@ from __future__ import print_function
|
||||
|
||||
from tensorflow.contrib.distributions.python.ops import gamma
|
||||
from tensorflow.python.framework import ops
|
||||
from tensorflow.python.framework import tensor_shape
|
||||
from tensorflow.python.framework import tensor_util
|
||||
from tensorflow.python.ops import array_ops
|
||||
from tensorflow.python.ops import math_ops
|
||||
from tensorflow.python.ops import random_ops
|
||||
|
||||
|
||||
class Exponential(gamma.Gamma):
|
||||
@ -45,3 +49,35 @@ class Exponential(gamma.Gamma):
|
||||
@property
|
||||
def lam(self):
|
||||
return self._lam
|
||||
|
||||
@property
|
||||
def is_reparameterized(self):
|
||||
# While the Gamma distribution is not reparameterizeable, the
|
||||
# exponential distribution is.
|
||||
return True
|
||||
|
||||
def sample(self, n, seed=None, name=None):
|
||||
"""Sample `n` observations from the Exponential Distributions.
|
||||
|
||||
Args:
|
||||
n: `Scalar`, type int32, the number of observations to sample.
|
||||
seed: Python integer, the random seed.
|
||||
name: The name to give this op.
|
||||
|
||||
Returns:
|
||||
samples: `[n, ...]`, a `Tensor` of `n` samples for each
|
||||
of the distributions determined by the hyperparameters.
|
||||
"""
|
||||
broadcast_shape = self._lam.get_shape()
|
||||
with ops.op_scope([self.lam, n], name, "ExponentialSample"):
|
||||
shape = array_ops.concat(
|
||||
0, [array_ops.pack([n]), array_ops.shape(self._lam)])
|
||||
sampled = random_ops.random_uniform(
|
||||
shape, maxval=math_ops.cast(1.0, dtype=self.dtype),
|
||||
dtype=self.dtype)
|
||||
|
||||
n_val = tensor_util.constant_value(n)
|
||||
final_shape = tensor_shape.vector(n_val).concatenate(broadcast_shape)
|
||||
sampled.set_shape(final_shape)
|
||||
|
||||
return -math_ops.log(sampled) / self._lam
|
||||
|
@ -206,3 +206,7 @@ class Gamma(ContinuousDistribution):
|
||||
beta = self._beta
|
||||
return (alpha - math_ops.log(beta) + math_ops.lgamma(alpha) +
|
||||
(1 - alpha) * math_ops.digamma(alpha))
|
||||
|
||||
@property
|
||||
def is_reparameterized(self):
|
||||
return False
|
||||
|
@ -229,3 +229,7 @@ class Gaussian(object):
|
||||
sampled.set_shape(final_shape)
|
||||
|
||||
return sampled * self._sigma + self._mu
|
||||
|
||||
@property
|
||||
def is_reparameterized(self):
|
||||
return True
|
||||
|
@ -454,3 +454,7 @@ class MultivariateNormal(object):
|
||||
samples.set_shape(final_shape)
|
||||
|
||||
return samples
|
||||
|
||||
@property
|
||||
def is_reparameterized(self):
|
||||
return True
|
||||
|
@ -277,6 +277,10 @@ class StudentT(ContinuousDistribution):
|
||||
|
||||
return samples * self._sigma + self._mu
|
||||
|
||||
@property
|
||||
def is_reparameterized(self):
|
||||
return True
|
||||
|
||||
def _ones(self):
|
||||
return array_ops.ones_like(self._df + self._mu + self._sigma)
|
||||
|
||||
|
@ -231,6 +231,10 @@ class Uniform(ContinuousDistribution):
|
||||
"""`b - a`."""
|
||||
return self.b - self.a
|
||||
|
||||
@property
|
||||
def is_reparameterized(self):
|
||||
return True
|
||||
|
||||
# TODO(rsepassi): Find a more efficient way of doing the broadcasting in_ones
|
||||
# and _zeros.
|
||||
def _ones(self):
|
||||
|
@ -24,7 +24,7 @@ cc_library(
|
||||
linkstatic = 1,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//tensorflow/contrib/ffmpeg/kernels:ffmpeg_lib",
|
||||
"//tensorflow/contrib/ffmpeg/default:ffmpeg_lib",
|
||||
"//tensorflow/core:framework_headers_lib",
|
||||
"//third_party/eigen3",
|
||||
],
|
||||
@ -38,7 +38,7 @@ cc_library(
|
||||
linkstatic = 1,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//tensorflow/contrib/ffmpeg/kernels:ffmpeg_lib",
|
||||
"//tensorflow/contrib/ffmpeg/default:ffmpeg_lib",
|
||||
"//tensorflow/core:framework_headers_lib",
|
||||
"//third_party/eigen3",
|
||||
],
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <cstdio>
|
||||
#include <set>
|
||||
|
||||
#include "tensorflow/contrib/ffmpeg/kernels/ffmpeg_lib.h"
|
||||
#include "tensorflow/contrib/ffmpeg/default/ffmpeg_lib.h"
|
||||
#include "tensorflow/core/framework/op.h"
|
||||
#include "tensorflow/core/framework/op_kernel.h"
|
||||
#include "tensorflow/core/lib/io/path.h"
|
||||
|
@ -25,7 +25,6 @@ cc_test(
|
||||
"--should_ffmpeg_be_installed=true",
|
||||
],
|
||||
data = [
|
||||
":testdata/test_sound1.mp3",
|
||||
"//tensorflow/contrib/ffmpeg:test_data",
|
||||
],
|
||||
tags = [
|
||||
@ -46,9 +45,6 @@ cc_test(
|
||||
args = [
|
||||
"--should_ffmpeg_be_installed=false",
|
||||
],
|
||||
data = [
|
||||
":testdata/test_sound1.mp3",
|
||||
],
|
||||
tags = [
|
||||
"local",
|
||||
"manual",
|
@ -13,15 +13,13 @@
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
#include "tensorflow/contrib/ffmpeg/kernels/ffmpeg_lib.h"
|
||||
#include "tensorflow/contrib/ffmpeg/default/ffmpeg_lib.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <tuple>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <vector>
|
@ -13,8 +13,8 @@
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
#ifndef THIRD_PARTY_TENSORFLOW_CONTRIB_FFMPEG_KERNELS_FFMPEG_LIB_H_
|
||||
#define THIRD_PARTY_TENSORFLOW_CONTRIB_FFMPEG_KERNELS_FFMPEG_LIB_H_
|
||||
#ifndef THIRD_PARTY_TENSORFLOW_CONTRIB_FFMPEG_DEFAULT_FFMPEG_LIB_H_
|
||||
#define THIRD_PARTY_TENSORFLOW_CONTRIB_FFMPEG_DEFAULT_FFMPEG_LIB_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -47,4 +47,4 @@ Status CreateAudioFile(const string& audio_format_id, int32 samples_per_second,
|
||||
} // namespace ffmpeg
|
||||
} // namespace tensorflow
|
||||
|
||||
#endif // THIRD_PARTY_TENSORFLOW_CONTRIB_FFMPEG_KERNELS_FFMPEG_LIB_H_
|
||||
#endif // THIRD_PARTY_TENSORFLOW_CONTRIB_FFMPEG_DEFAULT_FFMPEG_LIB_H_
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
#include "tensorflow/contrib/ffmpeg/kernels/ffmpeg_lib.h"
|
||||
#include "tensorflow/contrib/ffmpeg/default/ffmpeg_lib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
@ -35,7 +35,7 @@ namespace {
|
||||
const char kTestWavFilename[] =
|
||||
"contrib/ffmpeg/testdata/mono_10khz.wav";
|
||||
const char kTestMp3Filename[] =
|
||||
"contrib/ffmpeg/kernels/testdata/test_sound1.mp3";
|
||||
"contrib/ffmpeg/testdata/test_sound1.mp3";
|
||||
|
||||
// Set to true via a command line flag iff the test is expected to have FFmpeg
|
||||
// installed.
|
@ -15,7 +15,7 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "tensorflow/contrib/ffmpeg/kernels/ffmpeg_lib.h"
|
||||
#include "tensorflow/contrib/ffmpeg/default/ffmpeg_lib.h"
|
||||
#include "tensorflow/core/framework/op.h"
|
||||
#include "tensorflow/core/framework/op_kernel.h"
|
||||
|
||||
|
@ -117,8 +117,9 @@ def summarize_tensor(tensor, tag=None):
|
||||
Returns:
|
||||
The summary op created or None for string tensors.
|
||||
"""
|
||||
# Skips string tensors.
|
||||
if tensor.dtype.is_compatible_with(dtypes.string):
|
||||
# Skips string tensors and boolean tensors (not handled by the summaries).
|
||||
if (tensor.dtype.is_compatible_with(dtypes.string) or
|
||||
tensor.dtype.base_dtype == dtypes.bool):
|
||||
return None
|
||||
|
||||
if tensor.get_shape().ndims == 0:
|
||||
|
@ -61,6 +61,20 @@ py_test(
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "test_feeding_queue_runner",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"python/learn/tests/dataframe/test_feeding_queue_runner.py",
|
||||
],
|
||||
srcs_version = "PY2AND3",
|
||||
deps = [
|
||||
":learn",
|
||||
"//tensorflow:tensorflow_py",
|
||||
"//tensorflow/python:framework_test_lib",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "test_early_stopping",
|
||||
size = "medium",
|
||||
@ -108,6 +122,42 @@ py_test(
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "dnn_linear_combined_test",
|
||||
size = "small",
|
||||
srcs = ["python/learn/estimators/dnn_linear_combined_test.py"],
|
||||
srcs_version = "PY2AND3",
|
||||
deps = [
|
||||
":learn",
|
||||
"//tensorflow:tensorflow_py",
|
||||
"//tensorflow/python:framework_test_lib",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "dnn_test",
|
||||
size = "small",
|
||||
srcs = ["python/learn/estimators/dnn_test.py"],
|
||||
srcs_version = "PY2AND3",
|
||||
deps = [
|
||||
":learn",
|
||||
"//tensorflow:tensorflow_py",
|
||||
"//tensorflow/python:framework_test_lib",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "linear_test",
|
||||
size = "small",
|
||||
srcs = ["python/learn/estimators/linear_test.py"],
|
||||
srcs_version = "PY2AND3",
|
||||
deps = [
|
||||
":learn",
|
||||
"//tensorflow:tensorflow_py",
|
||||
"//tensorflow/python:framework_test_lib",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "test_grid_search",
|
||||
size = "small",
|
||||
|
@ -20,6 +20,9 @@ from __future__ import print_function
|
||||
import numpy as np
|
||||
|
||||
from tensorflow.contrib.learn.python.learn import datasets
|
||||
from tensorflow.contrib.learn.python.learn import estimators
|
||||
from tensorflow.contrib.learn.python.learn import graph_actions
|
||||
from tensorflow.contrib.learn.python.learn import io
|
||||
from tensorflow.contrib.learn.python.learn import models
|
||||
from tensorflow.contrib.learn.python.learn import monitors
|
||||
from tensorflow.contrib.learn.python.learn import ops
|
||||
|
@ -0,0 +1,144 @@
|
||||
# Copyright 2016 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
|
||||
"""Helper functions for enqueuing data from arrays and pandas `DataFrame`s."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
import tensorflow.contrib.learn.python.learn.dataframe.queues.feeding_queue_runner as fqr
|
||||
|
||||
# pylint: disable=g-import-not-at-top
|
||||
try:
|
||||
import pandas as pd
|
||||
HAS_PANDAS = True
|
||||
except ImportError:
|
||||
HAS_PANDAS = False
|
||||
|
||||
|
||||
class _ArrayFeedFn(object):
|
||||
"""Creates feed dictionaries from numpy arrays."""
|
||||
|
||||
def __init__(self, placeholders, array):
|
||||
if len(placeholders) != 2:
|
||||
raise ValueError("_array_feed_fn expects 2 placeholders; got {}.".format(
|
||||
len(placeholders)))
|
||||
self._placeholders = placeholders
|
||||
self._array = array
|
||||
self._reset()
|
||||
|
||||
def _reset(self):
|
||||
self._row_iterator = enumerate(self._array)
|
||||
|
||||
def __call__(self):
|
||||
try:
|
||||
index, row = next(self._row_iterator)
|
||||
except StopIteration:
|
||||
self._reset()
|
||||
index, row = next(self._row_iterator)
|
||||
return {self._placeholders[0]: index, self._placeholders[1]: row}
|
||||
|
||||
|
||||
class _PandasFeedFn(object):
|
||||
"""Creates feed dictionaries from pandas `DataFrames`."""
|
||||
|
||||
def __init__(self, placeholders, dataframe):
|
||||
if len(placeholders) != len(dataframe.columns) + 1:
|
||||
raise ValueError("Expected {} placeholders; got {}.".format(
|
||||
len(dataframe.columns), len(placeholders)))
|
||||
self._index_placeholder = placeholders[0]
|
||||
self._row_placeholders = placeholders[1:]
|
||||
self._dataframe = dataframe
|
||||
self._reset()
|
||||
|
||||
def _reset(self):
|
||||
self._row_iterator = self._dataframe.iterrows()
|
||||
|
||||
def __call__(self):
|
||||
try:
|
||||
index, row = next(self._row_iterator)
|
||||
except StopIteration:
|
||||
self._reset()
|
||||
index, row = next(self._row_iterator)
|
||||
feed_dict = dict(zip(self._row_placeholders, row))
|
||||
feed_dict[self._index_placeholder] = index
|
||||
return feed_dict
|
||||
|
||||
|
||||
def enqueue_data(data,
|
||||
capacity,
|
||||
shuffle=False,
|
||||
min_after_dequeue=None,
|
||||
seed=None):
|
||||
"""Creates a queue filled from a numpy array or pandas `DataFrame`.
|
||||
|
||||
Returns a queue filled with the rows of the given array or `DataFrame`. In
|
||||
the case of a pandas `DataFrame`, the first enqueued `Tensor` corresponds to
|
||||
the index of the `DataFrame`. For numpy arrays, the first enqueued `Tensor`
|
||||
contains the row number.
|
||||
|
||||
Args:
|
||||
data: a numpy `ndarray or` pandas `DataFrame` that will be read into the
|
||||
queue.
|
||||
capacity: the capacity of the queue.
|
||||
shuffle: whether or not to shuffle the rows of the array.
|
||||
min_after_dequeue: minimum number of elements that can remain in the queue
|
||||
after a dequeue operation. Only used when `shuffle` is true. If not set,
|
||||
defaults to `capacity` / 4.
|
||||
seed: used to seed RandomShuffleQueue. Only used when `shuffle` is True.
|
||||
|
||||
Returns:
|
||||
A queue filled with the rows of the given array or `DataFrame`.
|
||||
|
||||
Raises:
|
||||
TypeError: `data` is not a Pandas `DataFrame` or a numpy `ndarray`.
|
||||
"""
|
||||
# TODO(jamieas): create multithreaded version of enqueue_data.
|
||||
if isinstance(data, np.ndarray):
|
||||
dtypes = [tf.int64, tf.as_dtype(data.dtype)]
|
||||
shapes = [(), data.shape[1:]]
|
||||
get_feed_fn = _ArrayFeedFn
|
||||
elif HAS_PANDAS and isinstance(data, pd.DataFrame):
|
||||
dtypes = [tf.as_dtype(dt) for dt in [data.index.dtype] + list(data.dtypes)]
|
||||
shapes = [() for _ in dtypes]
|
||||
get_feed_fn = _PandasFeedFn
|
||||
else:
|
||||
raise TypeError(
|
||||
"data must be either a numpy array or pandas DataFrame if pandas is "
|
||||
"installed; got {}".format(
|
||||
type(data).__name__))
|
||||
|
||||
placeholders = [tf.placeholder(*type_and_shape)
|
||||
for type_and_shape in zip(dtypes, shapes)]
|
||||
if shuffle:
|
||||
min_after_dequeue = (capacity / 4 if min_after_dequeue is None else
|
||||
min_after_dequeue)
|
||||
queue = tf.RandomShuffleQueue(capacity,
|
||||
min_after_dequeue,
|
||||
dtypes=dtypes,
|
||||
shapes=shapes,
|
||||
seed=seed)
|
||||
else:
|
||||
queue = tf.FIFOQueue(capacity, dtypes=dtypes, shapes=shapes)
|
||||
enqueue_op = queue.enqueue(placeholders)
|
||||
feed_fn = get_feed_fn(placeholders, data)
|
||||
queue_runner = fqr.FeedingQueueRunner(queue=queue,
|
||||
enqueue_ops=[enqueue_op],
|
||||
feed_fn=feed_fn)
|
||||
tf.train.add_queue_runner(queue_runner)
|
||||
return queue
|
@ -0,0 +1,105 @@
|
||||
# Copyright 2016 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
|
||||
"""A `QueueRunner` that takes a feed function as an argument."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from tensorflow.python.framework import errors
|
||||
from tensorflow.python.platform import tf_logging as logging
|
||||
from tensorflow.python.training import queue_runner as qr
|
||||
|
||||
|
||||
class FeedingQueueRunner(qr.QueueRunner):
|
||||
"""A queue runner that allows the feeding of values such as numpy arrays."""
|
||||
|
||||
def __init__(self, queue=None, enqueue_ops=None, close_op=None,
|
||||
cancel_op=None, feed_fn=None):
|
||||
"""Initialize the queue runner.
|
||||
|
||||
For further documentation, see `queue_runner.py`. Note that
|
||||
`FeedingQueueRunner` does not support construction from protobuffer nor
|
||||
serialization to protobuffer.
|
||||
|
||||
Args:
|
||||
queue: A `Queue`.
|
||||
enqueue_ops: List of enqueue ops to run in threads later.
|
||||
close_op: Op to close the queue. Pending enqueue ops are preserved.
|
||||
cancel_op: Op to close the queue and cancel pending enqueue ops.
|
||||
feed_fn: a function that returns a dictionary mapping fed `Tensor`s to
|
||||
values.
|
||||
"""
|
||||
super(FeedingQueueRunner, self).__init__(queue, enqueue_ops, close_op,
|
||||
cancel_op)
|
||||
self._feed_fn = feed_fn
|
||||
|
||||
# pylint: disable=broad-except
|
||||
def _run(self, sess, enqueue_op, coord=None):
|
||||
"""Execute the enqueue op in a loop, close the queue in case of error.
|
||||
|
||||
Args:
|
||||
sess: A `Session`.
|
||||
enqueue_op: The `Operation` to run.
|
||||
coord: Optional `Coordinator` object for reporting errors and checking
|
||||
for stop conditions.
|
||||
|
||||
"""
|
||||
# TODO(jamieas): Reduce code duplication with `QueueRunner`.
|
||||
decremented = False
|
||||
try:
|
||||
while True:
|
||||
if coord and coord.should_stop():
|
||||
break
|
||||
try:
|
||||
feed_dict = None if self._feed_fn is None else self._feed_fn()
|
||||
sess.run(enqueue_op, feed_dict=feed_dict)
|
||||
except errors.OutOfRangeError:
|
||||
# This exception indicates that a queue was closed.
|
||||
with self._lock:
|
||||
self._runs -= 1
|
||||
decremented = True
|
||||
if self._runs == 0:
|
||||
try:
|
||||
sess.run(self._close_op)
|
||||
except Exception as e:
|
||||
# Intentionally ignore errors from close_op.
|
||||
logging.vlog(1, "Ignored exception: %s", str(e))
|
||||
return
|
||||
except Exception as e:
|
||||
# This catches all other exceptions.
|
||||
if coord:
|
||||
coord.request_stop(e)
|
||||
else:
|
||||
logging.error("Exception in QueueRunner: %s", str(e))
|
||||
with self._lock:
|
||||
self._exceptions_raised.append(e)
|
||||
raise
|
||||
finally:
|
||||
# Make sure we account for all terminations: normal or errors.
|
||||
if not decremented:
|
||||
with self._lock:
|
||||
self._runs -= 1
|
||||
|
||||
def _init_from_proto(self, queue_runner_def):
|
||||
raise NotImplementedError(
|
||||
"{} does not support initialization from proto.".format(type(
|
||||
self).__name__))
|
||||
|
||||
def to_proto(self):
|
||||
raise NotImplementedError(
|
||||
"{} does not support serialization to proto.".format(type(
|
||||
self).__name__))
|
@ -18,11 +18,17 @@ from __future__ import print_function
|
||||
|
||||
from tensorflow.contrib.learn.python.learn.estimators.autoencoder import TensorFlowDNNAutoencoder
|
||||
from tensorflow.contrib.learn.python.learn.estimators.base import TensorFlowEstimator, TensorFlowBaseTransformer
|
||||
from tensorflow.contrib.learn.python.learn.estimators.dnn import DNNClassifier
|
||||
from tensorflow.contrib.learn.python.learn.estimators.dnn import DNNRegressor
|
||||
from tensorflow.contrib.learn.python.learn.estimators.dnn import TensorFlowDNNClassifier
|
||||
from tensorflow.contrib.learn.python.learn.estimators.dnn import TensorFlowDNNRegressor
|
||||
from tensorflow.contrib.learn.python.learn.estimators.dnn_linear_combined import DNNLinearCombinedClassifier
|
||||
from tensorflow.contrib.learn.python.learn.estimators.dnn_linear_combined import DNNLinearCombinedRegressor
|
||||
from tensorflow.contrib.learn.python.learn.estimators.estimator import BaseEstimator
|
||||
from tensorflow.contrib.learn.python.learn.estimators.estimator import Estimator
|
||||
from tensorflow.contrib.learn.python.learn.estimators.estimator import ModeKeys
|
||||
from tensorflow.contrib.learn.python.learn.estimators.linear import LinearClassifier
|
||||
from tensorflow.contrib.learn.python.learn.estimators.linear import LinearRegressor
|
||||
from tensorflow.contrib.learn.python.learn.estimators.linear import TensorFlowClassifier
|
||||
from tensorflow.contrib.learn.python.learn.estimators.linear import TensorFlowLinearClassifier
|
||||
from tensorflow.contrib.learn.python.learn.estimators.linear import TensorFlowLinearRegressor
|
||||
|
@ -45,12 +45,13 @@ from tensorflow.python.ops import variable_scope as vs
|
||||
from tensorflow.python.training import training as train
|
||||
|
||||
from tensorflow.contrib.layers import optimizers
|
||||
from tensorflow.contrib.learn.python.learn import trainer
|
||||
from tensorflow.contrib.learn.python.learn.io.data_feeder import setup_train_data_feeder
|
||||
from tensorflow.contrib.learn.python.learn.io.data_feeder import setup_predict_data_feeder
|
||||
from tensorflow.contrib.learn.python.learn.ops.dropout_ops import DROPOUTS
|
||||
from tensorflow.contrib.learn.python.learn import monitors
|
||||
from tensorflow.contrib.learn.python.learn import monitors as monitors_lib
|
||||
from tensorflow.contrib.learn.python.learn.utils import checkpoints
|
||||
|
||||
from tensorflow.contrib.learn.python.learn.estimators import estimator
|
||||
from tensorflow.contrib.learn.python.learn.estimators import _sklearn
|
||||
from tensorflow.contrib.learn.python.learn.estimators._sklearn import NotFittedError
|
||||
from tensorflow.contrib.learn.python.learn.estimators.run_config import RunConfig
|
||||
@ -63,7 +64,35 @@ def _write_with_backup(filename, content):
|
||||
f.write(content)
|
||||
|
||||
|
||||
class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
def _copy_dir(dir_in, dir_out):
|
||||
gfile.MakeDirs(dir_out)
|
||||
for name in gfile.ListDirectory(dir_in):
|
||||
name_in = os.path.join(dir_in, name)
|
||||
name_out = os.path.join(dir_out, name)
|
||||
if gfile.IsDirectory(name_in):
|
||||
gfile.MakeDirs(name_out)
|
||||
_copy_dir(name_in, name_out)
|
||||
else:
|
||||
gfile.Copy(name_in, name_out, overwrite=True)
|
||||
|
||||
|
||||
def _new_tf_model_fn(model_fn, class_weight):
|
||||
"""Backward compatibility way of adding class weight and IS_TRAINING.
|
||||
|
||||
TODO(ipolosukhin): Remove this function after new layers are available.
|
||||
Specifically:
|
||||
* dropout and batch norm should work via update ops.
|
||||
* class weights should be retrieved from weights column or hparams.
|
||||
"""
|
||||
def _model_fn(features, targets, mode):
|
||||
ops.get_default_graph().add_to_collection('IS_TRAINING', mode == 'train')
|
||||
if class_weight is not None:
|
||||
constant_op.constant(class_weight, name='class_weight')
|
||||
return model_fn(features, targets)
|
||||
return _model_fn
|
||||
|
||||
|
||||
class TensorFlowEstimator(estimator.Estimator):
|
||||
"""Base class for all TensorFlow estimators.
|
||||
|
||||
Parameters:
|
||||
@ -109,101 +138,21 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
continue_training=False,
|
||||
config=None,
|
||||
verbose=1):
|
||||
self.model_fn = model_fn
|
||||
super(TensorFlowEstimator, self).__init__(
|
||||
model_fn=_new_tf_model_fn(model_fn, class_weight),
|
||||
classification=n_classes > 1,
|
||||
learning_rate=learning_rate,
|
||||
optimizer=optimizer,
|
||||
clip_gradients=clip_gradients,
|
||||
config=config)
|
||||
self.n_classes = n_classes
|
||||
self.batch_size = batch_size
|
||||
self.steps = steps
|
||||
self.verbose = verbose
|
||||
self.optimizer = optimizer
|
||||
self.learning_rate = learning_rate
|
||||
self.clip_gradients = clip_gradients
|
||||
self.continue_training = continue_training
|
||||
self._initialized = False
|
||||
self.class_weight = class_weight
|
||||
self._config = config
|
||||
self._data_feeder = None
|
||||
|
||||
def _setup_training(self):
|
||||
"""Sets up graph, model and trainer."""
|
||||
# Create config if not given.
|
||||
if self._config is None:
|
||||
self._config = RunConfig(verbose=self.verbose)
|
||||
# Create new graph.
|
||||
self._graph = ops.Graph()
|
||||
self._graph.add_to_collection('IS_TRAINING', True)
|
||||
with self._graph.as_default():
|
||||
random_seed.set_random_seed(self._config.tf_random_seed)
|
||||
self._global_step = variables.Variable(0,
|
||||
name='global_step',
|
||||
trainable=False)
|
||||
|
||||
# Setting up inputs and outputs.
|
||||
self._inp, self._out = self._data_feeder.input_builder()
|
||||
|
||||
# If class weights are provided, add them to the graph.
|
||||
# Different loss functions can use this tensor by name.
|
||||
if self.class_weight:
|
||||
self._class_weight_node = constant_op.constant(self.class_weight,
|
||||
name='class_weight')
|
||||
|
||||
# Add histograms for X and y if they are floats.
|
||||
if self._data_feeder.input_dtype in (np.float32, np.float64):
|
||||
logging_ops.histogram_summary('X', self._inp)
|
||||
if self._data_feeder.output_dtype in (np.float32, np.float64)\
|
||||
and self._out is not None:
|
||||
logging_ops.histogram_summary('y', self._out)
|
||||
|
||||
# Create model's graph.
|
||||
self._model_predictions, self._model_loss = self.model_fn(self._inp,
|
||||
self._out)
|
||||
|
||||
# Set up a single operator to merge all the summaries
|
||||
self._summaries = logging_ops.merge_all_summaries()
|
||||
|
||||
# Create trainer and augment graph with gradients and optimizer.
|
||||
# Additionally creates initialization ops.
|
||||
learning_rate = self.learning_rate
|
||||
optimizer = self.optimizer
|
||||
if callable(learning_rate):
|
||||
learning_rate = learning_rate(self._global_step)
|
||||
if callable(optimizer):
|
||||
optimizer = optimizer(learning_rate)
|
||||
self._train = optimizers.optimize_loss(self._model_loss,
|
||||
self._global_step,
|
||||
learning_rate=learning_rate,
|
||||
optimizer=optimizer,
|
||||
clip_gradients=self.clip_gradients)
|
||||
|
||||
# Update ops during training, e.g. batch_norm_ops
|
||||
self._train = control_flow_ops.group(self._train, *
|
||||
ops.get_collection('update_ops'))
|
||||
|
||||
# Get all initializers for all trainable variables.
|
||||
self._initializers = variables.initialize_all_variables()
|
||||
|
||||
# Create model's saver capturing all the nodes created up until now.
|
||||
self._saver = train.Saver(max_to_keep=self._config.keep_checkpoint_max,
|
||||
keep_checkpoint_every_n_hours=
|
||||
self._config.keep_checkpoint_every_n_hours)
|
||||
|
||||
# Enable monitor to create validation data dict with appropriate
|
||||
# tf placeholders
|
||||
self._monitor.create_val_feed_dict(self._inp, self._out)
|
||||
|
||||
# Create session to run model with.
|
||||
self._session = session.Session(self._config.master,
|
||||
config=self._config.tf_config)
|
||||
|
||||
# Run parameter initializers.
|
||||
self._session.run(self._initializers)
|
||||
|
||||
def _setup_summary_writer(self, logdir):
|
||||
"""Sets up summary writer to prepare for later optional visualization."""
|
||||
self._summary_writer = train.SummaryWriter(
|
||||
os.path.join(logdir,
|
||||
datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')),
|
||||
graph=self._session.graph)
|
||||
|
||||
def fit(self, X, y, monitor=None, logdir=None):
|
||||
def fit(self, x, y, steps=None, monitors=None, logdir=None):
|
||||
"""Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
|
||||
@ -214,63 +163,44 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
To restart learning, create new estimator.
|
||||
|
||||
Args:
|
||||
X: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
x: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
y: vector or matrix [n_samples] or [n_samples, n_outputs]. Can be
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
monitor: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
steps: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
monitors: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
logdir: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
Returns:
|
||||
Returns self.
|
||||
"""
|
||||
# Sets up data feeder.
|
||||
self._data_feeder = setup_train_data_feeder(X, y, self.n_classes,
|
||||
self.batch_size)
|
||||
|
||||
if monitor is None:
|
||||
self._monitor = monitors.default_monitor(verbose=self.verbose)
|
||||
else:
|
||||
self._monitor = monitor
|
||||
|
||||
if not self.continue_training or not self._initialized:
|
||||
# Sets up model and trainer.
|
||||
self._setup_training()
|
||||
self._initialized = True
|
||||
else:
|
||||
self._data_feeder.set_placeholders(self._inp, self._out)
|
||||
|
||||
# Sets up summary writer for later optional visualization.
|
||||
# Due to not able to setup _summary_writer in __init__ as it's not a
|
||||
# parameter of the model, here we need to check if such variable exists
|
||||
# and if it's None or not (in case it was setup in a previous run).
|
||||
# It is initialized only in the case where it wasn't before and log dir
|
||||
# is provided.
|
||||
if logdir:
|
||||
if (not hasattr(self, '_summary_writer') or
|
||||
(hasattr(self, '_summary_writer') and self._summary_writer is None)):
|
||||
self._setup_summary_writer(logdir)
|
||||
else:
|
||||
self._summary_writer = None
|
||||
|
||||
# Train model for given number of steps.
|
||||
trainer.train(self._session,
|
||||
self._train,
|
||||
self._model_loss,
|
||||
self._global_step,
|
||||
self._data_feeder.get_feed_dict_fn(),
|
||||
steps=self.steps,
|
||||
monitor=self._monitor,
|
||||
summary_writer=self._summary_writer,
|
||||
summaries=self._summaries,
|
||||
feed_params_fn=self._data_feeder.get_feed_params)
|
||||
if logdir is not None:
|
||||
self._model_dir = logdir
|
||||
self._data_feeder = setup_train_data_feeder(
|
||||
x, y, n_classes=self.n_classes, batch_size=self.batch_size)
|
||||
self._train_model(input_fn=self._data_feeder.input_builder,
|
||||
feed_fn=self._data_feeder.get_feed_dict_fn(),
|
||||
steps=steps or self.steps,
|
||||
monitors=monitors)
|
||||
return self
|
||||
|
||||
def partial_fit(self, X, y):
|
||||
def evaluate(self, x=None, y=None, input_fn=None, steps=None):
|
||||
"""See base class."""
|
||||
feed_fn = None
|
||||
if x is not None:
|
||||
eval_data_feeder = setup_train_data_feeder(
|
||||
x, y, n_classes=self.n_classes, batch_size=self.batch_size, epochs=1)
|
||||
input_fn, feed_fn = (eval_data_feeder.input_builder,
|
||||
eval_data_feeder.get_feed_dict_fn())
|
||||
return self._evaluate_model(
|
||||
input_fn=input_fn, feed_fn=feed_fn, steps=steps or self.steps)
|
||||
|
||||
def partial_fit(self, x, y):
|
||||
"""Incremental fit on a batch of samples.
|
||||
|
||||
This method is expected to be called several times consecutively
|
||||
@ -282,7 +212,7 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
to converge, and you want to split up training into subparts.
|
||||
|
||||
Args:
|
||||
X: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
x: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
y: vector or matrix [n_samples] or [n_samples, n_outputs]. Can be
|
||||
@ -292,33 +222,30 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
Returns:
|
||||
Returns self.
|
||||
"""
|
||||
return self.fit(X, y)
|
||||
|
||||
def _predict(self, X, axis=-1, batch_size=None):
|
||||
if not self._initialized:
|
||||
raise _sklearn.NotFittedError()
|
||||
return self.fit(x, y)
|
||||
|
||||
def _predict(self, x, axis=-1, batch_size=None):
|
||||
if self._graph is None:
|
||||
raise NotFittedError()
|
||||
# Use the batch size for fitting if the user did not specify one.
|
||||
if batch_size is None:
|
||||
batch_size = self.batch_size
|
||||
|
||||
self._graph.add_to_collection('IS_TRAINING', False)
|
||||
predict_data_feeder = setup_predict_data_feeder(X, batch_size=batch_size)
|
||||
preds = []
|
||||
dropouts = self._graph.get_collection(DROPOUTS)
|
||||
feed_dict = {prob: 1.0 for prob in dropouts}
|
||||
for data in predict_data_feeder:
|
||||
feed_dict[self._inp] = data
|
||||
predictions_for_batch = self._session.run(self._model_predictions,
|
||||
feed_dict)
|
||||
if self.n_classes > 1 and axis != -1:
|
||||
preds.append(predictions_for_batch.argmax(axis=axis))
|
||||
else:
|
||||
preds.append(predictions_for_batch)
|
||||
predict_data_feeder = setup_train_data_feeder(
|
||||
x, None, n_classes=None,
|
||||
batch_size=batch_size,
|
||||
shuffle=False, epochs=1)
|
||||
|
||||
return np.concatenate(preds, axis=0)
|
||||
preds = self._infer_model(
|
||||
input_fn=predict_data_feeder.input_builder,
|
||||
feed_fn=predict_data_feeder.get_feed_dict_fn())
|
||||
if self.n_classes > 1 and axis != -1:
|
||||
preds = preds['predictions'].argmax(axis=axis)
|
||||
else:
|
||||
preds = preds['predictions']
|
||||
return preds
|
||||
|
||||
def predict(self, X, axis=1, batch_size=None):
|
||||
def predict(self, x, axis=1, batch_size=None):
|
||||
"""Predict class or regression for X.
|
||||
|
||||
For a classification model, the predicted class for each sample in X is
|
||||
@ -326,7 +253,7 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
returned.
|
||||
|
||||
Args:
|
||||
X: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
x: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
axis: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -338,13 +265,13 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
y: array of shape [n_samples]. The predicted classes or predicted
|
||||
value.
|
||||
"""
|
||||
return self._predict(X, axis=axis, batch_size=batch_size)
|
||||
return self._predict(x, axis=axis, batch_size=batch_size)
|
||||
|
||||
def predict_proba(self, X, batch_size=None):
|
||||
def predict_proba(self, x, batch_size=None):
|
||||
"""Predict class probability of the input samples X.
|
||||
|
||||
Args:
|
||||
X: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
x: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
batch_size: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -352,7 +279,7 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
y: array of shape [n_samples, n_classes]. The predicted
|
||||
probabilities for each class.
|
||||
"""
|
||||
return self._predict(X, batch_size=batch_size)
|
||||
return self._predict(x, batch_size=batch_size)
|
||||
|
||||
def get_tensor(self, name):
|
||||
"""Returns tensor by name.
|
||||
@ -374,7 +301,9 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
Returns:
|
||||
Numpy array - value of the tensor.
|
||||
"""
|
||||
return self._session.run(self.get_tensor(name))
|
||||
if name.endswith(':0'):
|
||||
name = name[:-2]
|
||||
return checkpoints.load_variable(self.model_dir, name)
|
||||
|
||||
def get_variable_names(self):
|
||||
"""Returns list of all variable names in this model.
|
||||
@ -382,8 +311,7 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
Returns:
|
||||
List of names.
|
||||
"""
|
||||
with self._graph.as_default():
|
||||
return [v.name for v in variables.all_variables()]
|
||||
return [name for name, _ in checkpoints.list_variables(self.model_dir)]
|
||||
|
||||
def save(self, path):
|
||||
"""Saves checkpoints and graph to given path.
|
||||
@ -391,17 +319,12 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
Args:
|
||||
path: Folder to save model to.
|
||||
"""
|
||||
if not self._initialized:
|
||||
raise _sklearn.NotFittedError()
|
||||
if self._graph is None:
|
||||
raise NotFittedError
|
||||
|
||||
# Currently Saver requires absolute path to work correctly.
|
||||
path = os.path.abspath(path)
|
||||
# Copy model dir into new path.
|
||||
_copy_dir(self.model_dir, path)
|
||||
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
if not os.path.isdir(path):
|
||||
raise ValueError('Path %s should be a directory to save'
|
||||
'checkpoints and graph.' % path)
|
||||
# Save model definition.
|
||||
all_params = self.get_params()
|
||||
params = {}
|
||||
@ -414,25 +337,6 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
default=lambda o: o.__dict__ if hasattr(o, '__dict__') else None)
|
||||
_write_with_backup(os.path.join(path, 'model.def'), model_def)
|
||||
|
||||
# Save checkpoints.
|
||||
endpoints = '%s\n%s\n%s\n%s' % (self._inp.name, self._out.name,
|
||||
self._model_predictions.name,
|
||||
self._model_loss.name)
|
||||
_write_with_backup(os.path.join(path, 'endpoints'), endpoints)
|
||||
|
||||
# Save graph definition.
|
||||
_write_with_backup(
|
||||
os.path.join(path, 'graph.pbtxt'), str(self._graph.as_graph_def()))
|
||||
|
||||
# Save saver definition.
|
||||
_write_with_backup(
|
||||
os.path.join(path, 'saver.pbtxt'), str(self._saver.as_saver_def()))
|
||||
|
||||
# Save checkpoints.
|
||||
self._saver.save(self._session,
|
||||
os.path.join(path, 'model'),
|
||||
global_step=self._global_step)
|
||||
|
||||
def _restore(self, path):
|
||||
"""Restores this estimator from given path.
|
||||
|
||||
@ -442,57 +346,7 @@ class TensorFlowEstimator(_sklearn.BaseEstimator):
|
||||
Args:
|
||||
path: Path to checkpoints and other information.
|
||||
"""
|
||||
# Currently Saver requires absolute path to work correctly.
|
||||
path = os.path.abspath(path)
|
||||
|
||||
self._graph = ops.Graph()
|
||||
with self._graph.as_default():
|
||||
endpoints_filename = os.path.join(path, 'endpoints')
|
||||
if not os.path.exists(endpoints_filename):
|
||||
raise ValueError("Restore folder doesn't contain endpoints.")
|
||||
with gfile.Open(endpoints_filename) as foutputs:
|
||||
endpoints = foutputs.read().split('\n')
|
||||
graph_filename = os.path.join(path, 'graph.pbtxt')
|
||||
if not os.path.exists(graph_filename):
|
||||
raise ValueError("Restore folder doesn't contain graph definition.")
|
||||
with gfile.Open(graph_filename) as fgraph:
|
||||
graph_def = graph_pb2.GraphDef()
|
||||
text_format.Merge(fgraph.read(), graph_def)
|
||||
(self._inp, self._out, self._model_predictions,
|
||||
self._model_loss) = importer.import_graph_def(
|
||||
graph_def, name='', return_elements=endpoints)
|
||||
saver_filename = os.path.join(path, 'saver.pbtxt')
|
||||
if not os.path.exists(saver_filename):
|
||||
raise ValueError("Restore folder doesn't contain saver definition.")
|
||||
with gfile.Open(saver_filename) as fsaver:
|
||||
saver_def = train.SaverDef()
|
||||
text_format.Merge(fsaver.read(), saver_def)
|
||||
self._saver = train.Saver(saver_def=saver_def)
|
||||
|
||||
# Restore trainer
|
||||
self._global_step = self._graph.get_tensor_by_name('global_step:0')
|
||||
self._train = self._graph.get_operation_by_name('OptimizeLoss/train')
|
||||
|
||||
# Restore summaries.
|
||||
self._summaries = self._graph.get_operation_by_name(
|
||||
'MergeSummary/MergeSummary')
|
||||
|
||||
# Restore session.
|
||||
if not isinstance(self._config, RunConfig):
|
||||
self._config = RunConfig(verbose=self.verbose)
|
||||
self._session = session.Session(self._config.master,
|
||||
config=self._config.tf_config)
|
||||
checkpoint_path = train.latest_checkpoint(path)
|
||||
if checkpoint_path is None:
|
||||
raise ValueError(
|
||||
'Missing checkpoint files in the %s. Please '
|
||||
'make sure you are you have checkpoint file that describes '
|
||||
'latest checkpoints and appropriate checkpoints are there. '
|
||||
'If you have moved the folder, you at this point need to '
|
||||
'update manually update the paths in the checkpoint file.' % path)
|
||||
self._saver.restore(self._session, checkpoint_path)
|
||||
# Set to be initialized.
|
||||
self._initialized = True
|
||||
raise NotImplementedError
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@classmethod
|
||||
@ -549,7 +403,7 @@ class TensorFlowBaseTransformer(TensorFlowEstimator, _sklearn.TransformerMixin):
|
||||
|
||||
def fit(self, X, y=None, monitor=None, logdir=None):
|
||||
"""Fit a transformer."""
|
||||
return(super(TensorFlowBaseTransformer, self).fit(X, y, monitor=None, logdir=None))
|
||||
return(super(TensorFlowBaseTransformer, self).fit(X, y, monitors=None, logdir=None))
|
||||
|
||||
def fit_transform(self, X, y=None, monitor=None, logdir=None):
|
||||
"""Fit transformer and transform X using trained transformer."""
|
||||
|
@ -16,11 +16,176 @@ from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from tensorflow.contrib.learn.python.learn.estimators import _sklearn
|
||||
from tensorflow.contrib.learn.python.learn.estimators.base import TensorFlowEstimator
|
||||
from tensorflow.contrib import layers
|
||||
from tensorflow.contrib.learn.python.learn import models
|
||||
from tensorflow.contrib.learn.python.learn.estimators import _sklearn
|
||||
from tensorflow.contrib.learn.python.learn.estimators import dnn_linear_combined
|
||||
from tensorflow.contrib.learn.python.learn.estimators.base import TensorFlowEstimator
|
||||
from tensorflow.python.ops import nn
|
||||
|
||||
|
||||
# TODO(ipolosukhin): Merge thirdparty DNN with this.
|
||||
class DNNClassifier(dnn_linear_combined.DNNLinearCombinedClassifier):
|
||||
"""A classifier for TensorFlow DNN models.
|
||||
|
||||
Example:
|
||||
```
|
||||
installed_app_id = sparse_column_with_hash_bucket("installed_id", 1e6)
|
||||
impression_app_id = sparse_column_with_hash_bucket("impression_id", 1e6)
|
||||
|
||||
installed_emb = embedding_column(installed_app_id, dimension=16,
|
||||
combiner="sum")
|
||||
impression_emb = embedding_column(impression_app_id, dimension=16,
|
||||
combiner="sum")
|
||||
|
||||
estimator = DNNClassifier(
|
||||
feature_columns=[installed_emb, impression_emb],
|
||||
hidden_units=[1024, 512, 256])
|
||||
|
||||
# Input builders
|
||||
def input_fn_train: # returns X, Y
|
||||
pass
|
||||
estimator.train(input_fn_train)
|
||||
|
||||
def input_fn_eval: # returns X, Y
|
||||
pass
|
||||
estimator.evaluate(input_fn_eval)
|
||||
estimator.predict(x)
|
||||
```
|
||||
|
||||
Input of `fit`, `train`, and `evaluate` should have following features,
|
||||
otherwise there will be a `KeyError`:
|
||||
if `weight_column_name` is not `None`, a feature with
|
||||
`key=weight_column_name` whose value is a `Tensor`.
|
||||
for each `column` in `feature_columns`:
|
||||
- if `column` is a `SparseColumn`, a feature with `key=column.name`
|
||||
whose `value` is a `SparseTensor`.
|
||||
- if `column` is a `RealValuedColumn, a feature with `key=column.name`
|
||||
whose `value` is a `Tensor`.
|
||||
- if `feauture_columns` is None, then `input` must contains only real
|
||||
valued `Tensor`.
|
||||
|
||||
Parameters:
|
||||
hidden_units: List of hidden units per layer. All layers are fully
|
||||
connected. Ex. [64, 32] means first layer has 64 nodes and second one has
|
||||
32.
|
||||
feature_columns: An iterable containing all the feature columns used by the
|
||||
model. All items in the set should be instances of classes derived from
|
||||
`FeatureColumn`.
|
||||
model_dir: Directory to save model parameters, graph and etc.
|
||||
n_classes: number of target classes. Default is binary classification.
|
||||
It must be greater than 1.
|
||||
weight_column_name: A string defining feature column name representing
|
||||
weights. It is used to down weight or boost examples during training. It
|
||||
will be multiplied by the loss of the example.
|
||||
optimizer: An instance of `tf.Optimizer` used to train the model. If `None`,
|
||||
will use an Adagrad optimizer.
|
||||
activation_fn: Activation function applied to each layer. If `None`, will
|
||||
use `tf.nn.relu`.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
hidden_units,
|
||||
feature_columns=None,
|
||||
model_dir=None,
|
||||
n_classes=2,
|
||||
weight_column_name=None,
|
||||
optimizer=None,
|
||||
activation_fn=nn.relu):
|
||||
super(DNNClassifier, self).__init__(n_classes=n_classes,
|
||||
weight_column_name=weight_column_name,
|
||||
dnn_feature_columns=feature_columns,
|
||||
dnn_optimizer=optimizer,
|
||||
dnn_hidden_units=hidden_units,
|
||||
dnn_activation_fn=activation_fn)
|
||||
|
||||
def _get_train_ops(self, features, targets):
|
||||
"""See base class."""
|
||||
if self._dnn_feature_columns is None:
|
||||
self._dnn_feature_columns = layers.infer_real_valued_columns(features)
|
||||
return super(DNNClassifier, self)._get_train_ops(features, targets)
|
||||
|
||||
|
||||
class DNNRegressor(dnn_linear_combined.DNNLinearCombinedRegressor):
|
||||
"""A regressor for TensorFlow DNN models.
|
||||
|
||||
Example:
|
||||
```
|
||||
installed_app_id = sparse_column_with_hash_bucket("installed_id", 1e6)
|
||||
impression_app_id = sparse_column_with_hash_bucket("impression_id", 1e6)
|
||||
|
||||
installed_emb = embedding_column(installed_app_id, dimension=16,
|
||||
combiner="sum")
|
||||
impression_emb = embedding_column(impression_app_id, dimension=16,
|
||||
combiner="sum")
|
||||
|
||||
estimator = DNNRegressor(
|
||||
feature_columns=[installed_emb, impression_emb],
|
||||
hidden_units=[1024, 512, 256])
|
||||
|
||||
# Input builders
|
||||
def input_fn_train: # returns X, Y
|
||||
pass
|
||||
estimator.train(input_fn_train)
|
||||
|
||||
def input_fn_eval: # returns X, Y
|
||||
pass
|
||||
estimator.evaluate(input_fn_eval)
|
||||
estimator.predict(x)
|
||||
```
|
||||
|
||||
Input of `fit`, `train`, and `evaluate` should have following features,
|
||||
otherwise there will be a `KeyError`:
|
||||
if `weight_column_name` is not `None`, a feature with
|
||||
`key=weight_column_name` whose value is a `Tensor`.
|
||||
for each `column` in `feature_columns`:
|
||||
- if `column` is a `SparseColumn`, a feature with `key=column.name`
|
||||
whose `value` is a `SparseTensor`.
|
||||
- if `column` is a `RealValuedColumn, a feature with `key=column.name`
|
||||
whose `value` is a `Tensor`.
|
||||
- if `feauture_columns` is None, then `input` must contains only real
|
||||
valued `Tensor`.
|
||||
|
||||
|
||||
|
||||
Parameters:
|
||||
hidden_units: List of hidden units per layer. All layers are fully
|
||||
connected. Ex. [64, 32] means first layer has 64 nodes and second one has
|
||||
32.
|
||||
feature_columns: An iterable containing all the feature columns used by the
|
||||
model. All items in the set should be instances of classes derived from
|
||||
`FeatureColumn`.
|
||||
model_dir: Directory to save model parameters, graph and etc.
|
||||
weight_column_name: A string defining feature column name representing
|
||||
weights. It is used to down weight or boost examples during training. It
|
||||
will be multiplied by the loss of the example.
|
||||
optimizer: An instance of `tf.Optimizer` used to train the model. If `None`,
|
||||
will use an Adagrad optimizer.
|
||||
activation_fn: Activation function applied to each layer. If `None`, will
|
||||
use `tf.nn.relu`.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
hidden_units,
|
||||
feature_columns=None,
|
||||
model_dir=None,
|
||||
weight_column_name=None,
|
||||
optimizer=None,
|
||||
activation_fn=nn.relu):
|
||||
super(DNNRegressor, self).__init__(weight_column_name=weight_column_name,
|
||||
dnn_feature_columns=feature_columns,
|
||||
dnn_optimizer=optimizer,
|
||||
dnn_hidden_units=hidden_units,
|
||||
dnn_activation_fn=activation_fn)
|
||||
|
||||
def _get_train_ops(self, features, targets):
|
||||
"""See base class."""
|
||||
if self._dnn_feature_columns is None:
|
||||
self._dnn_feature_columns = layers.infer_real_valued_columns(features)
|
||||
return super(DNNRegressor, self)._get_train_ops(features, targets)
|
||||
|
||||
|
||||
# TODO(ipolosukhin): Deprecate this class in favor of DNNClassifier.
|
||||
class TensorFlowDNNClassifier(TensorFlowEstimator, _sklearn.ClassifierMixin):
|
||||
"""TensorFlow DNN Classifier model.
|
||||
|
||||
@ -84,16 +249,16 @@ class TensorFlowDNNClassifier(TensorFlowEstimator, _sklearn.ClassifierMixin):
|
||||
@property
|
||||
def weights_(self):
|
||||
"""Returns weights of the DNN weight layers."""
|
||||
return [self._session.run(w)
|
||||
return [self.get_tensor_value(w.name)
|
||||
for w in self._graph.get_collection('dnn_weights')
|
||||
] + [self.get_tensor_value('logistic_regression/weights:0')]
|
||||
] + [self.get_tensor_value('logistic_regression/weights')]
|
||||
|
||||
@property
|
||||
def bias_(self):
|
||||
"""Returns bias of the DNN's bias layers."""
|
||||
return [self._session.run(b)
|
||||
return [self.get_tensor_value(b.name)
|
||||
for b in self._graph.get_collection('dnn_biases')
|
||||
] + [self.get_tensor_value('logistic_regression/bias:0')]
|
||||
] + [self.get_tensor_value('logistic_regression/bias')]
|
||||
|
||||
|
||||
class TensorFlowDNNRegressor(TensorFlowEstimator, _sklearn.RegressorMixin):
|
||||
@ -157,13 +322,13 @@ class TensorFlowDNNRegressor(TensorFlowEstimator, _sklearn.RegressorMixin):
|
||||
@property
|
||||
def weights_(self):
|
||||
"""Returns weights of the DNN weight layers."""
|
||||
return [self._session.run(w)
|
||||
return [self.get_tensor_value(w.name)
|
||||
for w in self._graph.get_collection('dnn_weights')
|
||||
] + [self.get_tensor_value('linear_regression/weights:0')]
|
||||
] + [self.get_tensor_value('linear_regression/weights')]
|
||||
|
||||
@property
|
||||
def bias_(self):
|
||||
"""Returns bias of the DNN's bias layers."""
|
||||
return [self._session.run(b)
|
||||
return [self.get_tensor_value(b.name)
|
||||
for b in self._graph.get_collection('dnn_biases')
|
||||
] + [self.get_tensor_value('linear_regression/bias:0')]
|
||||
] + [self.get_tensor_value('linear_regression/bias')]
|
||||
|
@ -0,0 +1,490 @@
|
||||
# Copyright 2015 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""TensorFlow estimators for Linear and DNN joined training models."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import math
|
||||
|
||||
import six
|
||||
|
||||
from tensorflow.contrib import layers
|
||||
from tensorflow.contrib import metrics as metrics_lib
|
||||
from tensorflow.contrib.framework.python.ops import variables as variables
|
||||
from tensorflow.contrib.learn.python.learn.estimators import estimator
|
||||
from tensorflow.python.framework import ops
|
||||
from tensorflow.python.ops import array_ops
|
||||
from tensorflow.python.ops import control_flow_ops
|
||||
from tensorflow.python.ops import gradients
|
||||
from tensorflow.python.ops import logging_ops
|
||||
from tensorflow.python.ops import math_ops
|
||||
from tensorflow.python.ops import nn
|
||||
from tensorflow.python.ops import parsing_ops
|
||||
from tensorflow.python.ops import state_ops
|
||||
|
||||
|
||||
# TODO(ispir): Increase test coverage
|
||||
class _DNNLinearCombinedBaseEstimator(estimator.BaseEstimator):
|
||||
"""An estimator for TensorFlow Linear and DNN joined training models.
|
||||
|
||||
Input of `fit`, `train`, and `evaluate` should have following features,
|
||||
otherwise there will be a `KeyError`:
|
||||
if `weight_column_name` is not `None`, a feature with
|
||||
`key=weight_column_name` whose value is a `Tensor`.
|
||||
for each `column` in `dnn_feature_columns` + `linear_feature_columns`:
|
||||
- if `column` is a `SparseColumn`, a feature with `key=column.name`
|
||||
whose `value` is a `SparseTensor`.
|
||||
- if `column` is a `RealValuedColumn, a feature with `key=column.name`
|
||||
whose `value` is a `Tensor`.
|
||||
|
||||
Parameters:
|
||||
model_dir: Directory to save model parameters, graph and etc.
|
||||
n_classes: number of target classes. Default is binary classification.
|
||||
weight_column_name: A string defining feature column name representing
|
||||
weights. It is used to down weight or boost examples during training. It
|
||||
will be multiplied by the loss of the example.
|
||||
linear_feature_columns: An iterable containing all the feature columns used
|
||||
by linear part of the model. All items in the set should be instances of
|
||||
classes derived from `FeatureColumn`.
|
||||
linear_optimizer: An instance of `tf.Optimizer` used to apply gradients to
|
||||
the linear part of the model. If `None`, will use a FTRL optimizer.
|
||||
dnn_feature_columns: An iterable containing all the feature columns used by
|
||||
deep part of the model. All items in the set should be instances of
|
||||
classes derived from `FeatureColumn`.
|
||||
dnn_hidden_units: List of hidden units per layer. All layers are fully
|
||||
connected.
|
||||
dnn_optimizer: An instance of `tf.Optimizer` used to apply gradients to the
|
||||
deep part of the model. If `None`, will use an Adagrad optimizer.
|
||||
dnn_activation_fn: Activation function applied to each layer. If `None`,
|
||||
will use `tf.nn.relu`.
|
||||
|
||||
Raises:
|
||||
ValueError: If both linear_feature_columns and dnn_features_columns are
|
||||
empty at the same time.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
model_dir=None,
|
||||
n_classes=2,
|
||||
weight_column_name=None,
|
||||
linear_feature_columns=None,
|
||||
linear_optimizer=None,
|
||||
dnn_feature_columns=None,
|
||||
dnn_optimizer=None,
|
||||
dnn_hidden_units=None,
|
||||
dnn_activation_fn=nn.relu):
|
||||
super(_DNNLinearCombinedBaseEstimator, self).__init__(model_dir=model_dir)
|
||||
self._n_classes = n_classes
|
||||
self._weight_column_name = weight_column_name
|
||||
self._linear_feature_columns = linear_feature_columns
|
||||
self._linear_optimizer = linear_optimizer
|
||||
self._dnn_feature_columns = dnn_feature_columns
|
||||
self._dnn_optimizer = dnn_optimizer
|
||||
self._dnn_hidden_units = dnn_hidden_units
|
||||
self._dnn_activation_fn = dnn_activation_fn
|
||||
if self._dnn_activation_fn is None:
|
||||
self._dnn_activation_fn = nn.relu
|
||||
self._dnn_weight_collection = "DNNLinearCombined_dnn"
|
||||
self._linear_weight_collection = "DNNLinearCombined_linear"
|
||||
|
||||
def _get_train_ops(self, features, targets):
|
||||
"""See base class."""
|
||||
global_step = variables.get_global_step()
|
||||
assert global_step
|
||||
loss = self._loss(
|
||||
self._logits(features), targets, self._get_weight_tensor(features))
|
||||
logging_ops.scalar_summary("loss", loss)
|
||||
|
||||
linear_vars = self._get_linear_vars()
|
||||
dnn_vars = self._get_dnn_vars()
|
||||
grads = gradients.gradients(loss, dnn_vars + linear_vars)
|
||||
dnn_grads = grads[0:len(dnn_vars)]
|
||||
linear_grads = grads[len(dnn_vars):]
|
||||
|
||||
train_ops = self._get_linear_training_ops(
|
||||
linear_grads, linear_vars) + self._get_dnn_training_ops(dnn_grads,
|
||||
dnn_vars)
|
||||
|
||||
train_step = control_flow_ops.group(*train_ops, name="combined_training_op")
|
||||
with ops.control_dependencies([train_step]):
|
||||
with ops.get_default_graph().colocate_with(global_step):
|
||||
return state_ops.assign_add(global_step, 1).op, loss
|
||||
|
||||
def _get_eval_ops(self, features, targets, metrics):
|
||||
"""See base class."""
|
||||
predictions = self._get_predict_ops(features)
|
||||
result = {}
|
||||
for name, metric in six.iteritems(metrics):
|
||||
result[name] = metric(predictions, targets,
|
||||
self._get_weight_tensor(features))
|
||||
return result
|
||||
|
||||
def _get_default_metric_functions(self):
|
||||
"""See base class."""
|
||||
def _compute_loss(logits, targets, weights=None):
|
||||
return self._loss(logits, targets, weight_tensor=weights)
|
||||
|
||||
def _compute_accuracy(logits, targets, weights=None):
|
||||
if self._n_classes > 2:
|
||||
_, predictions = nn.top_k(logits, 1)
|
||||
else:
|
||||
predictions = array_ops.reshape(logits, [-1])
|
||||
predictions = math_ops.greater(predictions,
|
||||
array_ops.zeros_like(predictions))
|
||||
targets = array_ops.reshape(targets, [-1])
|
||||
return metrics_lib.accuracy(
|
||||
math_ops.to_int32(predictions), math_ops.to_int32(targets), weights)
|
||||
|
||||
result = {"loss": _compute_loss}
|
||||
if self._n_classes > 1:
|
||||
result["accuracy"] = _compute_accuracy
|
||||
return result
|
||||
|
||||
def _get_predict_ops(self, features):
|
||||
return self._logits(features)
|
||||
|
||||
def _get_feature_ops_from_example(self, examples_batch):
|
||||
column_types = layers.create_dict_for_parse_example(
|
||||
self._get_linear_feature_columns() + self._get_dnn_feature_columns())
|
||||
features = parsing_ops.parse_example(examples_batch, column_types)
|
||||
return features
|
||||
|
||||
def _num_label_columns(self):
|
||||
return 1 if self._n_classes <= 2 else self._n_classes
|
||||
|
||||
def _get_linear_feature_columns(self):
|
||||
return sorted(
|
||||
set(self._linear_feature_columns),
|
||||
key=lambda x: x.key) if self._linear_feature_columns else None
|
||||
|
||||
def _get_dnn_feature_columns(self):
|
||||
return sorted(set(
|
||||
self._dnn_feature_columns)) if self._dnn_feature_columns else None
|
||||
|
||||
def _dnn_logits(self, features):
|
||||
net = layers.input_from_feature_columns(
|
||||
features,
|
||||
self._get_dnn_feature_columns(),
|
||||
weight_collections=[self._dnn_weight_collection])
|
||||
for layer_id, num_hidden_units in enumerate(self._dnn_hidden_units):
|
||||
net = layers.legacy_fully_connected(
|
||||
net,
|
||||
num_hidden_units,
|
||||
activation_fn=self._dnn_activation_fn,
|
||||
weight_collections=[self._dnn_weight_collection],
|
||||
bias_collections=[self._dnn_weight_collection],
|
||||
name="hiddenlayer_%d" % layer_id)
|
||||
self._add_hidden_layer_summary(net, "hiddenlayer_%d" % layer_id)
|
||||
logit = layers.legacy_fully_connected(
|
||||
net,
|
||||
self._num_label_columns(),
|
||||
weight_collections=[self._dnn_weight_collection],
|
||||
bias_collections=[self._dnn_weight_collection],
|
||||
name="dnn_logit")
|
||||
self._add_hidden_layer_summary(logit, "dnn_logit")
|
||||
return logit
|
||||
|
||||
def _add_hidden_layer_summary(self, value, tag):
|
||||
# TODO(zakaria): Move this code to tf.learn and add test.
|
||||
logging_ops.scalar_summary("%s:fraction_of_zero_values" % tag,
|
||||
nn.zero_fraction(value))
|
||||
logging_ops.histogram_summary("%s:activation" % tag, value)
|
||||
|
||||
def _linear_logits(self, features):
|
||||
logits, _, _ = layers.weighted_sum_from_feature_columns(
|
||||
columns_to_tensors=features,
|
||||
feature_columns=self._get_linear_feature_columns(),
|
||||
num_outputs=self._num_label_columns(),
|
||||
weight_collections=[self._linear_weight_collection],
|
||||
name="linear")
|
||||
return logits
|
||||
|
||||
def _get_feature_dict(self, features):
|
||||
if isinstance(features, dict):
|
||||
return features
|
||||
return {"": features}
|
||||
|
||||
def _logits(self, features):
|
||||
if not (self._get_linear_feature_columns() or
|
||||
self._get_dnn_feature_columns()):
|
||||
raise ValueError("Either linear_feature_columns or dnn_feature_columns "
|
||||
"should be defined.")
|
||||
|
||||
features = self._get_feature_dict(features)
|
||||
if self._get_linear_feature_columns() and self._get_dnn_feature_columns():
|
||||
return self._linear_logits(features) + self._dnn_logits(features)
|
||||
elif self._get_dnn_feature_columns():
|
||||
return self._dnn_logits(features)
|
||||
else:
|
||||
return self._linear_logits(features)
|
||||
|
||||
def _get_weight_tensor(self, features):
|
||||
if not self._weight_column_name:
|
||||
return None
|
||||
else:
|
||||
return math_ops.to_float(features[self._weight_column_name])
|
||||
|
||||
def _loss(self, logits, target, weight_tensor):
|
||||
if self._n_classes < 2:
|
||||
loss_vec = math_ops.square(logits - math_ops.to_float(target))
|
||||
elif self._n_classes == 2:
|
||||
loss_vec = nn.sigmoid_cross_entropy_with_logits(logits,
|
||||
math_ops.to_float(target))
|
||||
else:
|
||||
loss_vec = nn.sparse_softmax_cross_entropy_with_logits(
|
||||
logits, array_ops.reshape(target, [-1]))
|
||||
|
||||
if weight_tensor is None:
|
||||
return math_ops.reduce_mean(loss_vec, name="loss")
|
||||
else:
|
||||
loss_vec = array_ops.reshape(loss_vec, shape=(-1,))
|
||||
loss_vec = math_ops.mul(
|
||||
loss_vec, array_ops.reshape(weight_tensor, shape=(-1,)))
|
||||
return math_ops.div(
|
||||
math_ops.reduce_sum(loss_vec),
|
||||
math_ops.to_float(math_ops.reduce_sum(weight_tensor)),
|
||||
name="loss")
|
||||
|
||||
def _get_linear_vars(self):
|
||||
if self._get_linear_feature_columns():
|
||||
return ops.get_collection(self._linear_weight_collection)
|
||||
return []
|
||||
|
||||
def _get_linear_training_ops(self, linear_grads, linear_vars):
|
||||
if self._get_linear_feature_columns():
|
||||
self._linear_optimizer = self._get_optimizer(
|
||||
self._linear_optimizer,
|
||||
default_optimizer="Ftrl",
|
||||
default_learning_rate=1. / math.sqrt(len(
|
||||
self._get_linear_feature_columns())))
|
||||
return [
|
||||
self._linear_optimizer.apply_gradients(zip(linear_grads, linear_vars))
|
||||
]
|
||||
return []
|
||||
|
||||
def _get_dnn_vars(self):
|
||||
if self._get_dnn_feature_columns():
|
||||
return ops.get_collection(self._dnn_weight_collection)
|
||||
return []
|
||||
|
||||
def _get_dnn_training_ops(self, dnn_grads, dnn_vars):
|
||||
if self._get_dnn_feature_columns():
|
||||
self._dnn_optimizer = self._get_optimizer(self._dnn_optimizer,
|
||||
default_optimizer="Adagrad",
|
||||
default_learning_rate=0.05)
|
||||
return [self._dnn_optimizer.apply_gradients(zip(dnn_grads, dnn_vars))]
|
||||
return []
|
||||
|
||||
def _get_optimizer(self, optimizer, default_optimizer, default_learning_rate):
|
||||
if optimizer is None:
|
||||
optimizer = default_optimizer
|
||||
if isinstance(optimizer, six.string_types):
|
||||
optimizer = layers.OPTIMIZER_CLS_NAMES[optimizer](
|
||||
learning_rate=default_learning_rate)
|
||||
return optimizer
|
||||
|
||||
|
||||
class DNNLinearCombinedClassifier(_DNNLinearCombinedBaseEstimator):
|
||||
"""A classifier for TensorFlow Linear and DNN joined training models.
|
||||
|
||||
Example:
|
||||
```
|
||||
installed_app_id = sparse_column_with_hash_bucket("installed_id", 1e6)
|
||||
impression_app_id = sparse_column_with_hash_bucket("impression_id", 1e6)
|
||||
|
||||
installed_x_impression = crossed_column(
|
||||
[installed_app_id, impression_app_id])
|
||||
|
||||
installed_emb = embedding_column(installed_app_id, dimension=16,
|
||||
combiner="sum")
|
||||
impression_emb = embedding_column(impression_app_id, dimension=16,
|
||||
combiner="sum")
|
||||
|
||||
estimator = DNNLinearCombinedClassifier(
|
||||
# common settings
|
||||
n_classes, weight_column_name,
|
||||
# wide settings
|
||||
linear_feature_columns=[installed_x_impression],
|
||||
linear_optimizer=tf.train.FtrlOptimizer(...),
|
||||
# deep settings
|
||||
dnn_feature_columns=[installed_emb, impression_emb],
|
||||
dnn_hidden_units=[1000, 500, 100],
|
||||
dnn_optimizer=tf.train.AdagradOptimizer(...))
|
||||
|
||||
# Input builders
|
||||
def input_fn_train: # returns X, Y
|
||||
...
|
||||
def input_fn_eval: # returns X, Y
|
||||
...
|
||||
estimator.train(input_fn_train)
|
||||
estimator.evaluate(input_fn_eval)
|
||||
estimator.predict(x)
|
||||
```
|
||||
|
||||
Input of `fit`, `train`, and `evaluate` should have following features,
|
||||
otherwise there will be a `KeyError`:
|
||||
if `weight_column_name` is not `None`, a feature with
|
||||
`key=weight_column_name` whose value is a `Tensor`.
|
||||
for each `column` in `dnn_feature_columns` + `linear_feature_columns`:
|
||||
- if `column` is a `SparseColumn`, a feature with `key=column.name`
|
||||
whose `value` is a `SparseTensor`.
|
||||
- if `column` is a `RealValuedColumn, a feature with `key=column.name`
|
||||
whose `value` is a `Tensor`.
|
||||
|
||||
Parameters:
|
||||
model_dir: Directory to save model parameters, graph and etc.
|
||||
n_classes: number of target classes. Default is binary classification.
|
||||
weight_column_name: A string defining feature column name representing
|
||||
weights. It is used to down weight or boost examples during training. It
|
||||
will be multiplied by the loss of the example.
|
||||
linear_feature_columns: An iterable containing all the feature columns used
|
||||
by linear part of the model. All items in the set must be instances of
|
||||
classes derived from `FeatureColumn`.
|
||||
linear_optimizer: An instance of `tf.Optimizer` used to apply gradients to
|
||||
the linear part of the model. If `None`, will use a FTRL optimizer.
|
||||
dnn_feature_columns: An iterable containing all the feature columns used by
|
||||
deep part of the model. All items in the set must be instances of
|
||||
classes derived from `FeatureColumn`.
|
||||
dnn_hidden_units: List of hidden units per layer. All layers are fully
|
||||
connected.
|
||||
dnn_optimizer: An instance of `tf.Optimizer` used to apply gradients to the
|
||||
deep part of the model. If `None`, will use an Adagrad optimizer.
|
||||
dnn_activation_fn: Activation function applied to each layer. If `None`,
|
||||
will use `tf.nn.relu`.
|
||||
|
||||
Raises:
|
||||
ValueError: If both linear_feature_columns and dnn_features_columns are
|
||||
empty at the same time.
|
||||
ValueError: If both n_classes < 2.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
model_dir=None,
|
||||
n_classes=2,
|
||||
weight_column_name=None,
|
||||
linear_feature_columns=None,
|
||||
linear_optimizer=None,
|
||||
dnn_feature_columns=None,
|
||||
dnn_optimizer=None,
|
||||
dnn_hidden_units=None,
|
||||
dnn_activation_fn=nn.relu):
|
||||
if n_classes < 2:
|
||||
raise ValueError("n_classes should be greater than 1. Given: {}".format(
|
||||
n_classes))
|
||||
|
||||
super(DNNLinearCombinedClassifier, self).__init__(
|
||||
model_dir=model_dir,
|
||||
n_classes=n_classes,
|
||||
weight_column_name=weight_column_name,
|
||||
linear_feature_columns=linear_feature_columns,
|
||||
linear_optimizer=linear_optimizer,
|
||||
dnn_feature_columns=dnn_feature_columns,
|
||||
dnn_optimizer=dnn_optimizer,
|
||||
dnn_hidden_units=dnn_hidden_units,
|
||||
dnn_activation_fn=dnn_activation_fn)
|
||||
|
||||
|
||||
class DNNLinearCombinedRegressor(_DNNLinearCombinedBaseEstimator):
|
||||
"""A regressor for TensorFlow Linear and DNN joined training models.
|
||||
|
||||
Example:
|
||||
```
|
||||
installed_app_id = sparse_column_with_hash_bucket("installed_id", 1e6)
|
||||
impression_app_id = sparse_column_with_hash_bucket("impression_id", 1e6)
|
||||
|
||||
installed_x_impression = crossed_column(
|
||||
[installed_app_id, impression_app_id])
|
||||
|
||||
installed_emb = embedding_column(installed_app_id, dimension=16,
|
||||
combiner="sum")
|
||||
impression_emb = embedding_column(impression_app_id, dimension=16,
|
||||
combiner="sum")
|
||||
|
||||
estimator = DNNLinearCombinedClassifier(
|
||||
# common settings
|
||||
n_classes, weight_column_name,
|
||||
# wide settings
|
||||
linear_feature_columns=[installed_x_impression],
|
||||
linear_optimizer=tf.train.FtrlOptimizer(...),
|
||||
# deep settings
|
||||
dnn_feature_columns=[installed_emb, impression_emb],
|
||||
dnn_hidden_units=[1000, 500, 100],
|
||||
dnn_optimizer=tf.train.AdagradOptimizer(...))
|
||||
|
||||
# Input builders
|
||||
def input_fn_train: # returns X, Y
|
||||
...
|
||||
def input_fn_eval: # returns X, Y
|
||||
...
|
||||
estimator.train(input_fn_train)
|
||||
estimator.evaluate(input_fn_eval)
|
||||
estimator.predict(x)
|
||||
```
|
||||
|
||||
Input of `fit`, `train`, and `evaluate` should have following features,
|
||||
otherwise there will be a `KeyError`:
|
||||
if `weight_column_name` is not `None`, a feature with
|
||||
`key=weight_column_name` whose value is a `Tensor`.
|
||||
for each `column` in `dnn_feature_columns` + `linear_feature_columns`:
|
||||
- if `column` is a `SparseColumn`, a feature with `key=column.name`
|
||||
whose `value` is a `SparseTensor`.
|
||||
- if `column` is a `RealValuedColumn, a feature with `key=column.name`
|
||||
whose `value` is a `Tensor`.
|
||||
|
||||
Parameters:
|
||||
model_dir: Directory to save model parameters, graph and etc.
|
||||
weight_column_name: A string defining feature column name representing
|
||||
weights. It is used to down weight or boost examples during training. It
|
||||
will be multiplied by the loss of the example.
|
||||
linear_feature_columns: An iterable containing all the feature columns used
|
||||
by linear part of the model. All items in the set must be instances of
|
||||
classes derived from `FeatureColumn`.
|
||||
linear_optimizer: An instance of `tf.Optimizer` used to apply gradients to
|
||||
the linear part of the model. If `None`, will use a FTRL optimizer.
|
||||
dnn_feature_columns: An iterable containing all the feature columns used by
|
||||
deep part of the model. All items in the set must be instances of
|
||||
classes derived from `FeatureColumn`.
|
||||
dnn_hidden_units: List of hidden units per layer. All layers are fully
|
||||
connected.
|
||||
dnn_optimizer: An instance of `tf.Optimizer` used to apply gradients to the
|
||||
deep part of the model. If `None`, will use an Adagrad optimizer.
|
||||
dnn_activation_fn: Activation function applied to each layer. If None, will
|
||||
use `tf.nn.relu`.
|
||||
|
||||
Raises:
|
||||
ValueError: If both linear_feature_columns and dnn_features_columns are
|
||||
empty at the same time.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
model_dir=None,
|
||||
weight_column_name=None,
|
||||
linear_feature_columns=None,
|
||||
linear_optimizer=None,
|
||||
dnn_feature_columns=None,
|
||||
dnn_optimizer=None,
|
||||
dnn_hidden_units=None,
|
||||
dnn_activation_fn=nn.relu):
|
||||
super(DNNLinearCombinedRegressor, self).__init__(
|
||||
model_dir=model_dir,
|
||||
n_classes=0,
|
||||
weight_column_name=weight_column_name,
|
||||
linear_feature_columns=linear_feature_columns,
|
||||
linear_optimizer=linear_optimizer,
|
||||
dnn_feature_columns=dnn_feature_columns,
|
||||
dnn_optimizer=dnn_optimizer,
|
||||
dnn_hidden_units=dnn_hidden_units,
|
||||
dnn_activation_fn=dnn_activation_fn)
|
@ -0,0 +1,254 @@
|
||||
# Copyright 2015 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Tests for DNNLinearCombinedEstimators."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
|
||||
|
||||
def _get_quantile_based_buckets(feature_values, num_buckets):
|
||||
quantiles = np.percentile(
|
||||
np.array(feature_values), ([100 * (i + 1.) / (num_buckets + 1.)
|
||||
for i in range(num_buckets)]))
|
||||
return list(quantiles)
|
||||
|
||||
|
||||
def _prepare_iris_data_for_logistic_regression():
|
||||
# Converts iris data to a logistic regression problem.
|
||||
iris = tf.contrib.learn.datasets.load_iris()
|
||||
ids = np.where((iris.target == 0) | (iris.target == 1))
|
||||
iris = tf.contrib.learn.datasets.base.Dataset(data=iris.data[ids],
|
||||
target=iris.target[ids])
|
||||
return iris
|
||||
|
||||
|
||||
def _iris_input_fn():
|
||||
iris = _prepare_iris_data_for_logistic_regression()
|
||||
return {
|
||||
'feature': tf.constant(iris.data, dtype=tf.float32)
|
||||
}, tf.constant(iris.target, shape=[100, 1], dtype=tf.int32)
|
||||
|
||||
|
||||
class DNNLinearCombinedClassifierTest(tf.test.TestCase):
|
||||
|
||||
def testLogisticRegression_MatrixData(self):
|
||||
"""Tests binary classification using matrix data as input."""
|
||||
iris = _prepare_iris_data_for_logistic_regression()
|
||||
cont_features = [
|
||||
tf.contrib.layers.real_valued_column('feature', dimension=4)]
|
||||
bucketized_feature = [tf.contrib.layers.bucketized_column(
|
||||
cont_features[0], _get_quantile_based_buckets(iris.data, 10))]
|
||||
|
||||
classifier = tf.contrib.learn.DNNLinearCombinedClassifier(
|
||||
linear_feature_columns=bucketized_feature,
|
||||
dnn_feature_columns=cont_features,
|
||||
dnn_hidden_units=[3, 3])
|
||||
|
||||
classifier.train(_iris_input_fn, steps=100)
|
||||
scores = classifier.evaluate(input_fn=_iris_input_fn, steps=100)
|
||||
self.assertGreater(scores['accuracy'], 0.9)
|
||||
|
||||
def testLogisticRegression_TensorData(self):
|
||||
"""Tests binary classification using Tensor data as input."""
|
||||
def _input_fn():
|
||||
iris = _prepare_iris_data_for_logistic_regression()
|
||||
features = {}
|
||||
for i in range(4):
|
||||
# The following shows how to provide the Tensor data for
|
||||
# RealValuedColumns.
|
||||
features.update({
|
||||
str(i): tf.reshape(tf.constant(iris.data[:, i], dtype=tf.float32),
|
||||
[-1, 1])})
|
||||
# The following shows how to provide the SparseTensor data for
|
||||
# a SparseColumn.
|
||||
features['dummy_sparse_column'] = tf.SparseTensor(
|
||||
values=['en', 'fr', 'zh'],
|
||||
indices=[[0, 0], [0, 1], [60, 0]],
|
||||
shape=[len(iris.target), 2])
|
||||
target = tf.reshape(tf.constant(iris.target, dtype=tf.float32), [-1, 1])
|
||||
return features, target
|
||||
|
||||
iris = _prepare_iris_data_for_logistic_regression()
|
||||
cont_features = [tf.contrib.layers.real_valued_column(str(i))
|
||||
for i in range(4)]
|
||||
linear_features = [
|
||||
tf.contrib.layers.bucketized_column(
|
||||
cont_features[i], _get_quantile_based_buckets(iris.data[:, str(i)],
|
||||
10)) for i in range(4)
|
||||
]
|
||||
linear_features.append(tf.contrib.layers.sparse_column_with_hash_bucket(
|
||||
'dummy_sparse_column', hash_bucket_size=100))
|
||||
|
||||
classifier = tf.contrib.learn.DNNLinearCombinedClassifier(
|
||||
linear_feature_columns=linear_features,
|
||||
dnn_feature_columns=cont_features,
|
||||
dnn_hidden_units=[3, 3])
|
||||
|
||||
classifier.train(input_fn=_input_fn, steps=100)
|
||||
scores = classifier.evaluate(input_fn=_input_fn, steps=100)
|
||||
self.assertGreater(scores['accuracy'], 0.9)
|
||||
|
||||
def testMultiClass(self):
|
||||
"""Tests multi-class classification using matrix data as input.
|
||||
|
||||
Please see testLogisticRegression_TensorData() for how to use Tensor
|
||||
data as input instead.
|
||||
"""
|
||||
iris = tf.contrib.learn.datasets.load_iris()
|
||||
cont_features = [
|
||||
tf.contrib.layers.real_valued_column('feature', dimension=4)]
|
||||
bucketized_features = [
|
||||
tf.contrib.layers.bucketized_column(
|
||||
cont_features[0], _get_quantile_based_buckets(iris.data, 10))]
|
||||
|
||||
classifier = tf.contrib.learn.DNNLinearCombinedClassifier(
|
||||
n_classes=3,
|
||||
linear_feature_columns=bucketized_features,
|
||||
dnn_feature_columns=cont_features,
|
||||
dnn_hidden_units=[3, 3])
|
||||
|
||||
classifier.train(_iris_input_fn, steps=100)
|
||||
scores = classifier.evaluate(input_fn=_iris_input_fn, steps=100)
|
||||
self.assertGreater(scores['accuracy'], 0.9)
|
||||
|
||||
def testWeightColumn(self):
|
||||
"""Tests weight column."""
|
||||
|
||||
def _input_fn_train():
|
||||
# Create 4 rows, one of them (y = x), three of them (y=Not(x))
|
||||
# First row has more weight than others. Model should fit (y=x) better
|
||||
# than (y=Not(x)) due to the relative higher weight of the first row.
|
||||
target = tf.constant([[1], [0], [0], [0]])
|
||||
features = {
|
||||
'x': tf.ones(shape=[4, 1], dtype=tf.float32),
|
||||
'w': tf.constant([[100.], [3.], [2.], [2.]])
|
||||
}
|
||||
return features, target
|
||||
|
||||
def _input_fn_eval():
|
||||
# Create 4 rows (y = x)
|
||||
target = tf.constant([[1], [1], [1], [1]])
|
||||
features = {
|
||||
'x': tf.ones(shape=[4, 1], dtype=tf.float32),
|
||||
'w': tf.constant([[1.], [1.], [1.], [1.]])
|
||||
}
|
||||
return features, target
|
||||
|
||||
classifier = tf.contrib.learn.DNNLinearCombinedClassifier(
|
||||
weight_column_name='w',
|
||||
linear_feature_columns=[tf.contrib.layers.real_valued_column('x')],
|
||||
dnn_feature_columns=[tf.contrib.layers.real_valued_column('x')],
|
||||
dnn_hidden_units=[3, 3])
|
||||
|
||||
classifier.train(input_fn=_input_fn_train, steps=100)
|
||||
scores = classifier.evaluate(input_fn=_input_fn_eval,
|
||||
steps=100)
|
||||
# If there is no weight column, model should learn y=Not(x). All examples in
|
||||
# eval data set are y=x. So if weight column is ignored, then accuracy
|
||||
# should be zero.
|
||||
self.assertGreater(scores['accuracy'], 0.9)
|
||||
|
||||
def testEvaluationShouldUseWeightColumn(self):
|
||||
"""Tests weight column in evaluation."""
|
||||
|
||||
def _input_fn_train():
|
||||
# Create 4 rows, one of them (y = x), three of them (y=Not(x))
|
||||
# First row has more weight than others. Model should fit (y=x) better
|
||||
# than (y=Not(x)) due to the relative higher weight of the first row.
|
||||
target = tf.constant([[1], [0], [0], [0]])
|
||||
features = {
|
||||
'x': tf.ones(shape=[4, 1], dtype=tf.float32),
|
||||
'w': tf.constant([[100.], [3.], [2.], [2.]])
|
||||
}
|
||||
return features, target
|
||||
|
||||
classifier = tf.contrib.learn.DNNLinearCombinedClassifier(
|
||||
weight_column_name='w',
|
||||
linear_feature_columns=[tf.contrib.layers.real_valued_column('x')],
|
||||
dnn_feature_columns=[tf.contrib.layers.real_valued_column('x')],
|
||||
dnn_hidden_units=[3, 3])
|
||||
|
||||
classifier.train(input_fn=_input_fn_train, steps=100)
|
||||
scores = classifier.evaluate(input_fn=_input_fn_train, steps=100)
|
||||
# If weight column is ignored, then accuracy should be 0.25. If it's not
|
||||
# ignored, then it should be greater than 0.6.
|
||||
self.assertGreater(scores['accuracy'], 0.6)
|
||||
|
||||
def testCustomOptimizerByObject(self):
|
||||
"""Tests binary classification using matrix data as input."""
|
||||
iris = _prepare_iris_data_for_logistic_regression()
|
||||
cont_features = [
|
||||
tf.contrib.layers.real_valued_column('feature', dimension=4)]
|
||||
bucketized_features = [
|
||||
tf.contrib.layers.bucketized_column(
|
||||
cont_features[0], _get_quantile_based_buckets(iris.data, 10))]
|
||||
|
||||
classifier = tf.contrib.learn.DNNLinearCombinedClassifier(
|
||||
linear_feature_columns=bucketized_features,
|
||||
linear_optimizer=tf.train.FtrlOptimizer(learning_rate=0.1),
|
||||
dnn_feature_columns=cont_features,
|
||||
dnn_hidden_units=[3, 3],
|
||||
dnn_optimizer=tf.train.AdagradOptimizer(learning_rate=0.1))
|
||||
|
||||
classifier.train(_iris_input_fn, steps=100)
|
||||
scores = classifier.evaluate(input_fn=_iris_input_fn, steps=100)
|
||||
self.assertGreater(scores['accuracy'], 0.9)
|
||||
|
||||
def testCustomOptimizerByString(self):
|
||||
"""Tests binary classification using matrix data as input."""
|
||||
iris = _prepare_iris_data_for_logistic_regression()
|
||||
cont_features = [
|
||||
tf.contrib.layers.real_valued_column('feature', dimension=4)]
|
||||
bucketized_features = [
|
||||
tf.contrib.layers.bucketized_column(
|
||||
cont_features[0], _get_quantile_based_buckets(iris.data, 10))]
|
||||
|
||||
classifier = tf.contrib.learn.DNNLinearCombinedClassifier(
|
||||
linear_feature_columns=bucketized_features,
|
||||
linear_optimizer='Ftrl',
|
||||
dnn_feature_columns=cont_features,
|
||||
dnn_hidden_units=[3, 3],
|
||||
dnn_optimizer='Adagrad')
|
||||
|
||||
classifier.train(_iris_input_fn, steps=100)
|
||||
scores = classifier.evaluate(input_fn=_iris_input_fn, steps=100)
|
||||
self.assertGreater(scores['accuracy'], 0.9)
|
||||
|
||||
|
||||
class DNNLinearCombinedRegressorTest(tf.test.TestCase):
|
||||
|
||||
def testRegression(self):
|
||||
"""Tests a regression problem."""
|
||||
|
||||
def _input_fn_train():
|
||||
# Create 4 rows of (y = x)
|
||||
target = tf.constant([[100.], [3.], [2.], [2.]])
|
||||
features = {'x': tf.constant([[100.], [3.], [2.], [2.]])}
|
||||
return features, target
|
||||
|
||||
classifier = tf.contrib.learn.DNNLinearCombinedRegressor(
|
||||
linear_feature_columns=[tf.contrib.layers.real_valued_column('x')],
|
||||
dnn_feature_columns=[tf.contrib.layers.real_valued_column('x')],
|
||||
dnn_hidden_units=[3, 3])
|
||||
|
||||
classifier.train(input_fn=_input_fn_train, steps=100)
|
||||
classifier.evaluate(input_fn=_input_fn_train, steps=1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tf.test.main()
|
77
tensorflow/contrib/learn/python/learn/estimators/dnn_test.py
Normal file
77
tensorflow/contrib/learn/python/learn/estimators/dnn_test.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright 2015 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Tests for DNNEstimators."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import tensorflow as tf
|
||||
|
||||
|
||||
def _iris_input_fn():
|
||||
iris = tf.contrib.learn.datasets.load_iris()
|
||||
return {
|
||||
'feature': tf.constant(iris.data, dtype=tf.float32)
|
||||
}, tf.constant(iris.target, shape=[150, 1], dtype=tf.int32)
|
||||
|
||||
|
||||
class DNNClassifierTest(tf.test.TestCase):
|
||||
|
||||
def testMultiClass(self):
|
||||
"""Tests multi-class classification using matrix data as input."""
|
||||
cont_features = [
|
||||
tf.contrib.layers.real_valued_column('feature', dimension=4)]
|
||||
|
||||
classifier = tf.contrib.learn.DNNClassifier(n_classes=3,
|
||||
feature_columns=cont_features,
|
||||
hidden_units=[3, 3])
|
||||
|
||||
classifier.train(_iris_input_fn, steps=1000)
|
||||
classifier.evaluate(input_fn=_iris_input_fn, steps=100)
|
||||
# TODO(ispir): Enable accuracy check after resolving the randomness issue.
|
||||
# self.assertGreater(scores['accuracy/mean'], 0.6)
|
||||
|
||||
|
||||
class DNNRegressorTest(tf.test.TestCase):
|
||||
|
||||
def testRegression(self):
|
||||
"""Tests multi-class classification using matrix data as input."""
|
||||
cont_features = [
|
||||
tf.contrib.layers.real_valued_column('feature', dimension=4)]
|
||||
|
||||
regressor = tf.contrib.learn.DNNRegressor(feature_columns=cont_features,
|
||||
hidden_units=[3, 3])
|
||||
|
||||
regressor.train(_iris_input_fn, steps=1000)
|
||||
regressor.evaluate(input_fn=_iris_input_fn, steps=100)
|
||||
|
||||
|
||||
def boston_input_fn():
|
||||
boston = tf.contrib.learn.datasets.load_boston()
|
||||
features = tf.cast(tf.reshape(tf.constant(boston.data), [-1, 13]), tf.float32)
|
||||
target = tf.cast(tf.reshape(tf.constant(boston.target), [-1, 1]), tf.float32)
|
||||
return features, target
|
||||
|
||||
|
||||
class InferedColumnTest(tf.test.TestCase):
|
||||
|
||||
def testTrain(self):
|
||||
est = tf.contrib.learn.DNNRegressor(hidden_units=[3, 3])
|
||||
est.train(input_fn=boston_input_fn, steps=1)
|
||||
_ = est.evaluate(input_fn=boston_input_fn, steps=1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tf.test.main()
|
@ -21,12 +21,16 @@ import abc
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
import types
|
||||
|
||||
import numpy as np
|
||||
import six
|
||||
|
||||
from tensorflow.contrib import framework as contrib_framework
|
||||
from tensorflow.contrib import layers
|
||||
from tensorflow.contrib import losses
|
||||
from tensorflow.contrib.learn.python.learn import graph_actions
|
||||
from tensorflow.contrib.learn.python.learn import monitors as monitors_lib
|
||||
from tensorflow.contrib.learn.python.learn.estimators import _sklearn as sklearn
|
||||
from tensorflow.contrib.learn.python.learn.estimators import run_config
|
||||
from tensorflow.contrib.learn.python.learn.estimators import tensor_signature
|
||||
@ -37,6 +41,8 @@ from tensorflow.contrib.learn.python.learn.io import data_feeder
|
||||
|
||||
from tensorflow.python.framework import ops
|
||||
from tensorflow.python.framework import random_seed
|
||||
from tensorflow.python.ops import control_flow_ops
|
||||
from tensorflow.python.ops import logging_ops
|
||||
from tensorflow.python.platform import tf_logging as logging
|
||||
from tensorflow.python.training import device_setter
|
||||
from tensorflow.python.training import saver
|
||||
@ -89,7 +95,7 @@ def _get_predict_input_fn(x, batch_size):
|
||||
|
||||
df = data_feeder.setup_train_data_feeder(x, None,
|
||||
n_classes=None,
|
||||
batch_size=batch_size)
|
||||
batch_size=batch_size, epochs=1)
|
||||
return df.input_builder, df.get_feed_dict_fn()
|
||||
|
||||
|
||||
@ -112,7 +118,7 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
# TODO(wicke): Remove this once launcher takes over config functionality
|
||||
_Config = run_config.RunConfig # pylint: disable=invalid-name
|
||||
|
||||
def __init__(self, model_dir=None):
|
||||
def __init__(self, model_dir=None, config=None):
|
||||
# Model directory.
|
||||
self._model_dir = model_dir
|
||||
if self._model_dir is None:
|
||||
@ -121,7 +127,10 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
self._model_dir)
|
||||
|
||||
# Create a run configuration
|
||||
self._config = BaseEstimator._Config()
|
||||
if config is None:
|
||||
self._config = BaseEstimator._Config()
|
||||
else:
|
||||
self._config = config
|
||||
|
||||
# Set device function depending if there are replicas or not.
|
||||
if self._config.num_ps_replicas > 0:
|
||||
@ -136,6 +145,12 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
self._features_info = None
|
||||
self._targets_info = None
|
||||
|
||||
self._graph = None
|
||||
|
||||
@property
|
||||
def model_dir(self):
|
||||
return self._model_dir
|
||||
|
||||
@abc.abstractproperty
|
||||
def _get_train_ops(self, features, targets):
|
||||
"""Method that builds model graph and returns trainer ops.
|
||||
@ -204,7 +219,7 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
"""
|
||||
return {}
|
||||
|
||||
def fit(self, x, y, steps, batch_size=32, monitor=None):
|
||||
def fit(self, x, y, steps, batch_size=32, monitors=None):
|
||||
"""Trains a model given training data X and y.
|
||||
|
||||
Args:
|
||||
@ -216,8 +231,8 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
(class labels in classification, real numbers in regression).
|
||||
steps: number of steps to train model for.
|
||||
batch_size: minibatch size to use on the input, defaults to 32.
|
||||
monitor: monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
monitors: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
Returns:
|
||||
Returns self.
|
||||
@ -226,24 +241,24 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
return self._train_model(input_fn=input_fn,
|
||||
feed_fn=feed_fn,
|
||||
steps=steps,
|
||||
monitor=monitor)
|
||||
monitors=monitors)
|
||||
|
||||
def train(self, input_fn, steps, monitor=None):
|
||||
def train(self, input_fn, steps, monitors=None):
|
||||
"""Trains a model given input builder function.
|
||||
|
||||
Args:
|
||||
input_fn: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
steps: number of steps to train model for.
|
||||
monitor: monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
monitors: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
Returns:
|
||||
Returns self.
|
||||
"""
|
||||
return self._train_model(input_fn=input_fn, steps=steps, monitor=monitor)
|
||||
return self._train_model(input_fn=input_fn, steps=steps, monitors=monitors)
|
||||
|
||||
def partial_fit(self, x, y, steps=1, batch_size=32, monitor=None):
|
||||
def partial_fit(self, x, y, steps=1, batch_size=32, monitors=None):
|
||||
"""Incremental fit on a batch of samples.
|
||||
|
||||
This method is expected to be called several times consecutively
|
||||
@ -263,8 +278,8 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
(class label in classification, real numbers in regression).
|
||||
steps: number of steps to train model for.
|
||||
batch_size: minibatch size to use on the input, defaults to 32.
|
||||
monitor: Monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
monitors: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
Returns:
|
||||
Returns self.
|
||||
@ -273,7 +288,7 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
return self._train_model(input_fn=input_fn,
|
||||
feed_fn=feed_fn,
|
||||
steps=steps,
|
||||
monitor=monitor)
|
||||
monitors=monitors)
|
||||
|
||||
def evaluate(self, x=None, y=None, input_fn=None, feed_fn=None,
|
||||
batch_size=32, steps=100, metrics=None):
|
||||
@ -323,7 +338,7 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
|
||||
Args:
|
||||
x: features.
|
||||
batch_size: OVerride default batch size.
|
||||
batch_size: Override default batch size.
|
||||
|
||||
Returns:
|
||||
Numpy array of predicted probabilities.
|
||||
@ -338,20 +353,24 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
(str(features), str(self._features_info)))
|
||||
else:
|
||||
self._features_info = tensor_signature.create_signatures(features)
|
||||
if self._targets_info is not None:
|
||||
if not tensor_signature.tensors_compatible(targets, self._targets_info):
|
||||
raise ValueError('Targets are incompatible with given information. '
|
||||
'Given targets: %s, required signatures: %s.' %
|
||||
(str(targets), str(self._targets_info)))
|
||||
else:
|
||||
self._targets_info = tensor_signature.create_signatures(targets)
|
||||
if targets is not None:
|
||||
if self._targets_info is not None:
|
||||
if not tensor_signature.tensors_compatible(targets, self._targets_info):
|
||||
raise ValueError('Targets are incompatible with given information. '
|
||||
'Given targets: %s, required signatures: %s.' %
|
||||
(str(targets), str(self._targets_info)))
|
||||
else:
|
||||
self._targets_info = tensor_signature.create_signatures(targets)
|
||||
|
||||
def _train_model(self,
|
||||
input_fn,
|
||||
steps,
|
||||
feed_fn=None,
|
||||
init_op=None,
|
||||
init_feed_fn=None,
|
||||
init_fn=None,
|
||||
device_fn=None,
|
||||
monitor=None,
|
||||
monitors=None,
|
||||
log_every_steps=100,
|
||||
fail_on_nan_loss=True):
|
||||
if self._config.execution_mode not in ('all', 'train'):
|
||||
@ -369,24 +388,42 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
# Device allocation
|
||||
device_fn = device_fn or self._device_fn
|
||||
|
||||
with ops.Graph().as_default() as g, g.device(device_fn):
|
||||
self._graph = ops.Graph()
|
||||
with self._graph.as_default() as g, g.device(device_fn):
|
||||
random_seed.set_random_seed(self._config.tf_random_seed)
|
||||
global_step = contrib_framework.create_global_step(g)
|
||||
features, targets = input_fn()
|
||||
self._check_inputs(features, targets)
|
||||
train_op, loss_op = self._get_train_ops(features, targets)
|
||||
|
||||
# Add default monitors.
|
||||
if monitors is None:
|
||||
monitors = []
|
||||
monitors += monitors_lib.get_default_monitors(
|
||||
loss_op=loss_op,
|
||||
summary_op=logging_ops.get_summary_op(),
|
||||
save_summary_steps=100)
|
||||
|
||||
# Setup monitors.
|
||||
for monitor in monitors:
|
||||
monitor.set_estimator(self)
|
||||
|
||||
return train(
|
||||
graph=g,
|
||||
output_dir=self._model_dir,
|
||||
train_op=train_op,
|
||||
loss_op=loss_op,
|
||||
global_step_tensor=global_step,
|
||||
init_op=init_op,
|
||||
init_feed_dict=init_feed_fn() if init_feed_fn is not None else None,
|
||||
init_fn=init_fn,
|
||||
log_every_steps=log_every_steps,
|
||||
supervisor_is_chief=(self._config.task == 0),
|
||||
supervisor_master=self._config.master,
|
||||
feed_fn=feed_fn,
|
||||
max_steps=steps,
|
||||
fail_on_nan_loss=fail_on_nan_loss)
|
||||
fail_on_nan_loss=fail_on_nan_loss,
|
||||
monitors=monitors)
|
||||
|
||||
def _evaluate_model(self, input_fn, steps, feed_fn=None, metrics=None):
|
||||
if self._config.execution_mode not in ('all', 'evaluate', 'eval_evalset'):
|
||||
@ -413,22 +450,41 @@ class BaseEstimator(sklearn.BaseEstimator):
|
||||
max_steps=steps)
|
||||
return eval_results
|
||||
|
||||
def _infer_model(self, x, batch_size=None, axis=None, proba=False):
|
||||
def _infer_model(self,
|
||||
x=None, input_fn=None, feed_fn=None,
|
||||
batch_size=None, axis=None, proba=False):
|
||||
# Converts inputs into tf.DataFrame / tf.Series.
|
||||
batch_size = -1 if batch_size is None else batch_size
|
||||
input_fn, feed_fn = _get_predict_input_fn(x, batch_size)
|
||||
if x is not None:
|
||||
input_fn, feed_fn = _get_predict_input_fn(x, batch_size)
|
||||
|
||||
checkpoint_path = saver.latest_checkpoint(self._model_dir)
|
||||
with ops.Graph().as_default() as g:
|
||||
random_seed.set_random_seed(self._config.tf_random_seed)
|
||||
contrib_framework.create_global_step(g)
|
||||
features, _ = input_fn()
|
||||
feed_dict = feed_fn() if feed_fn is not None else None
|
||||
predictions = self._get_predict_ops(features)
|
||||
if not isinstance(predictions, dict):
|
||||
predictions = {'predictions': predictions}
|
||||
# TODO(ipolosukhin): Support batching
|
||||
return infer(checkpoint_path, predictions, feed_dict=feed_dict)
|
||||
if feed_fn is None:
|
||||
return infer(checkpoint_path, predictions)
|
||||
preds = {}
|
||||
while True:
|
||||
try:
|
||||
feed_dict = feed_fn()
|
||||
except StopIteration:
|
||||
break
|
||||
if feed_dict is None:
|
||||
break
|
||||
outputs = infer(checkpoint_path, predictions, feed_dict=feed_dict)
|
||||
for key in outputs:
|
||||
if key not in preds:
|
||||
preds[key] = []
|
||||
preds[key].append(outputs[key])
|
||||
for key in preds:
|
||||
preds[key] = np.concatenate(preds[key], axis=0)
|
||||
return preds
|
||||
|
||||
|
||||
class Estimator(BaseEstimator):
|
||||
@ -449,16 +505,18 @@ class Estimator(BaseEstimator):
|
||||
(like tf.train.GradientDescentOptimizer).
|
||||
clip_gradients: clip_norm value for call to `clip_by_global_norm`. None
|
||||
denotes no gradient clipping.
|
||||
config: Configuration object.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
model_fn=None,
|
||||
model_dir=None,
|
||||
classification=True,
|
||||
learning_rate=0.01,
|
||||
optimizer='SGD',
|
||||
clip_gradients=None):
|
||||
super(Estimator, self).__init__(model_dir=model_dir)
|
||||
learning_rate=0.1,
|
||||
optimizer='Adagrad',
|
||||
clip_gradients=None,
|
||||
config=None):
|
||||
super(Estimator, self).__init__(model_dir=model_dir, config=config)
|
||||
|
||||
self._model_fn = model_fn
|
||||
self._classification = classification
|
||||
@ -486,12 +544,25 @@ class Estimator(BaseEstimator):
|
||||
Tuple of train `Operation` and loss `Tensor`.
|
||||
"""
|
||||
_, loss = self._model_fn(features, targets, ModeKeys.TRAIN)
|
||||
# TODO(ipolosukhin): Move this to TensorFlowEstimator when
|
||||
# moving out training.
|
||||
if isinstance(self.learning_rate, types.FunctionType):
|
||||
learning_rate = self.learning_rate(contrib_framework.get_global_step())
|
||||
else:
|
||||
learning_rate = self.learning_rate
|
||||
if isinstance(self.optimizer, types.FunctionType):
|
||||
optimizer = self.optimizer(learning_rate)
|
||||
else:
|
||||
optimizer = self.optimizer
|
||||
train_op = layers.optimize_loss(
|
||||
loss,
|
||||
contrib_framework.get_global_step(),
|
||||
learning_rate=self.learning_rate,
|
||||
optimizer=self.optimizer,
|
||||
learning_rate=learning_rate,
|
||||
optimizer=optimizer,
|
||||
clip_gradients=self.clip_gradients)
|
||||
# Add update ops.
|
||||
train_op = control_flow_ops.group(
|
||||
train_op, *ops.get_collection('update_ops'))
|
||||
return train_op, loss
|
||||
|
||||
def _get_eval_ops(self, features, targets, metrics):
|
||||
|
@ -37,6 +37,24 @@ def linear_model_fn(features, target, unused_mode):
|
||||
return tf.contrib.learn.models.linear_regression_zero_init(features, target)
|
||||
|
||||
|
||||
class CheckCallsMonitor(tf.contrib.learn.monitors.BaseMonitor):
|
||||
|
||||
def __init__(self):
|
||||
self.calls = None
|
||||
self.expect_calls = None
|
||||
|
||||
def begin(self, max_steps):
|
||||
self.calls = 0
|
||||
self.expect_calls = max_steps
|
||||
|
||||
def step_end(self, step, outputs):
|
||||
self.calls += 1
|
||||
return False
|
||||
|
||||
def end(self):
|
||||
assert self.calls == self.expect_calls
|
||||
|
||||
|
||||
class EstimatorTest(tf.test.TestCase):
|
||||
|
||||
def testTrain(self):
|
||||
@ -64,6 +82,12 @@ class EstimatorTest(tf.test.TestCase):
|
||||
with self.assertRaises(ValueError):
|
||||
est.train(input_fn=other_input_fn, steps=1)
|
||||
|
||||
def testMonitors(self):
|
||||
est = tf.contrib.learn.Estimator(model_fn=linear_model_fn,
|
||||
classification=False)
|
||||
est.train(input_fn=boston_input_fn, steps=21,
|
||||
monitors=[CheckCallsMonitor()])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tf.test.main()
|
||||
|
@ -16,11 +16,151 @@ from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from tensorflow.contrib.learn.python.learn.estimators import _sklearn
|
||||
from tensorflow.contrib.learn.python.learn.estimators.base import TensorFlowEstimator
|
||||
from tensorflow.contrib import layers
|
||||
from tensorflow.contrib.learn.python.learn import models
|
||||
from tensorflow.contrib.learn.python.learn.estimators import _sklearn
|
||||
from tensorflow.contrib.learn.python.learn.estimators import dnn_linear_combined
|
||||
from tensorflow.contrib.learn.python.learn.estimators.base import TensorFlowEstimator
|
||||
|
||||
|
||||
class LinearClassifier(dnn_linear_combined.DNNLinearCombinedClassifier):
|
||||
"""Linear classifier model.
|
||||
|
||||
Example:
|
||||
```
|
||||
installed_app_id = sparse_column_with_hash_bucket("installed_id", 1e6)
|
||||
impression_app_id = sparse_column_with_hash_bucket("impression_id", 1e6)
|
||||
|
||||
installed_x_impression = crossed_column(
|
||||
[installed_app_id, impression_app_id])
|
||||
|
||||
estimator = LinearClassifier(
|
||||
feature_columns=[impression_app_id, installed_x_impression])
|
||||
|
||||
# Input builders
|
||||
def input_fn_train: # returns X, Y
|
||||
...
|
||||
def input_fn_eval: # returns X, Y
|
||||
...
|
||||
estimator.train(input_fn_train)
|
||||
estimator.evaluate(input_fn_eval)
|
||||
estimator.predict(x)
|
||||
```
|
||||
|
||||
Input of `fit`, `train`, and `evaluate` should have following features,
|
||||
otherwise there will be a `KeyError`:
|
||||
if `weight_column_name` is not `None`, a feature with
|
||||
`key=weight_column_name` whose value is a `Tensor`.
|
||||
for each `column` in `feature_columns`:
|
||||
- if `column` is a `SparseColumn`, a feature with `key=column.name`
|
||||
whose `value` is a `SparseTensor`.
|
||||
- if `column` is a `RealValuedColumn, a feature with `key=column.name`
|
||||
whose `value` is a `Tensor`.
|
||||
- if `feauture_columns` is None, then `input` must contains only real
|
||||
valued `Tensor`.
|
||||
|
||||
|
||||
Parameters:
|
||||
feature_columns: An iterable containing all the feature columns used by the
|
||||
model. All items in the set should be instances of classes derived from
|
||||
`FeatureColumn`.
|
||||
model_dir: Directory to save model parameters, graph and etc.
|
||||
n_classes: number of target classes. Default is binary classification.
|
||||
weight_column_name: A string defining feature column name representing
|
||||
weights. It is used to down weight or boost examples during training. It
|
||||
will be multiplied by the loss of the example.
|
||||
optimizer: An instance of `tf.Optimizer` used to train the model. If `None`,
|
||||
will use an Ftrl optimizer.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
feature_columns=None,
|
||||
model_dir=None,
|
||||
n_classes=2,
|
||||
weight_column_name=None,
|
||||
optimizer=None):
|
||||
super(LinearClassifier, self).__init__(
|
||||
model_dir=model_dir,
|
||||
n_classes=n_classes,
|
||||
weight_column_name=weight_column_name,
|
||||
linear_feature_columns=feature_columns,
|
||||
linear_optimizer=optimizer)
|
||||
|
||||
def _get_train_ops(self, features, targets):
|
||||
"""See base class."""
|
||||
if self._linear_feature_columns is None:
|
||||
self._linear_feature_columns = layers.infer_real_valued_columns(features)
|
||||
return super(LinearClassifier, self)._get_train_ops(features, targets)
|
||||
|
||||
|
||||
class LinearRegressor(dnn_linear_combined.DNNLinearCombinedRegressor):
|
||||
"""Linear regressor model.
|
||||
|
||||
Example:
|
||||
```
|
||||
installed_app_id = sparse_column_with_hash_bucket("installed_id", 1e6)
|
||||
impression_app_id = sparse_column_with_hash_bucket("impression_id", 1e6)
|
||||
|
||||
installed_x_impression = crossed_column(
|
||||
[installed_app_id, impression_app_id])
|
||||
|
||||
estimator = LinearRegressor(
|
||||
feature_columns=[impression_app_id, installed_x_impression])
|
||||
|
||||
# Input builders
|
||||
def input_fn_train: # returns X, Y
|
||||
...
|
||||
def input_fn_eval: # returns X, Y
|
||||
...
|
||||
estimator.train(input_fn_train)
|
||||
estimator.evaluate(input_fn_eval)
|
||||
estimator.predict(x)
|
||||
```
|
||||
|
||||
Input of `fit`, `train`, and `evaluate` should have following features,
|
||||
otherwise there will be a KeyError:
|
||||
if `weight_column_name` is not None:
|
||||
key=weight_column_name, value=a `Tensor`
|
||||
for column in `feature_columns`:
|
||||
- if isinstance(column, `SparseColumn`):
|
||||
key=column.name, value=a `SparseTensor`
|
||||
- if isinstance(column, `RealValuedColumn`):
|
||||
key=column.name, value=a `Tensor`
|
||||
- if `feauture_columns` is None:
|
||||
input must contains only real valued `Tensor`.
|
||||
|
||||
Parameters:
|
||||
feature_columns: An iterable containing all the feature columns used by the
|
||||
model. All items in the set should be instances of classes derived from
|
||||
`FeatureColumn`.
|
||||
model_dir: Directory to save model parameters, graph and etc.
|
||||
weight_column_name: A string defining feature column name representing
|
||||
weights. It is used to down weight or boost examples during training. It
|
||||
will be multiplied by the loss of the example.
|
||||
optimizer: An instance of `tf.Optimizer` used to train the model. If `None`,
|
||||
will use an Ftrl optimizer.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
feature_columns=None,
|
||||
model_dir=None,
|
||||
n_classes=2,
|
||||
weight_column_name=None,
|
||||
optimizer=None):
|
||||
super(LinearRegressor, self).__init__(
|
||||
model_dir=model_dir,
|
||||
weight_column_name=weight_column_name,
|
||||
linear_feature_columns=feature_columns,
|
||||
linear_optimizer=optimizer)
|
||||
|
||||
def _get_train_ops(self, features, targets):
|
||||
"""See base class."""
|
||||
if self._linear_feature_columns is None:
|
||||
self._linear_feature_columns = layers.infer_real_valued_columns(features)
|
||||
return super(LinearRegressor, self)._get_train_ops(features, targets)
|
||||
|
||||
|
||||
# TODO(ipolosukhin): Deprecate this class in favor of LinearClassifier.
|
||||
class TensorFlowLinearRegressor(TensorFlowEstimator, _sklearn.RegressorMixin):
|
||||
"""TensorFlow Linear Regression model."""
|
||||
|
||||
@ -50,12 +190,12 @@ class TensorFlowLinearRegressor(TensorFlowEstimator, _sklearn.RegressorMixin):
|
||||
@property
|
||||
def weights_(self):
|
||||
"""Returns weights of the linear regression."""
|
||||
return self.get_tensor_value('linear_regression/weights:0')
|
||||
return self.get_tensor_value('linear_regression/weights')
|
||||
|
||||
@property
|
||||
def bias_(self):
|
||||
"""Returns bias of the linear regression."""
|
||||
return self.get_tensor_value('linear_regression/bias:0')
|
||||
return self.get_tensor_value('linear_regression/bias')
|
||||
|
||||
|
||||
class TensorFlowLinearClassifier(TensorFlowEstimator, _sklearn.ClassifierMixin):
|
||||
@ -89,12 +229,12 @@ class TensorFlowLinearClassifier(TensorFlowEstimator, _sklearn.ClassifierMixin):
|
||||
@property
|
||||
def weights_(self):
|
||||
"""Returns weights of the linear classifier."""
|
||||
return self.get_tensor_value('logistic_regression/weights:0')
|
||||
return self.get_tensor_value('logistic_regression/weights')
|
||||
|
||||
@property
|
||||
def bias_(self):
|
||||
"""Returns weights of the linear classifier."""
|
||||
return self.get_tensor_value('logistic_regression/bias:0')
|
||||
return self.get_tensor_value('logistic_regression/bias')
|
||||
|
||||
|
||||
TensorFlowRegressor = TensorFlowLinearRegressor
|
||||
|
155
tensorflow/contrib/learn/python/learn/estimators/linear_test.py
Normal file
155
tensorflow/contrib/learn/python/learn/estimators/linear_test.py
Normal file
@ -0,0 +1,155 @@
|
||||
# Copyright 2015 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Tests for estimators.linear."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import tensorflow as tf
|
||||
|
||||
|
||||
class LinearClassifierTest(tf.test.TestCase):
|
||||
|
||||
def testTrain(self):
|
||||
"""Tests that loss goes down with training."""
|
||||
|
||||
def input_fn():
|
||||
return {
|
||||
'age': tf.constant([1]),
|
||||
'language': tf.SparseTensor(values=['english'],
|
||||
indices=[[0, 0]],
|
||||
shape=[1, 1])
|
||||
}, tf.constant([[1.]])
|
||||
|
||||
language = tf.contrib.layers.sparse_column_with_hash_bucket('language', 100)
|
||||
age = tf.contrib.layers.real_valued_column('age')
|
||||
|
||||
classifier = tf.contrib.learn.LinearClassifier(
|
||||
feature_columns=[age, language])
|
||||
loss1 = classifier.train(input_fn, steps=100)
|
||||
loss2 = classifier.train(input_fn, steps=200)
|
||||
|
||||
self.assertLess(loss2, loss1)
|
||||
self.assertLess(loss2, 0.01)
|
||||
|
||||
def testTrainOptimizerWithL1Reg(self):
|
||||
"""Tests l1 regularized model has higher loss."""
|
||||
|
||||
def input_fn():
|
||||
return {
|
||||
'language': tf.SparseTensor(values=['hindi'],
|
||||
indices=[[0, 0]],
|
||||
shape=[1, 1])
|
||||
}, tf.constant([[1.]])
|
||||
|
||||
language = tf.contrib.layers.sparse_column_with_hash_bucket('language', 100)
|
||||
classifier_no_reg = tf.contrib.learn.LinearClassifier(
|
||||
feature_columns=[language])
|
||||
classifier_with_reg = tf.contrib.learn.LinearClassifier(
|
||||
feature_columns=[language],
|
||||
optimizer=tf.train.FtrlOptimizer(learning_rate=1.0,
|
||||
l1_regularization_strength=100.))
|
||||
loss_no_reg = classifier_no_reg.train(input_fn, steps=100)
|
||||
loss_with_reg = classifier_with_reg.train(input_fn, steps=100)
|
||||
self.assertLess(loss_no_reg, loss_with_reg)
|
||||
|
||||
def testTrainWithMissingFeature(self):
|
||||
"""Tests that training works with missing features."""
|
||||
|
||||
def input_fn():
|
||||
return {
|
||||
'language': tf.SparseTensor(values=['Swahili', 'turkish'],
|
||||
indices=[[0, 0], [2, 0]],
|
||||
shape=[3, 1])
|
||||
}, tf.constant([[1.], [1.], [1.]])
|
||||
|
||||
language = tf.contrib.layers.sparse_column_with_hash_bucket('language', 100)
|
||||
classifier = tf.contrib.learn.LinearClassifier(feature_columns=[language])
|
||||
loss = classifier.train(input_fn, steps=100)
|
||||
self.assertLess(loss, 0.01)
|
||||
|
||||
def testEval(self):
|
||||
"""Tests that eval produces correct metrics.
|
||||
"""
|
||||
|
||||
def input_fn():
|
||||
return {
|
||||
'age': tf.constant([[1], [2]]),
|
||||
'language': tf.SparseTensor(values=['greek', 'chinise'],
|
||||
indices=[[0, 0], [1, 0]],
|
||||
shape=[2, 1]),
|
||||
}, tf.constant([[1.], [0.]])
|
||||
|
||||
language = tf.contrib.layers.sparse_column_with_hash_bucket('language', 100)
|
||||
age = tf.contrib.layers.real_valued_column('age')
|
||||
classifier = tf.contrib.learn.LinearClassifier(
|
||||
feature_columns=[age, language])
|
||||
|
||||
# Evaluate on untrained model
|
||||
classifier.evaluate(input_fn=input_fn, steps=2)
|
||||
# TODO(ispir): Enable accuracy check after resolving the randomness issue.
|
||||
# self.assertAlmostEqual(.5, evaluated_values['accuracy/mean'])
|
||||
|
||||
# Evaluate on trained mdoel
|
||||
classifier.train(input_fn, steps=100)
|
||||
classifier.evaluate(input_fn=input_fn, steps=2)
|
||||
|
||||
# TODO(ispir): Enable accuracy check after resolving the randomness issue.
|
||||
# self.assertLess(evaluated_values['loss/mean'], 0.3)
|
||||
# self.assertGreater(evaluated_values['accuracy/mean'], .95)
|
||||
|
||||
|
||||
class LinearRegressorTest(tf.test.TestCase):
|
||||
|
||||
def testRegression(self):
|
||||
"""Tests that loss goes down with training."""
|
||||
|
||||
def input_fn():
|
||||
return {
|
||||
'age': tf.constant([1]),
|
||||
'language': tf.SparseTensor(values=['english'],
|
||||
indices=[[0, 0]],
|
||||
shape=[1, 1])
|
||||
}, tf.constant([[10.]])
|
||||
|
||||
language = tf.contrib.layers.sparse_column_with_hash_bucket('language', 100)
|
||||
age = tf.contrib.layers.real_valued_column('age')
|
||||
|
||||
classifier = tf.contrib.learn.LinearRegressor(
|
||||
feature_columns=[age, language])
|
||||
loss1 = classifier.train(input_fn, steps=100)
|
||||
loss2 = classifier.train(input_fn, steps=200)
|
||||
|
||||
self.assertLess(loss2, loss1)
|
||||
self.assertLess(loss2, 0.01)
|
||||
|
||||
|
||||
def boston_input_fn():
|
||||
boston = tf.contrib.learn.datasets.load_boston()
|
||||
features = tf.cast(tf.reshape(tf.constant(boston.data), [-1, 13]), tf.float32)
|
||||
target = tf.cast(tf.reshape(tf.constant(boston.target), [-1, 1]), tf.float32)
|
||||
return features, target
|
||||
|
||||
|
||||
class InferedColumnTest(tf.test.TestCase):
|
||||
|
||||
def testTrain(self):
|
||||
est = tf.contrib.learn.LinearRegressor()
|
||||
est.train(input_fn=boston_input_fn, steps=1)
|
||||
_ = est.evaluate(input_fn=boston_input_fn, steps=1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tf.test.main()
|
@ -111,12 +111,12 @@ class TensorFlowRNNClassifier(TensorFlowEstimator, _sklearn.ClassifierMixin):
|
||||
@property
|
||||
def bias_(self):
|
||||
"""Returns bias of the rnn layer."""
|
||||
return self.get_tensor_value('logistic_regression/bias:0')
|
||||
return self.get_tensor_value('logistic_regression/bias')
|
||||
|
||||
@property
|
||||
def weights_(self):
|
||||
"""Returns weights of the rnn layer."""
|
||||
return self.get_tensor_value('logistic_regression/weights:0')
|
||||
return self.get_tensor_value('logistic_regression/weights')
|
||||
|
||||
|
||||
class TensorFlowRNNRegressor(TensorFlowEstimator, _sklearn.RegressorMixin):
|
||||
@ -201,9 +201,9 @@ class TensorFlowRNNRegressor(TensorFlowEstimator, _sklearn.RegressorMixin):
|
||||
@property
|
||||
def bias_(self):
|
||||
"""Returns bias of the rnn layer."""
|
||||
return self.get_tensor_value('linear_regression/bias:0')
|
||||
return self.get_tensor_value('linear_regression/bias')
|
||||
|
||||
@property
|
||||
def weights_(self):
|
||||
"""Returns weights of the rnn layer."""
|
||||
return self.get_tensor_value('linear_regression/weights:0')
|
||||
return self.get_tensor_value('linear_regression/weights')
|
||||
|
@ -28,12 +28,14 @@ from six import reraise
|
||||
from tensorflow.contrib.framework.python.ops import ops as contrib_ops
|
||||
from tensorflow.contrib.framework.python.ops import variables as contrib_variables
|
||||
from tensorflow.contrib.layers.python.layers import summaries
|
||||
from tensorflow.contrib.learn.python.learn import monitors as monitors_lib
|
||||
from tensorflow.core.util.event_pb2 import SessionLog
|
||||
from tensorflow.python.client import session as tf_session
|
||||
from tensorflow.python.framework import errors
|
||||
from tensorflow.python.framework import ops
|
||||
from tensorflow.python.framework import tensor_util
|
||||
from tensorflow.python.ops import data_flow_ops
|
||||
from tensorflow.python.ops import logging_ops
|
||||
from tensorflow.python.ops import variables
|
||||
from tensorflow.python.platform import gfile
|
||||
from tensorflow.python.platform import tf_logging as logging
|
||||
@ -98,23 +100,24 @@ def _prepare_session(graph,
|
||||
start_services,
|
||||
global_step_tensor,
|
||||
init_op=None,
|
||||
init_feed_dict=None,
|
||||
init_fn=None,
|
||||
supervisor_is_chief=True,
|
||||
supervisor_master='',
|
||||
supervisor_save_model_secs=600,
|
||||
supervisor_save_summaries_secs=10):
|
||||
supervisor_save_model_secs=600):
|
||||
"""Starts a session using the supervisor."""
|
||||
if global_step_tensor is None:
|
||||
global_step_tensor = Supervisor.USE_DEFAULT
|
||||
supervisor = Supervisor(
|
||||
graph,
|
||||
init_op=init_op or Supervisor.USE_DEFAULT,
|
||||
init_feed_dict=init_feed_dict,
|
||||
is_chief=supervisor_is_chief,
|
||||
logdir=output_dir,
|
||||
saver=_make_saver(graph),
|
||||
global_step=global_step_tensor,
|
||||
summary_op=None,
|
||||
save_model_secs=supervisor_save_model_secs,
|
||||
save_summaries_secs=supervisor_save_summaries_secs,
|
||||
init_fn=init_fn)
|
||||
session = supervisor.PrepareSession(master=supervisor_master,
|
||||
start_standard_services=start_services)
|
||||
@ -122,6 +125,23 @@ def _prepare_session(graph,
|
||||
return supervisor, session
|
||||
|
||||
|
||||
def _run_with_monitors(session, step, tensors, feed_dict, monitors):
|
||||
"""Runs session for given tensors with monitor callbacks."""
|
||||
for monitor in monitors:
|
||||
tensors = monitor.step_begin(step, tensors)
|
||||
|
||||
outputs = session.run(tensors, feed_dict=feed_dict)
|
||||
outputs = dict(zip(
|
||||
[t.name if isinstance(t, ops.Tensor) else t for t in tensors],
|
||||
outputs))
|
||||
|
||||
should_stop = False
|
||||
for monitor in monitors:
|
||||
induce_stop = monitor.step_end(step, outputs)
|
||||
should_stop = should_stop or induce_stop
|
||||
return outputs, should_stop
|
||||
|
||||
|
||||
# TODO(ptucker): Add unit test.
|
||||
# TODO(wicke): switch to forced named kwargs
|
||||
def train(graph,
|
||||
@ -130,15 +150,17 @@ def train(graph,
|
||||
loss_op,
|
||||
global_step_tensor=None,
|
||||
init_op=None,
|
||||
init_feed_dict=None,
|
||||
init_fn=None,
|
||||
log_every_steps=10,
|
||||
supervisor_is_chief=True,
|
||||
supervisor_master='',
|
||||
supervisor_save_model_secs=600,
|
||||
supervisor_save_summaries_secs=10,
|
||||
supervisor_save_summaries_steps=100,
|
||||
feed_fn=None,
|
||||
max_steps=None,
|
||||
fail_on_nan_loss=True):
|
||||
fail_on_nan_loss=True,
|
||||
monitors=None):
|
||||
"""Train a model.
|
||||
|
||||
Given `graph`, a directory to write outputs to (`output_dir`), and some ops,
|
||||
@ -164,6 +186,8 @@ def train(graph,
|
||||
one is extracted from the graph using the same logic as in `Supervisor`.
|
||||
init_op: An op that initializes the graph. If `None`, use `Supervisor`'s
|
||||
default.
|
||||
init_feed_dict: A dictionary that maps `Tensor` objects to feed values.
|
||||
This feed dictionary will be used when `init_op` is evaluated.
|
||||
init_fn: Optional callable passed to Supervisor to initialize the model.
|
||||
log_every_steps: Output logs regularly. The logs contain timing data and the
|
||||
current loss.
|
||||
@ -172,13 +196,15 @@ def train(graph,
|
||||
supervisor_master: The master string to use when preparing the session.
|
||||
supervisor_save_model_secs: Save a checkpoint every
|
||||
`supervisor_save_model_secs` seconds when training.
|
||||
supervisor_save_summaries_secs: Save summaries every
|
||||
`supervisor_save_summaries_secs` seconds when training.
|
||||
supervisor_save_summaries_steps: Save summaries every
|
||||
`supervisor_save_summaries_steps` seconds when training.
|
||||
feed_fn: A function that is called every iteration to produce a `feed_dict`
|
||||
passed to `session.run` calls. Optional.
|
||||
max_steps: Train until `global_step_tensor` evaluates to this value.
|
||||
fail_on_nan_loss: If true, raise `NanLossDuringTrainingError` if `loss_op`
|
||||
evaluates to `NaN`. If false, continue training as if nothing happened.
|
||||
monitors: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
Returns:
|
||||
The final loss value.
|
||||
@ -194,17 +220,30 @@ def train(graph,
|
||||
graph, global_step_tensor)
|
||||
if global_step_tensor is None:
|
||||
raise ValueError('No "global_step" was provided or found in the graph.')
|
||||
|
||||
# TODO(ipolosukhin): Replace all functionality of Supervisor with Monitors.
|
||||
if not monitors:
|
||||
monitors = monitors_lib.get_default_monitors(
|
||||
loss_op=loss_op,
|
||||
summary_op=logging_ops.get_summary_op(),
|
||||
save_summary_steps=supervisor_save_summaries_steps,
|
||||
output_dir=output_dir)
|
||||
|
||||
# Start monitors, can create graph parts.
|
||||
for monitor in monitors:
|
||||
monitor.begin(max_steps=max_steps)
|
||||
|
||||
supervisor, session = _prepare_session(
|
||||
graph=graph,
|
||||
output_dir=output_dir,
|
||||
start_services=True,
|
||||
global_step_tensor=global_step_tensor,
|
||||
init_op=init_op,
|
||||
init_feed_dict=init_feed_dict,
|
||||
init_fn=init_fn,
|
||||
supervisor_is_chief=supervisor_is_chief,
|
||||
supervisor_master=supervisor_master,
|
||||
supervisor_save_model_secs=supervisor_save_model_secs,
|
||||
supervisor_save_summaries_secs=supervisor_save_summaries_secs)
|
||||
supervisor_save_model_secs=supervisor_save_model_secs)
|
||||
|
||||
with session:
|
||||
get_current_step = lambda: session.run(global_step_tensor)
|
||||
@ -215,13 +254,18 @@ def train(graph,
|
||||
loss_value = None
|
||||
logging.info('Training steps [%d,%s)', last_step, 'inf'
|
||||
if max_steps is None else str(max_steps))
|
||||
|
||||
excinfo = None
|
||||
try:
|
||||
while not supervisor.ShouldStop() and (
|
||||
(max_steps is None) or (last_step < max_steps)):
|
||||
start_time = time.time()
|
||||
feed_dict = feed_fn() if feed_fn is not None else None
|
||||
_, loss_value = session.run([train_op, loss_op], feed_dict=feed_dict)
|
||||
|
||||
outputs, should_stop = _run_with_monitors(
|
||||
session, last_step + 1, [train_op, loss_op], feed_dict, monitors)
|
||||
|
||||
loss_value = outputs[loss_op.name]
|
||||
if np.isnan(loss_value):
|
||||
failure_message = 'Model diverged with loss = NaN.'
|
||||
if fail_on_nan_loss:
|
||||
@ -230,6 +274,9 @@ def train(graph,
|
||||
else:
|
||||
logging.warning(failure_message)
|
||||
|
||||
if should_stop:
|
||||
break
|
||||
|
||||
this_step = get_current_step()
|
||||
|
||||
if this_step <= last_step:
|
||||
@ -268,12 +315,11 @@ def train(graph,
|
||||
logging.info('Saving checkpoint for step %d to checkpoint: %s.' % (
|
||||
last_step, ckpt_path))
|
||||
supervisor.saver.save(session, ckpt_path, global_step=last_step)
|
||||
if supervisor.summary_op is not None:
|
||||
summary_strs = session.run(supervisor.summary_op)
|
||||
supervisor.summary_writer.add_summary(summary_strs, last_step)
|
||||
supervisor.summary_writer.add_session_log(
|
||||
SessionLog(status=SessionLog.STOP), last_step)
|
||||
supervisor.summary_writer.close()
|
||||
|
||||
# Finish monitors.
|
||||
for monitor in monitors:
|
||||
monitor.end()
|
||||
|
||||
# catch OutOfRangeError which is thrown when queue is out of data (and for
|
||||
# other reasons as well).
|
||||
except errors.OutOfRangeError as e:
|
||||
@ -354,6 +400,9 @@ def evaluate(graph,
|
||||
if isinstance(value, ops.Tensor):
|
||||
summaries.summarize_tensor(value, tag=key)
|
||||
|
||||
# Create or get summary op.
|
||||
summary_op = logging_ops.get_summary_op()
|
||||
|
||||
# TODO(wicke): Don't use supervisor here, or switch to output_dir=eval_dir.
|
||||
supervisor, session = _prepare_session(
|
||||
graph=graph,
|
||||
@ -363,8 +412,7 @@ def evaluate(graph,
|
||||
init_op=init_op,
|
||||
supervisor_is_chief=True,
|
||||
supervisor_master=supervisor_master,
|
||||
supervisor_save_model_secs=None,
|
||||
supervisor_save_summaries_secs=None)
|
||||
supervisor_save_model_secs=None)
|
||||
global_step_tensor = supervisor.global_step
|
||||
|
||||
with session:
|
||||
@ -394,14 +442,17 @@ def evaluate(graph,
|
||||
', '.join('%s = %s' % (k, v)
|
||||
for k, v in eval_results.items()))
|
||||
finally:
|
||||
# Make our own summary writer and write a summary to the eval dir
|
||||
if supervisor.summary_op is not None:
|
||||
# Make our own summary writer and write a summary to the eval dir.
|
||||
# Only is feed_fn is not provided.
|
||||
# TODO(ipolosukhin): Convert evaluation to use streaming_metrics,
|
||||
# then we can save for non feed_fn as well.
|
||||
if summary_op is not None and feed_fn is None:
|
||||
summary_writer = None
|
||||
try:
|
||||
summary_writer = SummaryWriter(output_dir,
|
||||
graph_def=session.graph_def)
|
||||
|
||||
summary_str = session.run(supervisor.summary_op)
|
||||
summary_str = session.run(summary_op)
|
||||
if summary_str:
|
||||
summary_writer.add_summary(summary_str, current_global_step)
|
||||
finally:
|
||||
@ -414,7 +465,10 @@ def evaluate(graph,
|
||||
# catch OutOfRangeError which is thrown when queue is out of data (and for
|
||||
# other reasons as well).
|
||||
except errors.OutOfRangeError as e:
|
||||
logging.warn('Input queue exhausted: %s.', e)
|
||||
logging.warn('Input queue is exhausted: %s.', e)
|
||||
# catch StopIteration which is thrown is DataReader is out of data.
|
||||
except StopIteration as e:
|
||||
logging.info('Input iterator is exhausted: %s.', e)
|
||||
|
||||
return eval_results, current_global_step
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# TODO(ipolosukhin): Replace this module with feed-dict queue runners & queues.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
@ -33,6 +36,8 @@ from .dask_io import HAS_DASK, extract_dask_data, extract_dask_labels
|
||||
|
||||
def _get_in_out_shape(x_shape, y_shape, n_classes, batch_size):
|
||||
"""Returns shape for input and output of the data feeder."""
|
||||
if batch_size < 0:
|
||||
batch_size = x_shape[0]
|
||||
x_shape = list(x_shape[1:]) if len(x_shape) > 1 else [1]
|
||||
input_shape = [batch_size] + x_shape
|
||||
if y_shape is None:
|
||||
@ -65,7 +70,8 @@ def _is_iterable(X):
|
||||
return hasattr(X, 'next') or hasattr(X, '__next__')
|
||||
|
||||
|
||||
def setup_train_data_feeder(X, y, n_classes, batch_size):
|
||||
def setup_train_data_feeder(
|
||||
X, y, n_classes, batch_size, shuffle=True, epochs=None):
|
||||
"""Create data feeder, to sample inputs from dataset.
|
||||
|
||||
If X and y are iterators, use StreamingDataFeeder.
|
||||
@ -95,7 +101,8 @@ def setup_train_data_feeder(X, y, n_classes, batch_size):
|
||||
raise ValueError('Both X and y should be iterators for '
|
||||
'streaming learning to work.')
|
||||
data_feeder_cls = StreamingDataFeeder
|
||||
return data_feeder_cls(X, y, n_classes, batch_size)
|
||||
return data_feeder_cls(
|
||||
X, y, n_classes, batch_size, shuffle=shuffle, epochs=epochs)
|
||||
|
||||
|
||||
def _batch_data(X, batch_size):
|
||||
@ -189,7 +196,7 @@ class DataFeeder(object):
|
||||
output_dtype: dtype of output.
|
||||
"""
|
||||
|
||||
def __init__(self, X, y, n_classes, batch_size, random_state=None):
|
||||
def __init__(self, X, y, n_classes, batch_size, shuffle=True, random_state=None, epochs=None):
|
||||
x_dtype = np.int64 if X.dtype == np.int64 else np.float32
|
||||
y_dtype = (
|
||||
np.int64 if n_classes is not None and n_classes > 1 else np.float32)
|
||||
@ -201,6 +208,7 @@ class DataFeeder(object):
|
||||
self.y = y
|
||||
self.n_classes = n_classes
|
||||
self.batch_size = batch_size
|
||||
self.max_epochs = epochs
|
||||
self.input_shape, self.output_shape = _get_in_out_shape(self.X.shape, None
|
||||
if self.y is None
|
||||
else self.y.shape,
|
||||
@ -213,9 +221,13 @@ class DataFeeder(object):
|
||||
self.output_dtype = np.float32
|
||||
else:
|
||||
self.output_dtype = y.dtype
|
||||
self.shuffle = shuffle
|
||||
self.random_state = np.random.RandomState(
|
||||
42) if random_state is None else random_state
|
||||
self.indices = self.random_state.permutation(self.X.shape[0])
|
||||
if self.shuffle:
|
||||
self.indices = self.random_state.permutation(self.X.shape[0])
|
||||
else:
|
||||
self.indices = np.array(range(self.X.shape[0]))
|
||||
self.offset = 0
|
||||
self.epoch = 0
|
||||
self._epoch_placeholder = None
|
||||
@ -283,16 +295,19 @@ class DataFeeder(object):
|
||||
from X and y.
|
||||
"""
|
||||
def _feed_dict_fn():
|
||||
if self.max_epochs is not None and self.epoch + 1 > self.max_epochs:
|
||||
raise StopIteration
|
||||
assert self._input_placeholder != None
|
||||
feed_dict = {}
|
||||
if self._epoch_placeholder is not None:
|
||||
feed_dict[self._epoch_placeholder.name] = [self.epoch]
|
||||
|
||||
# take random indices
|
||||
# take next batch of indices
|
||||
if self.batch_size < 0:
|
||||
batch_indices = self.indices
|
||||
else:
|
||||
batch_indices = self.indices[self.offset:self.offset + self.batch_size]
|
||||
end = min(self.X.shape[0], self.offset + self.batch_size)
|
||||
batch_indices = self.indices[self.offset:end]
|
||||
|
||||
# assign input features from random indices
|
||||
inp = np.array(self.X[batch_indices]).reshape((batch_indices.shape[0], 1)) \
|
||||
@ -300,10 +315,13 @@ class DataFeeder(object):
|
||||
feed_dict[self._input_placeholder.name] = inp
|
||||
|
||||
# move offset and reset it if necessary
|
||||
self.offset += self.batch_size
|
||||
if self.offset >= self.X.shape[0]:
|
||||
self.indices = self.random_state.permutation(self.X.shape[0])
|
||||
self.offset = 0
|
||||
if self.batch_size > 0:
|
||||
self.offset += self.batch_size
|
||||
if self.offset >= self.X.shape[0]:
|
||||
self.indices = self.random_state.permutation(self.X.shape[0])
|
||||
self.offset = 0
|
||||
self.epoch += 1
|
||||
else:
|
||||
self.epoch += 1
|
||||
|
||||
# return early if there are no labels
|
||||
@ -359,15 +377,21 @@ class StreamingDataFeeder(DataFeeder):
|
||||
output_dtype: dtype of output.
|
||||
"""
|
||||
|
||||
def __init__(self, X, y, n_classes, batch_size):
|
||||
def __init__(self, X, y, n_classes, batch_size, shuffle=False, epochs=None):
|
||||
X_first_el = six.next(X)
|
||||
y_first_el = six.next(y)
|
||||
self.X = itertools.chain([X_first_el], X)
|
||||
self.y = itertools.chain([y_first_el], y)
|
||||
if y is not None:
|
||||
y_first_el = six.next(y)
|
||||
self.y = itertools.chain([y_first_el], y)
|
||||
else:
|
||||
y_first_el = None
|
||||
self.y = None
|
||||
self.n_classes = n_classes
|
||||
self.batch_size = batch_size
|
||||
self.input_shape, self.output_shape = _get_in_out_shape(
|
||||
[1] + list(X_first_el.shape), [1] + list(y_first_el.shape), n_classes,
|
||||
[1] + list(X_first_el.shape),
|
||||
[1] + list(y_first_el.shape) if y is not None else None,
|
||||
n_classes,
|
||||
batch_size)
|
||||
self.input_dtype = X_first_el.dtype
|
||||
# Convert float64 to float32, as all the parameters in the model are
|
||||
@ -396,21 +420,37 @@ class StreamingDataFeeder(DataFeeder):
|
||||
A function that when called samples a random subset of batch size
|
||||
from X and y.
|
||||
"""
|
||||
self.stopped = False
|
||||
|
||||
def _feed_dict_fn():
|
||||
if self.stopped:
|
||||
raise StopIteration
|
||||
inp = np.zeros(self.input_shape, dtype=self.input_dtype)
|
||||
out = np.zeros(self.output_shape, dtype=self.output_dtype)
|
||||
if self.y is not None:
|
||||
out = np.zeros(self.output_shape, dtype=self.output_dtype)
|
||||
for i in xrange(self.batch_size):
|
||||
inp[i, :] = six.next(self.X)
|
||||
y = six.next(self.y)
|
||||
if self.n_classes > 1:
|
||||
if len(self.output_shape) == 2:
|
||||
out.itemset((i, y), 1.0)
|
||||
# Add handling when queue ends.
|
||||
try:
|
||||
inp[i, :] = six.next(self.X)
|
||||
except StopIteration:
|
||||
self.stopped = True
|
||||
inp = inp[:i, :]
|
||||
if self.y is not None:
|
||||
out = out[:i]
|
||||
break
|
||||
|
||||
if self.y is not None:
|
||||
y = six.next(self.y)
|
||||
if self.n_classes > 1:
|
||||
if len(self.output_shape) == 2:
|
||||
out.itemset((i, y), 1.0)
|
||||
else:
|
||||
for idx, value in enumerate(y):
|
||||
out.itemset(tuple([i, idx, value]), 1.0)
|
||||
else:
|
||||
for idx, value in enumerate(y):
|
||||
out.itemset(tuple([i, idx, value]), 1.0)
|
||||
else:
|
||||
out[i] = y
|
||||
out[i] = y
|
||||
if self.y is None:
|
||||
return {self._input_placeholder.name: inp}
|
||||
return {self._input_placeholder.name: inp,
|
||||
self._output_placeholder.name: out}
|
||||
|
||||
@ -443,7 +483,7 @@ class DaskDataFeeder(object):
|
||||
input_dtype: dtype of input.
|
||||
output_dtype: dtype of output.
|
||||
"""
|
||||
def __init__(self, X, y, n_classes, batch_size, random_state=None):
|
||||
def __init__(self, X, y, n_classes, batch_size, shuffle=True, random_state=None):
|
||||
import dask.dataframe as dd
|
||||
# TODO(terrytangyuan): check X and y dtypes in dask_io like pandas
|
||||
self.X = X
|
||||
|
@ -17,221 +17,199 @@ from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
from tensorflow.core.framework import summary_pb2
|
||||
from tensorflow.python.training import training as train
|
||||
from tensorflow.contrib.learn.python.learn.io.data_feeder import setup_train_data_feeder
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
# pylint: disable=too-few-public-methods
|
||||
# pylint: disable=too-many-arguments
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
|
||||
|
||||
def default_monitor(verbose=1):
|
||||
"""Returns very simple monitor object to summarize training progress.
|
||||
|
||||
Args:
|
||||
verbose: Level of verbosity of output.
|
||||
|
||||
Returns:
|
||||
Default monitor object.
|
||||
"""
|
||||
return BaseMonitor(verbose=verbose)
|
||||
from tensorflow.python.platform import tf_logging as logging
|
||||
from tensorflow.python.training import summary_io
|
||||
|
||||
|
||||
class BaseMonitor(object):
|
||||
"""Base class for all learning monitors.
|
||||
|
||||
Stores and reports training loss throughout learning
|
||||
|
||||
Parameters:
|
||||
print_steps: Number of steps in between printing cost.
|
||||
early_stopping_rounds: Activates early stopping if this is not None.
|
||||
Loss needs to decrease at least every
|
||||
<early_stopping_rounds>
|
||||
round(s) to continue training. (default: None)
|
||||
verbose: Level of verbosity of output.
|
||||
"""Base class for Monitors.
|
||||
|
||||
Defines basic interfaces of Monitors.
|
||||
"""
|
||||
|
||||
def __init__(self, print_steps=100, early_stopping_rounds=None, verbose=1):
|
||||
self.print_steps = print_steps
|
||||
self.early_stopping_rounds = early_stopping_rounds
|
||||
|
||||
self.converged = False
|
||||
self.min_loss = np.inf
|
||||
self.min_loss_i = 0
|
||||
self.last_loss_seen = np.inf
|
||||
self.steps = 0
|
||||
self.print_train_loss_buffer = []
|
||||
self.all_train_loss_buffer = []
|
||||
self.verbose = verbose
|
||||
self.epoch = None
|
||||
|
||||
def update(self, global_step, step_number, training_loss, sess,
|
||||
feed_params_fn, loss_expression_tensor):
|
||||
"""Adds training_loss to monitor.
|
||||
|
||||
Triggers printed output if appropriate
|
||||
|
||||
Args:
|
||||
global_step: global step number
|
||||
step_number: current step in training
|
||||
training_loss: float value of training loss
|
||||
sess: session for computation (used to calculate validation loss)
|
||||
feed_params_fn: function generating dict with information like
|
||||
epoch. Sometimes None.
|
||||
loss_expression_tensor: Tensor applied to validation data to
|
||||
calculate val loss
|
||||
|
||||
"""
|
||||
self.steps = step_number
|
||||
self.global_step = global_step
|
||||
self.print_train_loss_buffer.append(training_loss)
|
||||
self.all_train_loss_buffer.append(training_loss)
|
||||
self.sess = sess
|
||||
self.loss_expression_tensor = loss_expression_tensor
|
||||
self._set_last_loss_seen()
|
||||
if self.last_loss_seen < self.min_loss:
|
||||
self.min_loss = self.last_loss_seen
|
||||
self.min_loss_i = self.steps
|
||||
self._set_epoch(feed_params_fn)
|
||||
self.report()
|
||||
|
||||
def _set_last_loss_seen(self):
|
||||
"""Sets last_loss_seen attribute to most recent training error."""
|
||||
self.last_loss_seen = self.all_train_loss_buffer[-1]
|
||||
self._estimator = None
|
||||
|
||||
def report(self):
|
||||
"""Checks whether to report, and prints loss information if appropriate."""
|
||||
if self.verbose and (self.steps % self.print_steps == 0):
|
||||
self._set_training_summary()
|
||||
print(self._summary_str)
|
||||
|
||||
def set_estimator(self, estimator):
|
||||
self._estimator = estimator
|
||||
|
||||
def monitor_inducing_stop(self):
|
||||
"""Returns True if the monitor requests the model stop.
|
||||
|
||||
Returns:
|
||||
True if the monitor requests the model stop (e.g. for early stopping).
|
||||
"""
|
||||
if self.early_stopping_rounds is None:
|
||||
return False
|
||||
stop_now = (self.steps - self.min_loss_i >= self.early_stopping_rounds)
|
||||
if stop_now:
|
||||
sys.stderr.write("Stopping. Best step:\n step {} with loss {}\n"
|
||||
.format(self.min_loss_i, self.min_loss))
|
||||
return stop_now
|
||||
|
||||
def create_val_feed_dict(self, inp, out):
|
||||
"""Validation requires access to TensorFlow placeholders.
|
||||
|
||||
Not used in this Monitor
|
||||
def begin(self, max_steps=None):
|
||||
"""Callback at the beginning of training/evaluation.
|
||||
|
||||
Args:
|
||||
inp: not used
|
||||
out: not used
|
||||
max_steps: Maximum steps this training will run until.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _set_epoch(self, feed_params_fn):
|
||||
"""Sets self.epoch from a function providing this info in a dict."""
|
||||
if feed_params_fn:
|
||||
feed_params = feed_params_fn()
|
||||
self.epoch = feed_params["epoch"] if "epoch" in feed_params else None
|
||||
|
||||
def _set_training_summary(self):
|
||||
"""Returns the string to be written describing training progress"""
|
||||
avg_train_loss = np.mean(self.print_train_loss_buffer)
|
||||
self.print_train_loss_buffer = []
|
||||
if self.epoch:
|
||||
self._summary_str = (
|
||||
"Step #{step}, epoch #{epoch}, avg. train loss: {loss:.5f}"
|
||||
.format(step=self.steps,
|
||||
loss=avg_train_loss,
|
||||
epoch=self.epoch))
|
||||
else:
|
||||
self._summary_str = ("Step #{step}, avg. train loss: {loss:.5f}"
|
||||
.format(step=self.global_step,
|
||||
loss=avg_train_loss))
|
||||
self._modify_summary_string()
|
||||
|
||||
def _modify_summary_string(self):
|
||||
"""Makes monitor specific changes to printed summary.
|
||||
|
||||
Nothing interesting in BaseMonitor
|
||||
"""
|
||||
def end(self):
|
||||
"""Callback at the end of training/evaluation."""
|
||||
pass
|
||||
|
||||
def epoch_begin(self, epoch):
|
||||
pass
|
||||
|
||||
class ValidationMonitor(BaseMonitor):
|
||||
"""Monitor that reports validation score and uses it for early stopping.
|
||||
def epoch_end(self, epoch):
|
||||
pass
|
||||
|
||||
def step_begin(self, step, tensors): # pylint: disable=unused-argument
|
||||
"""Callback before training step begins.
|
||||
|
||||
Use this callback to:
|
||||
- override which tensors to run.
|
||||
|
||||
Args:
|
||||
step: int, global step of the model.
|
||||
tensors: list of `Tensors` that going to be passed to session.run.
|
||||
|
||||
Returns:
|
||||
Dict of `Tensors` that going to be ran.
|
||||
"""
|
||||
return tensors
|
||||
|
||||
def step_end(self, step, output): # pylint: disable=unused-argument
|
||||
"""Callback after training step finished.
|
||||
|
||||
Use this callback to:
|
||||
- log results.
|
||||
- save checkpoints.
|
||||
- compute validation score.
|
||||
- perform early stopping.
|
||||
|
||||
Args:
|
||||
step: `int`, global step of the model.
|
||||
output: `dict` of `np.array` results executed.
|
||||
|
||||
Returns:
|
||||
`bool`, `True` if model should stop, `False` or `None` if continue.
|
||||
"""
|
||||
return False
|
||||
|
||||
|
||||
class EveryN(BaseMonitor):
|
||||
"""Base class for monitors that execute callbacks every n steps / seconds.
|
||||
|
||||
Parameters:
|
||||
val_X: Validation features
|
||||
val_y: Validation labels
|
||||
n_classes: Number of labels in output. 0 for regression
|
||||
print_steps: Number of steps in between printing cost.
|
||||
early_stopping_rounds: Activates early stopping if this is not None.
|
||||
Loss needs to decrease at least every
|
||||
<early_stopping_rounds>
|
||||
round(s) to continue training. (default: None)
|
||||
every_n_steps: int, calls `every_n_step_{begin,end}` every this many steps.
|
||||
first_n_steps: int, calls `every_n_step_{begin,end}` for first n steps.
|
||||
|
||||
TODO(ipolosukhin): Add also every n seconds.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
val_X,
|
||||
val_y,
|
||||
n_classes=0,
|
||||
print_steps=100,
|
||||
early_stopping_rounds=None):
|
||||
super(ValidationMonitor, self).__init__(
|
||||
print_steps=print_steps,
|
||||
early_stopping_rounds=early_stopping_rounds)
|
||||
self.val_feeder = setup_train_data_feeder(val_X, val_y, n_classes, -1)
|
||||
self.print_val_loss_buffer = []
|
||||
self.all_val_loss_buffer = []
|
||||
self._summary_writer = None
|
||||
def __init__(
|
||||
self, every_n_steps=100, first_n_steps=1):
|
||||
self._every_n_steps = every_n_steps
|
||||
self._first_n_steps = first_n_steps
|
||||
self._max_steps = None
|
||||
|
||||
def create_val_feed_dict(self, inp, out):
|
||||
"""Set tensorflow placeholders and create validation data feed."""
|
||||
self.val_feeder.set_placeholders(inp, out)
|
||||
self.val_dict = self.val_feeder.get_feed_dict_fn()()
|
||||
def begin(self, max_steps=None):
|
||||
self._max_steps = max_steps
|
||||
|
||||
def every_n_step_begin(self, step, tensors): # pylint: disable=unused-argument
|
||||
return tensors
|
||||
|
||||
def every_n_step_end(self, step, outputs): # pylint: disable=unused-argument
|
||||
return False
|
||||
|
||||
def step_begin(self, step, tensors):
|
||||
if (step <= self._first_n_steps or step % self._every_n_steps == 0 or
|
||||
step == self._max_steps):
|
||||
tensors = self.every_n_step_begin(step, tensors)
|
||||
return tensors
|
||||
|
||||
def step_end(self, step, output):
|
||||
to_stop = False
|
||||
if (step <= self._first_n_steps or step % self._every_n_steps == 0 or
|
||||
step == self._max_steps):
|
||||
to_stop = self.every_n_step_end(step, output)
|
||||
return to_stop
|
||||
|
||||
|
||||
class PrintTensor(EveryN):
|
||||
|
||||
def __init__(self, tensor_names, every_n=100, first_n=1):
|
||||
super(PrintTensor, self).__init__(every_n, first_n)
|
||||
self._tensor_names = tensor_names
|
||||
|
||||
def every_n_step_begin(self, unused_step, tensors):
|
||||
return tensors + self._tensor_names
|
||||
|
||||
def every_n_step_end(self, step, outputs):
|
||||
stats = []
|
||||
for name in self._tensor_names:
|
||||
if name in outputs:
|
||||
stats.append("%s = %s" % (name, str(outputs[name])))
|
||||
logging.info("Step %d: %s" % (step, ", ".join(stats)))
|
||||
|
||||
|
||||
class SummarySaver(EveryN):
|
||||
"""Saves summary every N seconds."""
|
||||
|
||||
def __init__(self, summary_op, save_steps=100, output_dir=None):
|
||||
# TODO(ipolosukhin): Implement every N seconds.
|
||||
super(SummarySaver, self).__init__(every_n_steps=save_steps)
|
||||
self._summary_op = summary_op
|
||||
self._summary_writer = None
|
||||
if output_dir:
|
||||
self._summary_writer = summary_io.SummaryWriter(output_dir)
|
||||
|
||||
def set_estimator(self, estimator):
|
||||
super(ValidationMonitor, self).set_estimator(estimator)
|
||||
if estimator._output_dir is None:
|
||||
return
|
||||
self._summary_writer = train.SummaryWriter(os.path.join(estimator._output_dir, 'eval'))
|
||||
super(SummarySaver, self).set_estimator(estimator)
|
||||
self._summary_writer = summary_io.SummaryWriter(self._estimator.model_dir)
|
||||
|
||||
def _set_last_loss_seen(self):
|
||||
"""Sets self.last_loss_seen to most recent validation loss.
|
||||
def every_n_step_begin(self, unused_step, tensors):
|
||||
return tensors + [self._summary_op]
|
||||
|
||||
Also stores this value to appropriate buffers
|
||||
"""
|
||||
[val_loss] = self.sess.run(
|
||||
[self.loss_expression_tensor],
|
||||
feed_dict=self.val_dict)
|
||||
self.last_loss_seen = val_loss
|
||||
self.all_val_loss_buffer.append(val_loss)
|
||||
self.print_val_loss_buffer.append(val_loss)
|
||||
if self._summary_writer is not None:
|
||||
summary = summary_pb2.Summary()
|
||||
value = summary.value.add()
|
||||
value.tag = "loss"
|
||||
value.simple_value = float(val_loss)
|
||||
self._summary_writer.add_summary(summary, self.global_step)
|
||||
def every_n_step_end(self, step, outputs):
|
||||
summary_strs = outputs[self._summary_op.name]
|
||||
if self._summary_writer:
|
||||
self._summary_writer.add_summary(summary_strs, step)
|
||||
return False
|
||||
|
||||
def _modify_summary_string(self):
|
||||
"""Flushes validation print buffer into summary string."""
|
||||
avg_val_loss = np.mean(self.print_val_loss_buffer)
|
||||
self.print_val_loss_buffer = []
|
||||
val_loss_string = "avg. val loss: {val_loss:.5f}".format(
|
||||
val_loss=avg_val_loss)
|
||||
self._summary_str = (", ".join([self._summary_str, val_loss_string]))
|
||||
def end(self):
|
||||
self._summary_writer.flush()
|
||||
|
||||
|
||||
class ValidationMonitor(EveryN):
|
||||
"""Runs evaluation every n steps.
|
||||
|
||||
Can do early stopping on validation loss if `early_stopping_rounds` provided.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, x=None, y=None, input_fn=None,
|
||||
every_n_steps=100, early_stopping_rounds=None):
|
||||
super(ValidationMonitor, self).__init__(every_n_steps=every_n_steps)
|
||||
if x is None and input_fn is None:
|
||||
raise ValueError("Either x or input_fn should be provided.")
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.input_fn = input_fn
|
||||
self.min_loss_step = 0
|
||||
self.min_loss = None
|
||||
self.early_stopping_rounds = early_stopping_rounds
|
||||
|
||||
def every_n_step_end(self, step, unused_outputs):
|
||||
outputs = self._estimator.evaluate(
|
||||
x=self.x, y=self.y, input_fn=self.input_fn)
|
||||
stats = []
|
||||
for name in outputs:
|
||||
stats.append("%s = %s" % (name, str(outputs[name])))
|
||||
logging.info("Validation (step %d): %s" % (step, ", ".join(stats)))
|
||||
if self.early_stopping_rounds is not None:
|
||||
if self.min_loss is None or outputs["loss"] < self.min_loss:
|
||||
self.min_loss = outputs["loss"]
|
||||
self.min_loss_step = step
|
||||
stop_now = (step - self.min_loss_step >= self.early_stopping_rounds)
|
||||
if stop_now:
|
||||
logging.info("Stopping. Best step: {} with loss {}."
|
||||
.format(self.min_loss_step, self.min_loss))
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_default_monitors(loss_op=None, summary_op=None, save_summary_steps=100,
|
||||
output_dir=None):
|
||||
monitors = []
|
||||
if loss_op is not None:
|
||||
monitors.append(PrintTensor([loss_op.name]))
|
||||
if summary_op is not None:
|
||||
monitors.append(SummarySaver(summary_op, save_steps=save_summary_steps,
|
||||
output_dir=output_dir))
|
||||
return monitors
|
||||
|
@ -17,9 +17,12 @@ from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from tensorflow.contrib import layers
|
||||
from tensorflow.contrib.learn.python.learn.ops import dropout_ops
|
||||
from tensorflow.python.framework import ops
|
||||
from tensorflow.python.ops import array_ops as array_ops_
|
||||
from tensorflow.python.ops import control_flow_ops
|
||||
from tensorflow.python.ops import nn
|
||||
from tensorflow.python.ops import variable_scope as vs
|
||||
from tensorflow.contrib.learn.python.learn.ops import dropout_ops
|
||||
|
||||
|
||||
def dnn(tensor_in, hidden_units, activation=nn.relu, dropout=None):
|
||||
@ -49,5 +52,9 @@ def dnn(tensor_in, hidden_units, activation=nn.relu, dropout=None):
|
||||
if activation is not None:
|
||||
tensor_in = activation(tensor_in)
|
||||
if dropout is not None:
|
||||
tensor_in = dropout_ops.dropout(tensor_in, prob=(1.0 - dropout))
|
||||
is_training = array_ops_.squeeze(ops.get_collection('IS_TRAINING'))
|
||||
tensor_in = control_flow_ops.cond(
|
||||
is_training,
|
||||
lambda: dropout_ops.dropout(tensor_in, prob=(1.0 - dropout)),
|
||||
lambda: tensor_in)
|
||||
return tensor_in
|
||||
|
@ -0,0 +1,120 @@
|
||||
# Copyright 2016 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
|
||||
"""Tests `FeedingQueueRunner` using arrays and `DataFrames`."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
import tensorflow.contrib.learn.python.learn.dataframe.queues.feeding_functions as ff
|
||||
|
||||
# pylint: disable=g-import-not-at-top
|
||||
try:
|
||||
import pandas as pd
|
||||
HAS_PANDAS = True
|
||||
except ImportError:
|
||||
HAS_PANDAS = False
|
||||
|
||||
|
||||
def get_rows(array, row_indices):
|
||||
rows = [array[i] for i in row_indices]
|
||||
return np.vstack(rows)
|
||||
|
||||
|
||||
class FeedingQueueRunnerTestCase(tf.test.TestCase):
|
||||
"""Tests for `FeedingQueueRunner`."""
|
||||
|
||||
def testArrayFeeding(self):
|
||||
with tf.Graph().as_default():
|
||||
array = np.arange(32).reshape([16, 2])
|
||||
q = ff.enqueue_data(array, capacity=100)
|
||||
batch_size = 3
|
||||
dq_op = q.dequeue_many(batch_size)
|
||||
with tf.Session() as sess:
|
||||
coord = tf.train.Coordinator()
|
||||
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
|
||||
for i in range(100):
|
||||
indices = [j % array.shape[0]
|
||||
for j in range(batch_size * i, batch_size * (i + 1))]
|
||||
expected_dq = get_rows(array, indices)
|
||||
dq = sess.run(dq_op)
|
||||
np.testing.assert_array_equal(indices, dq[0])
|
||||
np.testing.assert_array_equal(expected_dq, dq[1])
|
||||
coord.request_stop()
|
||||
coord.join(threads)
|
||||
|
||||
def testPandasFeeding(self):
|
||||
if not HAS_PANDAS:
|
||||
return
|
||||
with tf.Graph().as_default():
|
||||
array1 = np.arange(32)
|
||||
array2 = np.arange(32, 64)
|
||||
df = pd.DataFrame({"a": array1, "b": array2}, index=np.arange(64, 96))
|
||||
q = ff.enqueue_data(df, capacity=100)
|
||||
batch_size = 5
|
||||
dq_op = q.dequeue_many(5)
|
||||
with tf.Session() as sess:
|
||||
coord = tf.train.Coordinator()
|
||||
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
|
||||
for i in range(100):
|
||||
indices = [j % array1.shape[0]
|
||||
for j in range(batch_size * i, batch_size * (i + 1))]
|
||||
expected_df_indices = df.index[indices]
|
||||
expected_rows = df.iloc[indices]
|
||||
dq = sess.run(dq_op)
|
||||
np.testing.assert_array_equal(expected_df_indices, dq[0])
|
||||
for col_num, col in enumerate(df.columns):
|
||||
np.testing.assert_array_equal(expected_rows[col].values,
|
||||
dq[col_num + 1])
|
||||
coord.request_stop()
|
||||
coord.join(threads)
|
||||
|
||||
def testShuffle(self):
|
||||
array_size = 7
|
||||
batch_size = 3
|
||||
iterations = 1000
|
||||
mean = batch_size * iterations * 1.0 / array_size
|
||||
tolerance = 3
|
||||
with tf.Graph().as_default():
|
||||
array = np.arange(array_size)
|
||||
q = ff.enqueue_data(array, capacity=100, shuffle=True, seed=1234)
|
||||
dq_op = q.dequeue_many(batch_size)
|
||||
with tf.Session() as sess:
|
||||
coord = tf.train.Coordinator()
|
||||
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
|
||||
counts = {x: 0 for x in array}
|
||||
for _ in range(iterations):
|
||||
dq = sess.run(dq_op)
|
||||
for dqed in dq[1]:
|
||||
self.assertIn(dqed, array)
|
||||
counts[dqed] += 1
|
||||
for k, v in counts.items():
|
||||
self.assertGreater(
|
||||
mean + tolerance, v,
|
||||
"Value {} occurred {} times, expected {:.2f} +/- {}".format(
|
||||
k, v, mean, tolerance))
|
||||
self.assertLess(
|
||||
mean - tolerance, v,
|
||||
"Value {} occurred {} times, expected {:.2f} +/- {}".format(
|
||||
k, v, mean, tolerance))
|
||||
coord.request_stop()
|
||||
coord.join(threads)
|
||||
|
||||
if __name__ == "__main__":
|
||||
tf.test.main()
|
@ -14,7 +14,6 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import random
|
||||
|
||||
@ -61,13 +60,14 @@ class BaseTest(tf.test.TestCase):
|
||||
classifier.fit(iris.data, [float(x) for x in iris.target])
|
||||
self.assertEqual(
|
||||
classifier.get_variable_names(),
|
||||
["global_step:0", "logistic_regression/weights:0",
|
||||
"logistic_regression/bias:0",
|
||||
["OptimizeLoss/learning_rate",
|
||||
"OptimizeLoss/logistic_regression/bias/Adagrad",
|
||||
"OptimizeLoss/logistic_regression/softmax_classifier/"
|
||||
"softmax_cross_entropy_loss/value/avg:0",
|
||||
"OptimizeLoss/learning_rate:0",
|
||||
"OptimizeLoss/logistic_regression/weights/Adagrad:0",
|
||||
"OptimizeLoss/logistic_regression/bias/Adagrad:0"])
|
||||
"softmax_cross_entropy_loss/value/avg",
|
||||
"OptimizeLoss/logistic_regression/weights/Adagrad",
|
||||
"global_step",
|
||||
"logistic_regression/bias",
|
||||
"logistic_regression/weights"])
|
||||
|
||||
def testIrisSummaries(self):
|
||||
iris = datasets.load_iris()
|
||||
@ -84,9 +84,11 @@ class BaseTest(tf.test.TestCase):
|
||||
steps=250)
|
||||
classifier.fit(iris.data, iris.target)
|
||||
score1 = accuracy_score(iris.target, classifier.predict(iris.data))
|
||||
classifier.fit(iris.data, iris.target)
|
||||
classifier.fit(iris.data, iris.target, steps=500)
|
||||
score2 = accuracy_score(iris.target, classifier.predict(iris.data))
|
||||
self.assertGreater(score2, score1, "Failed with score = {0}".format(score2))
|
||||
self.assertGreater(
|
||||
score2, score1,
|
||||
"Failed with score2 {0} <= score1 {1}".format(score2, score1))
|
||||
|
||||
def testIrisStreaming(self):
|
||||
iris = datasets.load_iris()
|
||||
|
@ -38,7 +38,8 @@ class EarlyStoppingTest(tf.test.TestCase):
|
||||
|
||||
X_train, X_val, y_train, y_val = train_test_split(
|
||||
X_train, y_train, test_size=0.2)
|
||||
val_monitor = learn.monitors.ValidationMonitor(X_val, y_val, n_classes=3)
|
||||
val_monitor = learn.monitors.ValidationMonitor(X_val, y_val,
|
||||
early_stopping_rounds=100)
|
||||
|
||||
# classifier without early stopping - overfitting
|
||||
classifier1 = learn.TensorFlowDNNClassifier(hidden_units=[10, 20, 10],
|
||||
@ -52,7 +53,7 @@ class EarlyStoppingTest(tf.test.TestCase):
|
||||
n_classes=3,
|
||||
steps=1000)
|
||||
|
||||
classifier2.fit(X_train, y_train, val_monitor)
|
||||
classifier2.fit(X_train, y_train, monitors=[val_monitor])
|
||||
score2 = accuracy_score(y_test, classifier2.predict(X_test))
|
||||
|
||||
# self.assertGreater(score2, score1, "No improvement using early stopping.")
|
||||
|
@ -17,6 +17,7 @@ from __future__ import print_function
|
||||
|
||||
import random
|
||||
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
from tensorflow.contrib.learn.python import learn
|
||||
from tensorflow.contrib.learn.python.learn import datasets
|
||||
@ -48,7 +49,7 @@ class NonLinearTest(tf.test.TestCase):
|
||||
regressor = learn.TensorFlowDNNRegressor(hidden_units=[10, 20, 10],
|
||||
n_classes=0,
|
||||
batch_size=boston.data.shape[0],
|
||||
steps=200,
|
||||
steps=300,
|
||||
learning_rate=0.001)
|
||||
regressor.fit(boston.data, boston.target)
|
||||
score = mean_squared_error(boston.target, regressor.predict(boston.data))
|
||||
@ -79,6 +80,7 @@ class NonLinearTest(tf.test.TestCase):
|
||||
dropout=0.1)
|
||||
classifier.fit(iris.data, iris.target)
|
||||
score = accuracy_score(iris.target, classifier.predict(iris.data))
|
||||
# If the quality is lower - dropout is not working.
|
||||
self.assertGreater(score, 0.9, "Failed with score = {0}".format(score))
|
||||
|
||||
def testDNNDropout0_9(self):
|
||||
@ -94,7 +96,6 @@ class NonLinearTest(tf.test.TestCase):
|
||||
|
||||
def testRNN(self):
|
||||
random.seed(42)
|
||||
import numpy as np
|
||||
data = np.array(
|
||||
list([[2, 1, 2, 2, 3], [2, 2, 3, 4, 5], [3, 3, 1, 2, 1], [2, 4, 5, 4, 1]
|
||||
]),
|
||||
@ -103,7 +104,8 @@ class NonLinearTest(tf.test.TestCase):
|
||||
labels = np.array(list([1, 0, 1, 0]), dtype=np.float32)
|
||||
# targets for regression
|
||||
targets = np.array(list([10, 16, 10, 16]), dtype=np.float32)
|
||||
test_data = np.array(list([[1, 3, 3, 2, 1], [2, 3, 4, 5, 6]]))
|
||||
test_data = np.array(list([[1, 3, 3, 2, 1], [2, 3, 4, 5, 6]]),
|
||||
dtype=np.float32)
|
||||
|
||||
def input_fn(X):
|
||||
return tf.split(1, 5, X)
|
||||
@ -144,7 +146,6 @@ class NonLinearTest(tf.test.TestCase):
|
||||
|
||||
def testBidirectionalRNN(self):
|
||||
random.seed(42)
|
||||
import numpy as np
|
||||
data = np.array(
|
||||
list([[2, 1, 2, 2, 3], [2, 2, 3, 4, 5], [3, 3, 1, 2, 1], [2, 4, 5, 4, 1]
|
||||
]),
|
||||
@ -161,19 +162,20 @@ class NonLinearTest(tf.test.TestCase):
|
||||
input_op_fn=input_fn,
|
||||
bidirectional=True)
|
||||
classifier.fit(data, labels)
|
||||
predictions = classifier.predict(np.array(list([[1, 3, 3, 2, 1], [2, 3, 4,
|
||||
5, 6]])))
|
||||
test_data = np.array(list([[1, 3, 3, 2, 1], [2, 3, 4,
|
||||
5, 6]]), dtype=np.float32)
|
||||
predictions = classifier.predict(test_data)
|
||||
self.assertAllClose(predictions, np.array([1, 0]))
|
||||
|
||||
def testDNNAutoencoder(self):
|
||||
import numpy as np
|
||||
iris = datasets.load_iris()
|
||||
autoencoder = learn.TensorFlowDNNAutoencoder(hidden_units=[10, 20])
|
||||
transformed = autoencoder.fit_transform(iris.data[1:2])
|
||||
expected = np.array([[ -3.57627869e-07, 1.17000043e+00, 1.01902664e+00, 1.19209290e-07,
|
||||
0.00000000e+00, 1.19209290e-07, -5.96046448e-08, -2.38418579e-07,
|
||||
9.74681854e-01, 1.19209290e-07]])
|
||||
self.assertAllClose(transformed, expected)
|
||||
# def testDNNAutoencoder(self):
|
||||
# import numpy as np
|
||||
# iris = datasets.load_iris()
|
||||
# autoencoder = learn.TensorFlowDNNAutoencoder(hidden_units=[10, 20])
|
||||
# transformed = autoencoder.fit_transform(iris.data[1:2])
|
||||
# expected = np.array([[ -3.57627869e-07, 1.17000043e+00, 1.01902664e+00, 1.19209290e-07,
|
||||
# 0.00000000e+00, 1.19209290e-07, -5.96046448e-08, -2.38418579e-07,
|
||||
# 9.74681854e-01, 1.19209290e-07]])
|
||||
# self.assertAllClose(transformed, expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -33,10 +33,10 @@ class SaverTest(tf.test.TestCase):
|
||||
classifier = learn.TensorFlowLinearClassifier(n_classes=3)
|
||||
classifier.fit(iris.data, iris.target)
|
||||
classifier.save(path)
|
||||
new_classifier = learn.TensorFlowEstimator.restore(path)
|
||||
self.assertEqual(type(new_classifier), type(classifier))
|
||||
score = accuracy_score(iris.target, new_classifier.predict(iris.data))
|
||||
self.assertGreater(score, 0.5, 'Failed with score = {0}'.format(score))
|
||||
# new_classifier = learn.TensorFlowEstimator.restore(path)
|
||||
# self.assertEqual(type(new_classifier), type(classifier))
|
||||
# score = accuracy_score(iris.target, new_classifier.predict(iris.data))
|
||||
# self.assertGreater(score, 0.5, 'Failed with score = {0}'.format(score))
|
||||
|
||||
def testCustomModel(self):
|
||||
path = tf.test.get_temp_dir() + '/tmp.saver2'
|
||||
@ -49,10 +49,10 @@ class SaverTest(tf.test.TestCase):
|
||||
classifier = learn.TensorFlowEstimator(model_fn=custom_model, n_classes=3)
|
||||
classifier.fit(iris.data, iris.target)
|
||||
classifier.save(path)
|
||||
new_classifier = learn.TensorFlowEstimator.restore(path)
|
||||
self.assertEqual(type(new_classifier), type(classifier))
|
||||
score = accuracy_score(iris.target, new_classifier.predict(iris.data))
|
||||
self.assertGreater(score, 0.5, 'Failed with score = {0}'.format(score))
|
||||
# new_classifier = learn.TensorFlowEstimator.restore(path)
|
||||
# self.assertEqual(type(new_classifier), type(classifier))
|
||||
# score = accuracy_score(iris.target, new_classifier.predict(iris.data))
|
||||
# self.assertGreater(score, 0.5, 'Failed with score = {0}'.format(score))
|
||||
|
||||
def testDNN(self):
|
||||
path = tf.test.get_temp_dir() + '/tmp_saver3'
|
||||
@ -62,10 +62,10 @@ class SaverTest(tf.test.TestCase):
|
||||
n_classes=3)
|
||||
classifier.fit(iris.data, iris.target)
|
||||
classifier.save(path)
|
||||
new_classifier = learn.TensorFlowEstimator.restore(path)
|
||||
self.assertEqual(type(new_classifier), type(classifier))
|
||||
score = accuracy_score(iris.target, new_classifier.predict(iris.data))
|
||||
self.assertGreater(score, 0.5, 'Failed with score = {0}'.format(score))
|
||||
# new_classifier = learn.TensorFlowEstimator.restore(path)
|
||||
# self.assertEqual(type(new_classifier), type(classifier))
|
||||
# score = accuracy_score(iris.target, new_classifier.predict(iris.data))
|
||||
# self.assertGreater(score, 0.5, 'Failed with score = {0}'.format(score))
|
||||
|
||||
def testNoFolder(self):
|
||||
with self.assertRaises(ValueError):
|
||||
@ -80,7 +80,7 @@ class SaverTest(tf.test.TestCase):
|
||||
classifier.fit(iris.data, iris.target)
|
||||
classifier.save(path)
|
||||
os.remove(os.path.join(path, 'checkpoint'))
|
||||
with self.assertRaises(ValueError):
|
||||
with self.assertRaises(NotImplementedError):
|
||||
learn.TensorFlowEstimator.restore(path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -1,4 +1,7 @@
|
||||
"""Generic trainer for TensorFlow models."""
|
||||
"""Generic trainer for TensorFlow models.
|
||||
|
||||
This module is deprecated, please use graph_actions.
|
||||
"""
|
||||
# Copyright 2015-present The Scikit Flow Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,6 +22,8 @@ from __future__ import print_function
|
||||
|
||||
from six.moves import xrange # pylint: disable=redefined-builtin
|
||||
|
||||
from tensorflow.python.platform import tf_logging as logging
|
||||
|
||||
|
||||
def train(session,
|
||||
train_op,
|
||||
@ -45,6 +50,8 @@ def train(session,
|
||||
summaries: Joined object of all summaries that should be ran.
|
||||
feed_params_fn: Feed params function.
|
||||
"""
|
||||
logging.warning("learn.trainer.train is deprecated. "
|
||||
"Please use learn.graph_actions.train instead.")
|
||||
for step in xrange(steps):
|
||||
feed_dict = feed_dict_fn()
|
||||
if summaries is not None:
|
||||
@ -55,13 +62,5 @@ def train(session,
|
||||
global_step_value, loss_value, _ = session.run(
|
||||
[global_step, loss, train_op],
|
||||
feed_dict=feed_dict)
|
||||
monitor.update(step,
|
||||
global_step_value,
|
||||
loss_value,
|
||||
session,
|
||||
feed_params_fn,
|
||||
loss_expression_tensor=loss)
|
||||
if summaries is not None and summary_writer and summ is not None:
|
||||
summary_writer.add_summary(summ, global_step_value)
|
||||
if monitor.monitor_inducing_stop():
|
||||
break
|
||||
|
@ -20,16 +20,23 @@ from __future__ import print_function
|
||||
|
||||
import six
|
||||
|
||||
from tensorflow.python.framework import dtypes
|
||||
from tensorflow.python.ops import script_ops
|
||||
from tensorflow.python.ops import gen_io_ops
|
||||
from tensorflow.python.ops import state_ops
|
||||
from tensorflow.python.ops import variable_scope as vs
|
||||
from tensorflow.python.ops import variables
|
||||
from tensorflow.python.platform import gfile
|
||||
from tensorflow.python.platform import tf_logging as logging
|
||||
from tensorflow.python.training import saver
|
||||
from tensorflow.python.training import training as train
|
||||
|
||||
|
||||
def _get_checkpoint_filename(filepattern):
|
||||
"""Returns checkpoint filename given directory or specific filepattern."""
|
||||
if gfile.IsDirectory(filepattern):
|
||||
return saver.latest_checkpoint(filepattern)
|
||||
return filepattern
|
||||
|
||||
|
||||
def load_checkpoint(filepattern):
|
||||
"""Returns CheckpointReader for latest checkpoint.
|
||||
|
||||
@ -42,13 +49,11 @@ def load_checkpoint(filepattern):
|
||||
Raises:
|
||||
ValueError: if checkpoint_dir doesn't have 'checkpoint' file or checkpoints.
|
||||
"""
|
||||
if gfile.IsDirectory(filepattern):
|
||||
filename = saver.latest_checkpoint(filepattern)
|
||||
if filename is None:
|
||||
raise ValueError("Couldn't find 'checkpoint' file or checkpoints in "
|
||||
"given directory %s" % filepattern)
|
||||
return train.NewCheckpointReader(filename)
|
||||
return train.NewCheckpointReader(filepattern)
|
||||
filename = _get_checkpoint_filename(filepattern)
|
||||
if filename is None:
|
||||
raise ValueError("Couldn't find 'checkpoint' file or checkpoints in "
|
||||
"given directory %s" % filepattern)
|
||||
return train.NewCheckpointReader(filename)
|
||||
|
||||
|
||||
def load_variable(checkpoint_dir, name):
|
||||
@ -83,43 +88,49 @@ def list_variables(checkpoint_dir):
|
||||
return result
|
||||
|
||||
|
||||
def _checkpoint_initializer(variable, checkpoint_reader, tensor_name):
|
||||
"""Assigns variable to value that will be loaded from checkpoint's tensor.
|
||||
# pylint: disable=protected-access
|
||||
# Currently variable_scope doesn't provide very good APIs to access
|
||||
# all variables under scope and retrieve and check existing scopes.
|
||||
# TODO(ipolosukhin): Refactor variable_scope module to provide nicer APIs.
|
||||
|
||||
|
||||
def _set_checkpoint_initializer(variable, file_pattern, tensor_name, slice_spec,
|
||||
name="checkpoint_initializer"):
|
||||
"""Sets variable initializer to assign op form value in checkpoint's tensor.
|
||||
|
||||
Args:
|
||||
variable: `Variable` object.
|
||||
checkpoint_reader: `CheckpointReader` object.
|
||||
file_pattern: string, where to load checkpoints from.
|
||||
tensor_name: Name of the `Tensor` to load from checkpoint reader.
|
||||
|
||||
Returns:
|
||||
`Tensor` that returns value of `tensor_name` in checkpoint.
|
||||
|
||||
Raises:
|
||||
ValueError: if shape or dtype of `variable` doesn't match with Tensor in
|
||||
checkpoint.
|
||||
slice_spec: Slice specification for loading partitioned variables.
|
||||
name: Name of the operation.
|
||||
"""
|
||||
# Currently to avoid putting the whole tensor into the graph, this adds a
|
||||
# py_func function to the graph, that will return actual value.
|
||||
# TODO(ipolosukhin): Rewrite this as C++ op, that loads checkpoint at time.
|
||||
tensor = checkpoint_reader.get_tensor(tensor_name)
|
||||
def _tensor():
|
||||
return tensor
|
||||
if not variable.get_shape().is_compatible_with(tensor.shape):
|
||||
raise ValueError(
|
||||
"Shape of variable %s (%s) doesn't match with shape of "
|
||||
"tensor %s (%s) from checkpoint reader." % (
|
||||
variable.name, str(variable.get_shape()),
|
||||
tensor_name, str(tensor.shape)
|
||||
))
|
||||
if not dtypes.as_dtype(tensor.dtype).is_compatible_with(variable.dtype):
|
||||
raise ValueError(
|
||||
"DType of variable %s (%s) doesn't match with dtype of "
|
||||
"tensor %s (%s) from checkpoint reader." % (
|
||||
variable.name, str(variable.dtype),
|
||||
tensor_name, str(dtypes.as_dtype(tensor.dtype))
|
||||
))
|
||||
return state_ops.assign(
|
||||
variable, script_ops.py_func(_tensor, [], [tensor.dtype])[0])
|
||||
base_type = variable.dtype.base_dtype
|
||||
restore_op = gen_io_ops._restore_slice(
|
||||
file_pattern,
|
||||
tensor_name,
|
||||
slice_spec,
|
||||
base_type,
|
||||
preferred_shard=-1,
|
||||
name=name)
|
||||
variable._initializer_op = state_ops.assign(variable, restore_op)
|
||||
|
||||
|
||||
def _set_variable_or_list_initializer(variable_or_list, file_pattern,
|
||||
tensor_name):
|
||||
if isinstance(variable_or_list, (list, tuple)):
|
||||
# A set of slices.
|
||||
slice_name = None
|
||||
for v in variable_or_list:
|
||||
if slice_name is None:
|
||||
slice_name = v._save_slice_info.full_name
|
||||
elif slice_name != v._save_slice_info.full_name:
|
||||
raise ValueError("Slices must all be from the same tensor: %s != %s" %
|
||||
(slice_name, v._save_slice_info.full_name))
|
||||
_set_checkpoint_initializer(v, file_pattern, tensor_name,
|
||||
v._save_slice_info.spec)
|
||||
else:
|
||||
_set_checkpoint_initializer(variable_or_list, file_pattern, tensor_name, "")
|
||||
|
||||
|
||||
def init_from_checkpoint(checkpoint_dir, assignment_map):
|
||||
@ -133,8 +144,15 @@ def init_from_checkpoint(checkpoint_dir, assignment_map):
|
||||
current `scope_name` from `checkpoint_scope_name` with matching variable
|
||||
names.
|
||||
`'scope_name/variable_name': 'checkpoint_scope_name/some_other_variable'` -
|
||||
will initalize `scope_name/variable_name` variable
|
||||
from `checkpoint_scope_name/some_other_variable`.
|
||||
will initalize `scope_name/variable_name` variable
|
||||
from `checkpoint_scope_name/some_other_variable`.
|
||||
`variable: 'scope_varaible_name'` - will initialize given variable with
|
||||
variable from the checkpoint.
|
||||
`'scope_name/': '/'` - will load all variables in current `scope_name` from
|
||||
checkpoint's root (e.g. no scope).
|
||||
|
||||
Supports loading into partitioned variables, which are represented as
|
||||
'<variable>/part_<part #>'.
|
||||
|
||||
Example:
|
||||
```python
|
||||
@ -142,13 +160,18 @@ def init_from_checkpoint(checkpoint_dir, assignment_map):
|
||||
with tf.variable_scope('test'):
|
||||
m = tf.get_variable('my_var')
|
||||
with tf.variable_scope('test2'):
|
||||
m = tf.get_variable('my_var')
|
||||
var2 = tf.get_variable('my_var')
|
||||
...
|
||||
# Specify which variables to intialize from checkpoint.
|
||||
init_from_checkpoint(checkpoint_dir, {
|
||||
'test/my_var': 'some_var',
|
||||
'test2/', 'some_scope/'})
|
||||
...
|
||||
# Or use `Variable` objects to identify what to initialize.
|
||||
init_from_checkpoint(checkpoint_dir, {
|
||||
var2: 'some_scope/var2',
|
||||
})
|
||||
...
|
||||
# Initialize variables as usual.
|
||||
session.run(tf.get_all_variables())
|
||||
```
|
||||
@ -163,26 +186,50 @@ def init_from_checkpoint(checkpoint_dir, assignment_map):
|
||||
tf.errors.OpError: If missing checkpoints or tensors in checkpoints.
|
||||
ValueError: If missing variables in current graph.
|
||||
"""
|
||||
filepattern = _get_checkpoint_filename(checkpoint_dir)
|
||||
reader = load_checkpoint(checkpoint_dir)
|
||||
variable_map = reader.get_variable_to_shape_map()
|
||||
for current_name, tensor_name in six.iteritems(assignment_map):
|
||||
scopes = ""
|
||||
if "/" in current_name:
|
||||
scopes = current_name[:current_name.rindex("/")]
|
||||
current_name = current_name[current_name.rindex("/") + 1:]
|
||||
if current_name:
|
||||
var = None
|
||||
# Check if this is Variable object.
|
||||
if isinstance(current_name, variables.Variable):
|
||||
var = current_name
|
||||
else:
|
||||
var_scope = vs._get_default_variable_store()
|
||||
# Check if this is variable in var_store.
|
||||
var = var_scope._vars.get(current_name, None)
|
||||
# Also check if variable is partitioned as list.
|
||||
if var is None:
|
||||
if current_name + "/part_0" in var_scope._vars:
|
||||
var = []
|
||||
i = 0
|
||||
while current_name + "/part_%d" % i in var_scope._vars:
|
||||
var.append(var_scope._vars[current_name + "/part_%d" % i])
|
||||
i += 1
|
||||
if var is not None:
|
||||
# If 1 to 1 mapping was provided, find variable in the scope.
|
||||
if tensor_name not in variable_map:
|
||||
raise ValueError("Tensor %s is not found in %s checkpoint" % (
|
||||
tensor_name, checkpoint_dir
|
||||
))
|
||||
with vs.variable_scope(scopes, reuse=True):
|
||||
var = vs.get_variable(current_name)
|
||||
var._initializer_op = _checkpoint_initializer(var, reader, tensor_name) # pylint: disable=protected-access
|
||||
logging.info("Initialize variable %s from checkpoint %s with %s" % (
|
||||
var.name, checkpoint_dir, tensor_name
|
||||
))
|
||||
if isinstance(var, variables.Variable):
|
||||
# Additional at-call-time checks.
|
||||
if not var.get_shape().is_compatible_with(variable_map[tensor_name]):
|
||||
raise ValueError(
|
||||
"Shape of variable %s (%s) doesn't match with shape of "
|
||||
"tensor %s (%s) from checkpoint reader." % (
|
||||
var.name, str(var.get_shape()),
|
||||
tensor_name, str(variable_map[tensor_name])
|
||||
))
|
||||
_set_variable_or_list_initializer(var, filepattern, tensor_name)
|
||||
logging.info("Initialize variable %s from checkpoint %s with %s" % (
|
||||
current_name, checkpoint_dir, tensor_name
|
||||
))
|
||||
else:
|
||||
if "/" in current_name:
|
||||
scopes = current_name[:current_name.rindex("/")]
|
||||
current_name = current_name[current_name.rindex("/") + 1:]
|
||||
if not tensor_name.endswith("/"):
|
||||
raise ValueError(
|
||||
"Assignment map with scope only name (%s) "
|
||||
@ -191,21 +238,23 @@ def init_from_checkpoint(checkpoint_dir, assignment_map):
|
||||
scopes, tensor_name
|
||||
))
|
||||
# If scope to scope mapping was provided, find all variables in the scope.
|
||||
# TODO(ipolosukhin): Refactor variable_scope module to provide nicer APIs.
|
||||
var_scope = vs._get_default_variable_store() # pylint: disable=protected-access
|
||||
for var_name in var_scope._vars: # pylint: disable=protected-access
|
||||
for var_name in var_scope._vars:
|
||||
if var_name.startswith(scopes):
|
||||
# Lookup name with specified prefix and suffix from current variable.
|
||||
full_tensor_name = tensor_name + var_name[len(scopes) + 1:]
|
||||
# If tensor_name given is '/' (root), don't use it for full name.
|
||||
if tensor_name != "/":
|
||||
full_tensor_name = tensor_name + var_name[len(scopes) + 1:]
|
||||
else:
|
||||
full_tensor_name = var_name[len(scopes) + 1:]
|
||||
if full_tensor_name not in variable_map:
|
||||
raise ValueError(
|
||||
"Tensor %s (%s in %s) is not found in %s checkpoint" % (
|
||||
full_tensor_name, var_name[len(scopes) + 1:], tensor_name,
|
||||
checkpoint_dir
|
||||
))
|
||||
var = var_scope._vars[var_name] # pylint: disable=protected-access
|
||||
var._initializer_op = _checkpoint_initializer( # pylint: disable=protected-access
|
||||
var, reader, full_tensor_name)
|
||||
var = var_scope._vars[var_name]
|
||||
_set_variable_or_list_initializer(var, filepattern, full_tensor_name)
|
||||
logging.info("Initialize variable %s from checkpoint %s with %s" % (
|
||||
var_name, checkpoint_dir, tensor_name
|
||||
))
|
||||
# pylint: enable=protected-access
|
||||
|
@ -41,6 +41,24 @@ def _create_checkpoints(sess, checkpoint_dir):
|
||||
return v1_value, v2_value, v3_value, v4_value
|
||||
|
||||
|
||||
def _create_partition_checkpoints(sess, checkpoint_dir):
|
||||
checkpoint_prefix = os.path.join(checkpoint_dir, "model")
|
||||
checkpoint_state_name = "checkpoint"
|
||||
# TODO(ipolosukhin): Enable this when get_variable partitioning works.
|
||||
# v1 = tf.get_variable("var1", [100, 100],
|
||||
# partitioner=tf.variable_axis_size_partitioner(axis=0,
|
||||
# max_shard_bytes=512))
|
||||
v1 = tf.create_partitioned_variables(
|
||||
shape=[100, 100], slicing=[5, 1], name="var1",
|
||||
initializer=tf.truncated_normal_initializer(0.5))
|
||||
sess.run(tf.initialize_all_variables())
|
||||
v1_value = sess.run(v1)
|
||||
saver = tf.train.Saver()
|
||||
saver.save(sess, checkpoint_prefix, global_step=0,
|
||||
latest_filename=checkpoint_state_name)
|
||||
return v1_value
|
||||
|
||||
|
||||
class CheckpointsTest(tf.test.TestCase):
|
||||
|
||||
def testNoCheckpoints(self):
|
||||
@ -97,7 +115,7 @@ class CheckpointsTest(tf.test.TestCase):
|
||||
})
|
||||
checkpoints.init_from_checkpoint(checkpoint_dir, {
|
||||
"some_scope/some_other_scope/my2": "var2",
|
||||
"my3": "var3",
|
||||
my3: "var3",
|
||||
})
|
||||
|
||||
session.run(tf.initialize_all_variables())
|
||||
@ -107,7 +125,60 @@ class CheckpointsTest(tf.test.TestCase):
|
||||
self.assertAllEqual(my4.eval(session), v4)
|
||||
|
||||
# Check that tensors are not explicitly in the graph.
|
||||
self.assertLess(len(str(session.graph.as_graph_def())), 22000)
|
||||
self.assertLess(len(str(session.graph.as_graph_def())), 26000)
|
||||
|
||||
def testInitFromRootCheckpoint(self):
|
||||
checkpoint_dir = self.get_temp_dir()
|
||||
with self.test_session() as session:
|
||||
v1, v2, v3, v4 = _create_checkpoints(session, checkpoint_dir)
|
||||
|
||||
# New graph and session.
|
||||
with tf.Graph().as_default() as g:
|
||||
with self.test_session(graph=g) as session:
|
||||
with tf.variable_scope("some_scope"):
|
||||
my1 = tf.get_variable("var1", [1, 10])
|
||||
my2 = tf.get_variable("var2", [10, 10])
|
||||
my3 = tf.get_variable("var3", [100, 100])
|
||||
with tf.variable_scope("useful_scope"):
|
||||
my4 = tf.get_variable("var4", [9, 9])
|
||||
|
||||
checkpoints.init_from_checkpoint(checkpoint_dir, {
|
||||
"some_scope/": "/",
|
||||
})
|
||||
|
||||
session.run(tf.initialize_all_variables())
|
||||
self.assertAllEqual(my1.eval(session), v1)
|
||||
self.assertAllEqual(my2.eval(session), v2)
|
||||
self.assertAllEqual(my3.eval(session), v3)
|
||||
self.assertAllEqual(my4.eval(session), v4)
|
||||
|
||||
def testInitFromPartitionVar(self):
|
||||
checkpoint_dir = self.get_temp_dir()
|
||||
with self.test_session() as session:
|
||||
v1 = _create_partition_checkpoints(session, checkpoint_dir)
|
||||
|
||||
# New graph and session.
|
||||
with tf.Graph().as_default() as g:
|
||||
with self.test_session(graph=g) as session:
|
||||
with tf.variable_scope("some_scope"):
|
||||
# TODO(ipolosukhin): Enable this when get_variable partitioning works.
|
||||
# Currently get_variable with partitioner doesn't return Variable,
|
||||
# but returns a concat op.
|
||||
# my1 = tf.get_variable(
|
||||
# "my1", [100, 100],
|
||||
# partitioner=tf.variable_axis_size_partitioner(axis=0,
|
||||
# max_shard_bytes=100))
|
||||
my1 = tf.create_partitioned_variables(
|
||||
shape=[100, 100], slicing=[5, 1], name="my1",
|
||||
initializer=tf.truncated_normal_initializer(0.5))
|
||||
|
||||
checkpoints.init_from_checkpoint(checkpoint_dir, {
|
||||
"some_scope/my1": "var1",
|
||||
})
|
||||
|
||||
session.run(tf.initialize_all_variables())
|
||||
my1_values = session.run(my1)
|
||||
self.assertAllEqual(my1_values, v1)
|
||||
|
||||
def testInitFromCheckpointMissing(self):
|
||||
checkpoint_dir = self.get_temp_dir()
|
||||
@ -142,11 +213,6 @@ class CheckpointsTest(tf.test.TestCase):
|
||||
checkpoints.init_from_checkpoint(checkpoint_dir, {
|
||||
"some_scope/my1": "var1"})
|
||||
|
||||
# DType mismatch.
|
||||
with self.assertRaises(ValueError):
|
||||
checkpoints.init_from_checkpoint(checkpoint_dir, {
|
||||
"some_scope/my2": "var1"})
|
||||
|
||||
# Variable 'my1' and 'my2' are missing in given checkpoint scope.
|
||||
with self.assertRaises(ValueError):
|
||||
checkpoints.init_from_checkpoint(checkpoint_dir, {
|
||||
|
@ -146,8 +146,10 @@ from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_mean_rela
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_mean_squared_error
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_percentage_less
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_precision
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_precision_at_thresholds
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_recall
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_recall_at_k
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_recall_at_thresholds
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_root_mean_squared_error
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_sparse_precision_at_k
|
||||
from tensorflow.contrib.metrics.python.ops.metric_ops import streaming_sparse_recall_at_k
|
||||
|
@ -28,7 +28,6 @@ from tensorflow.python.framework import dtypes
|
||||
from tensorflow.python.framework import ops
|
||||
from tensorflow.python.ops import array_ops
|
||||
from tensorflow.python.ops import check_ops
|
||||
from tensorflow.python.ops import logging_ops
|
||||
from tensorflow.python.ops import math_ops
|
||||
from tensorflow.python.ops import nn
|
||||
from tensorflow.python.ops import sparse_ops
|
||||
@ -406,9 +405,9 @@ def streaming_precision(predictions, labels, ignore_mask=None,
|
||||
|
||||
Raises:
|
||||
ValueError: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not
|
||||
a list or tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
"""
|
||||
with variable_scope.variable_op_scope(
|
||||
[predictions, labels], name, 'precision'):
|
||||
@ -485,9 +484,9 @@ def streaming_recall(predictions, labels, ignore_mask=None,
|
||||
|
||||
Raises:
|
||||
ValueError: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not
|
||||
a list or tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
"""
|
||||
with variable_scope.variable_op_scope([predictions, labels], name, 'recall'):
|
||||
predictions, labels = _remove_squeezable_dimensions(predictions, labels)
|
||||
@ -521,6 +520,139 @@ def streaming_recall(predictions, labels, ignore_mask=None,
|
||||
return recall, update_op
|
||||
|
||||
|
||||
def _tp_fn_tn_fp(predictions, labels, thresholds, ignore_mask=None):
|
||||
"""Computes true_positives, false_negatives, true_negatives, false_positives.
|
||||
|
||||
The `_tp_fn_tn_fp` function creates four local variables, `true_positives`,
|
||||
`true_negatives`, `false_positives` and `false_negatives`.
|
||||
`true_positive[i]` is defined` as the number of values in `predictions` above
|
||||
`thresholds[i]` whose corresponding entry in `labels` is `True`.
|
||||
`false_negatives[i]` is defined` as the number of values in `predictions` at
|
||||
most `thresholds[i]` whose corresponding entry in `labels` is `True`.
|
||||
`true_negatives[i]` is defined` as the number of values in `predictions` at
|
||||
most `thresholds[i]` whose corresponding entry in `labels` is `False`.
|
||||
`false_positives[i]` is defined` as the number of values in `predictions`
|
||||
above `thresholds[i]` whose corresponding entry in `labels` is `False`.
|
||||
|
||||
These four variables are updated through the `update_op`.
|
||||
The streaming behavior is that the values of the variables after a few
|
||||
`update_op`s is the same as if the inputs had been concatenated and a single
|
||||
`update_op` had been performed.
|
||||
|
||||
If `ignore_mask` is not `None`, then the increment of the variables is
|
||||
performed using only the elements of `predictions` and `labels` whose
|
||||
corresponding value in `ignore_mask` is `False`.
|
||||
|
||||
Args:
|
||||
predictions: A floating point `Tensor` of arbitrary shape and whose values
|
||||
are in the range `[0, 1]`.
|
||||
labels: A binary `Tensor` whose shape matches `predictions`.
|
||||
thresholds: A python list or tuple of float thresholds in `[0, 1]`.
|
||||
ignore_mask: An optional, binary tensor whose size matches `predictions`.
|
||||
|
||||
Returns:
|
||||
true_positive: A variable of shape [len(thresholds)].
|
||||
false_negative: A variable of shape [len(thresholds)].
|
||||
true_negatives: A variable of shape [len(thresholds)].
|
||||
false_positives: A variable of shape [len(thresholds)].
|
||||
true_positives_update_op: An operation that increments the `true_positives`.
|
||||
false_negative_update_op: An operation that increments the `false_negative`.
|
||||
true_negatives_update_op: An operation that increments the `true_negatives`.
|
||||
false_positives_update_op: An operation that increments the
|
||||
`false_positives`.
|
||||
|
||||
Raises:
|
||||
ValueError: If the shape of `predictions` and `labels` do not match or if
|
||||
`ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
"""
|
||||
predictions, labels = _remove_squeezable_dimensions(predictions, labels)
|
||||
predictions.get_shape().assert_is_compatible_with(labels.get_shape())
|
||||
|
||||
num_thresholds = len(thresholds)
|
||||
|
||||
# Reshape predictions and labels to be column vectors
|
||||
predictions = array_ops.reshape(predictions, [-1, 1])
|
||||
labels = array_ops.reshape(labels, [-1, 1])
|
||||
|
||||
# Use static shape if known.
|
||||
num_predictions = predictions.get_shape().as_list()[0]
|
||||
|
||||
# Otherwise use dynamic shape.
|
||||
if num_predictions is None:
|
||||
num_predictions = array_ops.shape(predictions)[0]
|
||||
thresh_tiled = array_ops.tile(
|
||||
array_ops.expand_dims(array_ops.constant(thresholds), [1]),
|
||||
array_ops.pack([1, num_predictions]))
|
||||
|
||||
# Tile the predictions after thresholding them across different thresholds.
|
||||
pred_tiled = math_ops.cast(
|
||||
math_ops.greater(
|
||||
array_ops.tile(
|
||||
array_ops.transpose(predictions), [num_thresholds, 1]),
|
||||
thresh_tiled),
|
||||
dtype=dtypes.int32)
|
||||
# Tile labels by number of thresholds
|
||||
labels_tiled = array_ops.tile(array_ops.transpose(labels),
|
||||
[num_thresholds, 1])
|
||||
|
||||
true_positives = _create_local('true_positives', shape=[num_thresholds])
|
||||
false_negatives = _create_local('false_negatives', shape=[num_thresholds])
|
||||
true_negatives = _create_local('true_negatives', shape=[num_thresholds])
|
||||
false_positives = _create_local('false_positives', shape=[num_thresholds])
|
||||
|
||||
is_true_positive = math_ops.to_float(
|
||||
math_ops.logical_and(
|
||||
math_ops.equal(labels_tiled, 1), math_ops.equal(pred_tiled, 1)))
|
||||
is_false_negative = math_ops.to_float(
|
||||
math_ops.logical_and(
|
||||
math_ops.equal(labels_tiled, 1), math_ops.equal(pred_tiled, 0)))
|
||||
is_false_positive = math_ops.to_float(
|
||||
math_ops.logical_and(
|
||||
math_ops.equal(labels_tiled, 0), math_ops.equal(pred_tiled, 1)))
|
||||
is_true_negative = math_ops.to_float(
|
||||
math_ops.logical_and(
|
||||
math_ops.equal(labels_tiled, 0), math_ops.equal(pred_tiled, 0)))
|
||||
|
||||
if ignore_mask is not None:
|
||||
ignore_mask = array_ops.reshape(ignore_mask, [-1, 1])
|
||||
mask_tiled = array_ops.tile(array_ops.transpose(ignore_mask),
|
||||
[num_thresholds, 1])
|
||||
|
||||
labels_tiled.get_shape().assert_is_compatible_with(mask_tiled.get_shape())
|
||||
check_ops.assert_type(mask_tiled, dtypes.bool)
|
||||
is_true_positive = math_ops.select(
|
||||
mask_tiled,
|
||||
array_ops.zeros_like(labels_tiled, dtype=dtypes.float32),
|
||||
is_true_positive)
|
||||
is_false_negative = math_ops.select(
|
||||
mask_tiled,
|
||||
array_ops.zeros_like(labels_tiled, dtype=dtypes.float32),
|
||||
is_false_negative)
|
||||
is_false_positive = math_ops.select(
|
||||
mask_tiled,
|
||||
array_ops.zeros_like(labels_tiled, dtype=dtypes.float32),
|
||||
is_false_positive)
|
||||
is_true_negative = math_ops.select(
|
||||
mask_tiled,
|
||||
array_ops.zeros_like(labels_tiled, dtype=dtypes.float32),
|
||||
is_true_negative)
|
||||
|
||||
true_positives_update_op = state_ops.assign_add(
|
||||
true_positives, math_ops.reduce_sum(is_true_positive, 1))
|
||||
false_negatives_update_op = state_ops.assign_add(
|
||||
false_negatives, math_ops.reduce_sum(is_false_negative, 1))
|
||||
true_negatives_update_op = state_ops.assign_add(
|
||||
true_negatives, math_ops.reduce_sum(is_true_negative, 1))
|
||||
false_positives_update_op = state_ops.assign_add(
|
||||
false_positives, math_ops.reduce_sum(is_false_positive, 1))
|
||||
|
||||
return (true_positives, false_negatives, true_negatives, false_positives,
|
||||
true_positives_update_op, false_negatives_update_op,
|
||||
true_negatives_update_op, false_positives_update_op)
|
||||
|
||||
|
||||
def streaming_auc(predictions, labels, ignore_mask=None, num_thresholds=200,
|
||||
metrics_collections=None, updates_collections=None,
|
||||
name=None):
|
||||
@ -541,12 +673,12 @@ def streaming_auc(predictions, labels, ignore_mask=None, num_thresholds=200,
|
||||
|
||||
To faciliate the estimation of the AUC over a stream of data, the function
|
||||
creates an `update_op` operation whose behavior is dependent on the value of
|
||||
`weights`. If `weights` is None, then `update_op` increments the
|
||||
`ignore_mask`. If `ignore_mask` is None, then `update_op` increments the
|
||||
`true_positives`, `true_negatives`, `false_positives` and `false_negatives`
|
||||
counts with the number of each found in the current `predictions` and `labels`
|
||||
`Tensors`. If `weights` is not `None`, then the increment is performed using
|
||||
only the elements of `predictions` and `labels` whose corresponding value
|
||||
in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
`Tensors`. If `ignore_mask` is not `None`, then the increment is performed
|
||||
using only the elements of `predictions` and `labels` whose corresponding
|
||||
value in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
`update_op` also returns the `auc`.
|
||||
|
||||
Args:
|
||||
@ -563,108 +695,27 @@ def streaming_auc(predictions, labels, ignore_mask=None, num_thresholds=200,
|
||||
name: An optional variable_op_scope name.
|
||||
|
||||
Returns:
|
||||
auc: A tensor representing the current area-under-curve.
|
||||
auc: A scalar tensor representing the current area-under-curve.
|
||||
update_op: An operation that increments the `true_positives`,
|
||||
`true_negatives`, `false_positives` and `false_negatives` variables
|
||||
appropriately and whose value matches `auc`.
|
||||
|
||||
Raises:
|
||||
ValueError: If the shape of `predictions` and `labels` do not match or if
|
||||
`weights` is not `None` and its shape doesn't match `values`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
`ignore_mask` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not a list or
|
||||
tuple.
|
||||
"""
|
||||
with variable_scope.variable_op_scope([predictions, labels], name, 'auc'):
|
||||
predictions, labels = _remove_squeezable_dimensions(predictions, labels)
|
||||
predictions.get_shape().assert_is_compatible_with(labels.get_shape())
|
||||
kepsilon = 1e-7 # to account for floating point imprecisions
|
||||
thresholds = [(i + 1) * 1.0 / (num_thresholds - 1)
|
||||
for i in range(num_thresholds-2)]
|
||||
thresholds = [0.0 - kepsilon] + thresholds + [1.0 + kepsilon]
|
||||
|
||||
# Reshape predictions and labels to be column vectors
|
||||
logging_ops.Assert(
|
||||
math_ops.equal(
|
||||
array_ops.rank(predictions), 1),
|
||||
['Input predictions are expected to be a rank 1 tensor. Got ',
|
||||
array_ops.rank(predictions)])
|
||||
logging_ops.Assert(
|
||||
math_ops.equal(
|
||||
array_ops.rank(labels), 1),
|
||||
['Input labels are expected to be a rank 1 tensor. Got ',
|
||||
array_ops.rank(labels)])
|
||||
predictions = array_ops.reshape(predictions, [-1, 1])
|
||||
labels = array_ops.reshape(labels, [-1, 1])
|
||||
|
||||
kepsilon = 1e-7
|
||||
|
||||
# Use static shape if known.
|
||||
num_predictions = predictions.get_shape().as_list()[0]
|
||||
|
||||
# Otherwise use dynamic shape.
|
||||
if num_predictions is None:
|
||||
num_predictions = array_ops.shape(predictions)[0]
|
||||
thresh_tiled = array_ops.tile(
|
||||
array_ops.expand_dims(
|
||||
math_ops.linspace(0.0 - kepsilon, 1.0 + kepsilon, num_thresholds),
|
||||
[1]),
|
||||
array_ops.pack([1, num_predictions]))
|
||||
|
||||
# Tile the predictions after thresholding them across different thresholds.
|
||||
pred_tiled = math_ops.cast(
|
||||
math_ops.greater(
|
||||
array_ops.tile(
|
||||
array_ops.transpose(predictions), [num_thresholds, 1]),
|
||||
thresh_tiled),
|
||||
dtype=dtypes.int32)
|
||||
# Tile labels by number of thresholds
|
||||
labels_tiled = array_ops.tile(array_ops.transpose(labels),
|
||||
[num_thresholds, 1])
|
||||
|
||||
true_positives = _create_local('true_positives', shape=[num_thresholds])
|
||||
false_negatives = _create_local('false_negatives', shape=[num_thresholds])
|
||||
true_negatives = _create_local('true_negatives', shape=[num_thresholds])
|
||||
false_positives = _create_local('false_positives', shape=[num_thresholds])
|
||||
|
||||
is_true_positive = math_ops.to_float(
|
||||
math_ops.logical_and(
|
||||
math_ops.equal(labels_tiled, 1), math_ops.equal(pred_tiled, 1)))
|
||||
is_false_negative = math_ops.to_float(
|
||||
math_ops.logical_and(
|
||||
math_ops.equal(labels_tiled, 1), math_ops.equal(pred_tiled, 0)))
|
||||
is_false_positive = math_ops.to_float(
|
||||
math_ops.logical_and(
|
||||
math_ops.equal(labels_tiled, 0), math_ops.equal(pred_tiled, 1)))
|
||||
is_true_negative = math_ops.to_float(
|
||||
math_ops.logical_and(
|
||||
math_ops.equal(labels_tiled, 0), math_ops.equal(pred_tiled, 0)))
|
||||
|
||||
if ignore_mask is not None:
|
||||
mask_tiled = array_ops.tile(array_ops.transpose(ignore_mask),
|
||||
[num_thresholds, 1])
|
||||
labels_tiled.get_shape().assert_is_compatible_with(mask_tiled.get_shape())
|
||||
check_ops.assert_type(mask_tiled, dtypes.bool)
|
||||
is_true_positive = math_ops.select(
|
||||
mask_tiled,
|
||||
array_ops.zeros_like(labels_tiled, dtype=dtypes.float32),
|
||||
is_true_positive)
|
||||
is_false_negative = math_ops.select(
|
||||
mask_tiled,
|
||||
array_ops.zeros_like(labels_tiled, dtype=dtypes.float32),
|
||||
is_false_negative)
|
||||
is_false_positive = math_ops.select(
|
||||
mask_tiled,
|
||||
array_ops.zeros_like(labels_tiled, dtype=dtypes.float32),
|
||||
is_false_positive)
|
||||
is_true_negative = math_ops.select(
|
||||
mask_tiled,
|
||||
array_ops.zeros_like(labels_tiled, dtype=dtypes.float32),
|
||||
is_true_negative)
|
||||
|
||||
true_positives_compute_op = state_ops.assign_add(
|
||||
true_positives, math_ops.reduce_sum(is_true_positive, 1))
|
||||
false_negatives_compute_op = state_ops.assign_add(
|
||||
false_negatives, math_ops.reduce_sum(is_false_negative, 1))
|
||||
true_negatives_compute_op = state_ops.assign_add(
|
||||
true_negatives, math_ops.reduce_sum(is_true_negative, 1))
|
||||
false_positives_compute_op = state_ops.assign_add(
|
||||
false_positives, math_ops.reduce_sum(is_false_positive, 1))
|
||||
(true_positives, false_negatives, true_negatives, false_positives,
|
||||
true_positives_compute_op, false_negatives_compute_op,
|
||||
true_negatives_compute_op, false_positives_compute_op) = _tp_fn_tn_fp(
|
||||
predictions, labels, thresholds, ignore_mask)
|
||||
|
||||
epsilon = 1.0e-6
|
||||
assert array_ops.squeeze(
|
||||
@ -698,6 +749,149 @@ def streaming_auc(predictions, labels, ignore_mask=None, num_thresholds=200,
|
||||
return auc, update_op
|
||||
|
||||
|
||||
def streaming_precision_at_thresholds(predictions, labels, thresholds,
|
||||
ignore_mask=None,
|
||||
metrics_collections=None,
|
||||
updates_collections=None, name=None):
|
||||
"""Computes precision values for different `thresholds` on `predictions`.
|
||||
|
||||
The `streaming_precision_at_thresholds` function creates four local variables,
|
||||
`true_positives`, `true_negatives`, `false_positives` and `false_negatives`
|
||||
for various values of thresholds.
|
||||
`precision[i]` is defined as the number of values in `predictions` above
|
||||
`thresholds[i]` whose corresponding entry in `labels` is `True`
|
||||
(`true_positives[i]`) divided by the number of values in `predictions`
|
||||
above `thresholds[i]` (`true_positives[i] + false_positives[i]`).
|
||||
|
||||
If `ignore_mask` is not None then only values whose corresponding value in
|
||||
`ignore_mask` is `False` are considered.
|
||||
|
||||
`precision` is returned along with an `update_op` whose value equals that of
|
||||
`precision`.
|
||||
|
||||
Args:
|
||||
predictions: A floating point `Tensor` of arbitrary shape and whose values
|
||||
are in the range `[0, 1]`.
|
||||
labels: A binary `Tensor` whose shape matches `predictions`.
|
||||
thresholds: A python list or tuple of float thresholds in `[0, 1]`.
|
||||
ignore_mask: An optional, binary tensor whose size matches `predictions`.
|
||||
metrics_collections: An optional list of collections that `auc` should be
|
||||
added to.
|
||||
updates_collections: An optional list of collections that `update_op` should
|
||||
be added to.
|
||||
name: An optional variable_op_scope name.
|
||||
|
||||
Returns:
|
||||
precision: A float tensor of shape [len(thresholds)].
|
||||
update_op: An operation that increments the `true_positives`,
|
||||
`true_negatives`, `false_positives` and `false_negatives` variables that
|
||||
are used in the computation of `precision`.
|
||||
|
||||
Raises:
|
||||
ValueError: If the shape of `predictions` and `labels` do not match or if
|
||||
`ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
"""
|
||||
with variable_scope.variable_op_scope([predictions, labels], name,
|
||||
'precision_at_thresholds'):
|
||||
(true_positives, _, _, false_positives, true_positives_compute_op, _, _,
|
||||
false_positives_compute_op,) = _tp_fn_tn_fp(
|
||||
predictions, labels, thresholds, ignore_mask)
|
||||
|
||||
# avoid division by zero
|
||||
epsilon = 1e-7
|
||||
def compute_precision(name):
|
||||
precision = math_ops.div(true_positives,
|
||||
epsilon + true_positives + false_positives,
|
||||
name='precision_' + name)
|
||||
return precision
|
||||
|
||||
precision = compute_precision('value')
|
||||
with ops.control_dependencies([true_positives_compute_op,
|
||||
false_positives_compute_op]):
|
||||
update_op = compute_precision('update_op')
|
||||
|
||||
if metrics_collections:
|
||||
ops.add_to_collections(metrics_collections, precision)
|
||||
|
||||
if updates_collections:
|
||||
ops.add_to_collections(updates_collections, update_op)
|
||||
|
||||
return precision, update_op
|
||||
|
||||
|
||||
def streaming_recall_at_thresholds(predictions, labels, thresholds,
|
||||
ignore_mask=None, metrics_collections=None,
|
||||
updates_collections=None, name=None):
|
||||
"""Computes various recall values for different `thresholds` on `predictions`.
|
||||
|
||||
The `streaming_recall_at_thresholds` function creates four local variables,
|
||||
`true_positives`, `true_negatives`, `false_positives` and `false_negatives`
|
||||
for various values of thresholds.
|
||||
`recall[i]` is defined as the number of values in `predictions` above
|
||||
`thresholds[i]` whose corresponding entry in `labels` is `True`
|
||||
(`true_positives[i]`) divided by the number of True values in `labels`
|
||||
(`true_positives[i] + false_negatives[i]`).
|
||||
|
||||
If `ignore_mask` is not None then only values whose corresponding value in
|
||||
`ignore_mask` is `False` are considered.
|
||||
|
||||
`recall` are returned along with an `update_op` whose value equals that of
|
||||
`recall`.
|
||||
|
||||
Args:
|
||||
predictions: A floating point `Tensor` of arbitrary shape and whose values
|
||||
are in the range `[0, 1]`.
|
||||
labels: A binary `Tensor` whose shape matches `predictions`.
|
||||
thresholds: A python list or tuple of float thresholds in `[0, 1]`.
|
||||
ignore_mask: An optional, binary tensor whose size matches `predictions`.
|
||||
metrics_collections: An optional list of collections that `auc` should be
|
||||
added to.
|
||||
updates_collections: An optional list of collections that `update_op` should
|
||||
be added to.
|
||||
name: An optional variable_op_scope name.
|
||||
|
||||
Returns:
|
||||
recall: A float tensor of shape [len(thresholds)].
|
||||
update_op: An operation that increments the `true_positives`,
|
||||
`true_negatives`, `false_positives` and `false_negatives` variables that
|
||||
are used in the computation of `recall`.
|
||||
|
||||
Raises:
|
||||
ValueError: If the shape of `predictions` and `labels` do not match or if
|
||||
`ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
"""
|
||||
with variable_scope.variable_op_scope([predictions, labels], name,
|
||||
'recall_at_thresholds'):
|
||||
(true_positives, false_negatives, _, _, true_positives_compute_op,
|
||||
false_negatives_compute_op, _, _,) = _tp_fn_tn_fp(
|
||||
predictions, labels, thresholds, ignore_mask)
|
||||
|
||||
# avoid division by zero
|
||||
epsilon = 1e-7
|
||||
def compute_recall(name):
|
||||
recall = math_ops.div(true_positives,
|
||||
epsilon + true_positives + false_negatives,
|
||||
name='recall_' + name)
|
||||
return recall
|
||||
|
||||
recall = compute_recall('value')
|
||||
with ops.control_dependencies([true_positives_compute_op,
|
||||
false_negatives_compute_op]):
|
||||
update_op = compute_recall('update_op')
|
||||
|
||||
if metrics_collections:
|
||||
ops.add_to_collections(metrics_collections, recall)
|
||||
|
||||
if updates_collections:
|
||||
ops.add_to_collections(updates_collections, update_op)
|
||||
|
||||
return recall, update_op
|
||||
|
||||
|
||||
def streaming_recall_at_k(predictions, labels, k, ignore_mask=None,
|
||||
metrics_collections=None, updates_collections=None,
|
||||
name=None):
|
||||
@ -741,9 +935,9 @@ def streaming_recall_at_k(predictions, labels, k, ignore_mask=None,
|
||||
|
||||
Raises:
|
||||
ValueError: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or if
|
||||
either `metrics_collections` or `updates_collections` are not a list or
|
||||
tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
"""
|
||||
in_top_k = math_ops.to_float(nn.in_top_k(predictions, labels, k))
|
||||
return streaming_mean(in_top_k, _mask_to_weights(ignore_mask),
|
||||
|
@ -713,6 +713,266 @@ class StreamingAUCTest(tf.test.TestCase):
|
||||
self.assertAlmostEqual(expected_auc, auc.eval(), 2)
|
||||
|
||||
|
||||
class StreamingPrecisionRecallThresholdsTest(tf.test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
np.random.seed(1)
|
||||
tf.reset_default_graph()
|
||||
|
||||
def testMetricsCollection(self):
|
||||
my_collection_name = '__metrics__'
|
||||
prec, _ = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions=tf.ones((10, 1)),
|
||||
labels=tf.ones((10, 1)),
|
||||
thresholds=[0, 0.5, 1.0],
|
||||
metrics_collections=[my_collection_name])
|
||||
rec, _ = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions=tf.ones((10, 1)),
|
||||
labels=tf.ones((10, 1)),
|
||||
thresholds=[0, 0.5, 1.0],
|
||||
metrics_collections=[my_collection_name])
|
||||
self.assertListEqual(tf.get_collection(my_collection_name), [prec, rec])
|
||||
|
||||
def testUpdatesCollection(self):
|
||||
my_collection_name = '__updates__'
|
||||
_, precision_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions=tf.ones((10, 1)),
|
||||
labels=tf.ones((10, 1)),
|
||||
thresholds=[0, 0.5, 1.0],
|
||||
updates_collections=[my_collection_name])
|
||||
_, recall_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions=tf.ones((10, 1)),
|
||||
labels=tf.ones((10, 1)),
|
||||
thresholds=[0, 0.5, 1.0],
|
||||
updates_collections=[my_collection_name])
|
||||
self.assertListEqual(tf.get_collection(my_collection_name),
|
||||
[precision_op, recall_op])
|
||||
|
||||
def testValueTensorIsIdempotent(self):
|
||||
predictions = tf.random_uniform((10, 3), maxval=1, dtype=tf.float32, seed=1)
|
||||
labels = tf.random_uniform((10, 3), maxval=1, dtype=tf.int64, seed=1)
|
||||
thresholds = [0, 0.5, 1.0]
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
|
||||
with self.test_session() as sess:
|
||||
sess.run(tf.initialize_local_variables())
|
||||
|
||||
# Run several updates, then verify idempotency.
|
||||
sess.run([prec_op, rec_op])
|
||||
initial_prec = prec.eval()
|
||||
initial_rec = rec.eval()
|
||||
for _ in range(10):
|
||||
sess.run([prec_op, rec_op])
|
||||
self.assertAllClose(initial_prec, prec.eval())
|
||||
self.assertAllClose(initial_rec, rec.eval())
|
||||
|
||||
def testEffectivelyEquivalentShapes(self):
|
||||
inputs = np.random.randint(0, 2, size=(100, 1))
|
||||
|
||||
with self.test_session() as sess:
|
||||
predictions = tf.constant(inputs, dtype=tf.float32, shape=(100,))
|
||||
labels = tf.constant(inputs, shape=(100, 1))
|
||||
thresholds = [0.5]
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
|
||||
sess.run(tf.initialize_local_variables())
|
||||
sess.run([prec_op, rec_op])
|
||||
|
||||
self.assertEqual(1, prec.eval())
|
||||
self.assertEqual(1, rec.eval())
|
||||
|
||||
def testAllCorrect(self):
|
||||
inputs = np.random.randint(0, 2, size=(100, 1))
|
||||
|
||||
with self.test_session() as sess:
|
||||
predictions = tf.constant(inputs, dtype=tf.float32)
|
||||
labels = tf.constant(inputs)
|
||||
thresholds = [0.5]
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
|
||||
sess.run(tf.initialize_local_variables())
|
||||
sess.run([prec_op, rec_op])
|
||||
|
||||
self.assertEqual(1, prec.eval())
|
||||
self.assertEqual(1, rec.eval())
|
||||
|
||||
def testSomeCorrect(self):
|
||||
with self.test_session() as sess:
|
||||
predictions = tf.constant([1, 0, 1, 0], shape=(1, 4), dtype=tf.float32)
|
||||
labels = tf.constant([0, 1, 1, 0], shape=(1, 4))
|
||||
thresholds = [0.5]
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
|
||||
sess.run(tf.initialize_local_variables())
|
||||
sess.run([prec_op, rec_op])
|
||||
|
||||
self.assertAlmostEqual(0.5, prec.eval())
|
||||
self.assertAlmostEqual(0.5, rec.eval())
|
||||
|
||||
def testAllIncorrect(self):
|
||||
inputs = np.random.randint(0, 2, size=(100, 1))
|
||||
|
||||
with self.test_session() as sess:
|
||||
predictions = tf.constant(inputs, dtype=tf.float32)
|
||||
labels = tf.constant(1 - inputs, dtype=tf.float32)
|
||||
thresholds = [0.5]
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
|
||||
sess.run(tf.initialize_local_variables())
|
||||
sess.run([prec_op, rec_op])
|
||||
|
||||
self.assertAlmostEqual(0, prec.eval())
|
||||
self.assertAlmostEqual(0, rec.eval())
|
||||
|
||||
def testIgnoreMask(self):
|
||||
with self.test_session() as sess:
|
||||
predictions = tf.constant([[1, 0], [1, 0]], shape=(2, 2),
|
||||
dtype=tf.float32)
|
||||
labels = tf.constant([[0, 1], [1, 0]], shape=(2, 2))
|
||||
ignore_mask = tf.constant([[True, True], [False, False]], shape=(2, 2))
|
||||
thresholds = [0.5, 1.1]
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions, labels, thresholds, ignore_mask=ignore_mask)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions, labels, thresholds, ignore_mask=ignore_mask)
|
||||
|
||||
[prec_low, prec_high] = tf.split(0, 2, prec)
|
||||
prec_low = tf.reshape(prec_low, shape=())
|
||||
prec_high = tf.reshape(prec_high, shape=())
|
||||
[rec_low, rec_high] = tf.split(0, 2, rec)
|
||||
rec_low = tf.reshape(rec_low, shape=())
|
||||
rec_high = tf.reshape(rec_high, shape=())
|
||||
|
||||
sess.run(tf.initialize_local_variables())
|
||||
sess.run([prec_op, rec_op])
|
||||
|
||||
self.assertAlmostEqual(1.0, prec_low.eval(), places=5)
|
||||
self.assertAlmostEqual(0.0, prec_high.eval(), places=5)
|
||||
self.assertAlmostEqual(1.0, rec_low.eval(), places=5)
|
||||
self.assertAlmostEqual(0.0, rec_high.eval(), places=5)
|
||||
|
||||
def testExtremeThresholds(self):
|
||||
with self.test_session() as sess:
|
||||
predictions = tf.constant([1, 0, 1, 0], shape=(1, 4), dtype=tf.float32)
|
||||
labels = tf.constant([0, 1, 1, 1], shape=(1, 4))
|
||||
thresholds = [-1.0, 2.0] # lower/higher than any values
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
|
||||
[prec_low, prec_high] = tf.split(0, 2, prec)
|
||||
[rec_low, rec_high] = tf.split(0, 2, rec)
|
||||
|
||||
sess.run(tf.initialize_local_variables())
|
||||
sess.run([prec_op, rec_op])
|
||||
|
||||
self.assertAlmostEqual(0.75, prec_low.eval())
|
||||
self.assertAlmostEqual(0.0, prec_high.eval())
|
||||
self.assertAlmostEqual(1.0, rec_low.eval())
|
||||
self.assertAlmostEqual(0.0, rec_high.eval())
|
||||
|
||||
def testZeroLabelsPredictions(self):
|
||||
with self.test_session() as sess:
|
||||
predictions = tf.zeros([4], dtype=tf.float32)
|
||||
labels = tf.zeros([4])
|
||||
thresholds = [0.5]
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
predictions, labels, thresholds)
|
||||
|
||||
sess.run(tf.initialize_local_variables())
|
||||
sess.run([prec_op, rec_op])
|
||||
|
||||
self.assertAlmostEqual(0, prec.eval(), 6)
|
||||
self.assertAlmostEqual(0, rec.eval(), 6)
|
||||
|
||||
def testWithMultipleUpdates(self):
|
||||
num_samples = 5000
|
||||
batch_size = 10
|
||||
num_batches = num_samples / batch_size
|
||||
|
||||
# Create the labels and data.
|
||||
labels = np.random.randint(0, 2, size=(num_samples, 1))
|
||||
noise = np.random.normal(0.0, scale=0.2, size=(num_samples, 1))
|
||||
predictions = 0.4 + 0.2 * labels + noise
|
||||
predictions[predictions > 1] = 1
|
||||
predictions[predictions < 0] = 0
|
||||
thresholds = [0.3]
|
||||
|
||||
tp = 0
|
||||
fp = 0
|
||||
fn = 0
|
||||
tn = 0
|
||||
for i in range(num_samples):
|
||||
if predictions[i] > thresholds[0]:
|
||||
if labels[i] == 1:
|
||||
tp += 1
|
||||
else:
|
||||
fp += 1
|
||||
else:
|
||||
if labels[i] == 1:
|
||||
fn += 1
|
||||
else:
|
||||
tn += 1
|
||||
epsilon = 1e-7
|
||||
expected_prec = tp / (epsilon + tp + fp)
|
||||
expected_rec = tp / (epsilon + tp + fn)
|
||||
|
||||
labels = labels.astype(np.float32)
|
||||
predictions = predictions.astype(np.float32)
|
||||
|
||||
with self.test_session() as sess:
|
||||
# Reshape the data so its easy to queue up:
|
||||
predictions_batches = predictions.reshape((batch_size, num_batches))
|
||||
labels_batches = labels.reshape((batch_size, num_batches))
|
||||
|
||||
# Enqueue the data:
|
||||
predictions_queue = tf.FIFOQueue(num_batches, dtypes=tf.float32,
|
||||
shapes=(batch_size,))
|
||||
labels_queue = tf.FIFOQueue(num_batches, dtypes=tf.float32,
|
||||
shapes=(batch_size,))
|
||||
|
||||
for i in range(int(num_batches)):
|
||||
tf_prediction = tf.constant(predictions_batches[:, i])
|
||||
tf_label = tf.constant(labels_batches[:, i])
|
||||
sess.run([predictions_queue.enqueue(tf_prediction),
|
||||
labels_queue.enqueue(tf_label)])
|
||||
|
||||
tf_predictions = predictions_queue.dequeue()
|
||||
tf_labels = labels_queue.dequeue()
|
||||
|
||||
prec, prec_op = tf.contrib.metrics.streaming_precision_at_thresholds(
|
||||
tf_predictions, tf_labels, thresholds)
|
||||
rec, rec_op = tf.contrib.metrics.streaming_recall_at_thresholds(
|
||||
tf_predictions, tf_labels, thresholds)
|
||||
|
||||
sess.run(tf.initialize_local_variables())
|
||||
for _ in range(int(num_samples / batch_size)):
|
||||
sess.run([prec_op, rec_op])
|
||||
# Since this is only approximate, we can't expect a 6 digits match.
|
||||
# Although with higher number of samples/thresholds we should see the
|
||||
# accuracy improving
|
||||
self.assertAlmostEqual(expected_prec, prec.eval(), 2)
|
||||
self.assertAlmostEqual(expected_rec, rec.eval(), 2)
|
||||
|
||||
|
||||
class StreamingRecallAtKTest(tf.test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -304,6 +304,7 @@ int DataTypeSize(DataType dt) {
|
||||
return sizeof(T);
|
||||
switch (dt) {
|
||||
TF_CALL_POD_TYPES(CASE);
|
||||
TF_CALL_QUANTIZED_TYPES(CASE);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -50,10 +50,10 @@ namespace tensorflow {
|
||||
// You call it like:
|
||||
// GraphDefBuilder b;
|
||||
// using namespace ::tensorflow::ops; // NOLINT(build/namespaces)
|
||||
// Node* a = Const(7, b.opts());
|
||||
// Node* na = Const(7, b.opts());
|
||||
// // Note: WithName() returns a copy, opts is unchanged.
|
||||
// Node* b = Const(5, b.opts().WithName("control-input"));
|
||||
// Node* c = Identity(a, b.opts().WithControlInput(b));
|
||||
// Node* nb = Const(5, b.opts().WithName("control-input"));
|
||||
// Node* nc = Identity(na, b.opts().WithControlInput(nb));
|
||||
// GraphDef graph_def;
|
||||
// Status status = b.ToGraphDef(&graph_def);
|
||||
// if (!status.ok()) { /* Handle error */ }
|
||||
|
@ -25,12 +25,12 @@ namespace tensorflow {
|
||||
|
||||
Tensor VecShape(int64 v) {
|
||||
if (v >= std::numeric_limits<int32>::max()) {
|
||||
Tensor shape(DT_INT32, TensorShape({1}));
|
||||
Tensor shape(DT_INT64, TensorShape({1}));
|
||||
shape.vec<int64>()(0) = v;
|
||||
return shape;
|
||||
} else {
|
||||
Tensor shape(DT_INT64, TensorShape({1}));
|
||||
shape.vec<int64>()(0) = v;
|
||||
Tensor shape(DT_INT32, TensorShape({1}));
|
||||
shape.vec<int32>()(0) = v;
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ limitations under the License.
|
||||
#include "tensorflow/core/kernels/concat_lib.h"
|
||||
#include "tensorflow/core/kernels/split_lib.h"
|
||||
#include "tensorflow/core/kernels/tensor_array.h"
|
||||
#include "tensorflow/core/lib/core/refcount.h"
|
||||
#include "tensorflow/core/lib/core/errors.h"
|
||||
#include "tensorflow/core/lib/core/refcount.h"
|
||||
#include "tensorflow/core/lib/strings/strcat.h"
|
||||
@ -235,7 +234,7 @@ class TensorArrayGradOp : public TensorArrayCreationOp {
|
||||
}
|
||||
|
||||
auto creator = [this, tensor_array, array_size,
|
||||
tensor_array_output_handle](TensorArray** ret) {
|
||||
tensor_array_output_handle](TensorArray** ret) -> Status {
|
||||
*ret = new TensorArray(
|
||||
tensor_array->ElemType(), *tensor_array_output_handle, array_size,
|
||||
false /* dynamic_size */, true /* multiple_writes_aggregate */,
|
||||
|
@ -20,7 +20,7 @@ limitations under the License.
|
||||
#include "tensorflow/core/platform/platform.h"
|
||||
|
||||
// Include appropriate platform-dependent implementations
|
||||
#if defined(PLATFORM_GOOGLE)
|
||||
#if defined(PLATFORM_GOOGLE) || defined(GOOGLE_INTEGRAL_TYPES)
|
||||
#include "tensorflow/core/platform/google/integral_types.h"
|
||||
#elif defined(PLATFORM_POSIX) || defined(PLATFORM_POSIX_ANDROID) || \
|
||||
defined(PLATFORM_GOOGLE_ANDROID)
|
||||
|
@ -49,7 +49,7 @@ def conv_model(X, y):
|
||||
features = tf.reshape(features, [-1, 12])
|
||||
return learn.models.logistic_regression(features, y)
|
||||
|
||||
val_monitor = monitors.ValidationMonitor(X_val, y_val, n_classes=10, print_steps=50)
|
||||
val_monitor = monitors.ValidationMonitor(X_val, y_val, every_n_steps=50)
|
||||
# Create a classifier, train and predict.
|
||||
classifier = learn.TensorFlowEstimator(model_fn=conv_model, n_classes=10,
|
||||
steps=1000, learning_rate=0.05,
|
||||
|
@ -30,8 +30,7 @@ X_train, X_test, y_train, y_test = train_test_split(iris.data,
|
||||
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train,
|
||||
test_size=0.2, random_state=42)
|
||||
val_monitor = learn.monitors.ValidationMonitor(X_val, y_val,
|
||||
early_stopping_rounds=200,
|
||||
n_classes=3)
|
||||
early_stopping_rounds=200)
|
||||
|
||||
# classifier with early stopping on training data
|
||||
classifier1 = learn.TensorFlowDNNClassifier(hidden_units=[10, 20, 10],
|
||||
|
@ -219,10 +219,17 @@ Generate `n` samples.
|
||||
Base class for continuous probability distributions.
|
||||
|
||||
`ContinuousDistribution` defines the API for the likelihood functions `pdf`
|
||||
and `log_pdf` of continuous probability distributions.
|
||||
and `log_pdf` of continuous probability distributions, and a property
|
||||
`is_reparameterized` (returning `True` or `False`) which describes
|
||||
whether the samples of this distribution are calculated in a differentiable
|
||||
way from a non-parameterized distribution. For example, the `Normal`
|
||||
distribution with parameters `mu` and `sigma` is reparameterized as
|
||||
|
||||
Subclasses must override both `pdf` and `log_pdf` but one can call this base
|
||||
class's implementation.
|
||||
```Normal(mu, sigma) = sigma * Normal(0, 1) + mu```
|
||||
|
||||
Subclasses must override `pdf` and `log_pdf` but one can call this base
|
||||
class's implementation. They must also override the `is_reparameterized`
|
||||
property.
|
||||
|
||||
See `BaseDistribution` for more information on the API for probability
|
||||
distributions.
|
||||
@ -300,6 +307,13 @@ Same meaning as `batch_shape`. May be only partially defined.
|
||||
Same meaning as `event_shape`. May be only partially defined.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.ContinuousDistribution.is_reparameterized` {#ContinuousDistribution.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.ContinuousDistribution.log_cdf(value, name='log_cdf')` {#ContinuousDistribution.log_cdf}
|
||||
@ -609,6 +623,13 @@ where digamma(alpha) is the digamma function.
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Chi2.is_reparameterized` {#Chi2.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Chi2.log_cdf(x, name='log_cdf')` {#Chi2.log_cdf}
|
||||
@ -798,6 +819,13 @@ where digamma(alpha) is the digamma function.
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Exponential.is_reparameterized` {#Exponential.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Exponential.lam` {#Exponential.lam}
|
||||
@ -871,20 +899,20 @@ Log pdf of observations in `x` under these Gamma distribution(s).
|
||||
|
||||
#### `tf.contrib.distributions.Exponential.sample(n, seed=None, name=None)` {#Exponential.sample}
|
||||
|
||||
Generate `n` samples.
|
||||
Sample `n` observations from the Exponential Distributions.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`n`</b>: scalar. Number of samples to draw from each distribution.
|
||||
* <b>`seed`</b>: Python integer seed for RNG
|
||||
* <b>`name`</b>: name to give to the op.
|
||||
* <b>`n`</b>: `Scalar`, type int32, the number of observations to sample.
|
||||
* <b>`seed`</b>: Python integer, the random seed.
|
||||
* <b>`name`</b>: The name to give this op.
|
||||
|
||||
##### Returns:
|
||||
|
||||
|
||||
* <b>`samples`</b>: a `Tensor` of shape `(n,) + self.batch_shape + self.event_shape`
|
||||
with values of type `self.dtype`.
|
||||
* <b>`samples`</b>: `[n, ...]`, a `Tensor` of `n` samples for each
|
||||
of the distributions determined by the hyperparameters.
|
||||
|
||||
|
||||
- - -
|
||||
@ -1025,6 +1053,13 @@ where digamma(alpha) is the digamma function.
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Gamma.is_reparameterized` {#Gamma.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Gamma.log_cdf(x, name='log_cdf')` {#Gamma.log_cdf}
|
||||
@ -1226,6 +1261,13 @@ The entropy of Gaussian distribution(s).
|
||||
* <b>`entropy`</b>: tensor of dtype `dtype`, the entropy.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Gaussian.is_reparameterized` {#Gaussian.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Gaussian.log_cdf(x, name=None)` {#Gaussian.log_cdf}
|
||||
@ -1465,6 +1507,13 @@ The entropy of Student t distribution(s).
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.StudentT.is_reparameterized` {#StudentT.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.StudentT.log_cdf(value, name='log_cdf')` {#StudentT.log_cdf}
|
||||
@ -1697,6 +1746,13 @@ The entropy of Uniform distribution(s).
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Uniform.is_reparameterized` {#Uniform.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Uniform.log_cdf(x, name='log_cdf')` {#Uniform.log_cdf}
|
||||
@ -1913,6 +1969,13 @@ The entropies of these Multivariate Normals.
|
||||
* <b>`entropy`</b>: tensor of dtype `dtype`, the entropies.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.MultivariateNormal.is_reparameterized` {#MultivariateNormal.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.MultivariateNormal.log_pdf(x, name=None)` {#MultivariateNormal.log_pdf}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -242,9 +242,9 @@ values in `ignore_mask` are `False`. In addition to performing the updates,
|
||||
|
||||
|
||||
* <b>`ValueError`</b>: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not
|
||||
a list or tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
|
||||
|
||||
- - -
|
||||
@ -295,9 +295,9 @@ values in `ignore_mask` are `False`. In addition to performing the updates,
|
||||
|
||||
|
||||
* <b>`ValueError`</b>: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not
|
||||
a list or tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
|
||||
|
||||
- - -
|
||||
@ -321,12 +321,12 @@ numbers of thresholds more closely approximating the true AUC.
|
||||
|
||||
To faciliate the estimation of the AUC over a stream of data, the function
|
||||
creates an `update_op` operation whose behavior is dependent on the value of
|
||||
`weights`. If `weights` is None, then `update_op` increments the
|
||||
`ignore_mask`. If `ignore_mask` is None, then `update_op` increments the
|
||||
`true_positives`, `true_negatives`, `false_positives` and `false_negatives`
|
||||
counts with the number of each found in the current `predictions` and `labels`
|
||||
`Tensors`. If `weights` is not `None`, then the increment is performed using
|
||||
only the elements of `predictions` and `labels` whose corresponding value
|
||||
in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
`Tensors`. If `ignore_mask` is not `None`, then the increment is performed
|
||||
using only the elements of `predictions` and `labels` whose corresponding
|
||||
value in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
`update_op` also returns the `auc`.
|
||||
|
||||
##### Args:
|
||||
@ -347,7 +347,7 @@ in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
##### Returns:
|
||||
|
||||
|
||||
* <b>`auc`</b>: A tensor representing the current area-under-curve.
|
||||
* <b>`auc`</b>: A scalar tensor representing the current area-under-curve.
|
||||
* <b>`update_op`</b>: An operation that increments the `true_positives`,
|
||||
`true_negatives`, `false_positives` and `false_negatives` variables
|
||||
appropriately and whose value matches `auc`.
|
||||
@ -356,9 +356,9 @@ in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
|
||||
|
||||
* <b>`ValueError`</b>: If the shape of `predictions` and `labels` do not match or if
|
||||
`weights` is not `None` and its shape doesn't match `values`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
`ignore_mask` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not a list or
|
||||
tuple.
|
||||
|
||||
|
||||
- - -
|
||||
@ -411,9 +411,9 @@ recall value.
|
||||
|
||||
|
||||
* <b>`ValueError`</b>: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or if
|
||||
either `metrics_collections` or `updates_collections` are not a list or
|
||||
tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
|
||||
|
||||
- - -
|
||||
|
@ -100,6 +100,13 @@ where digamma(alpha) is the digamma function.
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Chi2.is_reparameterized` {#Chi2.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Chi2.log_cdf(x, name='log_cdf')` {#Chi2.log_cdf}
|
||||
|
@ -1,10 +1,17 @@
|
||||
Base class for continuous probability distributions.
|
||||
|
||||
`ContinuousDistribution` defines the API for the likelihood functions `pdf`
|
||||
and `log_pdf` of continuous probability distributions.
|
||||
and `log_pdf` of continuous probability distributions, and a property
|
||||
`is_reparameterized` (returning `True` or `False`) which describes
|
||||
whether the samples of this distribution are calculated in a differentiable
|
||||
way from a non-parameterized distribution. For example, the `Normal`
|
||||
distribution with parameters `mu` and `sigma` is reparameterized as
|
||||
|
||||
Subclasses must override both `pdf` and `log_pdf` but one can call this base
|
||||
class's implementation.
|
||||
```Normal(mu, sigma) = sigma * Normal(0, 1) + mu```
|
||||
|
||||
Subclasses must override `pdf` and `log_pdf` but one can call this base
|
||||
class's implementation. They must also override the `is_reparameterized`
|
||||
property.
|
||||
|
||||
See `BaseDistribution` for more information on the API for probability
|
||||
distributions.
|
||||
@ -82,6 +89,13 @@ Same meaning as `batch_shape`. May be only partially defined.
|
||||
Same meaning as `event_shape`. May be only partially defined.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.ContinuousDistribution.is_reparameterized` {#ContinuousDistribution.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.ContinuousDistribution.log_cdf(value, name='log_cdf')` {#ContinuousDistribution.log_cdf}
|
||||
|
@ -93,6 +93,13 @@ where digamma(alpha) is the digamma function.
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Exponential.is_reparameterized` {#Exponential.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Exponential.lam` {#Exponential.lam}
|
||||
@ -166,20 +173,20 @@ Log pdf of observations in `x` under these Gamma distribution(s).
|
||||
|
||||
#### `tf.contrib.distributions.Exponential.sample(n, seed=None, name=None)` {#Exponential.sample}
|
||||
|
||||
Generate `n` samples.
|
||||
Sample `n` observations from the Exponential Distributions.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`n`</b>: scalar. Number of samples to draw from each distribution.
|
||||
* <b>`seed`</b>: Python integer seed for RNG
|
||||
* <b>`name`</b>: name to give to the op.
|
||||
* <b>`n`</b>: `Scalar`, type int32, the number of observations to sample.
|
||||
* <b>`seed`</b>: Python integer, the random seed.
|
||||
* <b>`name`</b>: The name to give this op.
|
||||
|
||||
##### Returns:
|
||||
|
||||
|
||||
* <b>`samples`</b>: a `Tensor` of shape `(n,) + self.batch_shape + self.event_shape`
|
||||
with values of type `self.dtype`.
|
||||
* <b>`samples`</b>: `[n, ...]`, a `Tensor` of `n` samples for each
|
||||
of the distributions determined by the hyperparameters.
|
||||
|
||||
|
||||
- - -
|
||||
|
@ -124,6 +124,13 @@ where digamma(alpha) is the digamma function.
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Gamma.is_reparameterized` {#Gamma.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Gamma.log_cdf(x, name='log_cdf')` {#Gamma.log_cdf}
|
||||
|
@ -105,6 +105,13 @@ The entropy of Gaussian distribution(s).
|
||||
* <b>`entropy`</b>: tensor of dtype `dtype`, the entropy.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Gaussian.is_reparameterized` {#Gaussian.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Gaussian.log_cdf(x, name=None)` {#Gaussian.log_cdf}
|
||||
|
@ -125,6 +125,13 @@ The entropies of these Multivariate Normals.
|
||||
* <b>`entropy`</b>: tensor of dtype `dtype`, the entropies.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.MultivariateNormal.is_reparameterized` {#MultivariateNormal.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.MultivariateNormal.log_pdf(x, name=None)` {#MultivariateNormal.log_pdf}
|
||||
|
@ -137,6 +137,13 @@ The entropy of Student t distribution(s).
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.StudentT.is_reparameterized` {#StudentT.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.StudentT.log_cdf(value, name='log_cdf')` {#StudentT.log_cdf}
|
||||
|
@ -126,6 +126,13 @@ The entropy of Uniform distribution(s).
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Uniform.is_reparameterized` {#Uniform.is_reparameterized}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.distributions.Uniform.log_cdf(x, name='log_cdf')` {#Uniform.log_cdf}
|
||||
|
@ -12,7 +12,7 @@ Parameters:
|
||||
model_dir: Directory to save model parameters, graph and etc.
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.BaseEstimator.__init__(model_dir=None)` {#BaseEstimator.__init__}
|
||||
#### `tf.contrib.learn.BaseEstimator.__init__(model_dir=None, config=None)` {#BaseEstimator.__init__}
|
||||
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ Evaluates given model with provided evaluation data.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.BaseEstimator.fit(x, y, steps, batch_size=32, monitor=None)` {#BaseEstimator.fit}
|
||||
#### `tf.contrib.learn.BaseEstimator.fit(x, y, steps, batch_size=32, monitors=None)` {#BaseEstimator.fit}
|
||||
|
||||
Trains a model given training data X and y.
|
||||
|
||||
@ -64,8 +64,8 @@ Trains a model given training data X and y.
|
||||
(class labels in classification, real numbers in regression).
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`batch_size`</b>: minibatch size to use on the input, defaults to 32.
|
||||
* <b>`monitor`</b>: monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
@ -92,7 +92,14 @@ params : mapping of string to any
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.BaseEstimator.partial_fit(x, y, steps=1, batch_size=32, monitor=None)` {#BaseEstimator.partial_fit}
|
||||
#### `tf.contrib.learn.BaseEstimator.model_dir` {#BaseEstimator.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.BaseEstimator.partial_fit(x, y, steps=1, batch_size=32, monitors=None)` {#BaseEstimator.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -115,8 +122,8 @@ to converge, and you want to split up training into subparts.
|
||||
(class label in classification, real numbers in regression).
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`batch_size`</b>: minibatch size to use on the input, defaults to 32.
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
@ -151,7 +158,7 @@ Returns prediction probabilities for given features (classification).
|
||||
|
||||
|
||||
* <b>`x`</b>: features.
|
||||
* <b>`batch_size`</b>: OVerride default batch size.
|
||||
* <b>`batch_size`</b>: Override default batch size.
|
||||
|
||||
##### Returns:
|
||||
|
||||
@ -176,7 +183,7 @@ self
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.BaseEstimator.train(input_fn, steps, monitor=None)` {#BaseEstimator.train}
|
||||
#### `tf.contrib.learn.BaseEstimator.train(input_fn, steps, monitors=None)` {#BaseEstimator.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
@ -186,8 +193,8 @@ Trains a model given input builder function.
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitor`</b>: monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
|
@ -15,9 +15,10 @@ Parameters:
|
||||
(like tf.train.GradientDescentOptimizer).
|
||||
clip_gradients: clip_norm value for call to `clip_by_global_norm`. None
|
||||
denotes no gradient clipping.
|
||||
config: Configuration object.
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.Estimator.__init__(model_fn=None, model_dir=None, classification=True, learning_rate=0.01, optimizer='SGD', clip_gradients=None)` {#Estimator.__init__}
|
||||
#### `tf.contrib.learn.Estimator.__init__(model_fn=None, model_dir=None, classification=True, learning_rate=0.1, optimizer='Adagrad', clip_gradients=None, config=None)` {#Estimator.__init__}
|
||||
|
||||
|
||||
|
||||
@ -54,7 +55,7 @@ Evaluates given model with provided evaluation data.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.Estimator.fit(x, y, steps, batch_size=32, monitor=None)` {#Estimator.fit}
|
||||
#### `tf.contrib.learn.Estimator.fit(x, y, steps, batch_size=32, monitors=None)` {#Estimator.fit}
|
||||
|
||||
Trains a model given training data X and y.
|
||||
|
||||
@ -69,8 +70,8 @@ Trains a model given training data X and y.
|
||||
(class labels in classification, real numbers in regression).
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`batch_size`</b>: minibatch size to use on the input, defaults to 32.
|
||||
* <b>`monitor`</b>: monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
@ -97,7 +98,14 @@ params : mapping of string to any
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.Estimator.partial_fit(x, y, steps=1, batch_size=32, monitor=None)` {#Estimator.partial_fit}
|
||||
#### `tf.contrib.learn.Estimator.model_dir` {#Estimator.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.Estimator.partial_fit(x, y, steps=1, batch_size=32, monitors=None)` {#Estimator.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -120,8 +128,8 @@ to converge, and you want to split up training into subparts.
|
||||
(class label in classification, real numbers in regression).
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`batch_size`</b>: minibatch size to use on the input, defaults to 32.
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
@ -156,7 +164,7 @@ Returns prediction probabilities for given features (classification).
|
||||
|
||||
|
||||
* <b>`x`</b>: features.
|
||||
* <b>`batch_size`</b>: OVerride default batch size.
|
||||
* <b>`batch_size`</b>: Override default batch size.
|
||||
|
||||
##### Returns:
|
||||
|
||||
@ -181,7 +189,7 @@ self
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.Estimator.train(input_fn, steps, monitor=None)` {#Estimator.train}
|
||||
#### `tf.contrib.learn.Estimator.train(input_fn, steps, monitors=None)` {#Estimator.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
@ -191,8 +199,8 @@ Trains a model given input builder function.
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitor`</b>: monitor object to print training progress and invoke
|
||||
early stopping.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
|
@ -15,7 +15,14 @@ Returns weights of the linear classifier.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.fit(X, y, monitor=None, logdir=None)` {#TensorFlowClassifier.fit}
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowClassifier.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowClassifier.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -29,7 +36,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -37,8 +44,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -110,7 +119,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.partial_fit(X, y)` {#TensorFlowClassifier.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.model_dir` {#TensorFlowClassifier.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.partial_fit(x, y)` {#TensorFlowClassifier.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -125,7 +141,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -140,7 +156,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.predict(X, axis=1, batch_size=None)` {#TensorFlowClassifier.predict}
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.predict(x, axis=1, batch_size=None)` {#TensorFlowClassifier.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -151,7 +167,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -168,14 +184,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.predict_proba(X, batch_size=None)` {#TensorFlowClassifier.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.predict_proba(x, batch_size=None)` {#TensorFlowClassifier.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -260,6 +276,26 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.train(input_fn, steps, monitors=None)` {#TensorFlowClassifier.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowClassifier.weights_` {#TensorFlowClassifier.weights_}
|
||||
|
@ -38,7 +38,14 @@ Returns bias of the DNN's bias layers.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.fit(X, y, monitor=None, logdir=None)` {#TensorFlowDNNClassifier.fit}
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowDNNClassifier.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowDNNClassifier.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -52,7 +59,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -60,8 +67,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -133,7 +142,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.partial_fit(X, y)` {#TensorFlowDNNClassifier.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.model_dir` {#TensorFlowDNNClassifier.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.partial_fit(x, y)` {#TensorFlowDNNClassifier.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -148,7 +164,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -163,7 +179,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.predict(X, axis=1, batch_size=None)` {#TensorFlowDNNClassifier.predict}
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.predict(x, axis=1, batch_size=None)` {#TensorFlowDNNClassifier.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -174,7 +190,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -191,14 +207,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.predict_proba(X, batch_size=None)` {#TensorFlowDNNClassifier.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.predict_proba(x, batch_size=None)` {#TensorFlowDNNClassifier.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -283,6 +299,26 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.train(input_fn, steps, monitors=None)` {#TensorFlowDNNClassifier.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNClassifier.weights_` {#TensorFlowDNNClassifier.weights_}
|
||||
|
@ -38,7 +38,14 @@ Returns bias of the DNN's bias layers.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.fit(X, y, monitor=None, logdir=None)` {#TensorFlowDNNRegressor.fit}
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowDNNRegressor.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowDNNRegressor.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -52,7 +59,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -60,8 +67,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -133,7 +142,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.partial_fit(X, y)` {#TensorFlowDNNRegressor.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.model_dir` {#TensorFlowDNNRegressor.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.partial_fit(x, y)` {#TensorFlowDNNRegressor.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -148,7 +164,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -163,7 +179,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.predict(X, axis=1, batch_size=None)` {#TensorFlowDNNRegressor.predict}
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.predict(x, axis=1, batch_size=None)` {#TensorFlowDNNRegressor.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -174,7 +190,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -191,14 +207,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.predict_proba(X, batch_size=None)` {#TensorFlowDNNRegressor.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.predict_proba(x, batch_size=None)` {#TensorFlowDNNRegressor.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -287,6 +303,26 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.train(input_fn, steps, monitors=None)` {#TensorFlowDNNRegressor.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowDNNRegressor.weights_` {#TensorFlowDNNRegressor.weights_}
|
||||
|
@ -38,7 +38,14 @@ Parameters:
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.fit(X, y, monitor=None, logdir=None)` {#TensorFlowEstimator.fit}
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowEstimator.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowEstimator.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -52,7 +59,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -60,8 +67,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -133,7 +142,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.partial_fit(X, y)` {#TensorFlowEstimator.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.model_dir` {#TensorFlowEstimator.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.partial_fit(x, y)` {#TensorFlowEstimator.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -148,7 +164,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -163,7 +179,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.predict(X, axis=1, batch_size=None)` {#TensorFlowEstimator.predict}
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.predict(x, axis=1, batch_size=None)` {#TensorFlowEstimator.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -174,7 +190,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -191,14 +207,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.predict_proba(X, batch_size=None)` {#TensorFlowEstimator.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.predict_proba(x, batch_size=None)` {#TensorFlowEstimator.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -256,3 +272,23 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowEstimator.train(input_fn, steps, monitors=None)` {#TensorFlowEstimator.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
|
@ -15,7 +15,14 @@ Returns weights of the linear classifier.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.fit(X, y, monitor=None, logdir=None)` {#TensorFlowLinearClassifier.fit}
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowLinearClassifier.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowLinearClassifier.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -29,7 +36,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -37,8 +44,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -110,7 +119,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.partial_fit(X, y)` {#TensorFlowLinearClassifier.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.model_dir` {#TensorFlowLinearClassifier.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.partial_fit(x, y)` {#TensorFlowLinearClassifier.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -125,7 +141,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -140,7 +156,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.predict(X, axis=1, batch_size=None)` {#TensorFlowLinearClassifier.predict}
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.predict(x, axis=1, batch_size=None)` {#TensorFlowLinearClassifier.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -151,7 +167,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -168,14 +184,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.predict_proba(X, batch_size=None)` {#TensorFlowLinearClassifier.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.predict_proba(x, batch_size=None)` {#TensorFlowLinearClassifier.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -260,6 +276,26 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.train(input_fn, steps, monitors=None)` {#TensorFlowLinearClassifier.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearClassifier.weights_` {#TensorFlowLinearClassifier.weights_}
|
||||
|
@ -15,7 +15,14 @@ Returns bias of the linear regression.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.fit(X, y, monitor=None, logdir=None)` {#TensorFlowLinearRegressor.fit}
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowLinearRegressor.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowLinearRegressor.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -29,7 +36,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -37,8 +44,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -110,7 +119,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.partial_fit(X, y)` {#TensorFlowLinearRegressor.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.model_dir` {#TensorFlowLinearRegressor.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.partial_fit(x, y)` {#TensorFlowLinearRegressor.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -125,7 +141,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -140,7 +156,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.predict(X, axis=1, batch_size=None)` {#TensorFlowLinearRegressor.predict}
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.predict(x, axis=1, batch_size=None)` {#TensorFlowLinearRegressor.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -151,7 +167,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -168,14 +184,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.predict_proba(X, batch_size=None)` {#TensorFlowLinearRegressor.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.predict_proba(x, batch_size=None)` {#TensorFlowLinearRegressor.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -264,6 +280,26 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.train(input_fn, steps, monitors=None)` {#TensorFlowLinearRegressor.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowLinearRegressor.weights_` {#TensorFlowLinearRegressor.weights_}
|
||||
|
@ -48,7 +48,14 @@ Returns bias of the rnn layer.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.fit(X, y, monitor=None, logdir=None)` {#TensorFlowRNNClassifier.fit}
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowRNNClassifier.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowRNNClassifier.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -62,7 +69,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -70,8 +77,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -143,7 +152,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.partial_fit(X, y)` {#TensorFlowRNNClassifier.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.model_dir` {#TensorFlowRNNClassifier.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.partial_fit(x, y)` {#TensorFlowRNNClassifier.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -158,7 +174,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -173,7 +189,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.predict(X, axis=1, batch_size=None)` {#TensorFlowRNNClassifier.predict}
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.predict(x, axis=1, batch_size=None)` {#TensorFlowRNNClassifier.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -184,7 +200,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -201,14 +217,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.predict_proba(X, batch_size=None)` {#TensorFlowRNNClassifier.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.predict_proba(x, batch_size=None)` {#TensorFlowRNNClassifier.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -293,6 +309,26 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.train(input_fn, steps, monitors=None)` {#TensorFlowRNNClassifier.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNClassifier.weights_` {#TensorFlowRNNClassifier.weights_}
|
||||
|
@ -48,7 +48,14 @@ Returns bias of the rnn layer.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.fit(X, y, monitor=None, logdir=None)` {#TensorFlowRNNRegressor.fit}
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowRNNRegressor.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowRNNRegressor.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -62,7 +69,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -70,8 +77,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -143,7 +152,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.partial_fit(X, y)` {#TensorFlowRNNRegressor.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.model_dir` {#TensorFlowRNNRegressor.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.partial_fit(x, y)` {#TensorFlowRNNRegressor.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -158,7 +174,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -173,7 +189,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.predict(X, axis=1, batch_size=None)` {#TensorFlowRNNRegressor.predict}
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.predict(x, axis=1, batch_size=None)` {#TensorFlowRNNRegressor.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -184,7 +200,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -201,14 +217,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.predict_proba(X, batch_size=None)` {#TensorFlowRNNRegressor.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.predict_proba(x, batch_size=None)` {#TensorFlowRNNRegressor.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -297,6 +313,26 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.train(input_fn, steps, monitors=None)` {#TensorFlowRNNRegressor.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRNNRegressor.weights_` {#TensorFlowRNNRegressor.weights_}
|
||||
|
@ -15,7 +15,14 @@ Returns bias of the linear regression.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.fit(X, y, monitor=None, logdir=None)` {#TensorFlowRegressor.fit}
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.evaluate(x=None, y=None, input_fn=None, steps=None)` {#TensorFlowRegressor.evaluate}
|
||||
|
||||
See base class.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.fit(x, y, steps=None, monitors=None, logdir=None)` {#TensorFlowRegressor.fit}
|
||||
|
||||
Builds a neural network model given provided `model_fn` and training
|
||||
data X and y.
|
||||
@ -29,7 +36,7 @@ To restart learning, create new estimator.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -37,8 +44,10 @@ To restart learning, create new estimator.
|
||||
iterator that returns array of targets. The training target values
|
||||
(class labels in classification, real numbers in regression).
|
||||
|
||||
* <b>`monitor`</b>: Monitor object to print training progress and invoke early
|
||||
stopping
|
||||
* <b>`steps`</b>: int, number of steps to train.
|
||||
If None or 0, train for `self.steps`.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` objects to print training progress and
|
||||
invoke early stopping.
|
||||
* <b>`logdir`</b>: the directory to save the log file that can be used for
|
||||
optional visualization.
|
||||
|
||||
@ -110,7 +119,14 @@ Returns list of all variable names in this model.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.partial_fit(X, y)` {#TensorFlowRegressor.partial_fit}
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.model_dir` {#TensorFlowRegressor.model_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.partial_fit(x, y)` {#TensorFlowRegressor.partial_fit}
|
||||
|
||||
Incremental fit on a batch of samples.
|
||||
|
||||
@ -125,7 +141,7 @@ to converge, and you want to split up training into subparts.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
* <b>`x`</b>: matrix or tensor of shape [n_samples, n_features...]. Can be
|
||||
iterator that returns arrays of features. The training input
|
||||
samples for fitting the model.
|
||||
|
||||
@ -140,7 +156,7 @@ to converge, and you want to split up training into subparts.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.predict(X, axis=1, batch_size=None)` {#TensorFlowRegressor.predict}
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.predict(x, axis=1, batch_size=None)` {#TensorFlowRegressor.predict}
|
||||
|
||||
Predict class or regression for X.
|
||||
|
||||
@ -151,7 +167,7 @@ returned.
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`axis`</b>: Which axis to argmax for classification.
|
||||
By default axis 1 (next after batch) is used.
|
||||
Use 2 for sequence predictions.
|
||||
@ -168,14 +184,14 @@ returned.
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.predict_proba(X, batch_size=None)` {#TensorFlowRegressor.predict_proba}
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.predict_proba(x, batch_size=None)` {#TensorFlowRegressor.predict_proba}
|
||||
|
||||
Predict class probability of the input samples X.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`X`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`x`</b>: array-like matrix, [n_samples, n_features...] or iterator.
|
||||
* <b>`batch_size`</b>: If test set is too big, use batch size to split
|
||||
it into mini batches. By default the batch_size member variable is used.
|
||||
|
||||
@ -264,6 +280,26 @@ Returns
|
||||
self
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.train(input_fn, steps, monitors=None)` {#TensorFlowRegressor.train}
|
||||
|
||||
Trains a model given input builder function.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
||||
* <b>`input_fn`</b>: Input builder function, returns tuple of dicts or
|
||||
dict and Tensor.
|
||||
* <b>`steps`</b>: number of steps to train model for.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
Returns self.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
#### `tf.contrib.learn.TensorFlowRegressor.weights_` {#TensorFlowRegressor.weights_}
|
||||
|
@ -1,4 +1,4 @@
|
||||
### `tf.contrib.learn.train(graph, output_dir, train_op, loss_op, global_step_tensor=None, init_op=None, init_fn=None, log_every_steps=10, supervisor_is_chief=True, supervisor_master='', supervisor_save_model_secs=600, supervisor_save_summaries_secs=10, feed_fn=None, max_steps=None, fail_on_nan_loss=True)` {#train}
|
||||
### `tf.contrib.learn.train(graph, output_dir, train_op, loss_op, global_step_tensor=None, init_op=None, init_feed_dict=None, init_fn=None, log_every_steps=10, supervisor_is_chief=True, supervisor_master='', supervisor_save_model_secs=600, supervisor_save_summaries_steps=100, feed_fn=None, max_steps=None, fail_on_nan_loss=True, monitors=None)` {#train}
|
||||
|
||||
Train a model.
|
||||
|
||||
@ -27,6 +27,8 @@ program is terminated with exit code 1.
|
||||
one is extracted from the graph using the same logic as in `Supervisor`.
|
||||
* <b>`init_op`</b>: An op that initializes the graph. If `None`, use `Supervisor`'s
|
||||
default.
|
||||
* <b>`init_feed_dict`</b>: A dictionary that maps `Tensor` objects to feed values.
|
||||
This feed dictionary will be used when `init_op` is evaluated.
|
||||
* <b>`init_fn`</b>: Optional callable passed to Supervisor to initialize the model.
|
||||
* <b>`log_every_steps`</b>: Output logs regularly. The logs contain timing data and the
|
||||
current loss.
|
||||
@ -35,13 +37,15 @@ program is terminated with exit code 1.
|
||||
* <b>`supervisor_master`</b>: The master string to use when preparing the session.
|
||||
* <b>`supervisor_save_model_secs`</b>: Save a checkpoint every
|
||||
`supervisor_save_model_secs` seconds when training.
|
||||
* <b>`supervisor_save_summaries_secs`</b>: Save summaries every
|
||||
`supervisor_save_summaries_secs` seconds when training.
|
||||
* <b>`supervisor_save_summaries_steps`</b>: Save summaries every
|
||||
`supervisor_save_summaries_steps` seconds when training.
|
||||
* <b>`feed_fn`</b>: A function that is called every iteration to produce a `feed_dict`
|
||||
passed to `session.run` calls. Optional.
|
||||
* <b>`max_steps`</b>: Train until `global_step_tensor` evaluates to this value.
|
||||
* <b>`fail_on_nan_loss`</b>: If true, raise `NanLossDuringTrainingError` if `loss_op`
|
||||
evaluates to `NaN`. If false, continue training as if nothing happened.
|
||||
* <b>`monitors`</b>: List of `BaseMonitor` subclass instances. Used for callbacks
|
||||
inside the training loop.
|
||||
|
||||
##### Returns:
|
||||
|
||||
|
@ -17,12 +17,12 @@ numbers of thresholds more closely approximating the true AUC.
|
||||
|
||||
To faciliate the estimation of the AUC over a stream of data, the function
|
||||
creates an `update_op` operation whose behavior is dependent on the value of
|
||||
`weights`. If `weights` is None, then `update_op` increments the
|
||||
`ignore_mask`. If `ignore_mask` is None, then `update_op` increments the
|
||||
`true_positives`, `true_negatives`, `false_positives` and `false_negatives`
|
||||
counts with the number of each found in the current `predictions` and `labels`
|
||||
`Tensors`. If `weights` is not `None`, then the increment is performed using
|
||||
only the elements of `predictions` and `labels` whose corresponding value
|
||||
in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
`Tensors`. If `ignore_mask` is not `None`, then the increment is performed
|
||||
using only the elements of `predictions` and `labels` whose corresponding
|
||||
value in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
`update_op` also returns the `auc`.
|
||||
|
||||
##### Args:
|
||||
@ -43,7 +43,7 @@ in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
##### Returns:
|
||||
|
||||
|
||||
* <b>`auc`</b>: A tensor representing the current area-under-curve.
|
||||
* <b>`auc`</b>: A scalar tensor representing the current area-under-curve.
|
||||
* <b>`update_op`</b>: An operation that increments the `true_positives`,
|
||||
`true_negatives`, `false_positives` and `false_negatives` variables
|
||||
appropriately and whose value matches `auc`.
|
||||
@ -52,7 +52,7 @@ in `ignore_mask` is `False`. In addition to performing the updates,
|
||||
|
||||
|
||||
* <b>`ValueError`</b>: If the shape of `predictions` and `labels` do not match or if
|
||||
`weights` is not `None` and its shape doesn't match `values`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
`ignore_mask` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not a list or
|
||||
tuple.
|
||||
|
||||
|
@ -44,7 +44,7 @@ values in `ignore_mask` are `False`. In addition to performing the updates,
|
||||
|
||||
|
||||
* <b>`ValueError`</b>: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not
|
||||
a list or tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
|
||||
|
@ -44,7 +44,7 @@ values in `ignore_mask` are `False`. In addition to performing the updates,
|
||||
|
||||
|
||||
* <b>`ValueError`</b>: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or
|
||||
if either `metrics_collections` or `updates_collections` are not
|
||||
a list or tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
|
||||
|
@ -46,7 +46,7 @@ recall value.
|
||||
|
||||
|
||||
* <b>`ValueError`</b>: If the dimensions of `predictions` and `labels` don't match or
|
||||
if `weight` is not `None` and its shape doesn't match `predictions` or if
|
||||
either `metrics_collections` or `updates_collections` are not a list or
|
||||
tuple.
|
||||
if `ignore_mask` is not `None` and its shape doesn't match `predictions`
|
||||
or if either `metrics_collections` or `updates_collections` are not a list
|
||||
or tuple.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
### `tf.make_template(name_, func_, **kwargs)` {#make_template}
|
||||
### `tf.make_template(name_, func_, create_scope_now_=False, **kwargs)` {#make_template}
|
||||
|
||||
Given an arbitrary function, wrap it so that it does variable sharing.
|
||||
|
||||
@ -68,10 +68,14 @@ with tf.variable_scope(vs, reuse=True):
|
||||
w2 = scale_by_y2(input2)
|
||||
```
|
||||
|
||||
Note: The full variable scope is captured at the time of the first call.
|
||||
Depending on the value of `create_scope_now_`, the full variable scope may be
|
||||
captured either at the time of first call or at the time of construction. If
|
||||
this option is set to True, then all Tensors created by repeated calls to the
|
||||
template will have an extra trailing _N+1 to their name, as the first time the
|
||||
scope is entered in the Template constructor no Tensors are created.
|
||||
|
||||
Note: `name_` and `func_` have a following underscore to reduce the likelihood
|
||||
of collisions with kwargs.
|
||||
Note: `name_`, `func_` and `create_scope_now_` have a trailing underscore to
|
||||
reduce the likelihood of collisions with kwargs.
|
||||
|
||||
##### Args:
|
||||
|
||||
@ -79,14 +83,20 @@ of collisions with kwargs.
|
||||
* <b>`name_`</b>: A name for the scope created by this template. If necessary, the name
|
||||
will be made unique by appending `_N` to the name.
|
||||
* <b>`func_`</b>: The function to wrap.
|
||||
* <b>`create_scope_now_`</b>: Boolean controlling whether the scope should be created
|
||||
when the template is constructed or when the template is called. Default
|
||||
is False, meaning the scope is created when the template is called.
|
||||
* <b>`**kwargs`</b>: Keyword arguments to apply to `func_`.
|
||||
|
||||
##### Returns:
|
||||
|
||||
A function that will enter a `variable_scope` before calling `func_`. The
|
||||
first time it is called, it will create a non-reusing scope so that the
|
||||
variables will be unique. On each subsequent call, it will reuse those
|
||||
variables.
|
||||
A function to encapsulate a set of variables which should be created once
|
||||
and reused. An enclosing scope will created, either where `make_template`
|
||||
is called, or wherever the result is called, depending on the value of
|
||||
`create_scope_now_`. Regardless of the value, the first time the template
|
||||
is called it will enter the scope with no reuse, and call `func_` to create
|
||||
variables, which are guaranteed to be unique. All subsequent calls will
|
||||
re-enter the scope and reuse those variables.
|
||||
|
||||
##### Raises:
|
||||
|
||||
|
@ -11,6 +11,6 @@ Merges all summaries collected in the default graph.
|
||||
##### Returns:
|
||||
|
||||
If no summaries were collected, returns None. Otherwise returns a scalar
|
||||
`Tensor` of type`string` containing the serialized `Summary` protocol
|
||||
`Tensor` of type `string` containing the serialized `Summary` protocol
|
||||
buffer resulting from the merging.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
### `tf.nn.sufficient_statistics(x, axes, shift=True, keep_dims=False, name=None)` {#sufficient_statistics}
|
||||
### `tf.nn.sufficient_statistics(x, axes, shift=False, keep_dims=False, name=None)` {#sufficient_statistics}
|
||||
|
||||
Calculate the sufficient statistics for the mean and variance of `x`.
|
||||
|
||||
@ -6,6 +6,9 @@ These sufficient statistics are computed using the one pass algorithm on
|
||||
an input that's optionally shifted using the value of the 1st element in `x`.
|
||||
See:
|
||||
https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Computing_shifted_data
|
||||
Unfortunately, in some cases using a random individual sample as the shift
|
||||
value leads experimentally to very poor numerical stability, so it is disabled
|
||||
by default. The one-pass approach might have to be revised accordingly.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
### `tf.train.write_graph(graph_def, logdir, name, as_text=True)` {#write_graph}
|
||||
|
||||
Writes a graph proto on disk.
|
||||
Writes a graph proto to a file.
|
||||
|
||||
The graph is written as a binary proto unless `as_text` is `True`.
|
||||
|
||||
@ -14,7 +14,8 @@ tf.train.write_graph(sess.graph_def, '/tmp/my-model', 'train.pbtxt')
|
||||
|
||||
|
||||
* <b>`graph_def`</b>: A `GraphDef` protocol buffer.
|
||||
* <b>`logdir`</b>: Directory where to write the graph.
|
||||
* <b>`logdir`</b>: Directory where to write the graph. This can refer to remote
|
||||
filesystems, such as Google Cloud Storage (GCS).
|
||||
* <b>`name`</b>: Filename for the graph.
|
||||
* <b>`as_text`</b>: If `True`, writes the graph as an ASCII proto.
|
||||
|
||||
|
@ -824,7 +824,7 @@ convolutional neural networks (NIPS 2012)]
|
||||
|
||||
- - -
|
||||
|
||||
### `tf.nn.sufficient_statistics(x, axes, shift=True, keep_dims=False, name=None)` {#sufficient_statistics}
|
||||
### `tf.nn.sufficient_statistics(x, axes, shift=False, keep_dims=False, name=None)` {#sufficient_statistics}
|
||||
|
||||
Calculate the sufficient statistics for the mean and variance of `x`.
|
||||
|
||||
@ -832,6 +832,9 @@ These sufficient statistics are computed using the one pass algorithm on
|
||||
an input that's optionally shifted using the value of the 1st element in `x`.
|
||||
See:
|
||||
https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Computing_shifted_data
|
||||
Unfortunately, in some cases using a random individual sample as the shift
|
||||
value leads experimentally to very poor numerical stability, so it is disabled
|
||||
by default. The one-pass approach might have to be revised accordingly.
|
||||
|
||||
##### Args:
|
||||
|
||||
|
@ -1395,7 +1395,7 @@ Returns the current variable scope.
|
||||
|
||||
- - -
|
||||
|
||||
### `tf.make_template(name_, func_, **kwargs)` {#make_template}
|
||||
### `tf.make_template(name_, func_, create_scope_now_=False, **kwargs)` {#make_template}
|
||||
|
||||
Given an arbitrary function, wrap it so that it does variable sharing.
|
||||
|
||||
@ -1465,10 +1465,14 @@ with tf.variable_scope(vs, reuse=True):
|
||||
w2 = scale_by_y2(input2)
|
||||
```
|
||||
|
||||
Note: The full variable scope is captured at the time of the first call.
|
||||
Depending on the value of `create_scope_now_`, the full variable scope may be
|
||||
captured either at the time of first call or at the time of construction. If
|
||||
this option is set to True, then all Tensors created by repeated calls to the
|
||||
template will have an extra trailing _N+1 to their name, as the first time the
|
||||
scope is entered in the Template constructor no Tensors are created.
|
||||
|
||||
Note: `name_` and `func_` have a following underscore to reduce the likelihood
|
||||
of collisions with kwargs.
|
||||
Note: `name_`, `func_` and `create_scope_now_` have a trailing underscore to
|
||||
reduce the likelihood of collisions with kwargs.
|
||||
|
||||
##### Args:
|
||||
|
||||
@ -1476,14 +1480,20 @@ of collisions with kwargs.
|
||||
* <b>`name_`</b>: A name for the scope created by this template. If necessary, the name
|
||||
will be made unique by appending `_N` to the name.
|
||||
* <b>`func_`</b>: The function to wrap.
|
||||
* <b>`create_scope_now_`</b>: Boolean controlling whether the scope should be created
|
||||
when the template is constructed or when the template is called. Default
|
||||
is False, meaning the scope is created when the template is called.
|
||||
* <b>`**kwargs`</b>: Keyword arguments to apply to `func_`.
|
||||
|
||||
##### Returns:
|
||||
|
||||
A function that will enter a `variable_scope` before calling `func_`. The
|
||||
first time it is called, it will create a non-reusing scope so that the
|
||||
variables will be unique. On each subsequent call, it will reuse those
|
||||
variables.
|
||||
A function to encapsulate a set of variables which should be created once
|
||||
and reused. An enclosing scope will created, either where `make_template`
|
||||
is called, or wherever the result is called, depending on the value of
|
||||
`create_scope_now_`. Regardless of the value, the first time the template
|
||||
is called it will enter the scope with no reuse, and call `func_` to create
|
||||
variables, which are guaranteed to be unique. All subsequent calls will
|
||||
re-enter the scope and reuse those variables.
|
||||
|
||||
##### Raises:
|
||||
|
||||
|
@ -3078,7 +3078,7 @@ Merges all summaries collected in the default graph.
|
||||
##### Returns:
|
||||
|
||||
If no summaries were collected, returns None. Otherwise returns a scalar
|
||||
`Tensor` of type`string` containing the serialized `Summary` protocol
|
||||
`Tensor` of type `string` containing the serialized `Summary` protocol
|
||||
buffer resulting from the merging.
|
||||
|
||||
|
||||
@ -3346,7 +3346,7 @@ global_step: 10
|
||||
|
||||
### `tf.train.write_graph(graph_def, logdir, name, as_text=True)` {#write_graph}
|
||||
|
||||
Writes a graph proto on disk.
|
||||
Writes a graph proto to a file.
|
||||
|
||||
The graph is written as a binary proto unless `as_text` is `True`.
|
||||
|
||||
@ -3360,7 +3360,8 @@ tf.train.write_graph(sess.graph_def, '/tmp/my-model', 'train.pbtxt')
|
||||
|
||||
|
||||
* <b>`graph_def`</b>: A `GraphDef` protocol buffer.
|
||||
* <b>`logdir`</b>: Directory where to write the graph.
|
||||
* <b>`logdir`</b>: Directory where to write the graph. This can refer to remote
|
||||
filesystems, such as Google Cloud Storage (GCS).
|
||||
* <b>`name`</b>: Filename for the graph.
|
||||
* <b>`as_text`</b>: If `True`, writes the graph as an ASCII proto.
|
||||
|
||||
|
@ -92,8 +92,8 @@ creates a part of the graph and returns output tensors.
|
||||
If operation needs to save some `Tensor`s to Graph collections,
|
||||
put the arguments with names of the collections right before `name` argument.
|
||||
|
||||
* Tensor arguments should be either a single tensor or an iterable of tensors.
|
||||
*Not a "Tensor or list of Tensors".*
|
||||
* Tensor arguments should be either a single tensor or an iterable of tensors,
|
||||
not both. E.g. a "Tensor or list of Tensors" is too broad.
|
||||
|
||||
* Operations that take tensors as arguments should call `convert_to_tensor`
|
||||
to convert non-tensor inputs into tensors if they are using C++ operations.
|
||||
|
@ -15,6 +15,7 @@ load("//tensorflow:tensorflow.bzl", "cuda_py_test")
|
||||
load("//tensorflow:tensorflow.bzl", "cuda_py_tests")
|
||||
load("//tensorflow/core:platform/default/build_config.bzl", "tf_proto_library")
|
||||
load("//tensorflow/core:platform/default/build_config.bzl", "tf_proto_library_py")
|
||||
load("//tensorflow/core:platform/default/build_config.bzl", "tf_additional_lib_deps")
|
||||
|
||||
py_library(
|
||||
name = "python",
|
||||
@ -983,6 +984,7 @@ tf_py_wrap_cc(
|
||||
"lib/io/py_record_writer.i",
|
||||
"platform/base.i",
|
||||
"platform/numpy.i",
|
||||
"training/saver_io.i",
|
||||
"training/server_lib.i",
|
||||
"util/port.i",
|
||||
"util/py_checkpoint_reader.i",
|
||||
@ -994,12 +996,12 @@ tf_py_wrap_cc(
|
||||
":py_record_writer_lib",
|
||||
":python_op_gen",
|
||||
":tf_session_helper",
|
||||
"//tensorflow/core:lib",
|
||||
"//tensorflow/core/distributed_runtime:server_lib",
|
||||
"//tensorflow/core/distributed_runtime/rpc:grpc_server_lib",
|
||||
"//tensorflow/core/distributed_runtime/rpc:grpc_session",
|
||||
"//tensorflow/core:lib",
|
||||
"//tensorflow/core/distributed_runtime:server_lib",
|
||||
"//util/python:python_headers",
|
||||
],
|
||||
] + tf_additional_lib_deps(),
|
||||
)
|
||||
|
||||
py_library(
|
||||
|
@ -1256,17 +1256,50 @@ class ControlFlowTest(tf.test.TestCase):
|
||||
|
||||
def break_run_twice(ix):
|
||||
def _break():
|
||||
assert not ran_once[ix]
|
||||
ran_once[ix] = True
|
||||
return tf.constant(ix)
|
||||
return _break
|
||||
|
||||
# Should not fail - each conditional gets called exactly once
|
||||
# except default. Default gets called twice: once to create an
|
||||
# empty output and once for the actual cond switch.
|
||||
r6 = tf.case([(x < y, break_run_twice(0)), (x > y, break_run_twice(1))],
|
||||
default=break_run_twice(2))
|
||||
default=lambda: tf.constant(2))
|
||||
|
||||
self.assertAllEqual(r6.eval(), 0)
|
||||
|
||||
def testCaseSideEffects(self):
|
||||
with self.test_session() as sess:
|
||||
v0 = tf.Variable(-1)
|
||||
v1 = tf.Variable(-1)
|
||||
v2 = tf.Variable(-1)
|
||||
|
||||
a = lambda: control_flow_ops.with_dependencies([tf.assign(v0, 0)], 0)
|
||||
b = lambda: control_flow_ops.with_dependencies([tf.assign(v1, 1)], 1)
|
||||
c = lambda: control_flow_ops.with_dependencies([tf.assign(v2, 2)], 2)
|
||||
|
||||
x = tf.constant(1)
|
||||
y = tf.constant(2)
|
||||
|
||||
r0 = tf.case(((x < y, a), (x > y, b)), default=c, exclusive=True)
|
||||
r1 = tf.case(((x > y, a), (x < y, b)), default=c, exclusive=True)
|
||||
r2 = tf.case(((x > y, a), (x > y, b)), default=c, exclusive=True)
|
||||
|
||||
tf.initialize_all_variables().run()
|
||||
self.assertAllEqual(sess.run([v0, v1, v2]), [-1] * 3)
|
||||
self.assertEqual(2, r2.eval())
|
||||
self.assertAllEqual(sess.run([v0, v1, v2]), [-1, -1, 2])
|
||||
|
||||
tf.initialize_all_variables().run()
|
||||
self.assertAllEqual(sess.run([v0, v1, v2]), [-1] * 3)
|
||||
self.assertEqual(1, r1.eval())
|
||||
self.assertAllEqual(sess.run([v0, v1, v2]), [-1, 1, -1])
|
||||
|
||||
tf.initialize_all_variables().run()
|
||||
self.assertAllEqual(sess.run([v0, v1, v2]), [-1] * 3)
|
||||
self.assertEqual(0, r0.eval())
|
||||
self.assertAllEqual(sess.run([v0, v1, v2]), [0, -1, -1])
|
||||
|
||||
def testOneOpCond(self):
|
||||
with self.test_session():
|
||||
v = tf.Variable(0)
|
||||
|
@ -206,6 +206,27 @@ class TemplateTest(tf.test.TestCase):
|
||||
self.assertEqual("s1/nested_1/dummy:0", v1.name)
|
||||
self.assertEqual("s1_2/nested_1/dummy:0", v3.name)
|
||||
|
||||
def test_immediate_scope_creation(self):
|
||||
# Create templates in scope a then call in scope b. make_template should
|
||||
# capture the scope the first time it is called, and make_immediate_template
|
||||
# should capture the scope at construction time.
|
||||
with tf.variable_scope("ctor_scope"):
|
||||
tmpl_immed = template.make_template(
|
||||
"a", var_scoped_function, True) # create scope here
|
||||
tmpl_defer = template.make_template(
|
||||
"b", var_scoped_function, False) # default: create scope at __call__
|
||||
with tf.variable_scope("call_scope"):
|
||||
inner_imm_var = tmpl_immed()
|
||||
inner_defer_var = tmpl_defer()
|
||||
outer_imm_var = tmpl_immed()
|
||||
outer_defer_var = tmpl_defer()
|
||||
|
||||
self.assertNotEqual(inner_imm_var, inner_defer_var)
|
||||
self.assertEqual(outer_imm_var, inner_imm_var)
|
||||
self.assertEqual(outer_defer_var, inner_defer_var)
|
||||
|
||||
self.assertEqual("ctor_scope/a/dummy:0", inner_imm_var.name)
|
||||
self.assertEqual("call_scope/b/dummy:0", inner_defer_var.name)
|
||||
|
||||
if __name__ == "__main__":
|
||||
tf.test.main()
|
||||
|
@ -69,8 +69,8 @@ bool _BytesToStringPiece(PyObject* obj, tensorflow::StringPiece* result) {
|
||||
$1 = &temp;
|
||||
}
|
||||
|
||||
// C++ functions returning tensorflow::StringPiece will simply return bytes in Python,
|
||||
// or None if the StringPiece contained a NULL pointer.
|
||||
// C++ functions returning tensorflow::StringPiece will simply return bytes in
|
||||
// Python, or None if the StringPiece contained a NULL pointer.
|
||||
%typemap(out) tensorflow::StringPiece {
|
||||
if ($1.data()) {
|
||||
$result = PyBytes_FromStringAndSize($1.data(), $1.size());
|
||||
@ -79,3 +79,30 @@ bool _BytesToStringPiece(PyObject* obj, tensorflow::StringPiece* result) {
|
||||
$result = Py_None;
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a C++ string vector to a Python string list.
|
||||
%typemap(out) std::vector<string> {
|
||||
const int size = $1.size();
|
||||
auto temp_string_list = tensorflow::make_safe(PyList_New(size));
|
||||
if (!temp_string_list) {
|
||||
SWIG_fail;
|
||||
}
|
||||
tensorflow::Safe_PyObjectVector converted;
|
||||
converted.reserve(size);
|
||||
for (const string& op : $1) {
|
||||
%#if PY_MAJOR_VERSION >= 3
|
||||
PyObject* py_str = PyUnicode_FromStringAndSize(op.data(), op.size());
|
||||
%#else
|
||||
PyObject* py_str = PyString_FromStringAndSize(op.data(), op.size());
|
||||
%#endif
|
||||
if (!py_str) {
|
||||
SWIG_fail;
|
||||
}
|
||||
converted.emplace_back(tensorflow::make_safe(py_str));
|
||||
}
|
||||
for (int i = 0; i < converted.size(); ++i) {
|
||||
PyList_SET_ITEM(temp_string_list.get(), i, converted[i].release());
|
||||
}
|
||||
$result = temp_string_list.release();
|
||||
}
|
||||
|
||||
|
@ -1985,29 +1985,64 @@ def case(pred_fn_pairs, default, exclusive=False, name="case"):
|
||||
for i, p in enumerate(preds):
|
||||
with ops.name_scope("not_%d" % i):
|
||||
not_preds.append(math_ops.logical_not(p))
|
||||
and_not_preds = [constant_op.constant(True, name="and_not_true")]
|
||||
for i, notp in enumerate(not_preds[:-1]):
|
||||
and_not_preds = [constant_op.constant(True, name="always_true")]
|
||||
for i, notp in enumerate(not_preds):
|
||||
with ops.name_scope("and_not_%d" % i):
|
||||
and_not_preds.append(math_ops.logical_and(and_not_preds[-1], notp))
|
||||
|
||||
# preds = [p1, p2, p3]
|
||||
# fns = [f1, f2, f3]
|
||||
# not_preds = [~p1, ~p2, ~p3]
|
||||
# case_preds = [p1 & True,
|
||||
# and_not_preds = [True, ~p1, ~p1 & ~p2, ~p1 & ~p2 & ~p3]
|
||||
# case_preds = [p1,
|
||||
# p2 & ~p1,
|
||||
# p3 & ~p1 & ~ p2]
|
||||
# p3 & ~p2 & ~p1,
|
||||
# ~p3 & ~p2 & ~p1]
|
||||
|
||||
case_preds = []
|
||||
for i, (p, and_not_p_prev) in enumerate(zip(preds, and_not_preds)):
|
||||
for i, (p, and_not_p_prev) in enumerate(zip(preds, and_not_preds[:-1])):
|
||||
with ops.name_scope("case_%d" % i):
|
||||
case_preds.append(math_ops.logical_and(p, and_not_p_prev))
|
||||
with ops.name_scope("case_none_are_true"):
|
||||
case_preds.append(and_not_preds[-1])
|
||||
|
||||
# Create an empty tensor, or list, with the right type and shape
|
||||
with ops.name_scope("case_create_empty"):
|
||||
dummy_value = default()
|
||||
def _correct_empty(v):
|
||||
if isinstance(v, ops.Operation):
|
||||
return no_op()
|
||||
elif v.dtype == dtypes.string:
|
||||
return array_ops.constant("")
|
||||
else:
|
||||
return array_ops.constant(v.dtype.as_numpy_dtype())
|
||||
|
||||
if isinstance(dummy_value, collections.Sequence):
|
||||
dummy_type = type(dummy_value)
|
||||
empty = lambda: dummy_type(_correct_empty(v) for v in dummy_value)
|
||||
else:
|
||||
empty = lambda: _correct_empty(dummy_value)
|
||||
|
||||
# case_sequence = [
|
||||
# cond(~p3 & ~p2 & ~p1, default, empty),
|
||||
# cond(p3 & ~p2 & ~p1, f3, lambda: case_sequence[0]),
|
||||
# cond(p2 & ~p1, f2, lambda: case_sequence[1]),
|
||||
# cond(p1, f1, lambda: case_sequence[2])
|
||||
# ]
|
||||
#
|
||||
# And the return value will be case_sequence[-1]
|
||||
def _build_case():
|
||||
all_fns = [fn for fn in fns]
|
||||
all_fns.append(default)
|
||||
prev_case = None
|
||||
for i, (cp, fn) in enumerate(list(zip(case_preds, all_fns))[::-1]):
|
||||
prev_case = cond(
|
||||
cp, fn,
|
||||
empty if i == 0 else lambda: prev_case,
|
||||
name="If_%d" % i)
|
||||
return prev_case
|
||||
|
||||
# case_sequence = [cond(p3 & ..., f3, default),
|
||||
# cond(p2 & ..., f2, lambda: case_sequence[0]),
|
||||
# ...
|
||||
# cond(p1 & True, f1, lambda: case_sequence[i-1])]
|
||||
# and prev_case_seq will loop from case_sequence[0] to case_sequence[-1]
|
||||
if exclusive:
|
||||
# TODO(ebrevdo): Add Where() for DT_BOOL, replace with Size(Where(preds))
|
||||
preds_c = array_ops.pack(preds, name="preds_c")
|
||||
num_true_conditions = math_ops.reduce_sum(
|
||||
math_ops.cast(preds_c, dtypes.int32), name="num_true_conds")
|
||||
@ -2022,21 +2057,11 @@ def case(pred_fn_pairs, default, exclusive=False, name="case"):
|
||||
with ops.control_dependencies([
|
||||
logging_ops.Assert(condition=at_most_one_true_condition,
|
||||
data=error_msg, summarize=len(preds))]):
|
||||
prev_case_seq = None
|
||||
for i, (cp, fn) in enumerate(list(zip(case_preds, fns))[::-1]):
|
||||
prev_case_seq = cond(
|
||||
cp, fn,
|
||||
default if i == 0 else lambda: prev_case_seq,
|
||||
name="If_%d" % i)
|
||||
case_seq = _build_case()
|
||||
else:
|
||||
prev_case_seq = None
|
||||
for i, (cp, fn) in enumerate(list(zip(case_preds, fns))[::-1]):
|
||||
prev_case_seq = cond(
|
||||
cp, fn,
|
||||
default if i == 0 else lambda: prev_case_seq,
|
||||
name="If_%d" % i)
|
||||
case_seq = _build_case()
|
||||
|
||||
return prev_case_seq
|
||||
return case_seq
|
||||
|
||||
|
||||
ops.RegisterShape("Enter")(common_shapes.unchanged_shape)
|
||||
|
@ -261,7 +261,7 @@ def merge_all_summaries(key=ops.GraphKeys.SUMMARIES):
|
||||
|
||||
Returns:
|
||||
If no summaries were collected, returns None. Otherwise returns a scalar
|
||||
`Tensor` of type`string` containing the serialized `Summary` protocol
|
||||
`Tensor` of type `string` containing the serialized `Summary` protocol
|
||||
buffer resulting from the merging.
|
||||
"""
|
||||
summary_ops = ops.get_collection(key)
|
||||
@ -271,6 +271,30 @@ def merge_all_summaries(key=ops.GraphKeys.SUMMARIES):
|
||||
return merge_summary(summary_ops)
|
||||
|
||||
|
||||
def get_summary_op():
|
||||
"""Returns a single Summary op that would run all summaries.
|
||||
|
||||
Either existing one from `SUMMARY_OP` collection or merges all existing
|
||||
summaries.
|
||||
|
||||
Returns:
|
||||
If no summaries were collected, returns None. Otherwise returns a scalar
|
||||
`Tensor` of type `string` containing the serialized `Summary` protocol
|
||||
buffer resulting from the merging.
|
||||
"""
|
||||
summary_op = ops.get_collection(ops.GraphKeys.SUMMARY_OP)
|
||||
if summary_op is not None:
|
||||
if summary_op:
|
||||
summary_op = summary_op[0]
|
||||
else:
|
||||
summary_op = None
|
||||
if summary_op is None:
|
||||
summary_op = merge_all_summaries()
|
||||
if summary_op is not None:
|
||||
ops.add_to_collection(ops.GraphKeys.SUMMARY_OP, summary_op)
|
||||
return summary_op
|
||||
|
||||
|
||||
def scalar_summary(tags, values, collections=None, name=None):
|
||||
"""Outputs a `Summary` protocol buffer with scalar values.
|
||||
|
||||
|
@ -587,13 +587,16 @@ def separable_conv2d(input, depthwise_filter, pointwise_filter, strides,
|
||||
padding="VALID", name=name)
|
||||
|
||||
|
||||
def sufficient_statistics(x, axes, shift=True, keep_dims=False, name=None):
|
||||
def sufficient_statistics(x, axes, shift=False, keep_dims=False, name=None):
|
||||
"""Calculate the sufficient statistics for the mean and variance of `x`.
|
||||
|
||||
These sufficient statistics are computed using the one pass algorithm on
|
||||
an input that's optionally shifted using the value of the 1st element in `x`.
|
||||
See:
|
||||
https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Computing_shifted_data
|
||||
Unfortunately, in some cases using a random individual sample as the shift
|
||||
value leads experimentally to very poor numerical stability, so it is disabled
|
||||
by default. The one-pass approach might have to be revised accordingly.
|
||||
|
||||
Args:
|
||||
x: A `Tensor`.
|
||||
|
@ -752,6 +752,41 @@ def _calc_conv_weight_params(graph, node):
|
||||
filter_in_depth * filter_out_depth))
|
||||
|
||||
|
||||
@ops.RegisterStatistics("DepthwiseConv2dNative", "flops")
|
||||
def _calc_depthwise_conv_flops(graph, node):
|
||||
"""Calculates the compute resources needed for DepthwiseConv2dNative."""
|
||||
input_shape = graph_util.tensor_shape_from_node_def_name(graph, node.input[0])
|
||||
input_shape.assert_is_fully_defined()
|
||||
filter_shape = graph_util.tensor_shape_from_node_def_name(graph,
|
||||
node.input[1])
|
||||
filter_shape.assert_is_fully_defined()
|
||||
output_shape = graph_util.tensor_shape_from_node_def_name(graph, node.name)
|
||||
output_shape.assert_is_fully_defined()
|
||||
filter_height = int(filter_shape[0])
|
||||
filter_width = int(filter_shape[1])
|
||||
output_count = np.prod(output_shape.as_list())
|
||||
return ops.OpStats("flops", (output_count * filter_height * filter_width * 2))
|
||||
|
||||
|
||||
@ops.RegisterStatistics("DepthwiseConv2dNative", "weight_parameters")
|
||||
def _calc_depthwise_conv_weight_params(graph, node):
|
||||
"""Calculates the on-disk size of the weights for DepthwiseConv2dNative."""
|
||||
input_shape = graph_util.tensor_shape_from_node_def_name(graph, node.input[0])
|
||||
input_shape.assert_is_fully_defined()
|
||||
filter_shape = graph_util.tensor_shape_from_node_def_name(graph,
|
||||
node.input[1])
|
||||
filter_shape.assert_is_fully_defined()
|
||||
output_shape = graph_util.tensor_shape_from_node_def_name(graph, node.name)
|
||||
output_shape.assert_is_fully_defined()
|
||||
filter_height = int(filter_shape[0])
|
||||
filter_width = int(filter_shape[1])
|
||||
filter_in_depth = int(filter_shape[2])
|
||||
filter_channel_multiplier = int(filter_shape[3])
|
||||
return ops.OpStats("weight_parameters", (filter_height * filter_width *
|
||||
filter_in_depth *
|
||||
filter_channel_multiplier))
|
||||
|
||||
|
||||
@ops.RegisterShape("Conv3D")
|
||||
def _Conv3DShape(op):
|
||||
"""Shape function for Conv3D."""
|
||||
|
@ -57,9 +57,9 @@ def add_check_numerics_ops():
|
||||
"""
|
||||
check_op = []
|
||||
# This code relies on the ordering of ops in get_operations().
|
||||
# The consumer of a tensor always comes before that tensor's producer in
|
||||
# The producer of a tensor always comes before that tensor's consumer in
|
||||
# this list. This is true because get_operations() returns ops in the order
|
||||
# added, and ops can only be added once its inputs are added.
|
||||
# added, and an op can only be added after its inputs are added.
|
||||
for op in ops.get_default_graph().get_operations():
|
||||
for output in op.outputs:
|
||||
if output.dtype in [dtypes.float16, dtypes.float32, dtypes.float64]:
|
||||
|
@ -29,7 +29,7 @@ from tensorflow.python.platform import tf_logging as logging
|
||||
__all__ = ["make_template"]
|
||||
|
||||
|
||||
def make_template(name_, func_, **kwargs):
|
||||
def make_template(name_, func_, create_scope_now_=False, **kwargs):
|
||||
"""Given an arbitrary function, wrap it so that it does variable sharing.
|
||||
|
||||
This wraps `func_` in a Template and partially evaluates it. Templates are
|
||||
@ -98,29 +98,39 @@ def make_template(name_, func_, **kwargs):
|
||||
w2 = scale_by_y2(input2)
|
||||
```
|
||||
|
||||
Note: The full variable scope is captured at the time of the first call.
|
||||
Depending on the value of `create_scope_now_`, the full variable scope may be
|
||||
captured either at the time of first call or at the time of construction. If
|
||||
this option is set to True, then all Tensors created by repeated calls to the
|
||||
template will have an extra trailing _N+1 to their name, as the first time the
|
||||
scope is entered in the Template constructor no Tensors are created.
|
||||
|
||||
Note: `name_` and `func_` have a following underscore to reduce the likelihood
|
||||
of collisions with kwargs.
|
||||
Note: `name_`, `func_` and `create_scope_now_` have a trailing underscore to
|
||||
reduce the likelihood of collisions with kwargs.
|
||||
|
||||
Args:
|
||||
name_: A name for the scope created by this template. If necessary, the name
|
||||
will be made unique by appending `_N` to the name.
|
||||
func_: The function to wrap.
|
||||
create_scope_now_: Boolean controlling whether the scope should be created
|
||||
when the template is constructed or when the template is called. Default
|
||||
is False, meaning the scope is created when the template is called.
|
||||
**kwargs: Keyword arguments to apply to `func_`.
|
||||
|
||||
Returns:
|
||||
A function that will enter a `variable_scope` before calling `func_`. The
|
||||
first time it is called, it will create a non-reusing scope so that the
|
||||
variables will be unique. On each subsequent call, it will reuse those
|
||||
variables.
|
||||
A function to encapsulate a set of variables which should be created once
|
||||
and reused. An enclosing scope will created, either where `make_template`
|
||||
is called, or wherever the result is called, depending on the value of
|
||||
`create_scope_now_`. Regardless of the value, the first time the template
|
||||
is called it will enter the scope with no reuse, and call `func_` to create
|
||||
variables, which are guaranteed to be unique. All subsequent calls will
|
||||
re-enter the scope and reuse those variables.
|
||||
|
||||
Raises:
|
||||
ValueError: if the name is None.
|
||||
"""
|
||||
if kwargs:
|
||||
func_ = functools.partial(func_, **kwargs)
|
||||
return Template(name_, func_)
|
||||
return Template(name_, func_, create_scope_now=create_scope_now_)
|
||||
|
||||
|
||||
def _skip_common_stack_elements(stacktrace, base_case):
|
||||
@ -137,10 +147,13 @@ class Template(object):
|
||||
Templates are functions that create variables the first time they are called
|
||||
and reuse them thereafter. See `make_template` for full documentation.
|
||||
|
||||
Note: The full variable scope is captured at the time of the first call.
|
||||
Note: By default, the full variable scope is captured at the time of first
|
||||
call. If `create_scope_now_` is passed as True to the constructor, the full
|
||||
scope will be captured there, but no variables will created until the first
|
||||
call.
|
||||
"""
|
||||
|
||||
def __init__(self, name, func):
|
||||
def __init__(self, name, func, create_scope_now=False):
|
||||
"""Creates a template for the given function.
|
||||
|
||||
Args:
|
||||
@ -148,6 +161,15 @@ class Template(object):
|
||||
name will be made unique by appending `_N` to the it (see how
|
||||
`tf.variable_op_scope` treats the `default_name` for details).
|
||||
func: The function to apply each time.
|
||||
create_scope_now: Whether to create the scope at Template construction
|
||||
time, rather than first call. Defaults to false. Creating the scope at
|
||||
construction time may be more convenient if the template is to passed
|
||||
through much lower level code, and you want to be sure of the scope
|
||||
name without knowing exactly where it will be first called. If set to
|
||||
True, the scope will be created in the constructor, and all subsequent
|
||||
times in __call__, leading to a trailing numeral being added to the
|
||||
names of all created Tensors. If set to False, the scope will be created
|
||||
at the first call location.
|
||||
|
||||
Raises:
|
||||
ValueError: if the name is None.
|
||||
@ -157,7 +179,14 @@ class Template(object):
|
||||
self._name = name
|
||||
if name is None:
|
||||
raise ValueError("name cannot be None.")
|
||||
self._var_scope = None
|
||||
if create_scope_now:
|
||||
with variable_scope.variable_op_scope([], None, self._name) as vs:
|
||||
self._var_scope = vs
|
||||
else:
|
||||
self._var_scope = None
|
||||
# This variable keeps track of whether the template has been called yet,
|
||||
# which is not the same as whether the scope has been created.
|
||||
self._variables_created = False
|
||||
|
||||
def _call_func(self, args, kwargs, check_for_new_variables):
|
||||
try:
|
||||
@ -204,12 +233,23 @@ class Template(object):
|
||||
raise
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
# Capture the name of the variable_scope here because if we capture at
|
||||
# construction, then name_scopes would have a '_N+1' suffix.
|
||||
if self._var_scope:
|
||||
with variable_scope.variable_scope(self._var_scope, reuse=True):
|
||||
return self._call_func(args, kwargs, check_for_new_variables=True)
|
||||
if self._variables_created:
|
||||
# This is not the first visit to __call__, so variables have already
|
||||
# been created, and we want to reuse them.
|
||||
with variable_scope.variable_scope(self._var_scope, reuse=True):
|
||||
return self._call_func(args, kwargs, check_for_new_variables=True)
|
||||
else:
|
||||
# This is the first visit to __call__, but the scope has already been
|
||||
# created in the constructor. Set _variables_created so that subsequent
|
||||
# calls take the if branch above.
|
||||
self._variables_created = True
|
||||
with variable_scope.variable_scope(self._var_scope):
|
||||
return self._call_func(args, kwargs, check_for_new_variables=False)
|
||||
else:
|
||||
# The scope was not created at construction time, so create it here.
|
||||
# Subsequent calls should reuse variables.
|
||||
self._variables_created = True
|
||||
with variable_scope.variable_op_scope([], None, self._name) as vs:
|
||||
self._var_scope = vs
|
||||
return self._call_func(args, kwargs, check_for_new_variables=False)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user