I want to get the absolute value of the following array:
x = [1.1 -22.3 3.01, -1]
i.e.: I want an output of the type: x2 = [1.1 22.3 3.01 1]
However when I type:
abs(x)
I get an error:
ERROR: MethodError: no method matching abs(::Array{Float64,2})
Closest candidates are:
abs(::Pkg.Resolve.MaxSum.FieldValues.FieldValue) at /Users/vagrant/worker/juliapro-release-osx1011-0_6/build/tmp_julia/Julia-1.0.app/Contents/Resources/julia/share/julia/stdlib/v1.0/Pkg/src/resolve/FieldValues.jl:67
abs(::Pkg.Resolve.VersionWeights.VersionWeight) at /Users/vagrant/worker/juliapro-release-osx1011-0_6/build/tmp_julia/Julia-1.0.app/Contents/Resources/julia/share/julia/stdlib/v1.0/Pkg/src/resolve/VersionWeights.jl:40
abs(::Missing) at missing.jl:79
...
Stacktrace:
[1] top-level scope at none:0
Julia does not automatically apply scalar functions, like abs, to elements of an array. You should instead tell Julia this is what you want, and broadcast the scalar function abs over your array, see https://docs.julialang.org/en/v1/manual/arrays/#Broadcasting-1. This can be done as
julia> x = [1.1, -22.3, 3.01, -1];
julia> broadcast(abs, x)
4-element Array{Float64,1}:
1.1
22.3
3.01
1.0
or you can use "dot-notation", which is more ideomatic:
julia> abs.(x)
4-element Array{Float64,1}:
1.1
22.3
3.01
1.0
Related
In julia, we can use function map to round, for instance,
map(round, [1.00211111, 3.444444])
Then, the output is
2-element Vector{Float64}:
1.0
3.0
I want to save 3 digits. So I try this:
map(round(digits=3), [1.00211111, 3.444444])
But it generated errors. How can I do if I want to save 3 digits?
For this scenario just use broadcasting:
julia> round.([1.00211111, 3.444444], digits=3)
2-element Vector{Float64}:
1.002
3.444
However, if you want to use map, you can provide a lambda as an argument:
julia> map(x -> round(x, digits=3), [1.00211111, 3.444444])
2-element Vector{Float64}:
1.002
3.444
In PyTorch, you commonly have to zero our the gradients before doing back propagation. Is this the case in Flux? If so, what is the programatic way of doing this?
tl;dr
No, there is no need.
explanation
Flux used to use Tracker, a differentiation system in which each tracked array may hold a gradient. I think this is a similar design to pytorch. Back-propagating twice can lead to the problem which zeroing is intended to avoid (although the defaults try to protect you):
julia> using Tracker
julia> x_tr = Tracker.param([1 2 3])
Tracked 1×3 Matrix{Float64}:
1.0 2.0 3.0
julia> y_tr = sum(abs2, x_tr)
14.0 (tracked)
julia> Tracker.back!(y_tr, 1; once=false)
julia> x_tr.grad
1×3 Matrix{Float64}:
2.0 4.0 6.0
julia> Tracker.back!(y_tr, 1; once=false) # by default (i.e. with once=true) this would be an error
julia> x_tr.grad
1×3 Matrix{Float64}:
4.0 8.0 12.0
Now it uses Zygote, which does not use tracked array types. Instead, the evaluation to be traced must happen with the call to Zygote.gradient, it can then see and manipulate the source code to write new code for the gradient. Repeated calls to this generate the same gradients each time; there is no stored state to need cleaning up.
julia> using Zygote
julia> x = [1 2 3] # an ordinary Array
1×3 Matrix{Int64}:
1 2 3
julia> Zygote.gradient(x -> sum(abs2, x), x)
([2 4 6],)
julia> Zygote.gradient(x -> sum(abs2, x), x)
([2 4 6],)
julia> y, bk = Zygote.pullback(x -> sum(abs2, x), x);
julia> bk(1.0)
([2.0 4.0 6.0],)
julia> bk(1.0)
([2.0 4.0 6.0],)
Tracker can also be used this way, rather than handling param and back! yourself:
julia> Tracker.gradient(x -> sum(abs2, x), [1, 2, 3])
([2.0, 4.0, 6.0] (tracked),)
I create a new struct called HousingData, and also define function such as iterate and length. However, when I use the function collect for my HousingData object, I run into the following error.
TypeError: in typeassert, expected Integer, got a value of type Float64
import Base: length, size, iterate
struct HousingData
x
y
batchsize::Int
shuffle::Bool
num_instances::Int
function HousingData(
x, y; batchsize::Int=100, shuffle::Bool=false, dtype::Type=Array{Float64})
new(convert(dtype,x),convert(dtype,y),batchsize,shuffle,size(y)[end])
end
end
function length(d::HousingData)
return ceil(d.num_instances/d.batchsize)
end
function iterate(d::HousingData, state=ifelse(
d.shuffle, randperm(d.num_instances), collect(1:d.num_instances)))
if(length(state)==0)
return nothing
end
return ((d.x[:,state[1]],d.y[:,state[1]]),state[2:end])
end
x1 = randn(5, 100); y1 = rand(1, 100);
obj = HousingData(x1,y1; batchsize=20)
collect(obj)
There are multiple problems in your code. The first one is related to length not returning an integer, but rather a float. This is explained by the behavior of ceil:
julia> ceil(3.8)
4.0 # Notice: 4.0 (Float64) and not 4 (Int)
You can easily fix this:
function length(d::HousingData)
return Int(ceil(d.num_instances/d.batchsize))
end
Another problem lies in the logic of your iteration function, which is not consistent with the advertised length. To take a smaller example than yours:
julia> x1 = [i+j/10 for i in 1:2, j in 1:6]
2×6 Array{Float64,2}:
1.1 1.2 1.3 1.4 1.5 1.6
2.1 2.2 2.3 2.4 2.5 2.6
# As an aside, unless you really want to work with 1xN matrices
# it is more idiomatic in Julia to use 1D Vectors in such situations
julia> y1 = [Float64(j) for i in 1:1, j in 1:6]
1×6 Array{Float64,2}:
1.0 2.0 3.0 4.0 5.0 6.0
julia> obj = HousingData(x1,y1; batchsize=3)
HousingData([1.1 1.2 … 1.5 1.6; 2.1 2.2 … 2.5 2.6], [1.0 2.0 … 5.0 6.0], 3, false, 6)
julia> length(obj)
2
julia> for (i, e) in enumerate(obj)
println("$i -> $e")
end
1 -> ([1.1, 2.1], [1.0])
2 -> ([1.2, 2.2], [2.0])
3 -> ([1.3, 2.3], [3.0])
4 -> ([1.4, 2.4], [4.0])
5 -> ([1.5, 2.5], [5.0])
6 -> ([1.6, 2.6], [6.0])
The iterator produces 6 elements, whereas the length of this object is only 2. This explains why collect errors out:
julia> collect(obj)
ERROR: ArgumentError: destination has fewer elements than required
Knowing your code, you're probably the best person to fix its logic.
I am confused about using linspace in Julia 0.7. Here is the what I entered in the REPL and the result:
julia> a = linspace(0.1,1.1,6)
┌ Warning: `linspace(start, stop, length::Integer)` is deprecated, use `range(start, stop=stop, length=length)` instead.
│ caller = top-level scope
└ # Core :0
0.1:0.2:1.1
My question is about the deprecated warning and the suggested use of range. The range statement doesn't do the same thing as the linspace command.
If you enter the a = linspace(0.1,1.1,6) and collect(a), you get the following:
julia> collect(a)
6-element Array{Float64,1}:
0.1
0.3
0.5
0.7
0.9
1.1
If you enter b = range(0.1,1.1,6) and collect(b), you get:
julia> collect(b)
6-element Array{Float64,1}:
0.1
1.2
2.3
3.4
4.5
5.6
This is obviously not the same.
Why is linspace deprecated (perhaps a different question) and a non-equivalent range command suggested?
My actual question is: Is it safe to keep using linspace for the desired results it provides, and, if not, what should I be using instead?
You should use LinRange, as documented here.
A range with len linearly spaced elements between its start and stop. The size of the spacing is controlled by len, which must be an Int.
julia> LinRange(1.5, 5.5, 9)
9-element LinRange{Float64}:
1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5
Edit 2021: As of version 1.7 you can use the range function for this:
jl> range(1.5, 5.5, 9)
1.5:0.5:5.5
For version 1.6 you have to write: range(1.5, 5.5, length=9).
Following the deprecations, it is now:
julia> range(0.1, stop = 1.1, length = 6) |> collect
6-element Array{Float64,1}:
0.1
0.3
0.5
0.7
0.9
1.1
In your example, the second argument is a step, not the stop, notice this method is also deprecated, you have to use keyword arguments now:
julia> #which range(0.1, 1.1, 6)
range(start, step, length) in Base at deprecated.jl:53
I am trying to port some code and now I've hit a sticky bit. The original code is in C++. I need to port a union that has two 32 bit ints (in an array) and a double.
So far I have:
I1 = UInt32(56) # arbitrary integer values for example
I2 = UInt32(1045195987)
# do transforms on I1 and I2 as per the code I'm porting
A = bits(I1)
B = bits(I2)
return parse(Float64, string(A,B))
Is this the way to do it? The string operation seems expensive. Any advice appreciated.
I also come from mostly C/C++ programming, and this is what I do to handle the problem:
First, create an immutable type with two UInt32 elements:
immutable MyType
a::UInt32
b::UInt32
end
Then you can convert a vector of Float64 to that type with reinterpret.
For example:
julia> x = [1.5, 2.3]
2-element Array{Float64,1}:
1.5
2.3
julia> immutable MyType ; a::UInt32 ; b::UInt32 ; end
julia> y = reinterpret(MyType, x)
2-element Array{MyType,1}:
MyType(0x00000000,0x3ff80000)
MyType(0x66666666,0x40026666)
julia> x[1]
1.5
julia> y[1]
MyType(0x00000000,0x3ff80000)
julia> y[1].a
0x00000000
julia> y[1].b
0x3ff80000
Note: the two vectors still point to the same memory, so you can even update elements, using either type.
julia> x[1] = 10e91
1.0e92
julia> y[1].a
0xbf284e24
julia> y[1].b
0x53088ba3
julia> y[1] = MyType(1,2)
MyType(0x00000001,0x00000002)
julia> x[1]
4.2439915824e-314