Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/ops/init_ops_v2.py: 38%
248 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
1# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Initializers for TF 2."""
16import math
18import numpy as np
20from tensorflow.python.framework import constant_op
21from tensorflow.python.framework import dtypes
22from tensorflow.python.ops import array_ops
23from tensorflow.python.ops import gen_linalg_ops
24from tensorflow.python.ops import linalg_ops_impl
25from tensorflow.python.ops import math_ops
26from tensorflow.python.ops import random_ops
27from tensorflow.python.ops import stateless_random_ops
28from tensorflow.python.ops.init_ops import _compute_fans
29from tensorflow.python.util.tf_export import tf_export
31_PARTITION_SHAPE = "partition_shape"
32_PARTITION_OFFSET = "partition_offset"
35class Initializer:
36 """Initializer base class: all initializers inherit from this class.
38 Initializers should implement a `__call__` method with the following
39 signature:
41 ```python
42 def __call__(self, shape, dtype=None, **kwargs):
43 # returns a tensor of shape `shape` and dtype `dtype`
44 # containing values drawn from a distribution of your choice.
45 ```
46 """
48 def __call__(self, shape, dtype=None, **kwargs):
49 """Returns a tensor object initialized as specified by the initializer.
51 Args:
52 shape: Shape of the tensor.
53 dtype: Optional dtype of the tensor. If not provided will return tensor
54 of `tf.float32`.
55 **kwargs: Additional keyword arguments. Accepted values:
56 `partition_shape` and `partition_offset`. Used when creating a single
57 partition in a partitioned variable. `partition_shape` is the shape of
58 the partition (i.e. the shape of the returned tensor) and
59 `partition_offset` is a tuple of `int` specifying the offset of this
60 partition w.r.t each axis. For example, a tensor of shape `(30, 100)`
61 can be partitioned into two partitions: `p0` of shape `(10, 100)` and
62 `p1` of shape `(20, 100)`; if the initializer is called with
63 `partition_shape=(20, 100)` and `partition_offset=(10, 0)`, it should
64 return the value for `p1`.
65 """
66 raise NotImplementedError
68 def get_config(self):
69 """Returns the configuration of the initializer as a JSON-serializable dict.
71 Returns:
72 A JSON-serializable Python dict.
73 """
74 return {}
76 @classmethod
77 def from_config(cls, config):
78 """Instantiates an initializer from a configuration dictionary.
80 Example:
82 ```python
83 initializer = RandomUniform(-1, 1)
84 config = initializer.get_config()
85 initializer = RandomUniform.from_config(config)
86 ```
88 Args:
89 config: A Python dictionary.
90 It will typically be the output of `get_config`.
92 Returns:
93 An Initializer instance.
94 """
95 config.pop("dtype", None)
96 return cls(**config)
98 def _validate_kwargs(self, kwargs, support_partition=True):
99 for kwarg in kwargs:
100 if kwarg not in [_PARTITION_SHAPE, _PARTITION_OFFSET]:
101 raise TypeError(
102 "Keyword argument should be one of "
103 f"{list([_PARTITION_SHAPE, _PARTITION_OFFSET])}. Received: {kwarg}")
104 elif not support_partition:
105 raise ValueError(
106 f"{self.__class__.__name__} initializer doesn't support "
107 "partition-related arguments")
110@tf_export("zeros_initializer", v1=[])
111class Zeros(Initializer):
112 """Initializer that generates tensors initialized to 0.
114 Initializers allow you to pre-specify an initialization strategy, encoded in
115 the Initializer object, without knowing the shape and dtype of the variable
116 being initialized.
118 Examples:
120 >>> def make_variables(k, initializer):
121 ... return (tf.Variable(initializer(shape=[k], dtype=tf.float32)),
122 ... tf.Variable(initializer(shape=[k, k], dtype=tf.float32)))
123 >>> v1, v2 = make_variables(3, tf.zeros_initializer())
124 >>> v1
125 <tf.Variable ... shape=(3,) ... numpy=array([0., 0., 0.], dtype=float32)>
126 >>> v2
127 <tf.Variable ... shape=(3, 3) ... numpy=
128 array([[0., 0., 0.],
129 [0., 0., 0.],
130 [0., 0., 0.]], dtype=float32)>
131 >>> make_variables(4, tf.random_uniform_initializer(minval=-1., maxval=1.))
132 (<tf.Variable...shape=(4,) dtype=float32...>, <tf.Variable...shape=(4, 4) ...
133 """
135 def __call__(self, shape, dtype=dtypes.float32, **kwargs):
136 """Returns a tensor object initialized as specified by the initializer.
138 Args:
139 shape: Shape of the tensor.
140 dtype: Optional dtype of the tensor. Only numeric or boolean dtypes are
141 supported.
142 **kwargs: Additional keyword arguments.
144 Raises:
145 ValuesError: If the dtype is not numeric or boolean.
146 """
147 self._validate_kwargs(kwargs)
148 dtype = dtypes.as_dtype(dtype)
149 if not dtype.is_numpy_compatible or dtype == dtypes.string:
150 raise ValueError("Argument `dtype` expected to be numeric or boolean. "
151 f"Received {dtype}.")
152 if _PARTITION_SHAPE in kwargs:
153 shape = kwargs[_PARTITION_SHAPE]
154 return array_ops.zeros(shape, dtype)
157@tf_export("ones_initializer", v1=[])
158class Ones(Initializer):
159 """Initializer that generates tensors initialized to 1.
161 Initializers allow you to pre-specify an initialization strategy, encoded in
162 the Initializer object, without knowing the shape and dtype of the variable
163 being initialized.
165 Examples:
167 >>> def make_variables(k, initializer):
168 ... return (tf.Variable(initializer(shape=[k], dtype=tf.float32)),
169 ... tf.Variable(initializer(shape=[k, k], dtype=tf.float32)))
170 >>> v1, v2 = make_variables(3, tf.ones_initializer())
171 >>> v1
172 <tf.Variable ... shape=(3,) ... numpy=array([1., 1., 1.], dtype=float32)>
173 >>> v2
174 <tf.Variable ... shape=(3, 3) ... numpy=
175 array([[1., 1., 1.],
176 [1., 1., 1.],
177 [1., 1., 1.]], dtype=float32)>
178 >>> make_variables(4, tf.random_uniform_initializer(minval=-1., maxval=1.))
179 (<tf.Variable...shape=(4,) dtype=float32...>, <tf.Variable...shape=(4, 4) ...
180 """
182 def __call__(self, shape, dtype=dtypes.float32, **kwargs):
183 """Returns a tensor object initialized as specified by the initializer.
185 Args:
186 shape: Shape of the tensor.
187 dtype: Optional dtype of the tensor. Only numeric or boolean dtypes are
188 supported.
189 **kwargs: Additional keyword arguments.
191 Raises:
192 ValuesError: If the dtype is not numeric or boolean.
193 """
194 self._validate_kwargs(kwargs)
195 dtype = dtypes.as_dtype(dtype)
196 if not dtype.is_numpy_compatible or dtype == dtypes.string:
197 raise ValueError("Argument `dtype` expected to be numeric or boolean. "
198 f"Received {dtype}.")
199 if _PARTITION_SHAPE in kwargs:
200 shape = kwargs[_PARTITION_SHAPE]
201 return array_ops.ones(shape, dtype)
204@tf_export("constant_initializer", v1=[])
205class Constant(Initializer):
206 """Initializer that generates tensors with constant values.
208 Initializers allow you to pre-specify an initialization strategy, encoded in
209 the Initializer object, without knowing the shape and dtype of the variable
210 being initialized.
212 `tf.constant_initializer` returns an object which when called returns a tensor
213 populated with the `value` specified in the constructor. This `value` must be
214 convertible to the requested `dtype`.
216 The argument `value` can be a scalar constant value, or a list of
217 values. Scalars broadcast to whichever shape is requested from the
218 initializer.
220 If `value` is a list, then the length of the list must be equal to the number
221 of elements implied by the desired shape of the tensor. If the total number of
222 elements in `value` is not equal to the number of elements required by the
223 tensor shape, the initializer will raise a `TypeError`.
225 Examples:
227 >>> def make_variables(k, initializer):
228 ... return (tf.Variable(initializer(shape=[k], dtype=tf.float32)),
229 ... tf.Variable(initializer(shape=[k, k], dtype=tf.float32)))
230 >>> v1, v2 = make_variables(3, tf.constant_initializer(2.))
231 >>> v1
232 <tf.Variable ... shape=(3,) ... numpy=array([2., 2., 2.], dtype=float32)>
233 >>> v2
234 <tf.Variable ... shape=(3, 3) ... numpy=
235 array([[2., 2., 2.],
236 [2., 2., 2.],
237 [2., 2., 2.]], dtype=float32)>
238 >>> make_variables(4, tf.random_uniform_initializer(minval=-1., maxval=1.))
239 (<tf.Variable...shape=(4,) dtype=float32...>, <tf.Variable...shape=(4, 4) ...
241 >>> value = [0, 1, 2, 3, 4, 5, 6, 7]
242 >>> init = tf.constant_initializer(value)
243 >>> # Fitting shape
244 >>> tf.Variable(init(shape=[2, 4], dtype=tf.float32))
245 <tf.Variable ...
246 array([[0., 1., 2., 3.],
247 [4., 5., 6., 7.]], dtype=float32)>
248 >>> # Larger shape
249 >>> tf.Variable(init(shape=[3, 4], dtype=tf.float32))
250 Traceback (most recent call last):
251 ...
252 TypeError: ...value has 8 elements, shape is (3, 4) with 12 elements...
253 >>> # Smaller shape
254 >>> tf.Variable(init(shape=[2, 3], dtype=tf.float32))
255 Traceback (most recent call last):
256 ...
257 TypeError: ...value has 8 elements, shape is (2, 3) with 6 elements...
259 Args:
260 value: A Python scalar, list or tuple of values, or a N-dimensional numpy
261 array. All elements of the initialized variable will be set to the
262 corresponding value in the `value` argument.
264 Raises:
265 TypeError: If the input `value` is not one of the expected types.
266 """
268 def __init__(self, value=0):
269 if not (np.isscalar(value) or isinstance(value, (list, tuple, np.ndarray))):
270 raise TypeError(
271 f"Invalid type for initial value: {type(value).__name__}. Expected "
272 "Python scalar, list or tuple of values, or numpy.ndarray.")
273 self.value = value
275 def __call__(self, shape, dtype=None, **kwargs):
276 """Returns a tensor object initialized as specified by the initializer.
278 Args:
279 shape: Shape of the tensor.
280 dtype: Optional dtype of the tensor. If not provided the dtype of the
281 tensor created will be the type of the inital value.
282 **kwargs: Additional keyword arguments.
284 Raises:
285 TypeError: If the initializer cannot create a tensor of the requested
286 dtype.
287 """
288 self._validate_kwargs(kwargs, support_partition=False)
289 if dtype is not None:
290 dtype = dtypes.as_dtype(dtype)
291 return constant_op.constant(self.value, dtype=dtype, shape=shape)
293 def get_config(self):
294 return {"value": self.value}
297@tf_export("random_uniform_initializer", v1=[])
298class RandomUniform(Initializer):
299 """Initializer that generates tensors with a uniform distribution.
301 Initializers allow you to pre-specify an initialization strategy, encoded in
302 the Initializer object, without knowing the shape and dtype of the variable
303 being initialized.
305 Examples:
307 >>> def make_variables(k, initializer):
308 ... return (tf.Variable(initializer(shape=[k], dtype=tf.float32)),
309 ... tf.Variable(initializer(shape=[k, k], dtype=tf.float32)))
310 >>> v1, v2 = make_variables(3, tf.ones_initializer())
311 >>> v1
312 <tf.Variable ... shape=(3,) ... numpy=array([1., 1., 1.], dtype=float32)>
313 >>> v2
314 <tf.Variable ... shape=(3, 3) ... numpy=
315 array([[1., 1., 1.],
316 [1., 1., 1.],
317 [1., 1., 1.]], dtype=float32)>
318 >>> make_variables(4, tf.random_uniform_initializer(minval=-1., maxval=1.))
319 (<tf.Variable...shape=(4,) dtype=float32...>, <tf.Variable...shape=(4, 4) ...
321 Args:
322 minval: A python scalar or a scalar tensor. Lower bound of the range of
323 random values to generate (inclusive).
324 maxval: A python scalar or a scalar tensor. Upper bound of the range of
325 random values to generate (exclusive).
326 seed: A Python integer. Used to create random seeds. See
327 `tf.random.set_seed` for behavior.
328 """
330 def __init__(self, minval=-0.05, maxval=0.05, seed=None):
331 self.minval = minval
332 self.maxval = maxval
333 self.seed = seed
334 self._random_generator = _RandomGenerator(seed)
336 def __call__(self, shape, dtype=dtypes.float32, **kwargs):
337 """Returns a tensor object initialized as specified by the initializer.
339 Args:
340 shape: Shape of the tensor.
341 dtype: Optional dtype of the tensor. Only floating point and integer
342 types are supported.
343 **kwargs: Additional keyword arguments.
345 Raises:
346 ValueError: If the dtype is not numeric.
347 """
348 self._validate_kwargs(kwargs)
349 dtype = dtypes.as_dtype(dtype)
350 if not dtype.is_floating and not dtype.is_integer:
351 raise ValueError("Argument `dtype` expected to be numeric or boolean. "
352 f"Received {dtype}.")
353 if _PARTITION_SHAPE in kwargs:
354 shape = kwargs[_PARTITION_SHAPE]
355 return self._random_generator.random_uniform(shape, self.minval,
356 self.maxval, dtype)
358 def get_config(self):
359 return {
360 "minval": self.minval,
361 "maxval": self.maxval,
362 "seed": self.seed
363 }
366@tf_export("random_normal_initializer", v1=[])
367class RandomNormal(Initializer):
368 """Initializer that generates tensors with a normal distribution.
370 Initializers allow you to pre-specify an initialization strategy, encoded in
371 the Initializer object, without knowing the shape and dtype of the variable
372 being initialized.
374 Examples:
376 >>> def make_variables(k, initializer):
377 ... return (tf.Variable(initializer(shape=[k], dtype=tf.float32)),
378 ... tf.Variable(initializer(shape=[k, k], dtype=tf.float32)))
379 >>> v1, v2 = make_variables(3,
380 ... tf.random_normal_initializer(mean=1., stddev=2.))
381 >>> v1
382 <tf.Variable ... shape=(3,) ... numpy=array([...], dtype=float32)>
383 >>> v2
384 <tf.Variable ... shape=(3, 3) ... numpy=
385 ...
386 >>> make_variables(4, tf.random_uniform_initializer(minval=-1., maxval=1.))
387 (<tf.Variable...shape=(4,) dtype=float32...>, <tf.Variable...shape=(4, 4) ...
389 Args:
390 mean: a python scalar or a scalar tensor. Mean of the random values to
391 generate.
392 stddev: a python scalar or a scalar tensor. Standard deviation of the random
393 values to generate.
394 seed: A Python integer. Used to create random seeds. See
395 `tf.random.set_seed` for behavior.
397 """
399 def __init__(self, mean=0.0, stddev=0.05, seed=None):
400 self.mean = mean
401 self.stddev = stddev
402 self.seed = seed
403 self._random_generator = _RandomGenerator(seed)
405 def __call__(self, shape, dtype=dtypes.float32, **kwargs):
406 """Returns a tensor object initialized as specified by the initializer.
408 Args:
409 shape: Shape of the tensor.
410 dtype: Optional dtype of the tensor. Only floating point types are
411 supported.
412 **kwargs: Additional keyword arguments.
414 Raises:
415 ValueError: If the dtype is not floating point
416 """
417 self._validate_kwargs(kwargs)
418 dtype = _assert_float_dtype(dtype)
419 if _PARTITION_SHAPE in kwargs:
420 shape = kwargs[_PARTITION_SHAPE]
421 return self._random_generator.random_normal(shape, self.mean, self.stddev,
422 dtype)
424 def get_config(self):
425 return {
426 "mean": self.mean,
427 "stddev": self.stddev,
428 "seed": self.seed
429 }
432class TruncatedNormal(Initializer):
433 """Initializer that generates a truncated normal distribution.
435 Initializers allow you to pre-specify an initialization strategy, encoded in
436 the Initializer object, without knowing the shape and dtype of the variable
437 being initialized.
439 These values are similar to values from a `tf.initializers.RandomNormal`
440 except that values more than two standard deviations from the mean are
441 discarded and re-drawn. This is the recommended initializer for neural network
442 weights and filters.
444 Examples:
446 >>> def make_variables(k, initializer):
447 ... return (tf.Variable(initializer(shape=[k], dtype=tf.float32)),
448 ... tf.Variable(initializer(shape=[k, k], dtype=tf.float32)))
449 >>> v1, v2 = make_variables(
450 ... 3, tf.initializers.TruncatedNormal(mean=1., stddev=2.))
451 >>> v1
452 <tf.Variable ... shape=(3,) ... numpy=array([...], dtype=float32)>
453 >>> v2
454 <tf.Variable ... shape=(3, 3) ... numpy=
455 ...
456 >>> make_variables(4, tf.initializers.RandomUniform(minval=-1., maxval=1.))
457 (<tf.Variable...shape=(4,) dtype=float32...>, <tf.Variable...shape=(4, 4) ...
459 Args:
460 mean: a python scalar or a scalar tensor. Mean of the random values
461 to generate.
462 stddev: a python scalar or a scalar tensor. Standard deviation of the
463 random values to generate.
464 seed: A Python integer. Used to create random seeds. See
465 `tf.random.set_seed` for behavior.
466 """
468 def __init__(self, mean=0.0, stddev=0.05, seed=None):
469 self.mean = mean
470 self.stddev = stddev
471 self.seed = seed
472 self._random_generator = _RandomGenerator(seed)
474 def __call__(self, shape, dtype=dtypes.float32, **kwargs):
475 """Returns a tensor object initialized as specified by the initializer.
477 Args:
478 shape: Shape of the tensor.
479 dtype: Optional dtype of the tensor. Only floating point types are
480 supported.
481 **kwargs: Additional keyword arguments.
483 Raises:
484 ValueError: If the dtype is not floating point
485 """
486 self._validate_kwargs(kwargs)
487 dtype = _assert_float_dtype(dtype)
488 if _PARTITION_SHAPE in kwargs:
489 shape = kwargs[_PARTITION_SHAPE]
490 return self._random_generator.truncated_normal(shape, self.mean,
491 self.stddev, dtype)
493 def get_config(self):
494 return {
495 "mean": self.mean,
496 "stddev": self.stddev,
497 "seed": self.seed
498 }
501class VarianceScaling(Initializer):
502 """Initializer capable of adapting its scale to the shape of weights tensors.
504 Initializers allow you to pre-specify an initialization strategy, encoded in
505 the Initializer object, without knowing the shape and dtype of the variable
506 being initialized.
508 With `distribution="truncated_normal" or "untruncated_normal"`, samples are
509 drawn from a truncated/untruncated normal distribution with a mean of zero and
510 a standard deviation (after truncation, if used) `stddev = sqrt(scale / n)`
511 where n is:
513 - number of input units in the weight tensor, if mode = "fan_in"
514 - number of output units, if mode = "fan_out"
515 - average of the numbers of input and output units, if mode = "fan_avg"
517 With `distribution="uniform"`, samples are drawn from a uniform distribution
518 within [-limit, limit], with `limit = sqrt(3 * scale / n)`.
520 Examples:
522 >>> def make_variables(k, initializer):
523 ... return (tf.Variable(initializer(shape=[k], dtype=tf.float32)),
524 ... tf.Variable(initializer(shape=[k, k], dtype=tf.float32)))
525 >>> v1, v2 = make_variables(3, tf.initializers.VarianceScaling(scale=1.))
526 >>> v1
527 <tf.Variable ... shape=(3,) ... numpy=array([...], dtype=float32)>
528 >>> v2
529 <tf.Variable ... shape=(3, 3) ... numpy=
530 ...
531 >>> make_variables(4, tf.initializers.VarianceScaling(distribution='uniform'))
532 (<tf.Variable...shape=(4,) dtype=float32...>, <tf.Variable...shape=(4, 4) ...
534 Args:
535 scale: Scaling factor (positive float).
536 mode: One of "fan_in", "fan_out", "fan_avg".
537 distribution: Random distribution to use. One of "truncated_normal",
538 "untruncated_normal" and "uniform".
539 seed: A Python integer. Used to create random seeds. See
540 `tf.random.set_seed` for behavior.
542 Raises:
543 ValueError: In case of an invalid value for the "scale", mode" or
544 "distribution" arguments.
545 """
547 def __init__(self,
548 scale=1.0,
549 mode="fan_in",
550 distribution="truncated_normal",
551 seed=None):
552 if scale <= 0.:
553 raise ValueError("Argument `scale` must be a positive float. Received: "
554 f"{scale}")
555 if mode not in {"fan_in", "fan_out", "fan_avg"}:
556 raise ValueError("Argument `mode` should be one of ('fan_in', 'fan_out', "
557 f"'fan_avg'). Received: {mode}")
558 distribution = distribution.lower()
559 # Compatibility with keras-team/keras.
560 if distribution == "normal":
561 distribution = "truncated_normal"
562 if distribution not in {"uniform", "truncated_normal",
563 "untruncated_normal"}:
564 raise ValueError("Argument `distribution` should be one of ('uniform', "
565 "'truncated_normal', 'untruncated_normal'). Received: "
566 f"{distribution}")
567 self.scale = scale
568 self.mode = mode
569 self.distribution = distribution
570 self.seed = seed
571 self._random_generator = _RandomGenerator(seed)
573 def __call__(self, shape, dtype=dtypes.float32, **kwargs):
574 """Returns a tensor object initialized as specified by the initializer.
576 Args:
577 shape: Shape of the tensor.
578 dtype: Optional dtype of the tensor. Only floating point types are
579 supported.
580 **kwargs: Additional keyword arguments.
582 Raises:
583 ValueError: If the dtype is not floating point
584 """
585 self._validate_kwargs(kwargs)
586 dtype = _assert_float_dtype(dtype)
587 scale = self.scale
588 fan_in, fan_out = _compute_fans(shape)
589 if _PARTITION_SHAPE in kwargs:
590 shape = kwargs[_PARTITION_SHAPE]
591 if self.mode == "fan_in":
592 scale /= max(1., fan_in)
593 elif self.mode == "fan_out":
594 scale /= max(1., fan_out)
595 else:
596 scale /= max(1., (fan_in + fan_out) / 2.)
597 if self.distribution == "truncated_normal":
598 # constant from scipy.stats.truncnorm.std(a=-2, b=2, loc=0., scale=1.)
599 stddev = math.sqrt(scale) / .87962566103423978
600 return self._random_generator.truncated_normal(shape, 0.0, stddev, dtype)
601 elif self.distribution == "untruncated_normal":
602 stddev = math.sqrt(scale)
603 return self._random_generator.random_normal(shape, 0.0, stddev, dtype)
604 else:
605 limit = math.sqrt(3.0 * scale)
606 return self._random_generator.random_uniform(shape, -limit, limit, dtype)
608 def get_config(self):
609 return {
610 "scale": self.scale,
611 "mode": self.mode,
612 "distribution": self.distribution,
613 "seed": self.seed
614 }
617class Orthogonal(Initializer):
618 """Initializer that generates an orthogonal matrix.
620 Initializers allow you to pre-specify an initialization strategy, encoded in
621 the Initializer object, without knowing the shape and dtype of the variable
622 being initialized.
624 If the shape of the tensor to initialize is two-dimensional, it is initialized
625 with an orthogonal matrix obtained from the QR decomposition of a matrix of
626 random numbers drawn from a normal distribution.
627 If the matrix has fewer rows than columns then the output will have orthogonal
628 rows. Otherwise, the output will have orthogonal columns.
630 If the shape of the tensor to initialize is more than two-dimensional,
631 a matrix of shape `(shape[0] * ... * shape[n - 2], shape[n - 1])`
632 is initialized, where `n` is the length of the shape vector.
633 The matrix is subsequently reshaped to give a tensor of the desired shape.
635 Examples:
637 >>> def make_variables(k, initializer):
638 ... return (tf.Variable(initializer(shape=[k, k], dtype=tf.float32)),
639 ... tf.Variable(initializer(shape=[k, k, k], dtype=tf.float32)))
640 >>> v1, v2 = make_variables(3, tf.initializers.Orthogonal())
641 >>> v1
642 <tf.Variable ... shape=(3, 3) ...
643 >>> v2
644 <tf.Variable ... shape=(3, 3, 3) ...
645 >>> make_variables(4, tf.initializers.Orthogonal(gain=0.5))
646 (<tf.Variable ... shape=(4, 4) dtype=float32...
647 <tf.Variable ... shape=(4, 4, 4) dtype=float32...
649 Args:
650 gain: multiplicative factor to apply to the orthogonal matrix
651 seed: A Python integer. Used to create random seeds. See
652 `tf.random.set_seed` for behavior.
654 References:
655 [Saxe et al., 2014](https://openreview.net/forum?id=_wzZwKpTDF_9C)
656 ([pdf](https://arxiv.org/pdf/1312.6120.pdf))
657 """
659 def __init__(self, gain=1.0, seed=None):
660 self.gain = gain
661 self.seed = seed
662 self._random_generator = _RandomGenerator(seed)
664 def __call__(self, shape, dtype=dtypes.float32, **kwargs):
665 """Returns a tensor object initialized as specified by the initializer.
667 Args:
668 shape: Shape of the tensor.
669 dtype: Optional dtype of the tensor. Only floating point types are
670 supported.
671 **kwargs: Additional keyword arguments.
673 Raises:
674 ValueError: If the dtype is not floating point or the input shape is not
675 valid.
676 """
677 self._validate_kwargs(kwargs, support_partition=False)
678 dtype = _assert_float_dtype(dtype)
679 # Check the shape
680 if len(shape) < 2:
681 raise ValueError("The tensor to initialize, specified by argument `shape`"
682 " must be at least two-dimensional. Received shape="
683 f"{shape}")
684 # Flatten the input shape with the last dimension remaining
685 # its original shape so it works for conv2d
686 num_rows = 1
687 for dim in shape[:-1]:
688 num_rows *= dim
689 num_cols = shape[-1]
690 flat_shape = (max(num_cols, num_rows), min(num_cols, num_rows))
692 # Generate a random matrix
693 a = self._random_generator.random_normal(flat_shape, dtype=dtype)
694 # Compute the qr factorization
695 q, r = gen_linalg_ops.qr(a, full_matrices=False)
696 # Make Q uniform
697 d = array_ops.diag_part(r)
698 q *= math_ops.sign(d)
699 if num_rows < num_cols:
700 q = array_ops.matrix_transpose(q)
701 return self.gain * array_ops.reshape(q, shape)
703 def get_config(self):
704 return {"gain": self.gain, "seed": self.seed}
707class Identity(Initializer):
708 """Initializer that generates the identity matrix.
710 Initializers allow you to pre-specify an initialization strategy, encoded in
711 the Initializer object, without knowing the shape and dtype of the variable
712 being initialized.
714 Only usable for generating 2D matrices.
716 Examples:
718 >>> def make_variable(k, initializer):
719 ... return tf.Variable(initializer(shape=[k, k], dtype=tf.float32))
720 >>> make_variable(2, tf.initializers.Identity())
721 <tf.Variable ... shape=(2, 2) dtype=float32, numpy=
722 array([[1., 0.],
723 [0., 1.]], dtype=float32)>
724 >>> make_variable(3, tf.initializers.Identity(gain=0.5))
725 <tf.Variable ... shape=(3, 3) dtype=float32, numpy=
726 array([[0.5, 0. , 0. ],
727 [0. , 0.5, 0. ],
728 [0. , 0. , 0.5]], dtype=float32)>
730 Args:
731 gain: Multiplicative factor to apply to the identity matrix.
732 """
734 def __init__(self, gain=1.0):
735 self.gain = gain
737 def __call__(self, shape, dtype=dtypes.float32, **kwargs):
738 """Returns a tensor object initialized as specified by the initializer.
740 Args:
741 shape: Shape of the tensor.
742 dtype: Optional dtype of the tensor. Only floating point types are
743 supported.
744 **kwargs: Additional keyword arguments.
746 Raises:
747 ValueError: If the dtype is not floating point
748 ValueError: If the requested shape does not have exactly two axes.
749 """
750 self._validate_kwargs(kwargs, support_partition=False)
751 dtype = _assert_float_dtype(dtype)
752 if len(shape) != 2:
753 raise ValueError("The tensor to initialize, specified by argument `shape`"
754 " must be at least two-dimensional. Received shape="
755 f"{shape}")
756 initializer = linalg_ops_impl.eye(*shape, dtype=dtype)
757 return self.gain * initializer
759 def get_config(self):
760 return {"gain": self.gain}
763class GlorotUniform(VarianceScaling):
764 """The Glorot uniform initializer, also called Xavier uniform initializer.
766 Initializers allow you to pre-specify an initialization strategy, encoded in
767 the Initializer object, without knowing the shape and dtype of the variable
768 being initialized.
770 Draws samples from a uniform distribution within [-limit, limit] where `limit`
771 is `sqrt(6 / (fan_in + fan_out))` where `fan_in` is the number of input units
772 in the weight tensor and `fan_out` is the number of output units in the weight
773 tensor.
775 Examples:
777 >>> def make_variables(k, initializer):
778 ... return (tf.Variable(initializer(shape=[k, k], dtype=tf.float32)),
779 ... tf.Variable(initializer(shape=[k, k, k], dtype=tf.float32)))
780 >>> v1, v2 = make_variables(3, tf.initializers.GlorotUniform())
781 >>> v1
782 <tf.Variable ... shape=(3, 3) ...
783 >>> v2
784 <tf.Variable ... shape=(3, 3, 3) ...
785 >>> make_variables(4, tf.initializers.RandomNormal())
786 (<tf.Variable ... shape=(4, 4) dtype=float32...
787 <tf.Variable ... shape=(4, 4, 4) dtype=float32...
789 Args:
790 seed: A Python integer. Used to create random seeds. See
791 `tf.random.set_seed` for behavior.
793 References:
794 [Glorot et al., 2010](http://proceedings.mlr.press/v9/glorot10a.html)
795 ([pdf](http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf))
796 """
798 def __init__(self, seed=None):
799 super(GlorotUniform, self).__init__(
800 scale=1.0,
801 mode="fan_avg",
802 distribution="uniform",
803 seed=seed)
805 def get_config(self):
806 return {"seed": self.seed}
809class GlorotNormal(VarianceScaling):
810 """The Glorot normal initializer, also called Xavier normal initializer.
812 Initializers allow you to pre-specify an initialization strategy, encoded in
813 the Initializer object, without knowing the shape and dtype of the variable
814 being initialized.
816 Draws samples from a truncated normal distribution centered on 0 with `stddev
817 = sqrt(2 / (fan_in + fan_out))` where `fan_in` is the number of input units in
818 the weight tensor and `fan_out` is the number of output units in the weight
819 tensor.
821 Examples:
823 >>> def make_variables(k, initializer):
824 ... return (tf.Variable(initializer(shape=[k, k], dtype=tf.float32)),
825 ... tf.Variable(initializer(shape=[k, k, k], dtype=tf.float32)))
826 >>> v1, v2 = make_variables(3, tf.initializers.GlorotNormal())
827 >>> v1
828 <tf.Variable ... shape=(3, 3) ...
829 >>> v2
830 <tf.Variable ... shape=(3, 3, 3) ...
831 >>> make_variables(4, tf.initializers.RandomNormal())
832 (<tf.Variable ... shape=(4, 4) dtype=float32...
833 <tf.Variable ... shape=(4, 4, 4) dtype=float32...
835 Args:
836 seed: A Python integer. Used to create random seeds. See
837 `tf.random.set_seed` for behavior.
839 References:
840 [Glorot et al., 2010](http://proceedings.mlr.press/v9/glorot10a.html)
841 ([pdf](http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf))
842 """
844 def __init__(self, seed=None):
845 super(GlorotNormal, self).__init__(
846 scale=1.0,
847 mode="fan_avg",
848 distribution="truncated_normal",
849 seed=seed)
851 def get_config(self):
852 return {"seed": self.seed}
855# Aliases.
857# pylint: disable=invalid-name
858zeros_initializer = Zeros
859ones_initializer = Ones
860constant_initializer = Constant
861random_uniform_initializer = RandomUniform
862random_normal_initializer = RandomNormal
863truncated_normal_initializer = TruncatedNormal
864variance_scaling_initializer = VarianceScaling
865glorot_uniform_initializer = GlorotUniform
866glorot_normal_initializer = GlorotNormal
867orthogonal_initializer = Orthogonal
868identity_initializer = Identity
869# pylint: enable=invalid-name
872def lecun_normal(seed=None):
873 """LeCun normal initializer.
875 Initializers allow you to pre-specify an initialization strategy, encoded in
876 the Initializer object, without knowing the shape and dtype of the variable
877 being initialized.
879 Draws samples from a truncated normal distribution centered on 0 with `stddev
880 = sqrt(1 / fan_in)` where `fan_in` is the number of input units in the weight
881 tensor.
883 Examples:
885 >>> def make_variables(k, initializer):
886 ... return (tf.Variable(initializer(shape=[k, k], dtype=tf.float32)),
887 ... tf.Variable(initializer(shape=[k, k, k], dtype=tf.float32)))
888 >>> v1, v2 = make_variables(3, tf.initializers.lecun_normal())
889 >>> v1
890 <tf.Variable ... shape=(3, 3) ...
891 >>> v2
892 <tf.Variable ... shape=(3, 3, 3) ...
893 >>> make_variables(4, tf.initializers.RandomNormal())
894 (<tf.Variable ... shape=(4, 4) dtype=float32...
895 <tf.Variable ... shape=(4, 4, 4) dtype=float32...
897 Args:
898 seed: A Python integer. Used to seed the random generator.
900 Returns:
901 A callable Initializer with `shape` and `dtype` arguments which generates a
902 tensor.
904 References:
905 - Self-Normalizing Neural Networks,
906 [Klambauer et al., 2017]
907 (https://papers.nips.cc/paper/6698-self-normalizing-neural-networks)
908 ([pdf]
909 (https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf))
910 - Efficient Backprop,
911 [Lecun et al., 1998](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf)
912 """
913 return VarianceScaling(
914 scale=1., mode="fan_in", distribution="truncated_normal", seed=seed)
917def lecun_uniform(seed=None):
918 """LeCun uniform initializer.
920 Initializers allow you to pre-specify an initialization strategy, encoded in
921 the Initializer object, without knowing the shape and dtype of the variable
922 being initialized.
924 Draws samples from a uniform distribution within [-limit, limit] where `limit`
925 is `sqrt(3 / fan_in)` where `fan_in` is the number of input units in the
926 weight tensor.
928 Examples:
930 >>> def make_variables(k, initializer):
931 ... return (tf.Variable(initializer(shape=[k, k], dtype=tf.float32)),
932 ... tf.Variable(initializer(shape=[k, k, k], dtype=tf.float32)))
933 >>> v1, v2 = make_variables(3, tf.initializers.lecun_uniform())
934 >>> v1
935 <tf.Variable ... shape=(3, 3) ...
936 >>> v2
937 <tf.Variable ... shape=(3, 3, 3) ...
938 >>> make_variables(4, tf.initializers.RandomNormal())
939 (<tf.Variable ... shape=(4, 4) dtype=float32...
940 <tf.Variable ... shape=(4, 4, 4) dtype=float32...
942 Args:
943 seed: A Python integer. Used to seed the random generator.
945 Returns:
946 A callable Initializer with `shape` and `dtype` arguments which generates a
947 tensor.
949 References:
950 - Self-Normalizing Neural Networks,
951 [Klambauer et al., 2017](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) # pylint: disable=line-too-long
952 ([pdf](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf))
953 - Efficient Backprop,
954 [Lecun et al., 1998](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf)
955 """
956 return VarianceScaling(
957 scale=1., mode="fan_in", distribution="uniform", seed=seed)
960def he_normal(seed=None):
961 """He normal initializer.
963 Initializers allow you to pre-specify an initialization strategy, encoded in
964 the Initializer object, without knowing the shape and dtype of the variable
965 being initialized.
967 It draws samples from a truncated normal distribution centered on 0 with
968 `stddev = sqrt(2 / fan_in)` where `fan_in` is the number of input units in the
969 weight tensor.
971 Examples:
973 >>> def make_variables(k, initializer):
974 ... return (tf.Variable(initializer(shape=[k, k], dtype=tf.float32)),
975 ... tf.Variable(initializer(shape=[k, k, k], dtype=tf.float32)))
976 >>> v1, v2 = make_variables(3, tf.initializers.he_normal())
977 >>> v1
978 <tf.Variable ... shape=(3, 3) ...
979 >>> v2
980 <tf.Variable ... shape=(3, 3, 3) ...
981 >>> make_variables(4, tf.initializers.RandomNormal())
982 (<tf.Variable ... shape=(4, 4) dtype=float32...
983 <tf.Variable ... shape=(4, 4, 4) dtype=float32...
985 Args:
986 seed: A Python integer. Used to seed the random generator.
988 Returns:
989 A callable Initializer with `shape` and `dtype` arguments which generates a
990 tensor.
992 References:
993 [He et al., 2015](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) # pylint: disable=line-too-long
994 ([pdf](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf))
995 """
996 return VarianceScaling(
997 scale=2., mode="fan_in", distribution="truncated_normal", seed=seed)
1000def he_uniform(seed=None):
1001 """He uniform variance scaling initializer.
1003 Initializers allow you to pre-specify an initialization strategy, encoded in
1004 the Initializer object, without knowing the shape and dtype of the variable
1005 being initialized.
1007 Draws samples from a uniform distribution within [-limit, limit] where `limit`
1008 is `sqrt(6 / fan_in)` where `fan_in` is the number of input units in the
1009 weight tensor.
1011 Examples:
1013 >>> def make_variables(k, initializer):
1014 ... return (tf.Variable(initializer(shape=[k, k], dtype=tf.float32)),
1015 ... tf.Variable(initializer(shape=[k, k, k], dtype=tf.float32)))
1016 >>> v1, v2 = make_variables(3, tf.initializers.he_uniform())
1017 >>> v1
1018 <tf.Variable ... shape=(3, 3) ...
1019 >>> v2
1020 <tf.Variable ... shape=(3, 3, 3) ...
1021 >>> make_variables(4, tf.initializers.RandomNormal())
1022 (<tf.Variable ... shape=(4, 4) dtype=float32...
1023 <tf.Variable ... shape=(4, 4, 4) dtype=float32...
1025 Args:
1026 seed: A Python integer. Used to seed the random generator.
1028 Returns:
1029 A callable Initializer with `shape` and `dtype` arguments which generates a
1030 tensor.
1032 References:
1033 [He et al., 2015](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) # pylint: disable=line-too-long
1034 ([pdf](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf))
1035 """
1036 return VarianceScaling(
1037 scale=2., mode="fan_in", distribution="uniform", seed=seed)
1040# Utility functions.
1043def _assert_float_dtype(dtype):
1044 """Validate and return floating point type based on `dtype`.
1046 `dtype` must be a floating point type.
1048 Args:
1049 dtype: The data type to validate.
1051 Returns:
1052 Validated type.
1054 Raises:
1055 ValueError: if `dtype` is not a floating point type.
1056 """
1057 dtype = dtypes.as_dtype(dtype)
1058 if not dtype.is_floating:
1059 raise ValueError("Argument `dtype` is expected to be floating point. "
1060 f"Received: {dtype}.")
1061 return dtype
1064class _RandomGenerator:
1065 """Random generator that selects appropriate random ops."""
1067 def __init__(self, seed=None):
1068 super(_RandomGenerator, self).__init__()
1069 if seed is not None:
1070 # Stateless random ops requires 2-int seed.
1071 self.seed = [seed, 0]
1072 else:
1073 self.seed = None
1075 def random_normal(self, shape, mean=0.0, stddev=1, dtype=dtypes.float32):
1076 """A deterministic random normal if seed is passed."""
1077 if self.seed:
1078 op = stateless_random_ops.stateless_random_normal
1079 else:
1080 op = random_ops.random_normal
1081 return op(
1082 shape=shape, mean=mean, stddev=stddev, dtype=dtype, seed=self.seed)
1084 def random_uniform(self, shape, minval, maxval, dtype):
1085 """A deterministic random uniform if seed is passed."""
1086 if self.seed:
1087 op = stateless_random_ops.stateless_random_uniform
1088 else:
1089 op = random_ops.random_uniform
1090 return op(
1091 shape=shape, minval=minval, maxval=maxval, dtype=dtype, seed=self.seed)
1093 def truncated_normal(self, shape, mean, stddev, dtype):
1094 """A deterministic truncated normal if seed is passed."""
1095 if self.seed:
1096 op = stateless_random_ops.stateless_truncated_normal
1097 else:
1098 op = random_ops.truncated_normal
1099 return op(
1100 shape=shape, mean=mean, stddev=stddev, dtype=dtype, seed=self.seed)
1102# Compatibility aliases
1104# pylint: disable=invalid-name
1105zero = zeros = Zeros
1106one = ones = Ones
1107constant = Constant
1108uniform = random_uniform = RandomUniform
1109normal = random_normal = RandomNormal
1110truncated_normal = TruncatedNormal
1111identity = Identity
1112orthogonal = Orthogonal
1113glorot_normal = GlorotNormal
1114glorot_uniform = GlorotUniform