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.
Related
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),)
Suppose we have to take multiple input in one line in Python 3 then:-
1st method:-
x, y = input(), input()
2nd method:-
x, y = input().split()
3rd method:-
Using list comprehension
x, y = [int(x) for x in [x, y]]
4th method:-
x, y = map(int, input().split())
So these are the methods I know in python 3.
Can anyone tell me the alternate code in Julia?
readdlm(IOBuffer(readline()))
The best simple parser for all occasions is readdlm.
It will provide you processing any user input as an array and hence will be most robust for any circumstances:
julia> using DelimitedFiles
julia> readdlm(IOBuffer(readline()))
z b c
1×3 Array{Any,2}:
"z" "b" "c"
julia> readdlm(IOBuffer(readline()))
1 2
1×2 Array{Float64,2}:
1.0 2.0
Since it is an Array the same multi-argument assignment will work as in Python
julia> x, y = readdlm(IOBuffer(readline()))
1 2 3
1×3 Array{Float64,2}:
1.0 2.0 3.0
julia> x, y
(1.0, 2.0)
As we can't directly use input function I implemented like this in Julia.
function input()
x, y= readline(stdin), readline(stdin)
end
So I hope you liked this one.
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
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 have a function in which the user passes an argument to select which columns of a matrix should be processed as in the minimalistic example below:
function foo{P<:Real, T<:Integer}(;x::AbstractMatrix{P}=zeros(3, 10), colN::Union(T, AbstractVector{T})=1)
x[:,colN] = x[:,colN]+1
return x
end
I want to have a way for the user to specify that all columns should be processed, in the end I changed the function so that this would be the default behavior:
function foo{P<:Real, T<:Integer}(;x::AbstractMatrix{P}=zeros(3, 10), colN::Union(T, AbstractVector{T})=[1:size(x)[2]])
x[:,colN] = x[:,colN]+1
return x
end
originally, however, I wanted to allow the colN argument to take a String, so that the user could pass it the value "all" to mean that all columns should be processed, but the following doesn't work as I expected:
function foo{P<:Real, T<:Integer}(;x::AbstractMatrix{P}=zeros(3, 10), colN::Union(T, AbstractVector{T}, String)="all")
if colN == "all"
colN = [1:size(x)[2]]
end
x[:,colN] = x[:,colN]+1
return x
end
calling this last version of the function gives:
foo(colN="all")
ERROR: `__foo#8__` has no method matching __foo#8__(::Array{Float64,2}, ::ASCIIString)
why such an union between an Integer, a vector of integers, and a string doesn't seem to work?
The problem is that Julia can't deduce the type T when you pass a string, and is thus not able to resolve which method to call.
Consider the following two functions, f and g:
function f{T<:Integer}(x::Union(T,String))
x
end
function g{T<:Integer}(y::T, x::Union(T,String))
x
end
In this case, you will observe the following behavior:
f(1) is 1 because the value of T can be deduced
f("hello") gives an error because the value of T is unknown
g(1, "hello") is "hello" because the value of T can be deduced
That being said, I think that it would be more idiomatic Julia to use multiple dispatch instead of Union types to achieve what you want to do.
Update. Seeing as your colN is either a string or a list of indexes, I believe you would be fine with T = Int (or Int64 if you want to address a lot of memory). Compare the following function h to f and g above:
function h(x::Union(Int,String))
x
end
In this case, both h(1) and h("hello") work as expected (and e.g. h(1.0) raises an error).
There is no need to pass a string in this function to indicate handling all columns.
Also, it looks like the matrix should be passed in as a positional argument,
instead of a keyword argument.
so that Julia can specialize on it.
There are many ways to handle this more efficiently in Julia.
function foo{P<:Real, T<:Integer}(x::AbstractMatrix{P}, colN::Union(T, AbstractVector{T}))
x[:,colN] += 1
return x
end
function foo{P<:Real}(x::AbstractMatrix{P})
x[:,[1:size(x)[2]]] += 1
return x
end
so foo(zeros(10,3)) will give you:
3x10 Array{Float64,2}:
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
and foo(zeros(3,10),5) will give you:
3x10 Array{Float64,2}:
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0