You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* add known bugs to limitations
* Accessors
* Apply suggestions from code review
Co-authored-by: Brian Chen <[email protected]>
Co-authored-by: Brian Chen <[email protected]>
Copy file name to clipboardExpand all lines: docs/src/limitations.md
+53-7Lines changed: 53 additions & 7 deletions
Original file line number
Diff line number
Diff line change
@@ -1,11 +1,14 @@
1
-
# Limitations
1
+
# Design Limitations
2
2
3
-
Zygote aims to support differentiating any code you might write in Julia, but it still has a few limitations. Notably, you might encounter errors when trying to differentiate:
4
-
- array mutation
5
-
-`try`/`catch` statements
6
-
- "foreign call" expressions
3
+
Zygote aims to support differentiating any Julia code, but it still has a few limitations.
4
+
Notably, you might encounter errors when trying to differentiate:
5
+
- array mutation,
6
+
-`try`/`catch` statements,
7
+
- "foreign call" expressions.
7
8
8
-
In this section, we will introduce examples where each of these errors occurs as well as possible work-arounds.
9
+
This section gives examples where each of these errors occurs, as well as possible work-arounds.
10
+
11
+
Below, it also describes some known bugs in expressions Zygote ought to be able to handle.
9
12
10
13
## Array mutation
11
14
@@ -123,7 +126,7 @@ Stacktrace:
123
126
```
124
127
`jclock` will multiply the result of our C function by an argument. When we try to differentiate with respect to this argument, we get an `foreigncall` error.
125
128
126
-
##Solutions
129
+
# Solutions
127
130
128
131
For all of the errors above, the suggested solutions are similar. You have the following possible work arounds available (in order of preference):
129
132
1. avoid the error-inducing operation (e.g. do not use mutating functions)
Lastly, if the code causing problems can be fixed, but it is package code instead of your code, then you should open an issue. For functions built into Julia or its standard libraries, you can open an issue with Zygote.jl or ChainRules.jl. For functions in other packages, you can open an issue with the corresponding package issue tracker.
154
+
155
+
156
+
# Known Issues
157
+
158
+
Zygote's issue tracker has the current list of open [bugs](https://github.com/FluxML/Zygote.jl/issues?q=is%3Aissue+is%3Aopen+label%3Abug). There are some general principles about things you may wish to avoid if you can:
159
+
160
+
## `mutable struct`s
161
+
162
+
Zygote has limited support for mutation, and in particular will allow you to change a field in some `mutable struct X; a; b; end` by setting `x.a = val`.
163
+
164
+
However, this has [many limitations](https://github.com/FluxML/Zygote.jl/issues?q=is%3Aissue+is%3Aopen+mutable+struct) and should be avoided if possible.
165
+
166
+
The simple solution is to use only immutable `struct`s.
167
+
168
+
If you need to modify them, using something like `@set` from [Accessors.jl](https://github.com/JuliaObjects/Accessors.jl) should work well. This returns a new object, but does not have side-effects on other copies of it.
169
+
170
+
## Re-using variable names
171
+
172
+
It is common to accumulate values in a loop by re-binding the same variable name to a new value
173
+
many times, for example:
174
+
```
175
+
function mysum(x::Real, n::Int)
176
+
tot = 0.0
177
+
for i in 1:n
178
+
tot += x^n # binds symbol `tot` to new value
179
+
end
180
+
return tot
181
+
end
182
+
```
183
+
However, sometimes such re-binding confuses Zygote, especially if the type of the value changes. Especially if the variable is "boxed", as will happen if you re-bind from within a closure (such as the function created by a `do` block).
184
+
185
+
## Second derivatives
186
+
187
+
In principle Zygote supports taking derivatives of derivatives. There are, however, a few problems:
188
+
* Quite a few of its rules are not written in a way that is itself differentiable. For instance they may work by making an array then writing into it, which is mutation of the sort forbidden above.
189
+
* The complexity of the code grows rapidly, as Zygote differentiates its own un-optimised output.
190
+
* Reverse mode over reverse mode is seldom the best algorithm.
191
+
192
+
The issue tracker has a label for [second order](https://github.com/FluxML/Zygote.jl/issues?q=is%3Aissue+is%3Aopen+label%3A%22second+order%22), which will outline where the bodies are buried.
193
+
194
+
Often using a different AD system over Zygote is a better solution.
195
+
This is what [`hessian`](@ref) does, using ForwardDiff over Zygote, but other combinations are possible.
196
+
(Note that rules defined here mean that Zygote over ForwardDiff is translated to ForwardDiff over ForwardDiff.)
0 commit comments