組み込み開発のためのPython · レッスン 124 / 238
NumPy Tutorial:配列計算を始める
NumPyは多次元配列ndarrayとベクトル化演算を提供します。配列のshape、dtype、軸を確認し、Pythonリストとの違いやコピー・ビューの挙動を理解します。
NumPyは多次元配列ndarrayとベクトル化演算を提供します。配列のshape、dtype、軸を確認し、Pythonリストとの違いやコピー・ビューの挙動を理解します。 仕組みだけでなく、検証方法と運用上の注意も具体例で確認します。
NumPyを使う場面と役割
NumPyは数値データを多次元配列として保持し、同じ処理を多数の要素へまとめて適用するためのPythonライブラリーです。センサーの時系列、画像の画素、実験の反復結果などを扱うとき、Pythonのループを一つずつ実行するより簡潔な式で計算できます。NumPyはPython標準機能ではないため、プロジェクトの仮想環境へ導入し、実行時に使われているインタープリターと同じ環境か確認してください。数値計算の結果は入力の単位、欠損値、データ型に依存するので、配列を作った時点で前提を記録します。
ndarrayとPythonリストの違い
ndarrayは同じ型の値を連続的に扱う数値配列で、要素ごとの加算や乗算を一括して記述できます。Pythonリストで二つの数値リストを足すと連結になりますが、NumPy配列同士の加算は対応する要素の和です。この差を知らずに置き換えると、計算の意味が変わることがあります。配列は通常、要素型dtypeを一つ持つため、整数と小数を混ぜたときにどの型へ変換されるかも確認します。用途に合わせてリストの柔軟さとndarrayの計算機能を選び、型変換を暗黙のままにしないことが大切です。
配列を作りdtypeを確認する
np.arrayへリストやタプルを渡すと配列を作れます。np.zerosやnp.arangeなどの関数は、既知の形や連番を用意するときに便利です。作成後はshape、ndim、size、dtypeを表示し、想定した次元数と要素型か確かめましょう。測定値を整数で保持するか、小数を含む浮動小数点で保持するかは、計算精度やファイル形式に影響します。必要な場合はdtypeを明示しますが、狭い整数型へ変換すると値が範囲を超えたときに情報を失う可能性があります。境界値を含む入力で変換結果を試験してください。
shapeと軸の意味を整理する
shapeは各次元の要素数を表します。長さが四つの時系列はshapeが(4,)となり、四つの時点で三チャンネルを測ったデータなら(4, 3)のような二次元配列になります。軸番号は配列の次元に対応し、axisを指定した合計や平均はその軸を集約して結果の次元を減らします。行をサンプル、列を特徴量とするか、時刻を先頭の軸に置くかをデータ仕様に記録してください。形の取り違えは、式が実行できても誤った値を出すことがあります。各変換の前後でshapeを確認する習慣を付けましょう。
添字、スライス、順序
NumPyの添字は通常ゼロから始まり、負の添字は末尾側から数えます。スライスでは開始位置を含み、終了位置を含まないため、範囲の長さを確認しやすい一方で境界を誤りやすい特徴があります。二次元配列では行と列の添字をカンマで分け、特定行、列、矩形範囲を選択します。スライスは元配列のビューになる場合があり、取得した値を書き換えると元データも変化することがあります。独立したコピーが必要ならcopyを使い、共有されたメモリーを意識してください。抽出した配列のshapeと先頭・末尾の値を確認すると、範囲ミスを早く見つけられます。
ベクトル化演算とブロードキャスト
配列全体に対する演算は、対応する要素へ処理を適用します。例えば校正値を各サンプルから引く式は、明示的なループを使わずに表せます。異なるshapeの配列を計算するときはブロードキャスト規則に従い、末尾側から次元を比較して、一方が1または存在しない軸を広げます。便利な規則ですが、意図しない次元が自動で拡張されて計算が成立する場合もあります。結果が妥当か、入力shapeと出力shape、代表的な数値を確認してください。ブロードキャストで大量の一時配列を作るとメモリーを消費するため、大規模データでは処理方法を測定します。
集計、欠損、非有限値
sum、mean、min、maxなどの集計は、データ全体または指定軸の統計量を求めます。平均を計算する前に、欠損や計測失敗をどの値で表すか決めてください。NaNが含まれると通常の平均がNaNになることがあり、nanmeanなどの関数はNaNを無視して計算しますが、全要素が欠損の場合の結果には注意が必要です。infや極端な外れ値も結果を変えます。欠損をゼロへ置き換える処理は、ゼロが実測値として意味を持つ場合に誤解を生みます。件数、欠損数、分母となる有効件数を合わせて記録し、処理の判断を説明してください。
真偽値マスクで条件を選ぶ
配列の比較は要素ごとの真偽値配列を返し、そのマスクを使って条件に合う要素を抽出できます。範囲で選ぶときは各比較を括弧で囲み、NumPyの論理演算子を使います。Pythonのandやorは配列全体の真偽値を一つに決めようとするため、複数要素の配列に使うと曖昧さのエラーになります。マスクの長さと元配列の要素数が対応していることを確かめ、条件に一致する値がゼロ件の場合も扱います。マスクで抽出した結果がコピーかビューかは操作によって異なるため、更新する場合は明示的なコピーを使うなど、元データへの影響を試験してください。
乱数と再現可能な試験
シミュレーションや試験データを作るときは、NumPyの乱数生成器を利用できます。新しいコードではdefault_rngから生成器を作る方法が推奨されます。同じseedを設定すると同じ環境で再現しやすくなりますが、NumPyの版やアルゴリズムが変わった場合まで全環境の同一系列が保証されるとは限りません。再現性が必要なら、ライブラリーの版、seed、データ生成条件も記録します。乱数を何度も使う処理では生成器を引数として渡すと、テストで制御しやすくなります。seedだけ固定して検証を省かず、生成値の範囲、分布、件数が要件に合うか確認しましょう。
線形代数と数値精度
NumPyには行列積、内積、転置、連立方程式などの線形代数機能があります。配列の形が積の規則に合っていることを確認し、行列の転置と要素ごとの演算を区別してください。浮動小数点数は多くの十進小数を正確に表現できないため、計算結果を等号で直接比較せず、必要な許容誤差を定めた近似比較を使います。整数演算では型の範囲を超えた場合の挙動も型ごとに確認する必要があります。結果の桁数を表示上丸めることと、内部の計算精度を変えることは別です。使用する関数の仕様と数値条件を確認してから、実データへ適用しましょう。
メモリーと性能を測る
配列は高速な計算に役立ちますが、複数の大きな配列を同時に保持するとメモリーを圧迫します。配列のnbytesは要素データのバイト数を示しますが、オブジェクトや周辺構造の全メモリー量とは異なる点に注意してください。不要な中間配列を作らない、適切な型を選ぶ、まとまりごとに処理するなどの方法を検討します。最適化の前に、入力サイズ、実行時間、ピークメモリーを測定し、Pythonのループが本当にボトルネックか確認してください。小さなデータでは読みやすい処理が最善であることもあります。性能改善後も、元の計算結果と一致するテストを残しましょう。
エラーを調べて練習する
配列のshape不一致、添字範囲外、型変換、空配列、無効な数値はよくある問題です。例外メッセージを読んで原因となる演算を特定し、エラーを広く捕捉して空の結果へ置き換えるのは避けてください。練習として、複数チャンネルの測定配列を作り、各チャンネルの平均、範囲外の値の抽出、欠損数を求めてください。サンプル数がゼロ、すべて欠損、想定外のshape、整数上限付近も試します。計算式とshapeを説明できるようにし、確認に使ったNumPyの版を記録します。公式ドキュメントの関数仕様と自分の結果を照合することも、理解を確かなものにします。
コード例
手元のPython環境に貼り付ける前に、使用しているPythonの版と対象ライブラリの対応を確認してください。
import numpy as np
samples_mv = np.array([3290, 3310, 3275], dtype=np.int32)
print(samples_mv.shape, samples_mv.dtype)
print(samples_mv.mean())手を動かす課題
同じ測定値をlistとndarrayで扱い、型、要素ごとの演算、平均の計算結果を比較してください。