Repository navigation
Avoid NaN-propagation in scalar rules #551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ce76725
d83965c
fcc151f
09c25fb
6eb7457
721877f
47c4009
b54eba3
dc51058
4431401
9983b71
ddf1d7c
8852aa6
7f02ff7
06f8b67
e66a097
b7bdee1
3cdd108
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -292,12 +292,14 @@ function propagation_expr(Δs, ∂s, _conj=false, proj=identity) | |||||||||||
| end | ||||||||||||
| end | ||||||||||||
|
|
||||||||||||
| # Apply `muladd` iteratively. | ||||||||||||
| # Apply `strong_muladd` iteratively. | ||||||||||||
| # Explicit multiplication is only performed for the first pair of partial and gradient. | ||||||||||||
| (∂s_1, Δs_1), _∂s_Δs_tail = Iterators.peel(zip(_∂s, Δs)) | ||||||||||||
| init_expr = :($∂s_1 * $Δs_1) | ||||||||||||
| # zero gradients are treated as hard zeros. This avoids propagation of NaNs when | ||||||||||||
| # partials are non-finite | ||||||||||||
| init_expr = :(strong_mul($∂s_1, $Δs_1)) | ||||||||||||
| summed_∂_mul_Δs = foldl(_∂s_Δs_tail; init=init_expr) do ex, (∂s_i, Δs_i) | ||||||||||||
| :(muladd($∂s_i, $Δs_i, $ex)) | ||||||||||||
| :(strong_muladd($∂s_i, $Δs_i, $ex)) | ||||||||||||
| end | ||||||||||||
| return :($proj($summed_∂_mul_Δs)) | ||||||||||||
| end | ||||||||||||
|
|
@@ -615,3 +617,26 @@ function _constrain_and_name(arg::Expr, _) | |||||||||||
| return error("malformed arguments: $arg") | ||||||||||||
| end | ||||||||||||
| _constrain_and_name(name::Symbol, constraint) = Expr(:(::), name, constraint) # add type | ||||||||||||
|
|
||||||||||||
| """ | ||||||||||||
| strong_mul(x, y) | ||||||||||||
|
|
||||||||||||
| Multiply `x` and `y`. If `iszero(y)`, treat `y` as a hard zero even for non-finite `x`. | ||||||||||||
| """ | ||||||||||||
| strong_mul(x, y) = ifelse(iszero(y), zero(x), x) * y | ||||||||||||
|
|
||||||||||||
| """ | ||||||||||||
| strong_muladd(x, y, z) | ||||||||||||
|
|
||||||||||||
| Multiply `x` and `y` and add to `z`. If `iszero(y)`, treat `y` as a hard zero even for | ||||||||||||
| non-finite `x`. | ||||||||||||
| """ | ||||||||||||
| strong_muladd(x, y, z) = muladd(ifelse(iszero(y), zero(x), x), y, z) | ||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, instead of zeroing
Suggested change
I don't think it would matter, I'm mainly curious why it's not using the arguably more direct translation of the docstring. |
||||||||||||
|
|
||||||||||||
| # slightly faster for BigFloats | ||||||||||||
| strong_mul(x::BigFloat, y::BigFloat) = (iszero(y) ? zero(x) : x) * y | ||||||||||||
| strong_muladd(x::BigFloat, y::BigFloat, z) = muladd((iszero(y) ? zero(x) : x), y, z) | ||||||||||||
|
|
||||||||||||
| # avoid raising errors for NotImplemented | ||||||||||||
| strong_mul(x::NotImplemented, y) = (iszero(y) ? zero(x) : x) * y | ||||||||||||
| strong_muladd(x::NotImplemented, y, z) = muladd((iszero(y) ? zero(x) : x), y, z) | ||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -87,3 +87,6 @@ arguments. | |
| ``` | ||
| """ | ||
| struct NoTangent <: AbstractZero end | ||
|
|
||
| Base.zero(::NoTangent) = NoTangent() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These seem reasonable, but can you remind me: why are these changes in the PR here? I'd expect to mainly see definitions and uses of |
||
| Base.zero(::Type{NoTangent}) = NoTangent() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the docstring, I'd expect something like
ie adjusting the product i stead of
xwhen treatingyas a strong zero.Any particular (performance?) reason for the current code?