• Skip to main content

HEADBOOST

  • Python
  • NumPy
  • 文法
現在の場所:ホーム / NumPy / NumPyの算術演算 / NumPyベクトル / NumPyで外積を取得するouter()関数の使い方

NumPyで外積を取得するouter()関数の使い方

NumPyでは2つの異なる配列から外積を求めるには、numpy.outer()を使います。この関数は基本的に2つの1次元配列(ベクトル)から外積を計算します。多次元配列を渡した場合は1次元配列化してから計算します。そのため複数のベクトルの外積を一度に取得するには不向きです。そのような場合は、np.multiply.outer()を使います。

このページではこれらについて詳しく解説します。

なお外積は、例えば a = [a0, a1, …, an] と b = [b0, b1, …, bm] という2つのベクトルがある場合、次のように算出されます。

|a→ x b→| =
[[a0*b0, a0*b1, ..., a0*bm],
[a1* b0, a1* b1, ..., a1* bm],
......
[an* b0, an* b1, ..., an* bm]]

それでは始めましょう。

目次

  • 1. numpy.outer()関数の使い方
    • サンプルコード
  • 2. ufunc.outer()メソッドの使い方
    • サンプルコード
  • 3. まとめ

1. numpy.outer()関数の使い方

まずは、numpy.outer()の書式を確認しましょう。

numpy.outer関数

書き方:

np.outer(a, b, out=None)

パラメーター:

引数 型 解説
a   array_like  
(M, )
ベクトル。多次元配列の場合1次元配列のフラット化される。
b   array_like
(N, )
同上
out*   ndarray
(M, N)
これを指定した場合、指定した配列を関数の戻り値で上書きします。
* はオプション引数であることを示します。

戻り値: 

out: shape(M, N)の配列
aとbの外積を要素とした配列を戻します。out[i, j] = a[i] * b[j] です。

一緒に確認したい関数:

  • inner
  • einsum
  • tensordot
  • ufunc.outer

サンプルコード

それではサンプルコードを見てみましょう。

numpy.outer()は、引数に渡した2つの1次元配列(ベクトル)a とb の外積を算出します。

In [1]:
import numpy as np
a = np.array([1, 5, 3])
b = np.array([2, 4, 6])
np.outer(a, b)
Out[1]:
array([[ 2,  4,  6],
       [10, 20, 30],
       [ 6, 12, 18]])

多次元配列を渡した場合もベクトル化(1次元配列化)して処理します。

In [2]:
# 多次元配列を渡した場合も1次元化して計算
a = np.array([1, 5, 3, 2]).reshape(2, 2)
b = np.array([2, 4, 6])
np.outer(a, b)
Out[2]:
array([[ 2,  4,  6],
       [10, 20, 30],
       [ 6, 12, 18],
       [ 4,  8, 12]])

このように、numpy.outer()は1次元配列(ベクトル)同士の外積を算出します。

単純に2つのベクトルの外積を求めるだけなら、これを使えば十分です。しかし、複数のベクトルを格納した多次元配列から、外積を一括で取得したい場合はnumpy.outer()は不向きです。その場合は、次に解説するufunc.outer()を使います。

2. ufunc.outer()メソッドの使い方

結論から言うと、複数のベクトルデータを格納している多次元配列(例えば1次元軸要素に1つのベクトルというように)から、それぞれの外積を一括で取得したいような場合は、ufunc.outer()メソッドを使って、np.multiply.outer()と書く方が遥かに適しています。

ufunc というと見慣れない方も多いかもしれません。簡単に言うと、これは関数のことです。つまり、ufunc.outer() とは np.multiply() やnp.add() などの関数の後につなげて、np.multiply.outer() やnp.add.outer() というように使うメソッドであるということを意味します。

この ufunc.outer()メソッドは、次のようにfor文を回すのと同じことをします。配列A と B の次元数によってfor文を回す回数が異なりますが、以下では1次元配列同士の場合と2次元配列同士の場合を示しています。

# 1次元配列同士の場合
r = np.empty((A.size,B.size))
for i in range(A.size):
    for j in range(B.size):
        r[i,j] = op(A[i], B[j]) # op は任意の関数
# 2次元配列同士の場合
r = np.empty(a.shape + b.shape)
for i in range(a.shape[0]):
    for j in range(a.shape[1]):
        for k in range(b.shape[0]):
            for l in range(b.shape[1]):
                r[i, j, k, l] = op(a[i, j], b[k, l])  # op は任意の関数

以上のコードの最後の行の op は任意の関数です。ここでnp.multiply()を使うと、それぞれの配列から外積を取得するのと同じ処理になります。

つまり、np.multiply.outer(A, B)と書くことで、配列A, B のいずれかの軸に格納されているベクトルデータa やb から外積を算出することができます。

先に解説したnp.outer()との具体的な違いは、戻り値である外積を要素とした配列のshapeにあります。np.outer()は引数に渡した配列を1次元化して計算を行います。そのため、戻り値の配列のshapeは常に(a.size, b.size)です。一方で、np.multiply.outer()では、戻り値の配列のshape は常に a.shape + b.shape になります。例えば、前者がshape(2, 3) で後者がshape(4, 5) ならshape(2, 3, 4, 5) となります。

このようなわけでnp.multiply.outer()では、複数のベクトルデータセットから外積を一括で取得することができます。

それでは、ufunc.outer()の書式は次の通りです。

ufunc.outerメソッド

書き方:

ufunc.outer(A, B, **kwargs)

パラメーター:

引数 型 解説
A   array_like     配列
B   array_like  配列
kwargs*   any  dtype やout などのキーワード引数を設定可能です。
** はキーワード引数であることを示します。

戻り値: 

配列:上のコードのfor文を回した後のr

一緒に確認したい関数:

  • numpy.outer:
  • tensordot:

サンプルコード

解説は上で十分に行ったので、ここでは多次元配列同士の場合の処理を確認しておきましょう。

以下の2つの2次元配列を使います。

In [1]:
import numpy as np
a = np.array([1, 5, 3, 2]).reshape(2, 2)
a
Out[1]:
array([[1, 5],
       [3, 2]])
In [2]:
b = np.array([2, 4, 6, 7, 8, 9]).reshape(2, 3)
b
Out[2]:
array([[2, 4, 6],
       [7, 8, 9]])

np.multiply.outer()では、それぞれの外積をshape(2, 2, 2, 3)の形で返します。

In [3]:
#  np.multiply.outer()は、
# shape(a.shape, b.shape)で
# 外積を戻す。

 np.multiply.outer(a, b)
Out[3]:
array([[[[ 2,  4,  6],
         [ 7,  8,  9]],

        [[10, 20, 30],
         [35, 40, 45]]],


       [[[ 6, 12, 18],
         [21, 24, 27]],

        [[ 4,  8, 12],
         [14, 16, 18]]]])

ご覧のように、これを使うと、複数のベクトルの外積を一度に取得しているのと同じことになります。任意の外積はスライスで取り出すことができます。

In [4]:
 np.multiply.outer(a, b)[0, 0]
Out[4]:
array([[2, 4, 6],
       [7, 8, 9]])

一方で、np.outer()は1次元化して計算するため、使い勝手の面では劣ります。

In [5]:
#  np.outer()は、
# shape(a.size, b.size)で
# 外積を戻す。

np.outer(a, b)
Out[5]:
array([[ 2,  4,  6,  7,  8,  9],
       [10, 20, 30, 35, 40, 45],
       [ 6, 12, 18, 21, 24, 27],
       [ 4,  8, 12, 14, 16, 18]])

3. まとめ

以上が、NumPyにおいてベクトルの外積を取得する方法です。

まとめると、1次元配列同士(1つのベクトルデータを格納している配列同士)の外積を知りたいだけであれば、numpy.outer()を使います。

しかし、例えば2次元配列(横軸に1つのベクトルデータが格納されており、それが縦軸の数だけ存在するようなデータ)を使って、一括で外積を取得したいような場合は、numpy.multiply.outer()を使います。

一見難しく感じるかもしれませんが、慣れれば簡単なので、ぜひ参考にして頂ければと思います。

このエントリーをはてなブックマークに追加
Tweet

Filed Under: NumPyベクトル moriyama

About moriyama

Reader Interactions

コメントを残す コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。

Copyright © 2021 ·