バッチでベクトルの内積を計算する [Chainer]

Chainer(本記事の執筆時点で最新版は v4.3.0)の標準関数でサポートされていない(と思う)のでメモ。

次のコードでベクトルの内積が計算できます。

import numpy as np
import chainer.functions as F
from chainer import Variable

def inner_product(a, b):
    return F.sum(a * b, axis=1)


# [0.1, 0.2] と [-0.5, 0.4] の内積 -> 0.03
# [0.3, 0.4] と [-0.3, 0.2] の内積 -> -0.01
a = Variable(np.array([[0.1, 0.2], [0.3, 0.4]], dtype=np.float32))
b = Variable(np.array([[-0.5, 0.4], [-0.3, 0.2]], dtype=np.float32))

inner_product(a, b)
# => variable([ 0.03 -0.01])

もうこれで十分な気がしますが、一応詳細を説明します。

ベクトル  \boldsymbol{a} = (a_1, a_2, \cdots, a_n)^\top \boldsymbol{b} = (b_1, b_2, \cdots, b_n)^\top内積は次のように表されます。

{\displaystyle \boldsymbol{a} \cdot \boldsymbol{b} = \sum_{i=1}^n a_i b_i}

つまり、各成分の積を足していけば OK です。

冒頭のコードでは、a * b で要素(成分)ごとの積を求めています。そして、F.sum()axis=1 として、バッチ内のインスタンス単位で要素の総和を計算しています。

余談: 要素積を求めるのに * 演算子を使えば良いことに気づくまでしばらくかかりました。該当する関数が無いか、かなりドキュメントを漁っていました…。