アダマール積とは?定義やPythonでの実装を解説

アダマール積(Hadamard product)は、2つの行列の同じ位置の要素同士を掛け合わせる演算です。element-wise product(要素ごとの積)とも呼ばれ、機械学習や深層学習の論文で頻繁に登場します。

本記事では、アダマール積の定義から性質、通常の行列積との違い、そして深層学習での活用例までを解説します。

本記事の内容

  • アダマール積の定義
  • 通常の行列積との違い
  • アダマール積の数学的性質
  • 深層学習での応用
  • Pythonでの実装

アダマール積の定義

数学的定義

同じサイズの2つの行列 $\bm{A}, \bm{B} \in \mathbb{R}^{m \times n}$ のアダマール積 $\bm{C} = \bm{A} \odot \bm{B}$ は、各成分の積として定義されます。

$$ (\bm{A} \odot \bm{B})_{ij} = a_{ij} \cdot b_{ij} $$

記号 $\odot$ や $\circ$ が使われますが、論文によっては $\bm{A} \ast \bm{B}$ と書くこともあります。

具体例

$$ \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} \odot \begin{pmatrix} 5 & 6 \\ 7 & 8 \end{pmatrix} = \begin{pmatrix} 1 \times 5 & 2 \times 6 \\ 3 \times 7 & 4 \times 8 \end{pmatrix} = \begin{pmatrix} 5 & 12 \\ 21 & 32 \end{pmatrix} $$

通常の行列積との違い

アダマール積と通常の行列積は全く異なる演算です。

アダマール積 $\bm{A} \odot \bm{B}$ 行列積 $\bm{A}\bm{B}$
サイズの条件 同じサイズ $m \times n$ $\bm{A}$: $m \times k$, $\bm{B}$: $k \times n$
結果のサイズ $m \times n$ $m \times n$
計算 対応する要素の積 行と列の内積
可換性 $\bm{A} \odot \bm{B} = \bm{B} \odot \bm{A}$ 一般に $\bm{A}\bm{B} \neq \bm{B}\bm{A}$
計算量 $O(mn)$ $O(mkn)$

アダマール積の性質

可換律

$$ \bm{A} \odot \bm{B} = \bm{B} \odot \bm{A} $$

通常の行列積とは異なり、アダマール積は可換です。

結合律

$$ (\bm{A} \odot \bm{B}) \odot \bm{C} = \bm{A} \odot (\bm{B} \odot \bm{C}) $$

分配律

$$ \bm{A} \odot (\bm{B} + \bm{C}) = \bm{A} \odot \bm{B} + \bm{A} \odot \bm{C} $$

単位元

全成分が1の行列 $\bm{J}$(ones行列)が単位元です。

$$ \bm{A} \odot \bm{J} = \bm{A} $$

シューアの積定理

$\bm{A}$ と $\bm{B}$ がともに半正定値行列ならば、$\bm{A} \odot \bm{B}$ も半正定値行列です。この定理は、カーネル法でカーネル関数の積が再びカーネル関数になることの根拠となります。

トレースとの関係

アダマール積とトレースには以下の関係があります。

$$ \text{tr}(\bm{A}^\top \bm{B}) = \sum_{i,j} a_{ij} b_{ij} = \bm{1}^\top (\bm{A} \odot \bm{B}) \bm{1} $$

ここで $\bm{1}$ は全成分が1のベクトルです。この関係はフロベニウス内積と呼ばれます。

深層学習での応用

ゲート機構(LSTM, GRU)

LSTMやGRUなどのリカレントニューラルネットワークでは、アダマール積がゲート機構として使われます。

例えばLSTMの忘却ゲートでは、

$$ \bm{c}_t = \bm{f}_t \odot \bm{c}_{t-1} + \bm{i}_t \odot \tilde{\bm{c}}_t $$

ここで $\bm{f}_t$(忘却ゲート)の各要素は $[0, 1]$ の値を取り、前の時刻のセル状態 $\bm{c}_{t-1}$ のどの要素を保持するかを制御します。

Attention機構

Transformer系モデルのマスク付きAttentionでは、マスク行列とのアダマール積が使われます。

残差接続

一部のネットワークアーキテクチャでは、特徴量マップのスケーリングにアダマール積が用いられます。

Pythonでの実装

アダマール積の基本操作と性質の検証を行います。

import numpy as np
import matplotlib.pyplot as plt

# アダマール積の基本
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

# アダマール積(要素ごとの積)
hadamard = A * B  # NumPyでは * がアダマール積
matrix_product = A @ B  # @ が行列積

print("行列 A:")
print(A)
print("\n行列 B:")
print(B)
print(f"\nアダマール積 A * B:\n{hadamard}")
print(f"\n行列積 A @ B:\n{matrix_product}")

# 性質の検証
C = np.array([[2, 1], [0, 3]])

# 可換律
print(f"\n可換律: A*B == B*A ? {np.allclose(A*B, B*A)}")

# 結合律
print(f"結合律: (A*B)*C == A*(B*C) ? {np.allclose((A*B)*C, A*(B*C))}")

# 分配律
print(f"分配律: A*(B+C) == A*B+A*C ? {np.allclose(A*(B+C), A*B + A*C)}")

# トレースとの関係
trace_val = np.trace(A.T @ B)
hadamard_sum = np.sum(A * B)
print(f"\ntr(A^T B) = {trace_val}")
print(f"sum(A * B) = {hadamard_sum}")
print(f"一致: {trace_val == hadamard_sum}")

# シューアの積定理の検証
np.random.seed(42)
n = 5

# 半正定値行列の生成(A = X^T X で構成)
X1 = np.random.randn(10, n)
X2 = np.random.randn(10, n)
A_psd = X1.T @ X1
B_psd = X2.T @ X2

# アダマール積
C_hadamard = A_psd * B_psd

# 固有値の確認
eig_A = np.linalg.eigvalsh(A_psd)
eig_B = np.linalg.eigvalsh(B_psd)
eig_C = np.linalg.eigvalsh(C_hadamard)

print(f"\nシューアの積定理:")
print(f"A の最小固有値: {eig_A.min():.6f} (>= 0)")
print(f"B の最小固有値: {eig_B.min():.6f} (>= 0)")
print(f"A*B の最小固有値: {eig_C.min():.6f} (>= 0)")

# ゲート機構の可視化(LSTMの忘却ゲートのイメージ)
fig, axes = plt.subplots(1, 4, figsize=(16, 4))

signal = np.random.randn(8, 8)
gate = 1 / (1 + np.exp(-np.random.randn(8, 8) * 3))  # シグモイド
gated_signal = signal * gate

axes[0].imshow(signal, cmap='RdBu', vmin=-2, vmax=2)
axes[0].set_title('Signal')
axes[1].imshow(gate, cmap='gray', vmin=0, vmax=1)
axes[1].set_title('Gate (sigmoid)')
axes[2].set_text(0.5, 0.5, '$\\odot$', fontsize=40, ha='center', va='center',
                 transform=axes[2].transAxes)
axes[2].axis('off')
axes[3].imshow(gated_signal, cmap='RdBu', vmin=-2, vmax=2)
axes[3].set_title('Gated Signal')

plt.suptitle('Hadamard Product as Gating Mechanism', fontsize=13)
plt.tight_layout()
plt.show()

このコードでは、アダマール積の基本的な性質の検証と、深層学習のゲート機構におけるアダマール積の役割を可視化しています。

まとめ

本記事では、アダマール積について解説しました。

  • アダマール積は同じ位置の要素同士を掛け合わせる演算であり、$(\bm{A} \odot \bm{B})_{ij} = a_{ij} b_{ij}$ で定義される
  • 通常の行列積とは異なり、可換律が成り立つ
  • シューアの積定理により、半正定値行列のアダマール積は半正定値であり、カーネル法の理論的基盤となる
  • 深層学習では、LSTMやGRUのゲート機構としてアダマール積が重要な役割を果たす