Equimo 2.6.0__tar.gz → 2.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {equimo-2.6.0 → equimo-2.7.0}/CHANGELOG.md +38 -0
- {equimo-2.6.0 → equimo-2.7.0}/PKG-INFO +49 -10
- {equimo-2.6.0 → equimo-2.7.0}/README.md +46 -7
- {equimo-2.6.0 → equimo-2.7.0}/docs/stability.md +4 -0
- {equimo-2.6.0 → equimo-2.7.0}/pyproject.toml +4 -4
- equimo-2.7.0/src/equimo/__init__.py +1 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/__init__.py +2 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/activation.py +3 -1
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/attention.py +146 -12
- equimo-2.7.0/src/equimo/core/ops/__init__.py +18 -0
- equimo-2.7.0/src/equimo/core/ops/probability.py +203 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/ops/scan.py +1 -1
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/feature_extraction.py +3 -3
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/heads.py +10 -9
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/adapters.py +4 -4
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/prefix.py +12 -13
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/pooling.py +3 -4
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/layers/attention.py +48 -6
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/layers/decoder.py +4 -3
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/query_training/_loss.py +2 -3
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/segmentation.py +40 -3
- equimo-2.6.0/src/equimo/__init__.py +0 -1
- equimo-2.6.0/src/equimo/core/ops/__init__.py +0 -3
- {equimo-2.6.0 → equimo-2.7.0}/LICENSE.md +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/Apache-2.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/README.md +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/ast-BSD-3-Clause.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/convnext-Apache-2.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/convnextv2-CC-BY-NC-4.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/dinov2-Apache-2.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/dinov3-License.md +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/eupe-FAIR-Noncommercial-Research-License.md +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/lingbot-vision-Apache-2.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/siglip2-Apache-2.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/t0-alpha-Apache-2.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/tabpfn-3-License-v1.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/pretrained/tips-CC-BY-4.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/LICENSES/tfc-t0-APACHE-2.0.txt +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/NOTICE +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/docs/licensing/t0-source-provenance.md +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/docs/migration-v2.md +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/docs/timeseries.md +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/models/huggingface/NOTICE +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/models/huggingface/README.md +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/models/huggingface/convnext-conversion.json +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/_checkpoint_limits.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/_io.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/_pretrained.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/audio/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/audio/io.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/audio/layers/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/audio/layers/patch.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/audio/models/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/audio/models/ast.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/catalog.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/conversion/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/conversion/utils.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/_prng.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/emamodel.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/factory.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/implicit/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/implicit/_base.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/implicit/deq.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/implicit/injectors.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/implicit/stabilizers.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/implicit/strategies.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/intermediates.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/_registry.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/dropout.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/ffn.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/generic.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/mamba.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/norm.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/core/layers/rotary.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/_blocks.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/_serialization_codecs.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/_typing.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/audio/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/audio/recipes.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/audio/selectors.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/calibration.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/config.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/continued_ssl.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/inspection.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/labels.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/language/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/language/recipes.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/language/selectors.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/masks.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/merging.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/paths.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/_common.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/_compat.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/base.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/bitfit.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/dora.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/ia3.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/lora.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/prompts.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/scale_shift.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/peft/vera.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/recipes.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/regularization.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/selectors.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/serialization.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/surgery.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/tags.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/vision/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/vision/dense.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/vision/eomt.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/finetune/vision/pmt.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/language/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/language/models.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/language/tokenizers.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/registry.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/serialization.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/layers/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/layers/blocks.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/layers/mlp.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/layers/preprocessing.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/layers/registry.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/models/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/tabular/models/tabpfn.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/layers/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/layers/axis_attn.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/layers/blocks.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/layers/patch_encoder.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/layers/registry.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/layers/residual_mlp.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/models/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/timeseries/models/t0.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/utils.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/_encoder_identity.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/io.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/attention.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/convolution.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/downsample.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/patch.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/posemb.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/registry.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/squeeze_excite.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/layers/wavelet.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/_embedding.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/_features.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/attnet.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/convnext.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/deq.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/eomt.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/fastervit.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/iformer.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/lowformer.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/mlla.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/mobilenet.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/parcae.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/partialformer.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/pmd.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/pmt.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/reduceformer.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/shvit.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/vit.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/models/vssd.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/pmt_checkpoint.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/query_training/__init__.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/query_training/_assignment.py +0 -0
- {equimo-2.6.0 → equimo-2.7.0}/src/equimo/vision/query_training/_sampling.py +0 -0
|
@@ -2,6 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Equimo are documented here. Equimo follows Semantic Versioning from version 2.0.0 onward.
|
|
4
4
|
|
|
5
|
+
## [2.7.0] - 2026-10-26
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `equimo.core.ops` exports `softmax`, `log_softmax`, `softmax_cross_entropy_with_integer_labels`, and
|
|
10
|
+
`softmax_cross_entropy_with_logit_targets`, following "A Fix for Softmax and Cross-Entropy". They compute in at least
|
|
11
|
+
float32, return the input dtype, and keep the dominant logit's small gradient at high confidence. The logit-target
|
|
12
|
+
loss, for distillation, also preserves near-equality gradients, stops target gradients, and supports higher-order
|
|
13
|
+
derivatives.
|
|
14
|
+
- Experimental fused attention: `equimo.core.layers.with_attention_implementation(model, "cudnn")` runs core,
|
|
15
|
+
prefix-tuned, and tabular attention through cuDNN's fused kernel for bfloat16 or float16 models on CUDA GPUs, and
|
|
16
|
+
attention modules accept the same choice as an `implementation` argument. On an RTX 4080, it shortened ViT and EoMT
|
|
17
|
+
training steps by 7-22% and reduced their temporary memory by 17-56%. It does not support attention dropout or
|
|
18
|
+
jax2onnx export; the default `"xla"` implementation is unchanged.
|
|
19
|
+
- `semantic_crop_origins` places the fewest evenly spaced crops that cover a scaled image, for sliding-window evaluation
|
|
20
|
+
with `merge_semantic_crops`. With the shorter side scaled to the crop size, it matches the EoMT reference's windows,
|
|
21
|
+
except that its last crop always ends at the image edge: the reference's floating-point spacing stops a pixel short
|
|
22
|
+
for some sizes, such as a 1,347-pixel side with 448-pixel crops.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Equimo requires JAX and jaxlib 0.11.1 or newer. With it, a compiled step that captures both a frozen encoder and its
|
|
27
|
+
images as constants matches eager execution, which JAX 0.8.1 did not.
|
|
28
|
+
- Attention pooling, attention-pooling heads, adapter fusion, the tabular decoder, and the `"softmax"` activation
|
|
29
|
+
compute softmax in at least float32 with the corrected derivative of `equimo.core.ops.softmax`, returning the model
|
|
30
|
+
dtype. Tabular attention computes its softmax in at least float32. Attention logits are cast before scaling, avoiding
|
|
31
|
+
a second bfloat16 rounding when the square root of the head dimension is not a power of two. Float32 forward results
|
|
32
|
+
and checkpoint structure are unchanged.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- Query classification uses stable cross-entropy, so confident correct predictions retain nonzero losses and target
|
|
37
|
+
gradients.
|
|
38
|
+
- `selective_scan` returns the input dtype. Its float32 scan state leaked into bfloat16 outputs, unlike `ssd`.
|
|
39
|
+
- `merge_semantic_crops` raises a `ValueError` when the crops leave part of the scaled image uncovered. It returned NaN
|
|
40
|
+
scores there instead, and any final resize spread them to every output pixel, so the argmax labelled the whole image
|
|
41
|
+
class 0.
|
|
42
|
+
|
|
5
43
|
## [2.6.0] - 2026-10-17
|
|
6
44
|
|
|
7
45
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Equimo
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: Implementation of modern multimodal models in JAX/Equinox
|
|
5
5
|
License-Expression: MIT AND Apache-2.0
|
|
6
6
|
License-File: LICENSE.md
|
|
@@ -29,8 +29,8 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
29
29
|
Requires-Dist: banax>=0.1.2
|
|
30
30
|
Requires-Dist: einops>=0.8.0
|
|
31
31
|
Requires-Dist: equinox>=0.13.3
|
|
32
|
-
Requires-Dist: jax>=0.
|
|
33
|
-
Requires-Dist: jaxlib>=0.
|
|
32
|
+
Requires-Dist: jax>=0.11.1
|
|
33
|
+
Requires-Dist: jaxlib>=0.11.1
|
|
34
34
|
Requires-Dist: loguru>=0.7.3
|
|
35
35
|
Requires-Dist: lz4>=4.4.3
|
|
36
36
|
Requires-Dist: requests>=2.32.3
|
|
@@ -268,6 +268,7 @@ Minimal example:
|
|
|
268
268
|
import jax
|
|
269
269
|
import equimo.finetune as eqft
|
|
270
270
|
import equimo.vision.models as em
|
|
271
|
+
from equimo.core.ops import softmax_cross_entropy_with_integer_labels
|
|
271
272
|
|
|
272
273
|
key = jax.random.PRNGKey(0)
|
|
273
274
|
model = em.vit_tiny_patch16_224(num_classes=10, key=key)
|
|
@@ -288,7 +289,7 @@ frozen = plan.frozen
|
|
|
288
289
|
def loss_fn(trainable, batch):
|
|
289
290
|
model = plan.combine(trainable)
|
|
290
291
|
logits = jax.vmap(lambda x: model(x, key=key, inference=False))(batch["x"])
|
|
291
|
-
return
|
|
292
|
+
return softmax_cross_entropy_with_integer_labels(logits, batch["y"]).mean()
|
|
292
293
|
```
|
|
293
294
|
|
|
294
295
|
Frozen leaves are absent from `plan.trainable`; they are not assigned a zero learning rate. `plan.labels` and
|
|
@@ -997,14 +998,52 @@ import jax
|
|
|
997
998
|
import jax.numpy as jnp
|
|
998
999
|
import equinox as eqx
|
|
999
1000
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
)
|
|
1001
|
+
|
|
1002
|
+
def to_bfloat16(tree):
|
|
1003
|
+
return jax.tree_util.tree_map(
|
|
1004
|
+
lambda leaf: leaf.astype(jnp.bfloat16) if eqx.is_inexact_array(leaf) else leaf,
|
|
1005
|
+
tree,
|
|
1006
|
+
)
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
model_bf16 = to_bfloat16(model_fp32)
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
For training, keep float32 parameters and cast inside the loss. Gradients then return in float32 and the optimizer
|
|
1013
|
+
updates float32 values; bfloat16 parameters drop updates smaller than about 0.4% of their magnitude.
|
|
1014
|
+
|
|
1015
|
+
```python
|
|
1016
|
+
from equimo.core.ops import softmax_cross_entropy_with_integer_labels
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
@eqx.filter_value_and_grad
|
|
1020
|
+
def loss_and_grads(model_fp32, images, labels, key):
|
|
1021
|
+
model = to_bfloat16(model_fp32)
|
|
1022
|
+
keys = jax.random.split(key, images.shape[0])
|
|
1023
|
+
logits = jax.vmap(lambda x, k: model(x, key=k, inference=False))(images, keys)
|
|
1024
|
+
return softmax_cross_entropy_with_integer_labels(logits, labels).mean()
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
Numerically sensitive operations cast locally to float32 and return the model dtype: normalization statistics, rotary
|
|
1028
|
+
factors, and every softmax. Attention between tokens applies `jax.nn.softmax` to float32 logits. Other softmaxes
|
|
1029
|
+
(attention pooling, attention-pooling heads, adapter fusion, the tabular decoder, and the `"softmax"` activation) use
|
|
1030
|
+
`equimo.core.ops.softmax`, whose derivative also stays accurate for highly confident distributions. For the same reason,
|
|
1031
|
+
use the [`equimo.core.ops` classification losses](docs/finetuning/classification_losses.md). The
|
|
1032
|
+
[performance notes](docs/performance.md#softmax-precision) give the measurements behind these choices.
|
|
1033
|
+
|
|
1034
|
+
On NVIDIA GPUs with TF32 tensor cores (Ampere and newer), JAX's default precision may run float32 matrix multiplications
|
|
1035
|
+
as TF32. For float32 reference accuracy, run the computation under `jax.default_matmul_precision("highest")`.
|
|
1036
|
+
|
|
1037
|
+
On CUDA GPUs, bfloat16 and float16 models can run attention through cuDNN's fused kernel, which saves memory and time on
|
|
1038
|
+
long sequences. This is experimental, requires inactive attention dropout, and cannot be exported with jax2onnx:
|
|
1039
|
+
|
|
1040
|
+
```python
|
|
1041
|
+
from equimo.core.layers import with_attention_implementation
|
|
1042
|
+
|
|
1043
|
+
model = with_attention_implementation(model_bf16, "cudnn") # "xla" switches back
|
|
1004
1044
|
```
|
|
1005
1045
|
|
|
1006
|
-
|
|
1007
|
-
applied internally where needed.
|
|
1046
|
+
See the [fused-attention measurements](docs/performance.md#fused-attention).
|
|
1008
1047
|
|
|
1009
1048
|
## Contributing
|
|
1010
1049
|
|
|
@@ -216,6 +216,7 @@ Minimal example:
|
|
|
216
216
|
import jax
|
|
217
217
|
import equimo.finetune as eqft
|
|
218
218
|
import equimo.vision.models as em
|
|
219
|
+
from equimo.core.ops import softmax_cross_entropy_with_integer_labels
|
|
219
220
|
|
|
220
221
|
key = jax.random.PRNGKey(0)
|
|
221
222
|
model = em.vit_tiny_patch16_224(num_classes=10, key=key)
|
|
@@ -236,7 +237,7 @@ frozen = plan.frozen
|
|
|
236
237
|
def loss_fn(trainable, batch):
|
|
237
238
|
model = plan.combine(trainable)
|
|
238
239
|
logits = jax.vmap(lambda x: model(x, key=key, inference=False))(batch["x"])
|
|
239
|
-
return
|
|
240
|
+
return softmax_cross_entropy_with_integer_labels(logits, batch["y"]).mean()
|
|
240
241
|
```
|
|
241
242
|
|
|
242
243
|
Frozen leaves are absent from `plan.trainable`; they are not assigned a zero learning rate. `plan.labels` and
|
|
@@ -945,14 +946,52 @@ import jax
|
|
|
945
946
|
import jax.numpy as jnp
|
|
946
947
|
import equinox as eqx
|
|
947
948
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
)
|
|
949
|
+
|
|
950
|
+
def to_bfloat16(tree):
|
|
951
|
+
return jax.tree_util.tree_map(
|
|
952
|
+
lambda leaf: leaf.astype(jnp.bfloat16) if eqx.is_inexact_array(leaf) else leaf,
|
|
953
|
+
tree,
|
|
954
|
+
)
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
model_bf16 = to_bfloat16(model_fp32)
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
For training, keep float32 parameters and cast inside the loss. Gradients then return in float32 and the optimizer
|
|
961
|
+
updates float32 values; bfloat16 parameters drop updates smaller than about 0.4% of their magnitude.
|
|
962
|
+
|
|
963
|
+
```python
|
|
964
|
+
from equimo.core.ops import softmax_cross_entropy_with_integer_labels
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
@eqx.filter_value_and_grad
|
|
968
|
+
def loss_and_grads(model_fp32, images, labels, key):
|
|
969
|
+
model = to_bfloat16(model_fp32)
|
|
970
|
+
keys = jax.random.split(key, images.shape[0])
|
|
971
|
+
logits = jax.vmap(lambda x, k: model(x, key=k, inference=False))(images, keys)
|
|
972
|
+
return softmax_cross_entropy_with_integer_labels(logits, labels).mean()
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
Numerically sensitive operations cast locally to float32 and return the model dtype: normalization statistics, rotary
|
|
976
|
+
factors, and every softmax. Attention between tokens applies `jax.nn.softmax` to float32 logits. Other softmaxes
|
|
977
|
+
(attention pooling, attention-pooling heads, adapter fusion, the tabular decoder, and the `"softmax"` activation) use
|
|
978
|
+
`equimo.core.ops.softmax`, whose derivative also stays accurate for highly confident distributions. For the same reason,
|
|
979
|
+
use the [`equimo.core.ops` classification losses](docs/finetuning/classification_losses.md). The
|
|
980
|
+
[performance notes](docs/performance.md#softmax-precision) give the measurements behind these choices.
|
|
981
|
+
|
|
982
|
+
On NVIDIA GPUs with TF32 tensor cores (Ampere and newer), JAX's default precision may run float32 matrix multiplications
|
|
983
|
+
as TF32. For float32 reference accuracy, run the computation under `jax.default_matmul_precision("highest")`.
|
|
984
|
+
|
|
985
|
+
On CUDA GPUs, bfloat16 and float16 models can run attention through cuDNN's fused kernel, which saves memory and time on
|
|
986
|
+
long sequences. This is experimental, requires inactive attention dropout, and cannot be exported with jax2onnx:
|
|
987
|
+
|
|
988
|
+
```python
|
|
989
|
+
from equimo.core.layers import with_attention_implementation
|
|
990
|
+
|
|
991
|
+
model = with_attention_implementation(model_bf16, "cudnn") # "xla" switches back
|
|
952
992
|
```
|
|
953
993
|
|
|
954
|
-
|
|
955
|
-
applied internally where needed.
|
|
994
|
+
See the [fused-attention measurements](docs/performance.md#fused-attention).
|
|
956
995
|
|
|
957
996
|
## Contributing
|
|
958
997
|
|
|
@@ -30,6 +30,10 @@ tensor contract, and Equinox PyTree structure may change in a minor release whil
|
|
|
30
30
|
adapter is developed. Such changes will be recorded in the changelog. Existing T0 archives remain covered by the
|
|
31
31
|
checkpoint integrity and loading commitments below; this exception applies to the Python and raw-array API around them.
|
|
32
32
|
|
|
33
|
+
Fused cuDNN attention, selected with `equimo.core.layers.with_attention_implementation` or `implementation="cudnn"`, is
|
|
34
|
+
experimental. Its supported dtypes, masks, and module coverage follow cuDNN and `jax.nn.dot_product_attention` and may
|
|
35
|
+
change in a minor release. The default `implementation="xla"` is stable.
|
|
36
|
+
|
|
33
37
|
Optional integrations remain optional. Their public Equimo wrappers are stable, but the supported Python range may be
|
|
34
38
|
narrower when an upstream dependency does not publish wheels. Equimo documents and tests those exceptions explicitly.
|
|
35
39
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "Equimo"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.7.0"
|
|
4
4
|
description = "Implementation of modern multimodal models in JAX/Equinox"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12,<3.15"
|
|
@@ -27,8 +27,8 @@ dependencies = [
|
|
|
27
27
|
"banax>=0.1.2",
|
|
28
28
|
"einops>=0.8.0",
|
|
29
29
|
"equinox>=0.13.3",
|
|
30
|
-
"jax>=0.
|
|
31
|
-
"jaxlib>=0.
|
|
30
|
+
"jax>=0.11.1",
|
|
31
|
+
"jaxlib>=0.11.1",
|
|
32
32
|
"loguru>=0.7.3",
|
|
33
33
|
"lz4>=4.4.3",
|
|
34
34
|
"requests>=2.32.3",
|
|
@@ -87,7 +87,7 @@ source-include = [
|
|
|
87
87
|
|
|
88
88
|
[dependency-groups]
|
|
89
89
|
dev = [
|
|
90
|
-
"jax2onnx>=0.
|
|
90
|
+
"jax2onnx>=0.17.0",
|
|
91
91
|
"mdformat==1.0.0",
|
|
92
92
|
"mdformat-footnote==0.1.3",
|
|
93
93
|
"mdformat-gfm==1.0.0",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.7.0"
|
|
@@ -38,6 +38,7 @@ __all__ = [
|
|
|
38
38
|
"register_ffn",
|
|
39
39
|
"register_mixer",
|
|
40
40
|
"register_norm",
|
|
41
|
+
"with_attention_implementation",
|
|
41
42
|
]
|
|
42
43
|
|
|
43
44
|
from .activation import get_act, register_act
|
|
@@ -48,6 +49,7 @@ from .attention import (
|
|
|
48
49
|
get_attn_block,
|
|
49
50
|
register_attn,
|
|
50
51
|
register_attn_block,
|
|
52
|
+
with_attention_implementation,
|
|
51
53
|
)
|
|
52
54
|
from .dropout import DropPath, DropPathAdd, get_dropout, register_dropout
|
|
53
55
|
from .ffn import (
|
|
@@ -3,6 +3,8 @@ from typing import Callable, Optional
|
|
|
3
3
|
|
|
4
4
|
import jax
|
|
5
5
|
|
|
6
|
+
from equimo.core.ops import softmax
|
|
7
|
+
|
|
6
8
|
_ACT_REGISTRY: dict[str, Callable] = {}
|
|
7
9
|
|
|
8
10
|
|
|
@@ -65,5 +67,5 @@ _ACT_REGISTRY["elu"] = jax.nn.elu
|
|
|
65
67
|
_ACT_REGISTRY["sigmoid"] = jax.nn.sigmoid
|
|
66
68
|
_ACT_REGISTRY["hard_sigmoid"] = jax.nn.hard_sigmoid
|
|
67
69
|
_ACT_REGISTRY["hard_swish"] = jax.nn.hard_swish
|
|
68
|
-
_ACT_REGISTRY["softmax"] =
|
|
70
|
+
_ACT_REGISTRY["softmax"] = softmax
|
|
69
71
|
_ACT_REGISTRY["relu6"] = jax.nn.relu6
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import dataclasses
|
|
2
|
+
from typing import Callable, List, Literal, Optional, TypeVar
|
|
2
3
|
|
|
3
4
|
import equinox as eqx
|
|
4
5
|
import jax
|
|
@@ -59,6 +60,131 @@ def _broadcast_attention_mask(
|
|
|
59
60
|
) from error
|
|
60
61
|
|
|
61
62
|
|
|
63
|
+
AttentionImplementation = Literal["xla", "cudnn"]
|
|
64
|
+
_IMPLEMENTATIONS = ("xla", "cudnn")
|
|
65
|
+
# cuDNN's fused attention backward requires sequence lengths divisible by 64.
|
|
66
|
+
_CUDNN_SEQUENCE_MULTIPLE = 64
|
|
67
|
+
|
|
68
|
+
_Model = TypeVar("_Model")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _check_implementation(implementation: str) -> None:
|
|
72
|
+
if implementation not in _IMPLEMENTATIONS:
|
|
73
|
+
raise ValueError(
|
|
74
|
+
f"implementation must be one of {_IMPLEMENTATIONS}, got {implementation!r}."
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _check_cudnn_dropout(
|
|
79
|
+
dropout: eqx.nn.Dropout | None, inference: Optional[bool]
|
|
80
|
+
) -> None:
|
|
81
|
+
"""Reject attention-probability dropout, which the fused kernel cannot apply."""
|
|
82
|
+
if dropout is None:
|
|
83
|
+
return
|
|
84
|
+
if inference is None:
|
|
85
|
+
inference = dropout.inference
|
|
86
|
+
if not inference and dropout.p != 0:
|
|
87
|
+
raise ValueError(
|
|
88
|
+
"implementation='cudnn' does not support attention dropout. Set the "
|
|
89
|
+
"attention dropout rate to 0, call with inference=True, or use "
|
|
90
|
+
"implementation='xla'."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _fused_attention(
|
|
95
|
+
q: jax.Array,
|
|
96
|
+
k: jax.Array,
|
|
97
|
+
v: jax.Array,
|
|
98
|
+
allowed: jax.Array | None = None,
|
|
99
|
+
*,
|
|
100
|
+
implementation: AttentionImplementation = "cudnn",
|
|
101
|
+
) -> jax.Array:
|
|
102
|
+
"""Fused dot-product attention over ``(..., heads, seq, head_dim)`` inputs.
|
|
103
|
+
|
|
104
|
+
``allowed`` broadcasts to ``(..., heads, query, key)``. Fully masked query rows
|
|
105
|
+
return zeros, as in the unfused path. Keys and values may have fewer heads
|
|
106
|
+
than queries if that number divides the query heads. ``implementation`` is
|
|
107
|
+
passed to :func:`jax.nn.dot_product_attention`; ``"xla"`` lets CPU tests
|
|
108
|
+
check the padding and masking.
|
|
109
|
+
"""
|
|
110
|
+
if implementation == "cudnn" and q.dtype not in (jnp.bfloat16, jnp.float16):
|
|
111
|
+
raise ValueError(
|
|
112
|
+
"implementation='cudnn' requires bfloat16 or float16 attention inputs, "
|
|
113
|
+
f"got {q.dtype}. Cast the model or use implementation='xla'."
|
|
114
|
+
)
|
|
115
|
+
*leading, heads, query_len, head_dim = q.shape
|
|
116
|
+
key_len = k.shape[-2]
|
|
117
|
+
padded_query = query_len + -query_len % _CUDNN_SEQUENCE_MULTIPLE
|
|
118
|
+
padded_key = key_len + -key_len % _CUDNN_SEQUENCE_MULTIPLE
|
|
119
|
+
|
|
120
|
+
def batch_first(x: jax.Array, length: int) -> jax.Array:
|
|
121
|
+
x = jnp.swapaxes(x, -3, -2)
|
|
122
|
+
x = x.reshape(-1, *x.shape[-3:])
|
|
123
|
+
return jnp.pad(x, ((0, 0), (0, length - x.shape[1]), (0, 0), (0, 0)))
|
|
124
|
+
|
|
125
|
+
q = batch_first(q, padded_query)
|
|
126
|
+
k, v = batch_first(k, padded_key), batch_first(v, padded_key)
|
|
127
|
+
batch = q.shape[0]
|
|
128
|
+
if allowed is None:
|
|
129
|
+
out = jax.nn.dot_product_attention(
|
|
130
|
+
q,
|
|
131
|
+
k,
|
|
132
|
+
v,
|
|
133
|
+
query_seq_lengths=jnp.full((batch,), query_len, jnp.int32),
|
|
134
|
+
key_value_seq_lengths=jnp.full((batch,), key_len, jnp.int32),
|
|
135
|
+
implementation=implementation,
|
|
136
|
+
)
|
|
137
|
+
else:
|
|
138
|
+
# Materialize the mask for every head: a broadcast head axis fails under
|
|
139
|
+
# vmap (jax-ml/jax#34920). Padding adds masked queries and keys.
|
|
140
|
+
mask = jnp.broadcast_to(allowed, (*leading, heads, query_len, key_len))
|
|
141
|
+
mask = jnp.pad(
|
|
142
|
+
mask.reshape(batch, heads, query_len, key_len),
|
|
143
|
+
((0, 0), (0, 0), (0, padded_query - query_len), (0, padded_key - key_len)),
|
|
144
|
+
)
|
|
145
|
+
out = jax.nn.dot_product_attention(
|
|
146
|
+
q, k, v, mask=mask, implementation=implementation
|
|
147
|
+
)
|
|
148
|
+
# cuDNN returns the mean value for fully masked rows instead of zeros.
|
|
149
|
+
has_key = jnp.swapaxes(jnp.any(mask, axis=-1), 1, 2)
|
|
150
|
+
out = jnp.where(has_key[..., None], out, 0)
|
|
151
|
+
out = out[:, :query_len].reshape(*leading, query_len, heads, head_dim)
|
|
152
|
+
return jnp.swapaxes(out, -3, -2)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def with_attention_implementation(
|
|
156
|
+
model: _Model, implementation: AttentionImplementation
|
|
157
|
+
) -> _Model:
|
|
158
|
+
"""Return ``model`` with every attention module using ``implementation``.
|
|
159
|
+
|
|
160
|
+
``"cudnn"`` runs core and tabular attention through NVIDIA cuDNN's fused
|
|
161
|
+
kernel (:func:`jax.nn.dot_product_attention`), which computes logits in
|
|
162
|
+
float32 without materializing them. It requires a CUDA GPU, bfloat16 or
|
|
163
|
+
float16 inputs, and inactive attention dropout, and it cannot be exported
|
|
164
|
+
with jax2onnx; switch back to ``"xla"`` before exporting. Parameters and
|
|
165
|
+
checkpoint layouts are unchanged. The setting is static, so compiled
|
|
166
|
+
functions retrace after switching.
|
|
167
|
+
"""
|
|
168
|
+
_check_implementation(implementation)
|
|
169
|
+
|
|
170
|
+
def is_attention(node) -> bool:
|
|
171
|
+
return isinstance(node, eqx.Module) and any(
|
|
172
|
+
field.name == "implementation" for field in dataclasses.fields(node)
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
def switch(node):
|
|
176
|
+
if not is_attention(node):
|
|
177
|
+
return node
|
|
178
|
+
# tree_at cannot replace static fields, and copy.copy returns the same
|
|
179
|
+
# module, so rebuild the instance as Equinox's unflattening does.
|
|
180
|
+
switched = object.__new__(type(node))
|
|
181
|
+
switched.__dict__.update(node.__dict__)
|
|
182
|
+
object.__setattr__(switched, "implementation", implementation)
|
|
183
|
+
return switched
|
|
184
|
+
|
|
185
|
+
return jax.tree.map(switch, model, is_leaf=is_attention)
|
|
186
|
+
|
|
187
|
+
|
|
62
188
|
@register_attn()
|
|
63
189
|
class Attention(eqx.Module):
|
|
64
190
|
"""Multi-head self attention over tensors shaped ``(..., seq, dim)``.
|
|
@@ -67,11 +193,15 @@ class Attention(eqx.Module):
|
|
|
67
193
|
batch-aligned with shape ``(..., query, key)`` or directly broadcastable to
|
|
68
194
|
``(..., heads, query, key)``. Fully masked query rows receive zero attention
|
|
69
195
|
probability mass.
|
|
196
|
+
|
|
197
|
+
``implementation="cudnn"`` selects the fused kernel described in
|
|
198
|
+
:func:`with_attention_implementation`.
|
|
70
199
|
"""
|
|
71
200
|
|
|
72
201
|
dim: int = eqx.field(static=True)
|
|
73
202
|
num_heads: int = eqx.field(static=True)
|
|
74
203
|
head_dim: int = eqx.field(static=True)
|
|
204
|
+
implementation: AttentionImplementation = eqx.field(static=True)
|
|
75
205
|
|
|
76
206
|
qkv: eqx.nn.Linear
|
|
77
207
|
proj: eqx.nn.Linear
|
|
@@ -93,12 +223,15 @@ class Attention(eqx.Module):
|
|
|
93
223
|
proj_drop: float = 0.0,
|
|
94
224
|
norm_layer: str | type[eqx.Module] = "layernorm",
|
|
95
225
|
eps: float = 1e-5,
|
|
226
|
+
implementation: AttentionImplementation = "xla",
|
|
96
227
|
**kwargs,
|
|
97
228
|
):
|
|
98
229
|
self.num_heads = num_heads
|
|
99
230
|
self.head_dim = dim // num_heads
|
|
100
231
|
self.dim = dim
|
|
101
232
|
assert self.head_dim * num_heads == dim, "dim must be divisible by num_heads"
|
|
233
|
+
_check_implementation(implementation)
|
|
234
|
+
self.implementation = implementation
|
|
102
235
|
|
|
103
236
|
key_qkv, key_proj = jr.split(key, 2)
|
|
104
237
|
norm_layer = get_norm(norm_layer)
|
|
@@ -139,23 +272,24 @@ class Attention(eqx.Module):
|
|
|
139
272
|
)
|
|
140
273
|
q, k = apply_rotary_qk(q, k, rotary)
|
|
141
274
|
|
|
142
|
-
|
|
143
|
-
jnp.einsum("...hqd,...hkd->...hqk", q, k) / jnp.sqrt(self.head_dim)
|
|
144
|
-
).astype(jnp.float32)
|
|
275
|
+
allowed = None
|
|
145
276
|
if mask is not None:
|
|
146
277
|
allowed = _broadcast_attention_mask(
|
|
147
278
|
mask,
|
|
148
279
|
x_ndim=x.ndim,
|
|
149
|
-
shape=
|
|
280
|
+
shape=(*q.shape[:-1], k.shape[-2]),
|
|
150
281
|
)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
282
|
+
if self.implementation == "cudnn":
|
|
283
|
+
_check_cudnn_dropout(self.attn_drop, inference)
|
|
284
|
+
x = _fused_attention(q, k, v, allowed)
|
|
285
|
+
else:
|
|
286
|
+
attn = jnp.einsum("...hqd,...hkd->...hqk", q, k).astype(
|
|
287
|
+
jnp.float32
|
|
288
|
+
) / jnp.sqrt(self.head_dim)
|
|
289
|
+
attn = jax.nn.softmax(attn, axis=-1, where=allowed).astype(x.dtype)
|
|
290
|
+
attn = self.attn_drop(attn, inference=inference, key=key1)
|
|
291
|
+
x = jnp.einsum("...hqk,...hkd->...hqd", attn, v)
|
|
157
292
|
|
|
158
|
-
x = jnp.einsum("...hqk,...hkd->...hqd", attn, v)
|
|
159
293
|
x = jnp.swapaxes(x, -3, -2).reshape(*x.shape[:-3], x.shape[-2], self.dim)
|
|
160
294
|
x = _apply_module_last_dim(self.proj, x)
|
|
161
295
|
return self.proj_drop(x, inference=inference, key=key2)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .scan import non_causal_linear_attn, segsum, selective_scan, ssd
|
|
2
|
+
from .probability import (
|
|
3
|
+
log_softmax,
|
|
4
|
+
softmax,
|
|
5
|
+
softmax_cross_entropy_with_integer_labels,
|
|
6
|
+
softmax_cross_entropy_with_logit_targets,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"non_causal_linear_attn",
|
|
11
|
+
"segsum",
|
|
12
|
+
"selective_scan",
|
|
13
|
+
"ssd",
|
|
14
|
+
"log_softmax",
|
|
15
|
+
"softmax",
|
|
16
|
+
"softmax_cross_entropy_with_integer_labels",
|
|
17
|
+
"softmax_cross_entropy_with_logit_targets",
|
|
18
|
+
]
|