| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| """Structural parity tests for the DoRA-factored reference kernel. |
| |
| Asserts that the pure-PyTorch reference (``dora_factored_forward``) is numerically equivalent to a |
| naive dense DoRA effective-weight baseline written inline below. Mirrors the discipline of PEFT's |
| merged ``tests/test_dora_factored_norm.py`` (huggingface/peft#3382): deterministic seed, small |
| shapes, dense-vs-factored comparison. Runs on CPU with no GPU / no PEFT / no Triton. |
| """ |
|
|
| import pytest |
| import torch |
| from dora_factored import dora_factored_forward |
|
|
|
|
| def _dense_dora_weight(base_weight, lora_a, lora_b, scaling, dora_scale): |
| """Naive dense DoRA effective weight: materialize ``W + s·BA`` then column-normalize. |
| |
| This is the ~10-line baseline the factored reference must match. It mirrors |
| ``DoraLinearLayer.get_weight_norm`` (the dense path) composed with the DoRA magnitude rescale. |
| """ |
| weight = base_weight + scaling * (lora_b @ lora_a) |
| col_norm = torch.linalg.norm(weight, dim=1) |
| scale = (dora_scale / col_norm).unsqueeze(-1) |
| return scale * weight |
|
|
|
|
| @pytest.mark.parametrize("scaling", [1.0, 0.5, 2.0]) |
| @pytest.mark.parametrize( |
| "dtype, atol, rtol", |
| [ |
| |
| (torch.float32, 1e-5, 1e-5), |
| |
| |
| |
| (torch.bfloat16, 5e-2, 5e-2), |
| ], |
| ) |
| def test_reference_matches_dense_dora(scaling, dtype, atol, rtol): |
| torch.manual_seed(0) |
| d_out, d_in, r = 32, 48, 4 |
| base_weight = torch.randn(d_out, d_in, dtype=dtype) |
| lora_a = torch.randn(r, d_in, dtype=dtype) |
| lora_b = torch.randn(d_out, r, dtype=dtype) |
| |
| dora_scale = torch.randn(d_out, dtype=dtype).abs() + 0.5 |
|
|
| dense = _dense_dora_weight(base_weight, lora_a, lora_b, scaling, dora_scale) |
| factored = dora_factored_forward(base_weight, lora_a, lora_b, scaling, dora_scale) |
|
|
| assert factored.shape == dense.shape == (d_out, d_in) |
| torch.testing.assert_close(factored, dense, atol=atol, rtol=rtol) |
|
|
|
|
| def test_factored_norm_matches_dense_norm(): |
| |
| |
| |
| |
| from dora_factored.reference import _factored_weight_norm |
|
|
| torch.manual_seed(1) |
| d_out, d_in, r = 16, 24, 3 |
| base_weight = torch.randn(d_out, d_in) |
| lora_a = torch.randn(r, d_in) |
| lora_b = torch.randn(d_out, r) |
| scaling = 0.75 |
|
|
| dense_norm = torch.linalg.norm(base_weight + scaling * (lora_b @ lora_a), dim=1) |
| factored_norm = _factored_weight_norm(base_weight, lora_a, lora_b, scaling) |
|
|
| assert factored_norm.shape == (d_out,) |
| torch.testing.assert_close(factored_norm, dense_norm, atol=1e-5, rtol=1e-5) |
|
|
|
|
| def test_reference_shape_and_finite(): |
| torch.manual_seed(2) |
| base_weight = torch.randn(16, 24) |
| lora_a = torch.randn(3, 24) |
| lora_b = torch.randn(16, 3) |
| out = dora_factored_forward(base_weight, lora_a, lora_b, scaling=0.75, dora_scale=torch.ones(16)) |
| assert out.shape == (16, 24) |
| assert torch.isfinite(out).all() |
|
|
|
|
| def test_scalar_dora_scale_broadcasts(): |
| |
| |
| torch.manual_seed(3) |
| base_weight = torch.randn(8, 12) |
| lora_a = torch.randn(2, 12) |
| lora_b = torch.randn(8, 2) |
|
|
| per_column = dora_factored_forward(base_weight, lora_a, lora_b, 1.0, torch.full((8,), 1.5)) |
| scalar = dora_factored_forward(base_weight, lora_a, lora_b, 1.0, torch.tensor(1.5)) |
| torch.testing.assert_close(scalar, per_column, atol=1e-5, rtol=1e-5) |
|
|