Clamp tensor to min/max in differentiable way. Args: tensor: The tensor to clamp. min: Pair of threshold to start clamping and value to clamp to. The first value should be larger than the second. max: Pair of threshold to start clamping and value to clamp to.
(
tensor: torch.Tensor,
min: SoftClampRange | None = None,
max: SoftClampRange | None = None,
)
| 73 | |
| 74 | |
| 75 | def softclamp( |
| 76 | tensor: torch.Tensor, |
| 77 | min: SoftClampRange | None = None, |
| 78 | max: SoftClampRange | None = None, |
| 79 | ) -> torch.Tensor: |
| 80 | """Clamp tensor to min/max in differentiable way. |
| 81 | |
| 82 | Args: |
| 83 | tensor: The tensor to clamp. |
| 84 | min: Pair of threshold to start clamping and value to clamp to. |
| 85 | The first value should be larger than the second. |
| 86 | max: Pair of threshold to start clamping and value to clamp to. |
| 87 | The first value should be smaller than the second. |
| 88 | |
| 89 | Returns: |
| 90 | The clamped tensor. |
| 91 | """ |
| 92 | |
| 93 | def normalize(clamp_range: SoftClampRange) -> torch.Tensor: |
| 94 | value0, value1 = clamp_range |
| 95 | return value0 + (value1 - value0) * torch.tanh((tensor - value0) / (value1 - value0)) |
| 96 | |
| 97 | tensor_clamped = tensor |
| 98 | if min is not None: |
| 99 | tensor_clamped = torch.maximum(tensor_clamped, normalize(min)) |
| 100 | if max is not None: |
| 101 | tensor_clamped = torch.minimum(tensor_clamped, normalize(max)) |
| 102 | |
| 103 | return tensor_clamped |
| 104 | |
| 105 | |
| 106 | class ClampWithPushback(autograd.Function): |
nothing calls this directly
no test coverage detected