logo

ジュリア、Python(NumPy、PyTorch)の配列の次元の違い 📂ジュリア

ジュリア、Python(NumPy、PyTorch)の配列の次元の違い

概要

JuliaとNumPy、PyTorch(以降、便宜上Pythonと呼ぶ)の高次元配列を扱う際、各次元が意味するものが異なるため注意が必要だ。この違いはJuliaの配列が列優先であり、Pythonの配列が行優先であるために生じる。ちなみに同じ列優先のMatlabはJuliaとの違いがないため、Matlabに慣れているユーザーは特に注意する必要はないが、Pythonに慣れている人はインデックスの間違いに注意しよう。

  • 配列の次元とベクトルの次元を混同して使っているので、しっかり理解しよう。

説明

1次元配列

Juliaでは、サイズが$n$の配列は$n$次元の列ベクトルを意味する。

julia> ones(3)
3-element Vector{Float64}:
 1.0
 1.0
 1.0

Pythonでは、サイズが$n$の配列は$n$次元の行ベクトルを意味する。

>>> import numpy as np
>>> np.ones(3)
array([1., 1., 1.])

列か行かの違いはあるが、1次元配列であるため、インデックスに特に注意する点はない。

2次元配列

表面上は2次元までは違いがないように見える。しかし、その意味は異なるので注意が必要だ。まず、Juliaでは配列の次元が後方に伸びる。つまり$(m,n)$配列とは、サイズが$m$の1次元配列(列ベクトル)が$n$個あることを意味する。具体的には$(3,2)$配列は、3次元の列ベクトルが2個あるということだ。

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

また、Juliaは「列優先」なので、成分のインデックスは上から下へ先に、そして左から右に大きくなる。

julia> A = reshape(range(1,6), (3,2))
3×2 reshape(::UnitRange{Int64}, 3, 2) with eltype Int64:
 1  4
 2  5
 3  6

julia> for i ∈ 1:6
           println(A[i])
       end
1
2
3
4
5
6

一方、Pythonの配列では新しい次元が前方へ伸びる。つまり$(m,n)$配列とは、サイズが$n$の1次元配列(行ベクトル)が$m$個あるということだ。以下の結果からは、配列が行単位で区分されているのがわかる。

>>> np.ones([3,2])
array([[1., 1.],
       [1., 1.],
       [1., 1.]])

つまり、見た目だけでは、JuliaとPythonの$(m,n)$配列はどちらも$m \times n$の行列だが、列優先/行優先の違いのためにインデックスの順序が異なる。インデックスの方向はJuliaでは上下左右、Pythonでは左右上下だ。

# julia에서 2차원 배열의 인덱싱은 위에서 아래로, 그 다음 좌에서 우로
julia> A = reshape(range(1,6), (3,2))
3×2 reshape(::UnitRange{Int64}, 3, 2) with eltype Int64:
 1  4
 2  5
 3  6

# python에서 2차원 배열의 인덱싱은 좌에서 우로, 그 다음 위에서 아래로 
>>> np.arange(6).reshape(3,2)
array([[0, 1],
       [2, 3],
       [4, 5]])

3次元配列

Juliaでは、配列の新しい次元が後ろに追加されると言った。従って、$(m,n,k)$配列は、$(m,n)$配列が$k$個あることを意味する。

julia> ones(3,2,4)
3×2×4 Array{Float64, 3}:
[:, :, 1] =
 1.0  1.0
 1.0  1.0
 1.0  1.0

[:, :, 2] =
 1.0  1.0
 1.0  1.0
 1.0  1.0

[:, :, 3] =
 1.0  1.0
 1.0  1.0
 1.0  1.0

[:, :, 4] =
 1.0  1.0
 1.0  1.0
 1.0  1.0

一方、Pythonでは$(m,n,k)$配列は、$(n,k)$配列が$m$個あるということだ。

>>> np.ones([3,2,4])
array([[[1., 1., 1., 1.],
        [1., 1., 1., 1.]],

       [[1., 1., 1., 1.],
        [1., 1., 1., 1.]],

       [[1., 1., 1., 1.],
        [1., 1., 1., 1.]]])

機械学習で

画像データで、$H=\text{hieht}$が高さ、$W=\text{width}$が幅、$C=\text{channel}$がチャンネル数、$B=\text{batch size}$がバッチサイズとした場合、PyTorchでは$(B,C,H,W)$配列であり、Juliaでは$(H,W,C,B)$である。

環境

  • OS: Windows11
  • バージョン: Julia 1.7.1, Python 3.9.2, numpy 1.19.5