Download model/legacy/initializers.py from OneScience-Group/NeuralGCM: direct link, hf CLI and curl.
- Browser
- Download file 4.81 kB
-
https://huggingface.co/OneScience-Group/NeuralGCM/resolve/main/model/legacy/initializers.py
- Command line
-
hf download hf://OneScience-Group/NeuralGCM/model/legacy/initializers.py
-
curl -L -o initializers.py https://huggingface.co/OneScience-Group/NeuralGCM/resolve/main/model/legacy/initializers.py
4.81 kB
| # Copyright 2024 Google LLC | |
| # | |
| # 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 | |
| # | |
| # https://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. | |
| """Implementation of custom initializers for NN parameters.""" | |
| from typing import Any, Optional, Sequence | |
| import gin | |
| import haiku as hk | |
| import jax | |
| import numpy as np | |
| # Registering default initializers. | |
| Constant = gin.external_configurable(hk.initializers.Constant) | |
| VarianceScaling = gin.external_configurable(hk.initializers.VarianceScaling) | |
| Orthogonal = gin.external_configurable(hk.initializers.Orthogonal) | |
| def _compute_fans( | |
| shape: Sequence[int], | |
| fan_in_axes: Optional[Sequence[int]] = None, | |
| ) -> tuple[int, int]: | |
| """Computes the number of input and output units for a weight shape.""" | |
| # adapted from dm-haiku/_src/initializers.py | |
| if len(shape) < 1: | |
| fan_in = fan_out = 1 | |
| elif len(shape) == 1: | |
| fan_in = fan_out = shape[0] | |
| elif len(shape) == 2: | |
| fan_in, fan_out = shape | |
| else: | |
| if fan_in_axes is not None: | |
| # Compute fan-in using user-specified fan-in axes. | |
| fan_in = np.prod([shape[i] for i in fan_in_axes]) | |
| fan_out = np.prod([s for i, s in enumerate(shape) | |
| if i not in fan_in_axes]) | |
| else: | |
| # If no axes specified, assume convolution kernels (2D, 3D, or more.) | |
| # kernel_shape: (..., input_depth, depth) | |
| receptive_field_size = np.prod(shape[:-2]) | |
| fan_in = shape[-2] * receptive_field_size | |
| fan_out = shape[-1] * receptive_field_size | |
| return fan_in, fan_out # pyrefly: ignore[bad-return] | |
| class ReducingVarianceScaling(hk.initializers.Initializer): # pyrefly: ignore[invalid-inheritance] | |
| """Initializer that result in variance that reduces as width increases. | |
| Initializes weights that result in features with expected variance of | |
| `scale / n`, where `n` corresponds to the width of the layer. This initializer | |
| can be used in the output layer to achieve µ parameterization [1]. | |
| References: | |
| [1]: https://arxiv.org/abs/2203.03466 | |
| """ | |
| def __init__( | |
| self, | |
| scale=1.0, | |
| mode='fan_in', | |
| distribution='truncated_normal', | |
| fan_in_axes=None, | |
| ): | |
| """Constructs `ReducingVarianceScaling` initializer. | |
| Args: | |
| scale: Variance scale for a width == 1 initialization. | |
| mode: One of ``fan_in``, ``fan_out``, ``fan_avg`` | |
| distribution: Random distribution to use. One of ``truncated_normal``, | |
| ``normal`` or ``uniform``. | |
| fan_in_axes: Optional sequence of int specifying which axes of the shape | |
| are part of the fan-in. If none provided, then the weight is assumed | |
| to be like a convolution kernel, where all leading dimensions are part | |
| of the fan-in, and only the trailing dimension is part of the fan-out. | |
| Useful if instantiating multi-headed attention weights. | |
| """ | |
| if scale < 0.0: | |
| raise ValueError('`scale` must be a positive float.') | |
| if mode not in {'fan_in', 'fan_out', 'fan_avg'}: | |
| raise ValueError('Invalid `mode` argument:', mode) | |
| distribution = distribution.lower() | |
| if distribution not in {'normal', 'truncated_normal', 'uniform'}: | |
| raise ValueError('Invalid `distribution` argument:', distribution) | |
| self.scale = scale | |
| self.mode = mode | |
| self.distribution = distribution | |
| self.fan_in_axes = fan_in_axes | |
| def __call__(self, shape: Sequence[int], dtype: Any) -> jax.Array: | |
| scale = self.scale | |
| fan_in, fan_out = _compute_fans(shape, self.fan_in_axes) | |
| if self.mode == 'fan_in': | |
| scale /= max(1.0, fan_in) ** 2 | |
| elif self.mode == 'fan_out': | |
| scale /= max(1.0, fan_out) ** 2 | |
| else: | |
| scale /= max(1.0, (fan_in + fan_out) / 2.0) ** 2 | |
| if self.distribution == 'truncated_normal': | |
| stddev = np.sqrt(scale) | |
| # Adjust stddev for truncation. | |
| # Constant from scipy.stats.truncnorm.std(a=-2, b=2, loc=0., scale=1.) | |
| distribution_stddev = np.asarray(.87962566103423978, dtype=dtype) | |
| stddev = stddev / distribution_stddev | |
| return hk.initializers.TruncatedNormal(stddev=stddev)(shape, dtype) | |
| elif self.distribution == 'normal': | |
| stddev = np.sqrt(scale) | |
| return hk.initializers.RandomNormal(stddev=stddev)(shape, dtype) | |
| else: | |
| limit = np.sqrt(3.0 * scale) | |
| uniform_init = hk.initializers.RandomUniform(minval=-limit, maxval=limit) | |
| return uniform_init(shape, dtype) | |