要素ごとの演算
1. 学習内容
- ❶ 算術 —
+ - * / // % **およびそれに対応する関数 - ❷ 比較 —
> < >= <= == !=ブールマスクの生成 - ❸ 論理演算 —
& | ^ ~やnp.logical_andなど - ❹ ベクトル化とループ — パフォーマンスの比較と原理
- ❺ ufuncの概要 — ユニバーサル関数の概念と性質
2. ストーリー
ボブはforループを使って100万個の数を2乗する――所要時間は0.3秒だ。アリスはa ** 2を1行記述する――所要時間は3ミリ秒だ。
「NumPyの演算はPythonのループではありません。C言語レベルのufuncによるバッチ処理であり、100倍高速です。」
ボブが「ufuncって何?」と尋ねると、アリスはターミナルを開いてnp.addと入力した――すべては要素ごとの演算から始まるのだ。
3. 主要な概念
(1) 算術演算子と関数
NumPy の演算は、配列のすべての要素に対して行われ、形状は自動的にブロードキャストされます:
import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
print(a + b) # [11 22 33 44]
print(a * b) # [10 40 90 160]
print(a ** 2) # [ 1 4 9 16]
print(b // a) # [10 10 10 10]
print(b % a) # [0 0 0 0]
> 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.
各演算子は、NumPyの関数に対応しています:
| 演算子 | 関数 | 説明 |
|---|---|---|
+ |
np.add |
追加 |
- |
np.subtract |
引き算 |
* |
np.multiply |
乗算 |
/ |
np.true_divide |
真の除算 |
// |
np.floor_divide |
フロア区分 |
% |
np.mod |
モジュロ |
** |
np.power |
電源 |
(2) 比較演算
比較は要素単位で行われ、ブール配列(マスク)が返されます:
a = np.array([3, 7, 1, 9, 5])
print(a > 4) # [False True False True True]
print(a == 7) # [False True False False False]
print((a >= 3) & (a <= 7)) # [ True True False False True]
> 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.
(3) 論理演算
要素ごとの論理演算を行うには、ビット演算子 & | ^ ~(and or not ではない)を使用してください:
a = np.array([True, True, False, False])
b = np.array([True, False, True, False])
print(a & b) # [ True False False False]
print(a | b) # [ True True True False]
print(~a) # [False False True True]
print(np.logical_and(a, b)) # [ True False False False]
> 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.
(4) ユニバーサル関数 の概念
ユニバーサル関数(ユニバーサル関数)は、NumPyにおける要素ごとの演算のための低レベルの抽象化です:
- 各ufuncは、すべての要素に対して同じ演算を適用するC言語レベルのループです
- ブロードキャスト、型昇格、出力バッファリングに対応しています
.types、.nin、.noutのプロパティを持つ
print(np.add.nin) # 2 (number of inputs)
print(np.add.nout) # 1 (number of outputs)
print(np.add.types) # list of supported type signatures
> 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) ▶ サンプル
> 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.
: 算術演算(難易度 ⭐)
import numpy as np
a = np.array([2, 4, 6, 8])
b = np.array([1, 3, 5, 7])
print("a + b =", a + b) # [ 3 7 11 15]
print("a - b =", a - b) # [1 1 1 1]
print("a * b =", a * b) # [ 2 12 30 56]
print("a / b =", a / b) # [2. 1.33 1.2 1.14]
print("a // b =", a // b) # [2 1 1 1]
print("a % b =", a % b) # [0 1 1 1]
print("a 3 =", a 3) # [ 8 64 216 512]
> 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.
(2) ▶ サンプル
> 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.
: 比較用マスク(難易度 ⭐)
import numpy as np
scores = np.array([55, 82, 91, 47, 73, 100])
pass_mask = scores >= 60
print("Pass mask:", pass_mask)
print("Pass scores:", scores[pass_mask])
excellent = scores >= 90
print("Excellent:", scores[excellent])
mid_range = (scores >= 60) & (scores < 90)
print("Mid-range:", scores[mid_range])
> 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.
(3) ▶ サンプル:ユニバーサル関数 の出力パラメータの使用(難易度 ⭐⭐)
import numpy as np
a = np.array([10, 20, 30, 40])
b = np.array([3, 4, 5, 6])
# In-place addition using out parameter
result = np.empty(4)
np.add(a, b, out=result)
print("Result:", result)
# Chain operations with out
np.multiply(result, 2, out=result)
print("Doubled:", result)
# Comparison ufunc
print("a > 15:", np.greater(a, 15))
出力:
TEXT結果:[13 24 35 46] 2倍:[26 48 70 92] a > 15: [偽 真 真 真]
❓ よくある質問
+ ではなく np.add を使うのですか?+ が np.add を呼び出しています。 dtype、out、where のような追加のパラメータが必要な場合や、ユニバーサル関数 をコールバックとして渡す場合は、関数形式を使用してください。inf または -inf が生じ、0/0 では nan が生じます。また、 np.seterr に基づいて警告が表示される場合があります。整数のゼロ除算では ZeroDivisionError が発生します。📖 まとめ
- 算術演算子
+ - * / // % **は要素ごとの演算であり、それぞれに対応するnp.xxx関数がある - 比較演算子は、条件付きフィルタリング用のブールマスクを生成します
- 論理演算には
& | ^ ~を使用し、and or notは使用しません。また、np.logical_*の関数も使用可能です。 - Cレベルのufuncsを活用することで、ベクトル化はPythonのループよりも50~200倍高速です
- ufuncs は NumPy の要素単位演算エンジンであり、ブロードキャスティングと型昇格をサポートしています
📝 練習問題
-
初心者(難易度 ⭐):
x = np.linspace(-5, 5, 100)を作成してください。ベクトル化を用いてシグモイド関数1 / (1 + np.exp(-x))を計算し、0.5 を超える結果がいくつあるかを数えてください。 -
中級(難易度 ⭐⭐):forループとベクトル化の両方を用いて、100万個の乱数に対して
np.sin(x)を計算してください。実行時間を比較し、速度向上率を算出してください。 -
上級(難易度 ⭐⭐⭐):
x = np.linspace(-3, 3, 20)に対して、ベクトル化された ReLU 関数max(0, x)を実装してください。ブールマスクx * (x > 0)とnp.maximum(0, x)の両方を使用して実装してください。