汎用関数 (ufunc)
1. 学習内容
- ❶ ユニバーサル関数(ユニバーサル関数)とは何か
- ❷ ユニバーサル関数 の属性:nin、nout、ntypes、types
- ❸ ユニバーサル関数 メソッド:reduce、accumulate、outer、reduceat
- ❹
np.frompyfuncを使用したカスタム ユニバーサル関数 の作成
2. 主要な概念
(1) ufuncとは何か
ユニバーサル関数(汎用関数)とは、ndarrayに対して要素単位で演算を行うC言語レベルの関数です。すべての算術演算子は、内部でufuncを呼び出しています。
PYTHON
import numpy as np
# Operators are ufuncs
print(np.add) # ufunc 'add'
print(np.multiply) # ufunc 'multiply'
print(np.sin) # ufunc 'sin'
# ufunc attributes
print(np.add.nin) # 2 (number of inputs)
print(np.add.nout) # 1 (number of outputs)
print(np.add.ntypes) # number of supported type combinations
(2) ユニバーサル関数 メソッド
PYTHON
a = np.array([1, 2, 3, 4, 5])
# reduce: apply repeatedly to reduce to single value
print(np.add.reduce(a)) # 15 (sum)
print(np.multiply.reduce(a)) # 120 (product)
# accumulate: running result
print(np.add.accumulate(a)) # [1 3 6 10 15]
# outer: apply to all pairs
print(np.multiply.outer([1, 2, 3], [10, 20, 30]))
# [[10 20 30]
# [20 40 60]
# [30 60 90]]
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
print("add:", np.add)
print("multiply:", np.multiply)
print("sin:", np.sin)
print(f"np.add.nin: {np.add.nin}")
print(f"np.add.nout: {np.add.nout}")
print(f"np.add.ntypes: {np.add.ntypes}")
出力:
TEXTadd: ユニバーサル関数 'add' multiply: ユニバーサル関数 'multiply' sin: ユニバーサル関数 'sin' np.add.nin: 2 np.add.nout: 1 np.add.ntypes: 22
(2) ▶ サンプル:ユニバーサル関数 reduce と accumulate(難易度 ⭐⭐)
PYTHON
import numpy as np
a = np.array([1, 2, 3, 4, 5])
# reduce: apply repeatedly to get a single value
print("add.reduce:", np.add.reduce(a))
print("multiply.reduce:", np.multiply.reduce(a))
# accumulate: running result
print("add.accumulate:", np.add.accumulate(a))
print("multiply.accumulate:", np.multiply.accumulate(a))
出力:
TEXTadd.reduce: 15 multiply.reduce: 120 add.accumulate: [ 1 3 6 10 15] multiply.accumulate: [ 1 2 6 24 120]
(3) ▶ サンプル:ユニバーサル関数 outer(難易度 ⭐⭐)
PYTHON
import numpy as np
# Outer product: multiply every pair
x = np.array([1, 2, 3])
y = np.array([10, 20, 30, 40])
print("outer:\n", np.multiply.outer(x, y))
# Comparison outer
a = np.array([1, 3, 5])
b = np.array([2, 4, 6])
print("greater.outer:\n", np.greater.outer(a, b))
出力:
TEXT外側: [[ 10 20 30 40] [ 20 40 60 80] [ 30 60 90 120]] greater.outer: [[False False False] [ 真 偽 偽] [ True True False]]
Q ufuncと通常の関数の違いは何ですか?
A ufuncは要素単位で処理を行い、ブロードキャスト、型昇格、出力バッファリングを自動的に処理します。C言語で実装されているため、Pythonの関数よりもはるかに高速です。
Q カスタム ユニバーサル関数 を作成するにはどうすればよいですか?
A
np.frompyfunc(func, nin, nout) を使用して Python 関数をラップします。これにより生成される ユニバーサル関数 はブロードキャスティングに対応しますが、依然として Python レベルでの処理となるため、パフォーマンスには限界があります。Q
reduceat とは何ですか?A
np.add.reduceat(a, indices) は、特定のスライスに対して reduce を適用します。セグメントごとの合計やグループ化された演算に役立ちます。❓ よくある質問
Q 最も重要なポイントは何か?
A NumPyの演算はベクトル化されているため、パフォーマンスを向上させるにはPythonのループは避けるべきだ。
Q さらに詳しく知りたい場合はどうすればよいですか?
A 詳細なリファレンスや高度なトピックについては、numpy.org の NumPy 公式ドキュメントをご覧ください。
Q これはNumPy 2.xでも動作しますか?
A はい。すべての例はNumPy 2.xと互換性があります。一部の古いAPI(np.random.seedなど)は引き続きサポートされていますが、最新の代替APIの使用をお勧めします。
📖 まとめ
- ufuncs は C レベルの要素ごとの関数です:
np.add、np.multiply、np.sinなど。 - 属性:
nin、nout、ntypes、typesは、ユニバーサル関数 インターフェースを記述しています - 手法:
reduce(単一値)、accumulate(連続)、outer(全ペア)、reduceat(セグメント) - ufuncs は、NumPy のベクトル化とブロードキャスティングを支える基盤です
📝 練習問題
-
初心者向け(難易度 ⭐):
np.addの属性(nin、nout、ntypes、types)を挙げてください。それぞれの意味を説明してください。 -
中級(難易度 ⭐⭐):
np.add.reduceを使って配列の和を求め、np.add.accumulateを使って累積和を計算し、np.multiply.outerを使って九九表を作成してください。 -
上級(難易度 ⭐⭐⭐):
np.frompyfuncを使用して、2つの数値のうち大きい方を返すカスタム ユニバーサル関数 を作成します。これを2つの配列に適用し、np.maximumと比較してください。