こんにちは、小澤です。
前回は、NumPyの応用機能として、サンプル配列を用いた関数について学びました。今回も引き続き、NumPyの応用機能について学んでいきましょう。教科書『Pythonによる新しいデータ分析の教科書(第2版)』の4.1.3章「NumPyの各機能」ではブロードキャストと配列の掛け算の部分(124ページ〜129ページ)です。
ブロードキャスト
NumPyのブロードキャストは、異なる形状の配列間で算術演算を行う際に、自動的に次元を調整する機能です。これにより、配列のサイズが異なる場合でも、明示的な次元の調整なしに演算を行うことが可能になります。ブロードキャストは、ユニバーサルファンクションと同じく、NumPyにとって非常に強力な機能です。
まず、ブロードキャストのルールについて整理しておきましょう。
- 次元の数が異なる場合:次元の数が少ない配列の形状の先頭に1を追加して、両方の配列の次元数を揃えます。
- 特定の次元のサイズが1の場合:その次元に沿って、大きいサイズに合わせて要素をコピーします。
- いずれの次元のサイズも互いに一致するか、どちらかが1である場合:ブロードキャストが可能です。
- 上記の条件を満たさない場合:ブロードキャストは不可能であり、エラーが発生します。
スカラーと配列の四則演算
スカラー(単一の数値データ)と配列を四則演算する場合、スカラーは配列の各要素に加算されます。なお、NumPyをインポートしますが、ここではnpと別名定義しています。
import numpy as np # 配列の定義 a = np.array([10, 20, 30]) # スカラーとの加算 a + 5 # array([15, 25, 35]) # スカラーから配列の各要素を引く 5 – a # array([ -5, -15, -25]) # スカラーとの掛け算 a * 2 # array([20, 40, 60]) # スカラーのべき乗 a ** 2 # array([100, 400, 900]) # スカラーで割る a / 10 # array([1., 2., 3.]) # 割り切れない場合 a / 3 # array([ 3.33333333, 6.66666667, 10. ]) # ゼロで除算した場合 a / 0 # array([inf, inf, inf]) # 1e-10(10の-10乗)という非常に小さな数値で除算した場合 a / (1e-10) # array([[1.e+10, 2.e+10, 3.e+10], # [4.e+10, 5.e+10, 6.e+10]]) |
ちなみに、ブロードキャストを使わずにNumPy配列の各要素にスカラーを加える方法は以下のようになります。少々冗長になるかもしれません。
[x + 5 for x in a] # [15, 25, 35] |
異なるサイズの配列の足し算
次元が異なる2つの配列を加算する場合は、ブロードキャストによって自動的に形状が調整されます。
この例では、配列aは形状は (3, 1) 、配列 bは形状 (1, 3) です。ブロードキャストにより、aは各列にbの要素が加算される形で形状 (3, 3) に拡張され、bも同様に各行にaの要素が加算される形で形状 (3, 3) に拡張されます。結果として得られる配列は以下のようになります。
import numpy as np # 配列の定義 a = np.array([10, 20, 30]) # [10 20 30] # 形状が(3, 1)の配列 b = np.array([[1], [2], [3]]) # [[1] # [2] # [3]] # 配列の足し算 a + b # array([[11, 21, 31], # [12, 22, 32], # [13, 23, 33]]) # 引き算 a – b # array([[ 9, 19, 29], # [ 8, 18, 28], # [ 7, 17, 27]]) # 掛け算 a * b # array([[10, 20, 30], # [20, 40, 60], # [30, 60, 90]]) # 割り算 a / b # array([[10. , 20. , 30. ], # [ 5. , 10. , 15. ], # [ 3.33333333, 6.66666667, 10. ]]) |
配列の掛け算
NumPyで配列の掛け算を行う方法には、要素ごとの掛け算と行列積(ドット積)の2種類があります。これらは異なる計算を行うため、使用する状況に応じて適切な方を選択する必要があります。
要素ごとの掛け算
要素ごとの掛け算は、2つの配列の対応する要素同士を掛け合わせるものです。この操作には、*演算子またはnp.multiply()関数を使用します。配列の形状が異なる場合、ここでもブロードキャストのルールに従って形状が調整されます。
import numpy as np # 配列を定義 a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) # 要素ごとの掛け算 result = a * b # または result = np.multiply(a, b) print(result) # [ 4 10 18] |
行列積
行列積は、線形代数における行列の掛け算です。教科書で紹介しているのは、こちらの行列積です。2つの配列の行列積を計算するには、np.dot()関数、np.matmul()関数、または、@演算子を使用します。行列積を計算するためには、最初の配列の列数と2番目の配列の行数が一致している必要があります。
import numpy as np # 2×3行列 a = np.array([[1, 2, 3], [4, 5, 6]]) # 3×2行列 b = np.array([[7, 8], [9, 10], [11, 12]]) # 行列積 result = np.dot(a, b) # または result = a @ b # または result = np.matmul(a, b) print(result) # [[ 58 64] # [139 154]] |
まとめ
今回は、NumPyの配列操作におけるブロードキャストと掛け算を紹介しました。これらの機能は、さまざまな数値計算を効率的に行うために使用されますので、ぜひ理解してください。
次回も引き続き、NumPyの応用機能について説明します。真偽値、関数とメソッドを取り上げます。ぜひ次回もお楽しみにしてください。