How to create a ones array in Julia?

Viewed 396

In many Machine Learning use cases, you need to create an array filled with ones, with specific dimensions. In Python, I would use np.ones((2, 1)). What is the analog version of this in Julia?

2 Answers

Julia has a built in ones function which can be used as follows:

  julia> ones(1,2)
  1×2 Matrix{Float64}:
   1.0  1.0

You can read more about the ones function in the Julia docs.

The answer by Logan is excellent. You can just use the ones function.

BUT, you can also often not use it.

For instance, a common use of a vector of ones is to multiply that vector times another vector so you get a matrix where each row just has the same value as in the corresponding element of the matrix. Then you can add that matrix to something. This allows you add the values of a vector to the corresponding rows of a matrix. You get code like this:

>>> A = np.random.rand(4,3)
>>> x = np.random.rand(4)
array([0.01250529, 0.9620139 , 0.70991563, 0.99795451])
>>> A + np.reshape(np.ones(3), (1,3)) * np.reshape(x, (4,1)) 
array([[0.09141967, 0.83982525, 0.16960596],
       [1.39104681, 1.10755182, 1.60876696],
       [1.14249757, 1.68167344, 1.64738165],
       [1.10653393, 1.45162139, 1.23878815]])

This is actually a lot of extra work for the computer because Python can't optimize this and a lot of extra work is going on. You could also use so called broadcasting to do this extension more simply, but you still have to get x into the right shape:

>>> A + x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (4,3) (4,) 
>>> A + np.reshape(x, (4,1))
array([[0.09141967, 0.83982525, 0.16960596],
       [1.39104681, 1.10755182, 1.60876696],
       [1.14249757, 1.68167344, 1.64738165],
       [1.10653393, 1.45162139, 1.23878815]])

In Julia, the extension of the vector to the same shape as the matrix you to which you want to add can be done more simply using the broadcast operator. Thus, the code above simplifies to

julia> A = rand(4,3)
4×3 Matrix{Float64}:
 0.885593  0.494999  0.534039
 0.915725  0.479218  0.229797
 0.739122  0.670486  0.247376
 0.419879  0.857314  0.652547

julia> x = rand(4)
4-element Vector{Float64}:
 0.9574839624590326
 0.9736140903654276
 0.6051487944513263
 0.3581090323172089

julia> A .+ x
4×3 Matrix{Float64}:
 1.84308   1.45248  1.49152
 1.88934   1.45283  1.20341
 1.34427   1.27563  0.852524
 0.777988  1.21542  1.01066

One reason that this works better is because there is less noise in the syntax because arrays are primitive to Julia.

Much more importantly, though, compiler sees the use of the broadcast operator and it can generate very efficient code (and can even vectorize it). In fact, x doesn't even have to be an actual vector as long as it has a few of the same methods defined for it.

In fact, if you really do need a vector or matrix of all ones (or some other constant) you can use broadcast with scalars as well

julia> A .+ 1
4×3 Matrix{Float64}:
 1.88559  1.495    1.53404
 1.91572  1.47922  1.2298
 1.73912  1.67049  1.24738
 1.41988  1.85731  1.65255
Related