3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Rust] ベクトルが並んだ ndarray から各ベクトルのノルムをまとめて計算 [Python/numpy]

Posted at

d 次元ベクトルが N 個並んだ ndarray x が与えられたとします. 例えば d=3 次元空間ならこんな感じ.

>>> x = np.random.normal(size=(8,3))
>>> x
array([[-0.35165099,  0.75272535,  0.2327542 ],
[ 0.1591356 , -0.42135054, -0.47746836],
[-0.65012207,  0.42038207,  1.46586837],
[ 1.89249086, -0.9594884 ,  1.49124505],
[-2.04557264, -1.00044391, -3.70700719],
[-0.53573469, -0.91952356,  0.02255211],
[ 1.19644064,  0.13071411, -1.80561646],
[-0.68594263, -0.53059182, -0.47844146]])
>>> 
>>> x.shape
(8, 3)

本記事ではこの N 個のデータに対して一斉に Euclid ノルムを計算するといった問題を扱います. 従って欲しいものは shape (N,) の ndarray になります. なお以下では x, y は同じ shape (N, d) の 2 つのベクトルを表します.

Python (numpy) 版

for i in range(N) みたいな感じで順番に処理するのはとても遅いのでやめましょう. そのための numpy です. 要点は np.sum または np.max するときに axis=1 と指定することです.

Euclid 距離

$$\left| x, y \right| = \left[ \sum_{i=0}^{d-1} (x_i - y_i)^2 \right]^\frac{1}{2}$$

Euclid 距離

euclid = np.sqrt(np.sum( (x-y)**2, axis=1)) 

Euclid ノルム

euclid = np.sqrt(np.sum( (x**2, axis=1)) 

マンハッタン距離

$$\left| x, y \right| = \sum_{i=0}^{d-1} \left| x_i - y_i \right|$$

マンハッタン距離

manhattan = np.sum(np.fabs(x-y), axis=1)) 

マンハッタンノルム

manhattan = np.sum(np.fabs(x), axis=1)) 

Chebyshev 距離

$$\left| x, y \right| = \max ( | x - y | )$$

Chebyshev 距離

chebyshev = np.amax(np.fabs(x - y), axis=1)

Chebyshev ノルム

chebyshev = np.amax(np.fabs(x), axis=1)

Minkowski 距離 (Lp ノルム)

$$\left| x, y \right| = \left[ \sum_{i=0}^{d-1} \left| x_i - y_i \right|^p \right]^\frac{1}{p}$$

Minkowski 距離

minkowski = (np.sum( np.fabs(x-y)**p, axis=1))**(1./p)

$L^p$ ノルム

minkowski = (np.sum( np.fabs(x)**p, axis=1))**(1./p)

Rust 版

D: usize をコンパイル時定数として x: Vec<[f64;D]> に対して同じことをしてみます. 書くのが面倒になってきたのでノルムだけ.

Euclid 距離

let euclid = x.iter()
    .map(|v| v.iter().map(|&u| u*u).sum::<f64>().sqrt())
    .collect::<Vec<_>>();

マンハッタン距離

let manhattan = x.iter()
    .map(|v| v.iter().map(|&u| u.abs()).sum::<f64>())
    .collect::<Vec<_>>();

Chebyshev 距離

let chebyshev = x.iter()
    .map(|v| v.iter().map(|&u| u.abs()).fold(0.0/0.0, f64::max))
    .collect::<Vec<_>>();

参考: Rustでf32やf64の配列の最大値を得る方法

Minkowski 距離

let minkowski = x.iter()
    .map(|v| v.iter().map(|&u| u.abs().powf(p)).sum::<f64>().powf(1./p))
    .collect::<Vec<_>>();

Rust - ndarray 版

let euclid = (&x*&x).sum_axis(Axis(1))
    .mapv_into(|v| v.sqrt());
let manhattan = &x.mapv_into(|v| v.abs())
    .sum_axis(Axis(1));
let chebyshev = &x.mapv_into(|v| v.abs())
    .fold_axis(Axis(1), 0.0 / 0.0, |&p, &u| { f64::max(p,u)});
let minkowski = &x.mapv_into(|v| v.abs().powf(p))
    .sum_axis(Axis(1))
    .mapv_into(|v| v.powf(1./p));

関連項目

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?