web-dev-qa-db-ja.com

np.unravel_indexの直感的な説明は何ですか?

タイトルが言っていることのほとんど。私はドキュメントを読んで、しばらくの間この機能を試しましたが、この変換の物理的な兆候が何であるかを見分けることはできません。

21
austinkjensen

コンピュータのメモリは直線的にアドレスされます。各メモリセルは番号に対応しています。メモリブロックは、最初の要素のメモリアドレスであるベース、およびアイテムインデックスでアドレス指定できます。たとえば、ベースアドレスが10,000であると仮定します。

item index      0       1       2       3
memory address  10,000  10,001  10,002  10,003

多次元ブロックを保存するには、それらのジオメトリを何らかの方法で線形メモリに収まるように作成する必要があります。 CおよびNumPyでは、これは行ごとに行われます。 2Dの例は次のとおりです。

  | 0      1      2      3
--+------------------------
0 | 0      1      2      3
1 | 4      5      6      7
2 | 8      9     10     11

したがって、たとえば、この3行4列のブロックでは、2Dインデックス(1, 2)は線形インデックスに対応します6これは1 x 4 + 2

unravel_indexは逆を行います。線形インデックスが与えられると、対応するNDインデックスを計算します。これはブロックの次元に依存するため、これらも渡す必要があります。したがって、この例では、元の2Dインデックス(1, 2)線形インデックスから戻る6

>>> np.unravel_index(6, (3, 4))
(1, 2)

注:上記では、いくつかの詳細について説明します。 1)アイテムのインデックスをメモリアドレスに変換するには、アイテムのサイズも考慮する必要があります。たとえば、整数は通常4バイトまたは8バイトです。したがって、後者の場合、アイテムiのメモリアドレスはbase + 8 x i。 2)。 NumPyは、提案されているよりも少し柔軟です。必要に応じて、列ごとにNDデータを整理できます。メモリ内で連続していないがギャップなどを残しているデータも処理できます。

25
Paul Panzer

ドキュメントの例から始めます。

_>>> np.unravel_index([22, 41, 37], (7,6))
(array([3, 6, 6]), array([4, 5, 1]))
_

まず、_(7,6)_は、インデックスを元に戻すターゲット配列の次元を指定します。第二に、_[22, 41, 37]_はこの配列のいくつかのインデックスです配列が平坦化されている場合 7 x 6配列が平坦化されている場合、そのインデックスは次のようになります

_[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
   17, 18, 19, 20, 21, *22*, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
   34, 35, 36, *37*, 38, 39, 40, *41*]
_

これらのインデックスを元の位置に戻し、薄暗い_(7, 6)_配列に戻すと、次のようになります。

_      [[ 0,   1,   2,   3,   4,   5],
       [ 6,   7,   8,   9,  10,  11],
       [12,  13,  14,  15,  16,  17],
       [18,  19,  20,  21, *22*, 23],  <- (3, 4)
       [24,  25,  26,  27,  28,  29],
       [30,  31,  32,  33,  34,  35],
       [36, *37*, 38,  39,  40, *41*]]
           (6, 1)               (6,5)
_

_unravel_index_関数の戻り値は、配列が平坦化されていない場合に[22、41、37]のインデックスはどうあるべきかを示しています。配列が平坦化されていない場合、これらのインデックスは[(3, 4), (6, 5), (6,1)]になっているはずです。つまり、この関数は、平坦化された配列のインデックスを平坦化されていないバージョンに転送します。

https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.unravel_index.html

33
Tai

これは、他の2つの回答と内容は同じですが、より直感的かもしれません。 2次元の行列または配列がある場合は、さまざまな方法で参照できます。 (row、col)を入力して(row、col)の値を取得するか、各セルに単一番号のインデックスを付けることができます。 unravel_indexは、マトリックス内の値を参照するこれら2つの方法の間で変換するだけです。

enter image description here

これは、2より大きい次元に拡張可能です。また、逆変換を実行するnp.ravel_multi_index()に注意する必要があります。配列のインデックスと形状が必要なことに注意してください。

また、インデックスマトリックスに2つの10があります。

16
Jon

非常に簡単な例で説明できます。これはnp.ravel_multi_indexnp.unravel_index

X = np.array([[4,  2],
              [9,  3],
              [8,  5],
              [3,  3],
              [5,  6]])
X.shape = (5, 2)

すべてのがXに存在する場所を見つける

idx = np.where(X==3)

Output: idx = (array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))
i.e,  x = [1, 3, 3]
      y = [1, 0, 1]

インデックスのx、yを返します[Xは2次元であるため]


Uが適用される場合ravel_multi_index取得したidxに対して

idx_flat = np.ravel_multi_index(idx, X.shape)

Output: idx_flat = array([3, 6, 7], dtype=int64)
idx_flat is a linear index of X where value 3 presents

上記の例から、理解できます。

  • ravel_multi_indexは、多次元インデックス(nd配列)を一次元インデックス(線形配列)に変換します
  • インデックスでのみ機能します。つまり、入力と出力の両方がインデックスです。

結果のインデックスは、X.ravel()の直接インデックスになります。以下で確認できますx_linear

x_linear = X.ravel()
Output: x_linear = array([4, 2, 9, 3, 8, 5, 3, 3, 5, 6])

一方、nravel_indexは非常に単純で、上記の逆(np.ravel_multi_index)

idx = np.unravel_index(idx_flat , X.shape)
Output: (array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))

idx = np.where(X == 3)と同じです

  • unravel_indexは、1次元のインデックス(線形配列)を多次元のインデックス(nd配列)に変換します
  • インデックスでのみ機能します。つまり、入力と出力の両方がインデックスです。
0