形状演算

形状演算

1. 学習内容



2. ある開発者の実話

(1) 問題点

ボブは、3×4 の 12 個のデータポイントを 4×3 に変形させ、「メモリの再配置」をしているつもりだったが、その変形処理のたびにデータがコピーされていたため、メモリと処理速度が著しく低下してしまった。

(2) 解決策

アリスは彼にMermaidの図を見せながら、「reshapeはメタデータのみを変更するもので、データは1バイトたりとも移動しない。それがNumPyの高速化の秘訣よ」と説明した。演算の結果がビューである限り、データはコピーされない。

(3) 成果

ボブが「ビューとコピー」の違いを理解すると、彼の形状操作コードはメモリ使用量を1桁減らし、実行速度も数倍向上した。フラット化のみが真のコピーであり、それ以外(リシェイプ、ラヴェル、トランスポーズ、スワップアクスなど)はすべてビューである。



3. 形状演算の詳細

(1) reshape の仕組み

reshape は配列の形状を変更しますが、データをコピーすることはありません。これは配列のメタデータ(形状とストライド)のみを変更するものであり、メモリ内の生データはそのまま残ります。

PYTHON
import numpy as np

a = np.arange(12)
b = a.reshape(3, 4)

print(a.shape)   # (12,)
print(b.shape)   # (3, 4)
print(b.base is a)  # True — b is a view of a
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

PYTHON
# reshape does NOT copy data
b[0, 0] = 999
print(a[0])  # 999 — modifying b changes a!
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

メモリダイアグラムの再構成

100%
graph LR
    A["Original Array<br/>shape=(12,)"] -->|"reshape(3,4)"| B["View<br/>shape=(3,4)"]
    A -->|"reshape(4,3)"| C["View<br/>shape=(4,3)"]
    A -->|"reshape(2,6)"| D["View<br/>shape=(2,6)"]

    style A fill:#4CAF50,color:#fff
    style B fill:#2196F3,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#9C27B0,color:#fff
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

要点:A、B、C、Dはすべて同じメモリを共有しており、単にその「解釈」の仕方が異なるだけである。


(2) -1 自動推論

reshape 内で -1 を使用すると、NumPy がその次元のサイズを自動的に計算するようになります。

PYTHON
a = np.arange(12)

# NumPy infers: 12 / 3 = 4
b = a.reshape(3, -1)     # shape = (3, 4)
c = a.reshape(2, -1)     # shape = (2, 6)
d = a.reshape(-1, 6)     # shape = (2, 6)
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(3) フラット化とラヴェル

メソッド 戻り値 コピーする? メモリ
ndarray.flatten() 1次元配列 常にコピーされる 新しいメモリ
ndarray.ravel() 1次元配列 可能であれば参照 通常は共有
PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

f = a.flatten()  # always a copy
r = a.ravel()    # usually a view

f[0] = 999
print(a[0, 0])   # 0 — f is a copy, a unchanged

r[0] = 999
print(a[0, 0])   # 999 — r is a view, a changed
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(4) 転置と .T

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)
print(a.shape)   # (3, 4)

b = a.T          # transpose — view, no copy
print(b.shape)   # (4, 3)

# For multi-dimensional arrays, transpose accepts an axis order
c = a.transpose(1, 0)
print(c.shape)   # (4, 3)
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(5) newaxis と squeeze

PYTHON
import numpy as np

a = np.array([1, 2, 3])       # shape (3,)

# newaxis adds a dimension
b = a[np.newaxis, :]           # shape (1, 3)
c = a[:, np.newaxis]           # shape (3, 1)
d = a[np.newaxis, :, np.newaxis]  # shape (1, 3, 1)

# squeeze removes dimensions of size 1
e = np.squeeze(d)              # shape (3,) — back to original
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。


(1) ▶ サンプル

TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

: -1 による自動推論を用いた再構成 (難易度 ⭐)

PYTHON
import numpy as np

a = np.arange(24)

# Use -1 for auto-inference
b = a.reshape(2, -1)      # 2 x 12
c = a.reshape(3, -1)      # 3 x 8
d = a.reshape(4, -1)      # 4 x 6
e = a.reshape(6, -1)      # 6 x 4

print(f"a.shape={a.shape}")
print(f"b.shape={b.shape}")  # (2, 12)
print(f"c.shape={c.shape}")  # (3, 8)
print(f"d.shape={d.shape}")  # (4, 6)
print(f"e.shape={e.shape}")  # (6, 4)
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(2) ▶ サンプル

TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

: flatten 対 ravel — copy 対 view (難易度 ⭐⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

# flatten always copies
flat = a.flatten()
flat[0] = 999
print("After flat[0]=999, a[0,0]=", a[0,0])  # 0 (unchanged)

# ravel usually returns a view
rav = a.ravel()
rav[0] = 999
print("After rav[0]=999, a[0,0]=", a[0,0])  # 999 (changed!)
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(3) ▶ サンプル

TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

: transpose と newaxis (難易度 ⭐⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

# Transpose
print("Original shape:", a.shape)     # (3, 4)
print("Transposed shape:", a.T.shape)  # (4, 3)

# newaxis: add dimensions
row = np.array([1, 2, 3])
print("row shape:", row.shape)                # (3,)
print("row[np.newaxis,:] shape:", row[np.newaxis, :].shape)  # (1, 3)
print("row[:,np.newaxis] shape:", row[:, np.newaxis].shape)  # (3, 1)
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。



4. 比較表

(1) 形状演算の概要

操作 戻り値 データをコピーするか? ユースケース
reshape 表示 なし 形状を変更
flatten コピー はい 安全な1D変換
ravel 表示(通常) まれ 高速 1D
T / transpose 表示 なし 軸の順序変更
newaxis 表示 なし 寸法を追加
squeeze 表示 なし サイズが1小さい次元を除外
swapaxes 表示 なし 2つの軸を入れ替える

(2) 表示とコピー

機能 表示 コピー
メモリ 共有 新規割り当て
変更 オリジナルへの影響 独立
速度 O(1) O(n)
base 属性 出典へのリンク なし
使用すべき場面 読み取り専用または意図的な共有 安全な変更


5. 原理図

100%
graph TB
    A["Original (12,)"] -->|reshape/flatten/ravel| B["New shape"]
    A --> C["data buffer: [0 1 2 ... 11]"]
    B --> C
    B -->|flatten| D["copy of data buffer"]
    B -->|ravel| C
    B -->|transpose| C
    B -->|newaxis| C
    
    style A fill:#4CAF50,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#E91E63,color:#fff


❓ よくある質問

Q reshape は常にビューを返しますか?
A ほとんどの場合、そうです。ただし、配列がメモリ上で連続している場合に限ります。配列が連続していない場合(例えば、転置を行った後など)、reshape はコピーを行う必要がある場合があります。 必要に応じて、まず np.ascontiguousarray() を使用してください。
Q .T と .transpose() の違いは何ですか?
A .T は、すべての軸を反転させるショートカットです(順序を逆にした .transpose() と同等です)。 2次元配列の場合、これらは同じ動作をします。3次元以上の配列の場合、.Tはすべての軸を反転させますが、.transpose(1,0,2)では順序を指定できます。
Q 「flatten」と「ravel」は、それぞれどのような場合に使うべきですか?
A 1次元の結果を変更する予定があり、元のデータに影響を与えたくない場合は、「flatten」を使用してください(安全なコピー)。 単に読み取るだけの場合や、変更を反映させたい場合は、ravel を使用してください(処理が速く、通常はビューとして扱われます)。
Q reshape における -1 は何を意味しますか?
A これは NumPy に対して「この次元を自動的に決定する」よう指示するものです。-1 は 1 つだけ指定可能です。NumPy はこれを total_size / product_of_other_dims として計算します。

📖 まとめ



📝 練習問題

  1. 初心者(難易度 ⭐):20要素の配列を作成し、-1 を使用して、それを (4,5)、(5,4)、(2,10)、(10,2) の形に再構成してください。 すべての形状が正しいことを確認してください。

  2. 中級(難易度 ⭐⭐):3×4の配列を作成し、それを転置した後、転置した結果をreshapeで再成形してみてください。reshapeを使用しても、コピーは回避できるでしょうか? .base に確認してみてください。

  3. 上級(難易度 ⭐⭐⭐):形状が (2,3,4) の3次元配列を作成してください。 transpose(2,0,1) を使用して軸の順序を変更してください。結果において各次元が何を表しているかを説明してください。その後、swapaxes を使用して同じ結果を得てください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%