Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonでのベクトル化とは?NumPyによる高速な配列演算の基礎を解説

本記事では、Python 3.xにおける「ベクトル化(Vectorization)」の概念と、その実装に用いられるさまざまなテクニックについて解説します。ループ処理を排除した効率的なコードの書き方を、具体例とともに見ていきましょう。

ベクトル化とは何か?

ベクトル化とは、ループを使用せずに配列操作を実装するテクニックです。関数を活用することで、コードの実行時間や計算時間を大幅に短縮できます。

ベクトル化では、配列に対して個別に処理を行うのではなく、ベクトル全体に対して一括で演算を実行します。代表的な演算には以下のようなものがあります。

  • ドット積(内積・スカラー積):2つのベクトルから単一のスカラー値を出力する演算
  • アウター積(外積):結果として、ベクトルの長さ × 長さ の次元を持つ正方行列を生成する演算
  • 要素ごとの乗算(Element-wise multiplication):同じインデックスの要素同士を掛け合わせる演算。行列の次元は変化しません

ドット積(内積)の実装例

それでは、従来のループ処理とNumPyによるベクトル化処理を比較してみましょう。以下のコードでは、10万〜30万の整数を持つ2つの配列のドット積を、それぞれの方法で計算し、処理時間を測定しています。

サンプルコード

import time
import numpy
import array

p = array.array('q')
for i in range(100000, 200000):
    p.append(i)

q = array.array('q')
for i in range(200000, 300000):
    q.append(i)

# 従来の方法:ループによるドット積
tic = time.process_time()
dot_value = 0.0
for i in range(len(p)):
    dot_value += p[i] * q[i]
toc = time.process_time()
print("dot_product of vector arrays = " + str(dot_value))
print("Computation time taken = " + str(1000 * (toc - tic)) + "ms")

# ベクトル化:NumPyによるドット積
n_tic = time.process_time()
n_dot_product = numpy.dot(p, q)
n_toc = time.process_time()
print("\nn_dot_product of vector arrays = " + str(n_dot_product))
print("Computation time taken = " + str(1000 * (n_toc - n_tic)) + "ms")

実行結果

dot_product of vector arrays = 3833313333350000.0
Computation time taken = 116.51723400000068ms

n_dot_product of vector arrays = 3833313333350000
Computation time taken = 2.5412239999997865ms

この結果を見ると、NumPyの dot() 関数を使ったベクトル化処理は、ループ処理と比較して約40倍以上高速であることがわかります。これは、NumPyが内部でC言語レベルの最適化された演算を行っているためです。

主要な関数の解説

ここで、上記のコードで使用した主な関数について詳しく見ていきます。

  • outer(a, b):2つのNumPy配列を引数として受け取り、2つのベクトルのアウター積(外積)を返します。
  • multiply(a, b):2つのNumPy配列を引数として受け取り、要素ごとの乗算(アダマール積)の結果を返します。
  • dot(a, b):2つのNumPy配列を引数として受け取り、ドット積(内積)を返します。
  • zeros((n, m)):形状とデータ型を引数として受け取り、指定された形状と型のゼロで初期化された行列を返します。
  • process_time():現在のプロセスのシステムCPU時間とユーザーCPU時間の合計値(小数秒)を返します。スリープ中の経過時間は含まれません。

まとめ

本記事では、Pythonにおけるベクトル化の基本概念と、NumPyを活用した高速な配列演算の方法について学びました。ループ処理をベクトル化された演算に置き換えることで、コードの可読性が向上するだけでなく、実行速度も大幅に改善されます。大規模な数値計算やデータ処理を行う際には、ぜひベクトル化を活用してみてください。

  1. 【初心者向け】Pythonでラップタイマーを作成する方法を解説

    Pythonを使ってストップウォッチのような「ラップタイマー」を作成するには、標準ライブラリの time モジュールが便利です。この記事では、Enterキーを押すたびにラップ時間を計測し、Ctrl+Cで計測を終了できるシンプルなラップタイマーの実装方法を、サンプルコードとともにわかりやすく解説します。ラップタイマーの仕組み基本的な仕組みは以下のとおりです。あらかじめラップ数は固定せず、無限ループで計測を続けるtry-exceptブロックを使い、Ctrl+C(KeyboardInterrupt)で安全に終了する現在時刻と開始時刻・前回ラップ時刻の差分から、合計時間とラップ時間を算出するサンプルコ

  2. Pythonで時系列データをプロットする方法をわかりやすく解説

    Pythonのmatplotlibを使えば、時系列データ(日時を軸にしたデータ)を簡単にグラフ化できます。ここでは、datetimeオブジェクトを含むデータを折れ線グラフとして描画する基本的な手順を紹介します。 時系列プロットの基本手順 numpyを使用して、x軸(日時データ)とy軸(数値データ)を作成します。 plot()メソッドを使って、作成したx・yのデータをプロットします。 show()メソッドを実行して、図を画面に表示します。 コード例 以下のサンプルコードでは、2021年1月1日の0時から23時までの24個の日時データを生成し、それに対応するランダムな数値をy軸としてプロットし