I have some categorical data represented with a symbol in Julia for a few different problems I want to solve which I think fits well into the form necessary for a One-Hot encoding. How can I setup and represent this data in Flux.jl?
If you are un-familiar with the general concept of One-Hot encodings, it is worth taking some time to read about it here: https://machinelearningmastery.com/why-one-hot-encode-data-in-machine-learning/ the general gist is that in cases where you are working with non-numerical data (some category names like "cat" or "dog" rather that 0 or 1), you need a way to take the existing encoding (some string of text perhaps) and switch it to a numerical value that a machine learning model will understand.
Flux provides a built in One-Hot Encoding function which can be used as follows:
julia> using Flux: onehot
julia> onehot(:b, [:a, :b, :c])
3-element Flux.OneHotVector{3,UInt32}:
0
1
0
julia> onehot(:c, [:a, :b, :c])
3-element Flux.OneHotVector{3,UInt32}:
0
0
1
In the first example, we assume that if we get the array:
3-element Flux.OneHotVector{3,UInt32}:
0
1
0
that it is the numerical representation of the symbol :b. The latter example is the same but for the case of the symbol :c.
Related
I'm trying to construct the identity matrix in Julia 1.1. After looking at the documentation I found that I could compute a 4x4 Identity matrix as follows:
julia> Id4 =1* Matrix(I, 4, 4)
4×4 Array{Int64,2}:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Is this the most julianic way of coding it or is there a better/shorter way, as it is an often used matrix?
Given using LinearAlgebra, the most julianic way of expressing the identity matrix is:
I
This answer may seem trite, but it is also kind of profound. The whole point of the operator I is that in the vast majority of cases where users want an identity matrix, it is not necessary to actually instantiate that matrix.
Let's say you want a 1000x1000 identity matrix. Why waste time building the entire matrix, when you could just use I, noting that sizeof(I) evaluates to 1 (ie the size of the object is 1 byte). All functions in base Julia (including LinearAlgebra) understand what I is, and can use it appropriately without having to waste time building the actual matrix it represents first.
Now, it may be the case that for some reason you need to specify the type of the elements of your identity matrix. Note:
julia> I
UniformScaling{Bool}
true*I
so in this case, you are using a notional identity matrix with a diagonal of true and off-diagonal of false. This is sufficient in many cases, even if your other matrices are Int or Float64. Internally, Julia will use methods that specialize on the types. However, if you want to specify your identity matrix to contain integers or floats, use:
julia> 1I
UniformScaling{Int64}
1*I
julia> 1.0I
UniformScaling{Float64}
1.0*I
Note that sizeof(1I) evaluates to 8, indicating the notional Int64 types of the members of that matrix.
Also note that you can use e.g. 5I if you want a notional matrix with 5 on the diagonal and 0 elsewhere.
In some cases (and these cases are much rarer than many might think), you may need to actually build the matrix. In this case, you can use e.g.:
Matrix(1I, 3, 3) # Identity matrix of Int type
Matrix(1.0I, 3, 3) # Identity matrix of Float64 type
Matrix(I, 3, 3) # Identity matrix of Bool type
Bogumił has also pointed out in the comments that if you are uncomfortable with implying the type of the output in the first argument of the constructors above, you can also use the (slightly more verbose):
Matrix{Int}(I, 3, 3) # Identity matrix of Int type
Matrix{Float64}(I, 3, 3) # Identity matrix of Float64 type
Matrix{Bool}(I, 3, 3) # Identity matrix of Bool type
and specify the type explicitly.
But really, the only times you would probably need to do this are as follows:
When you want to input an identity matrix into a function in a package written in such a way that the input must be a concrete matrix type.
When you want to start out with an identity matrix but then mutate it in place into something else via one or several transformations.
Let's say I have an NTuple with 4 entries of Int64 uninitiallized. How do I set the value of each index separately?
I tried the setindex function of base but it didn't work. Any idea?
T = NTuple{4,Int64}
setindex(T,9,2) # set T(2) to 9
You probably meant NTuple{4, Int64} not Ntuple{4, Int64}.
NTuple is a compact way of representing the type tuples having elements of a single type (not actual values but their types; the thing that might be confusing here is that NTuple{4, Int64} is also technically a value that you can bind to a variable, but this is not what you probably want to do given your question).
You can check this by looking up help on it. In your case it represents a type for a tuple of length 4 and all elements of type Int64. For example (1,2,3,4) is such a tuple. You can check it by writing (1,2,3,4) isa NTuple{4, Int64} which will evaluate to true.
Now if you ask why a tuple like (1,2,3,4) does not support setindex! the reason is that tuples are immutable in Julia, see https://docs.julialang.org/en/latest/manual/types/#Tuple-Types-1. This means that you have to assign a value to each field of a tuple upon its construction and it cannot be mutated.
If you want a mutable container you should probably consider using a vector instead of a tuple. For example:
julia> x = Vector{Int}(undef, 4)
4-element Array{Int64,1}:
0
0
0
0
julia> x[2] = 9
9
julia> x
4-element Array{Int64,1}:
0
9
0
0
Looking to find the numeric placement of letters in a random letter vector using a function equivalent to foo.
myletters = ["a","c","b","d","z"]
foo(myletters)
# [1,3,2,4,26]
Edit: If you're looking for the numeric distance from 'a', here's one solution:
julia> Int.(first.(["a","c","b","d","z"])) - Int('a') + 1
5-element Array{Int64,1}:
1
3
2
4
26
It will gracefully handle unicode (those simply are later code points and thus will have larger values) and longer strings (by only looking at the first character). Capitals, numbers, and some symbols will appear as negative numbers since their code points come before a.
Previous answer: I think you're looking for sortperm. It gives you a vector of indices that, if you index back into the original array with it, will put it in sorted order.
julia> sortperm(["a","c","b","d"])
4-element Array{Int64,1}:
1
3
2
4
I came up with the somewhat convoluted solution:
[reshape((1:26)[myletters[i] .== string.('a':'z')],1)[1] for i=1:length(myletters)]
Or using map
map(x -> reshape((1:26)[x .== string.('a':'z')],1)[1], myletters)
In Matlab I can write:
[0:n]
to get an array (1,n). For n=2, I get:
0 1 2
How to do the same in Julia? The purpose is to get the same type of array (1,3).
I know I can write [0 1 2], but I want something general like in Matlab.
In julia, the colon operator (in this context, anyway) returns a UnitRange object. This is an iterable object; that means you can use it with a for loop, or you can collect all its contents, etc. If you collect its contents, what you get here is a Vector.
If what you're after is explicitly a RowVector, then you can collect the contents of the UnitRange, and reshape the resulting vector accordingly (which in this case can be done via a simple transpose operation).
julia> collect(1:3).'
1×3 RowVector{Int64,Array{Int64,1}}:
1 2 3
The .' transpose operator is also defined for UnitRange arguments:
julia> (1:3).'
1×3 RowVector{Int64,UnitRange{Int64}}:
1 2 3
However, note the difference in the resulting type; if you apply .' again, you get a UnitRange object back again.
If you don't particularly like having a "RowVector" object, and want a straightforward array, use that in an Array constructor:
julia> Array((1:3).')
1×3 Array{Int64,2}:
1 2 3
(above as of latest julia 0.7 dev version)
I was delighted to learn that Julia allows a beautifully succinct way to form inner products:
julia> x = [1;0]; y = [0;1];
julia> x'y
1-element Array{Int64,1}:
0
This alternative to dot(x,y) is nice, but it can lead to surprises:
julia> #printf "Inner product = %f\n" x'y
Inner product = ERROR: type: non-boolean (Array{Bool,1}) used in boolean context
julia> #printf "Inner product = %f\n" dot(x,y)
Inner product = 0.000000
So while i'd like to write x'y, it seems best to avoid it, since otherwise I need to be conscious of pitfalls related to scalars versus 1-by-1 matrices.
But I'm new to Julia, and probably I'm not thinking in the right way. Do others use this succinct alternative to dot, and if so, when is it safe to do so?
There is a conceptual problem here. When you do
julia> x = [1;0]; y = [0;1];
julia> x'y
0
That is actually turned into a matrix * vector product with dimensions of 2x1 and 1 respectively, resulting in a 1x1 matrix. Other languages, such as MATLAB, don't distinguish between a 1x1 matrix and a scalar quantity, but Julia does for a variety of reasons. It is thus never safe to use it as alternative to the "true" inner product function dot, which is defined to return a scalar output.
Now, if you aren't a fan of the dots, you can consider sum(x.*y) of sum(x'y). Also keep in mind that column and row vectors are different: in fact, there is no such thing as a row vector in Julia, more that there is a 1xN matrix. So you get things like
julia> x = [ 1 2 3 ]
1x3 Array{Int64,2}:
1 2 3
julia> y = [ 3 2 1]
1x3 Array{Int64,2}:
3 2 1
julia> dot(x,y)
ERROR: `dot` has no method matching dot(::Array{Int64,2}, ::Array{Int64,2})
You might have used a 2d row vector where a 1d column vector was required.
Note the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].
You can convert to a column vector with the vec() function.
The error message suggestion is dot(vec(x),vec(y), but sum(x.*y) also works in this case and is shorter.
julia> sum(x.*y)
10
julia> dot(vec(x),vec(y))
10
Now, you can write x⋅y instead of dot(x,y).
To write the ⋅ symbol, type \cdot followed by the TAB key.
If the first argument is complex, it is conjugated.
Now, dot() and ⋅ also work for matrices.
Since version 1.0, you need
using LinearAlgebra
before you use the dot product function or operator.