Skip to content

Commit fa53f71

Browse files
authored
fix: improve numerical stability by conditionally using float32 in Anima (kohya-ss#2302)
* fix: improve numerical stability by conditionally using float32 in block computations * doc: update README for improvement stability for fp16 training on Anima in version 0.10.3
1 parent 1dae34b commit fa53f71

3 files changed

Lines changed: 18 additions & 4 deletions

File tree

README-ja.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ Stable Diffusion等の画像生成モデルの学習、モデルによる画像
5050

5151
### 更新履歴
5252

53+
- **Version 0.10.3 (2026-04-02):**
54+
- Animaでfp16で学習する際の安定性をさらに改善しました。[PR #2302](https://github.com/kohya-ss/sd-scripts/pull/2302) 問題をご報告いただいた方々に深く感謝します。
55+
5356
- **Version 0.10.2 (2026-03-30):**
5457
- SD/SDXLのLECO学習に対応しました。[PR #2285](https://github.com/kohya-ss/sd-scripts/pull/2285) および [PR #2294](https://github.com/kohya-ss/sd-scripts/pull/2294) umisetokikaze氏に深く感謝します。
5558
- 詳細は[ドキュメント](./docs/train_leco.md)をご覧ください。

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ If you find this project helpful, please consider supporting its development via
4747

4848
### Change History
4949

50+
- **Version 0.10.3 (2026-04-02):**
51+
- Stability when training with fp16 on Anima has been further improved. See [PR #2302](https://github.com/kohya-ss/sd-scripts/pull/2302) for details. We deeply appreciate those who reported the issue.
52+
5053
- **Version 0.10.2 (2026-03-30):**
5154
- LECO training for SD/SDXL is now supported. Many thanks to umisetokikaze for [PR #2285](https://github.com/kohya-ss/sd-scripts/pull/2285) and [PR #2294](https://github.com/kohya-ss/sd-scripts/pull/2294).
5255
- Please refer to the [documentation](./docs/train_leco.md) for details.

library/anima_models.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -738,9 +738,9 @@ def forward(
738738
x_B_T_H_W_D: torch.Tensor,
739739
emb_B_T_D: torch.Tensor,
740740
adaln_lora_B_T_3D: Optional[torch.Tensor] = None,
741+
use_fp32: bool = False,
741742
):
742743
# Compute AdaLN modulation parameters (in float32 when fp16 to avoid overflow in Linear layers)
743-
use_fp32 = x_B_T_H_W_D.dtype == torch.float16
744744
with torch.autocast(device_type=x_B_T_H_W_D.device.type, dtype=torch.float32, enabled=use_fp32):
745745
if self.use_adaln_lora:
746746
assert adaln_lora_B_T_3D is not None
@@ -863,11 +863,11 @@ def _forward(
863863
emb_B_T_D: torch.Tensor,
864864
crossattn_emb: torch.Tensor,
865865
attn_params: attention.AttentionParams,
866+
use_fp32: bool = False,
866867
rope_emb_L_1_1_D: Optional[torch.Tensor] = None,
867868
adaln_lora_B_T_3D: Optional[torch.Tensor] = None,
868869
extra_per_block_pos_emb: Optional[torch.Tensor] = None,
869870
) -> torch.Tensor:
870-
use_fp32 = x_B_T_H_W_D.dtype == torch.float16
871871
if use_fp32:
872872
# Cast to float32 for better numerical stability in residual connections. Each module will cast back to float16 by enclosing autocast context.
873873
x_B_T_H_W_D = x_B_T_H_W_D.float()
@@ -959,6 +959,7 @@ def forward(
959959
emb_B_T_D: torch.Tensor,
960960
crossattn_emb: torch.Tensor,
961961
attn_params: attention.AttentionParams,
962+
use_fp32: bool = False,
962963
rope_emb_L_1_1_D: Optional[torch.Tensor] = None,
963964
adaln_lora_B_T_3D: Optional[torch.Tensor] = None,
964965
extra_per_block_pos_emb: Optional[torch.Tensor] = None,
@@ -972,6 +973,7 @@ def forward(
972973
emb_B_T_D,
973974
crossattn_emb,
974975
attn_params,
976+
use_fp32,
975977
rope_emb_L_1_1_D,
976978
adaln_lora_B_T_3D,
977979
extra_per_block_pos_emb,
@@ -994,6 +996,7 @@ def custom_forward(*inputs):
994996
emb_B_T_D,
995997
crossattn_emb,
996998
attn_params,
999+
use_fp32,
9971000
rope_emb_L_1_1_D,
9981001
adaln_lora_B_T_3D,
9991002
extra_per_block_pos_emb,
@@ -1007,6 +1010,7 @@ def custom_forward(*inputs):
10071010
emb_B_T_D,
10081011
crossattn_emb,
10091012
attn_params,
1013+
use_fp32,
10101014
rope_emb_L_1_1_D,
10111015
adaln_lora_B_T_3D,
10121016
extra_per_block_pos_emb,
@@ -1018,6 +1022,7 @@ def custom_forward(*inputs):
10181022
emb_B_T_D,
10191023
crossattn_emb,
10201024
attn_params,
1025+
use_fp32,
10211026
rope_emb_L_1_1_D,
10221027
adaln_lora_B_T_3D,
10231028
extra_per_block_pos_emb,
@@ -1338,16 +1343,19 @@ def forward_mini_train_dit(
13381343

13391344
attn_params = attention.AttentionParams.create_attention_params(self.attn_mode, self.split_attn)
13401345

1346+
# Determine whether to use float32 for block computations based on input dtype (use float32 for better stability when input is float16)
1347+
use_fp32 = x_B_T_H_W_D.dtype == torch.float16
1348+
13411349
for block_idx, block in enumerate(self.blocks):
13421350
if self.blocks_to_swap:
13431351
self.offloader.wait_for_block(block_idx)
13441352

1345-
x_B_T_H_W_D = block(x_B_T_H_W_D, t_embedding_B_T_D, crossattn_emb, attn_params, **block_kwargs)
1353+
x_B_T_H_W_D = block(x_B_T_H_W_D, t_embedding_B_T_D, crossattn_emb, attn_params, use_fp32, **block_kwargs)
13461354

13471355
if self.blocks_to_swap:
13481356
self.offloader.submit_move_blocks(self.blocks, block_idx)
13491357

1350-
x_B_T_H_W_O = self.final_layer(x_B_T_H_W_D, t_embedding_B_T_D, adaln_lora_B_T_3D=adaln_lora_B_T_3D)
1358+
x_B_T_H_W_O = self.final_layer(x_B_T_H_W_D, t_embedding_B_T_D, adaln_lora_B_T_3D=adaln_lora_B_T_3D, use_fp32=use_fp32)
13511359
x_B_C_Tt_Hp_Wp = self.unpatchify(x_B_T_H_W_O)
13521360
return x_B_C_Tt_Hp_Wp
13531361

0 commit comments

Comments
 (0)