NumPyレシピ | 複数のベクトルのノルム(大きさ)はnp.linalg.normで高速計算できる!

データサイエンス

Ciao!みなさんこんにちは!このブログでは主に
(1)pythonデータ解析,
(2)DTM音楽作成,
(3)お料理,
(4)博士転職
の4つのトピックについて発信しています。

今回はPythonデータ解析、複数のベクトルのノルムを高速に計算する方法です。一組のベクトルでしか内積を計算できないnp.dot()と異なり、ノルムの計算については複数のベクトルでもnp.linalg.norm()というメソッドを用いて計算することができます。速度的にもnp.linalg.norm()で十分です。

この記事を読めば、複数のベクトルのノルムを高速計算する方法がわかります。

Kaiko
Kaiko

この記事はこんな人におすすめ

  • Pythonでデータ解析をしている
  • Numpyでベクトルのノルムを高速に計算したい



Abstract | 複数のベクトルのノルム計算はNumPyの関数でOK

前回の記事

では、複数組のベクトルの内積を計算するにはNumPyの関数np.dot()では対応していないので、高速計算するには工夫が必要と書きました。

今回は複数のベクトルの内積を求めることを考えます。こちらはnp.linalg.norm()の関数でaxis引数を指定することによって高速に計算が可能です。NumPyの関数は大抵はnp.linalg.norm()のように、配列計算に対応しているので、特に工夫しなくても高速計算ができる便利な仕様となっています。うまく活用して快適なデータ解析ライフを過ごしましょう!



Background | やりたいこと

\(n\)個のベクトル\(\vec{u}_{i}\)のノルム(ベクトルの大きさ)を計算することを考えます。すなわち出力としては\(n\)個のスカラー量を求めます。 例として、以下のように10000個の2次元ベクトル\(\vec{u}_{i}\)それぞれのノルムを求めることを考えます。

import numpy as np

# fix random seed
np.random.seed(0)

# number of sample
n = 10000

# get n vectors
u = np.random.normal(size=[n,2]) # n 2-dim vectors

# print first element of array
print('u:', u[0]) # 2-dim vector



Method | np.linalg.norm()を使う

複数のベクトルのノルムはnp.linalg.norm()で一発で計算できます。

np.linalg.norm()の挙動

axis引数を指定せずにnp.linalg.norm()を動かすと、与えられた配列全体が一つのベクトルであるとしてノルムが計算されます。
今回の例では2\(\times\)1000の行列全体のノルムが計算されます。

print(np.linalg.norm(u))

ここで、1000個のベクトル\(\vec{u}_{i}\)のうち一番最初のものを引数として与え、ノルムを計算してみます。

print(np.linalg.norm(u[0]))

今度はu[0]が一つのベクトルとして認識されるので、u[0]のノルムが計算されます。



axis引数によるノルム計算方向の指定

axis引数で、どの軸方向にノルムの計算を行うかを指定します。 この指定を行うことで、複数のベクトルのノルムを計算することができます。
この例では、axis = 0がベクトルの数、axis = 1が成分方向なので、axis = 1についてノルムを取ります。

import time

# time measurement befort calculation
t1 = time.process_time()

# get norm by np.linalg.norm()
val_norm = np.linalg.norm(u, axis = 1)

# time measurement after calculation
t2 = time.process_time()

# elapsed time
delta_t = t2 - t1 # sec
print('elapsed [ms]: ', delta_t * 10**3)

# print first 5 elements
print('val_norm:', val_norm[:5])

私の環境ではだいたい1から5ミリ秒程度となります。



Discussion | 成分計算との比較¶

試しに成分計算による実装を行って、np.linalg.norm()との比較をしてみましょう。

成分計算でm次元のベクトルn個のノルムを計算する関数

ノルムは各成分の二乗を足し上げてルートを取ったものです。以下のような関数として実装することができます。ここでは次元の数は未定(m次元)とし、次元方向にループを取ることにします。

# function to get norm by element-wise calculation
def get_norm_by_elmcal_md(u_s):
    """
    arguments:
        u_s <2d array [n,m]>: m-dim vectors
    returns:
        inner_prod <1d array [n]>: inner product
    """
    # get parameters
    n, m = np.shape(u_s) # number and dimension of vector
    
    # prepare output array
    val_norm = np.zeros([n]) # <1d array [n]>
    
    # loop for dimension
    for j in range(m):
        val_norm += u_s[:,j]**2
    
    # end 
    return val_norm**0.5



成分計算によるm次元のベクトルn個のノルムの計算

上の関数を使って先程の例のベクトルのノルムを計算してみます。

import time

# time measurement befort calculation
t1 = time.process_time()

# get norm by np.linalg.norm()
val_norm1 = get_norm_by_elmcal_md(u)

# time measurement after calculation
t2 = time.process_time()

# elapsed time
delta_t = t2 - t1 # sec
print('elapsed [ms]: ', delta_t * 10**3)

# print first 5 elements
print('val_norm1:', val_norm1[:5])

私の環境ではだいたい1から5ミリ秒程度となります。np.linalg.normを使う場合と変わりません。
np.linalg.normを使えば十分であることがわかります。



今回作成したPythonコード

今回書いたPythonコードを載せておきます。ご参考のためにご利用ください。



Conclusion | まとめ

最後までご覧頂きありがとうございます!
Pythonで複数のベクトルのノルムを高速に計算するをご紹介しました!

複数のベクトルの内積とは異なり、複数のベクトルのノルムはnp.linalg.norm()で簡単に高速計算ができます。みなさんも試してみてください!

以上「NumPyレシピ | 複数のベクトルのノルム(大きさ)はnp.linalg.normで高速計算できる!」でした!
またお会いしましょう!Ciao!

コメント

タイトルとURLをコピーしました