Julia: Flux.jl: "function gradient does not accept keyword arguments" - julia

I'm trying to use Flux.jl v"0.6.10 (which I freshly installed and which looks like an awesome package) with Julia Version 1.1.0 and copied the following code from the "basic" section of the documation of flux.jl
using Flux.Tracker
f(x) = 3x^2 + 2x + 1;
df(x) = Tracker.gradient(f, x; nest = true)[1];
df(2)
However I got this error message:
ERROR: function gradient does not accept keyword arguments
Stacktrace:
[1] kwfunc(::Any) at ./boot.jl:330
[2] df(::Int64) at ./REPL[3]:1
[3] top-level scope at none:0
What am I doing wrong?

Well I just found that the version that I installed and update is the v"0.6.10 (although I just ran (v1.1) pkg> update Flux). However in the documentation, the code above is df(x) = Tracker.gradient(f, x)[1] for the definition of the gradient (and not df(x) = Tracker.gradient(f, x; nest = true)[1];, which is valid for the version v"0.8.3)

Related

Julia CUDA: UndefVarError: parameters not defined

I have a program for doing Fourier series and I wanted to switch to CuArrays to make it faster. The code is as follows (extract):
#Arrays I want to use
coord = CuArray{ComplexF64,1}(complex.(a[:,1],a[:,2]))
t=CuArray{Float64,1}(-L:(2L/(N-1)):L)
#Array of indexes in the form [0,1,-1,2,-2,...]
n=[((-1)^i)div(i,2) for i in 1:grado]
#Array of functions I need for calculations
base= [x -> exp(π * im * i * x / L) / L for i in n]
base[i](1.) #This line is OK
base[i](-1:.1:1) #This line is OK
base[i].(t) #This line gives error!
base[i].(CuArray{Float64,1}(t)) #This line gives error!
And the error is:
GPU broadcast resulted in non-concrete element type Any.
This probably means that the function you are broadcasting contains an error or type instability.
If I change it like this
base= [(x::Float64) -> (exp(π * im * i * x / L) / L)::ComplexF64 for i in n]
the same lines still give error, but the error now is:
UndefVarError: parameters not defined
Any idea how I could fix this?
Thank you in advance!
Package information:
(#v1.6) pkg> st CUDA
Status `C:\Users\marce\.julia\environments\v1.6\Project.toml`
[052768ef] CUDA v2.6.2
P.S.: This other function has the same problem:
function integra(inizio, fine, arr)
N=size(arr,1)
h=(fine-inizio)/N
integrale=sum(arr)
integrale -= (first(arr)+last(arr))/2
integrale *= h
end
L=2
integra(-L,L,coord)
The first and easier problem is that you should take care to declare global variables to be constant so that the compiler can assume a constant type: const L = 2. A mere L = 2 allows you to do something like L = SomeOtherType(), and if that type can be Anything, so must the return type of your functions. On the CPU that's only a performance hit, but it's a no-no for the GPU. If you actually want L to vary in value, pass it in as an argument so the compiler can still infer types within a function.
Your ::ComplexF64 assertion did actually force a concrete return type, though the middle of the function is still type unstable (check with #code_warntype). The second problem you ran into after that patch was probably caused by this recently patched conflict between ExprTools.jl and LLVM.jl. Seems like you just need to update the packages or maybe reinstall them.

How to mark functions as `#deprecate`d?

(Question refers to Julia version v1.5)
I'm trying to understand how the #deprecate macro works in Julia. The documentation is unfortunately not clear to me:
#deprecate old new [ex=true]
Deprecate method old and specify the replacement call new. Prevent
#deprecate from exporting old by setting ex to false. #deprecate
defines a new method with the same signature as old.
Warning:
As of Julia 1.5, functions defined by #deprecate do not print warning when julia is run without the --depwarn=yes flag set, as the default value of --depwarn option is no. The warnings are printed from tests run by Pkg.test().
Examples
julia> #deprecate old(x) new(x)
old (generic function with 1 method)
julia> #deprecate old(x) new(x)
false old (generic function with 1 method)
So what do I do?
function old(x::Int)
print("Old behavior")
end
function new(x::Int)
print("New behavior")
end
# Adding true/false argument doesn't change my observations.
#deprecate old(x) new(x) # false
old(3)
# Prints "Old behaviour". No warning.
# Also: The deprecation is not mentioned in the help (julia>? old)
The aim of this #deprecate macro seems to be replacing functions? I find that counterintuitive. How can mark a function as deprecated (i.e. users should receive a warning and a hint what to use as a replacement, also it should be in the documentation)?
edit: I noticed my error. The signatures (in my case the ::Int) have to be identical for this to work. However, how do I get a warning?
Imagine you have this method as part of the public API of your library in version 1:
# v1.0.0
mult3(x::Int) = 3x
In version 2, you'd like to stop supporting mult3 (which is a breaking change). But the same feature will still be available using a more general method:
# v2.0.0
mult(x, y) = x * y
Users of version 1 are used to using mult3, which means that their code will break when they will update to v2. Therefore, you might want to release an intermediate version in the v1.x family, where mult3 exists but is deprecated and implemented in terms of mult:
# v1.1 - transition
# This is the new API for v2
mult(x, y) = x*y
# The old API is still supported, but deprecated and implemented using the old one
#deprecate mult3(x::Int) mult(3, x)
# The above is more or less equivalent to defining
# function mult3(x::Int)
# # print an error message is `--depwarn` has been set
# return mult(3, x)
# end
The v1 API is not broken in late v1.x versions, but users calling deprecated methods will see the following kind of messages to help them transition to the newer v2 API:
julia> mult3(14)
┌ Warning: `mult3(x::Int)` is deprecated, use `mult(3, x)` instead.
│ caller = top-level scope at REPL[3]:1
└ # Core REPL[3]:1
42
(but starting with Julia 1.5, the warning will only be shown if --depwarn=yes has been provided in Julia's command line or if it appears in a test suite run by Pkg.test())
Alternatively, and as mentioned in comments, you may want to leave the old implementation around, simply warning users when they call it. To this end, you can use Base.depwarn directly:
# v1.1 - transition
# This is the new API for v2
mult(x, y) = x*y
# The old API is still supported, but deprecated
# It is implemented by itself:
function mult3(x)
Base.depwarn("`mult3(x)` is deprecated, use `mult(3,x)` instead.", :mult3)
return 3x
end
When --depwarn=yes has been provided in Julia's command line, this produces the same kind of warning as #deprecate:
julia> mult3(14)
┌ Warning: `mult3(x)` is deprecated, use `mult(3,x)` instead.
│ caller = top-level scope at REPL[4]:1
└ # Core REPL[4]:1
42
Starting with Julia 1.6, depwarn will accept a keyword argument to force warning emission even when users haven't asked for them with --depwarn=yes:
julia> Base.depwarn("Foo is deprecated", :foo, force=true)
┌ Warning: Foo is deprecated
│ caller = ip:0x0
└ # Core :-1

Object not defined in Loop

I create an object and then try to use it in a loop
a = 0
for i in 1:2
a += 1
end
However, this results in the following error:
UndefVarError: a not defined
Have I forgotten how loops work or what is going wrong?
The point is that your a is a global variable and in Julia versions between 1.0 and 1.4.2 the local scoping for variables within loops was introduced. More precisely if you do not explicitly say you want to mutate a global variable (global a += 1) a new variable within a local scope is introduced.
The best thing to do is to upgrade to Julia 1.5. Julia 1.5 has introduced back soft scoping in the REPL.
If you need to stick with the current Julia version you could use global keyword or place your code in a function or use Jupyter notebook instead (that has soft scoping) or surround your code around let...end block such as:
let
a = 0
for i in 1:2
a += 1
end
a
end

UndefVarError: Normal not defined

At the moment of running the model the "Normal" says that it is not defined. However, the idea is that it is a function that indicates random numbers of normal distribution with specific mean and variance.
The original code was made in Julia V0.5.2 but Julia 1.0.3 mentions that "Normal" does not exist.
n=5000;
t=15000;
lambda=0.8;
sigmae1=0.05;
sigmae2=0.1;
sigmaz= 0.013;
n_lambda= trunc(Int, lambda*n)
eshocks1=rand(Normal(0.0,sigmae1), n_lambda, t);
eshocks2=rand(Normal(0.0,sigmae2), n - n_lambda, t);
zshocks =rand(Normal(0.0, sigmaz),1, t);
UndefVarError: Normal not defined
Stacktrace:
[1] top-level scope at In[5]:21
add Distributions, then put
using Distributions
at the top of the code, for use with newer Julia versions. The later versions of Julia tend to have non-Base functions as optional modules that need to be added to the installation.

octave map over multiple arguments

I want to map a function that takes two arguments over two vectors of the same length, taking an argument from each of these vectors. I can do it with one argument:
map(#sqrt, 1:10)
ans = ....
help map gives the following example:
map(#min, A, B)
ans = ...
where A and B are 2 by 2 matrices, and the result matrix is the element-wise minimum. But when I try this example, I get the following error:
A = rand(2,2);
B = rand(2,2);
map(#min, A, B)
error: invalid assignment to cs-list outside multiple assignment.
error: assignment to cell array failed
error: assignment failed, or no method for `<unknown type> = scalar'
error: called from:
error: C:\Octave\3.2.4_gcc-4.4.0\share\octave\packages\miscellaneous-1.0.9\map.m at line 108, column 21
What am I doing wrong? My system is Win7, 64 bit, and as you can see, my octave version is 3.2.4.
Thanks to this question, I was able to find out that map is being deprecated, and the correct function to use is arrayfun, which works out of the box, both with octave version 3.2.4, which is what I got when downloading a normal windows installer, and with octave version 3.6.2, which I got using cygwin. In version 3.6.2 it even seems that map requires the miscellaneous package, which arrayfun does not.
So I will never know what I did wrong, or if there is a bug (unlikely, given that the function is pretty standard), but my problem was solved by just substituting arrayfun:
A = rand(2,2);
B = rand(2,2);
arrayfun(#min, A, B)
ans = .... % correct answer

Resources