행렬의 아다마르 곱
Hadamard Product of Matrices
정의
두 행렬 $A, B \in M_{m \times n}$의 아다마르 곱Hadamard product $A \odot B$를 다음과 같이 정의한다.
$$ A \odot B = \begin{bmatrix} a_{11} & \cdots & a_{1n} \\ \vdots & \ddots & \vdots \\ a_{m1} & \cdots & a_{mn} \end{bmatrix} \odot\begin{bmatrix} b_{11} & \cdots & b_{1n} \\ \vdots & \ddots & \vdots \\ b_{m1} & \cdots & b_{mn} \end{bmatrix} := \begin{bmatrix} a_{11}b_{11} & \cdots & a_{1n}b_{1n} \\ \vdots & \ddots & \vdots \\ a_{m1}b_{m1} & \cdots & a_{mn}b_{mn} \end{bmatrix} $$
$$ [A \odot B]_{ij} := [A]_{ij} [B]_{ij} $$
설명
$\odot$의 $\TeX$ 코드는 \odot
이다.
성분별 곱elementwise product이라고도 많이 부른다. 행렬 곱과는 다르게, 크기가 같아야 정의되고 교환법칙도 성립한다.
- $A \odot B = B \odot A$
- $(A \odot B) \odot C = A \odot (B \odot C)$
- $A \odot (B + C) = A \odot B + A \odot C$
- $k(A \odot B) = (kA) \odot B = A \odot (kB)$
프로그래밍 언어에서
이와 같은 성분별pointwise 연산은 기존의 연산에 점point .
을 추가하는 식으로 구현되어있다. 이러한 표기는 굉장히 직관적인데, 가령 곱셈이 *
라면 점별 곱셈은 .*
이다.
줄리아
julia> A = [1 2 3; 4 5 6]
2×3 Matrix{Int64}:
1 2 3
4 5 6
julia> B = [2 2 2; 2 2 2]
2×3 Matrix{Int64}:
2 2 2
2 2 2
julia> A.*B
2×3 Matrix{Int64}:
2 4 6
8 10 12
매트랩
>> A = [1 2 3; 4 5 6]
A =
1 2 3
4 5 6
>> B = [2 2 2; 2 2 2]
B =
2 2 2
2 2 2
>> A.*B
ans =
2 4 6
8 10 12
다만 파이썬의 경우 과학계산을 위한 언어가 아니기 때문에 줄리아나 매트랩과 같이 구현되어있지않다. 곱셈 기호 *
가 성분별 곱셈을 의미하고, 행렬곱은 @
로 쓴다.
>>> import numpy
>>> A = np.array([[1, 2, 3], [4, 5, 6]])
>>> B = np.array([[2, 2, 2], [2, 2, 2]])
>>> A*B
array([[ 2, 4, 6],
[ 8, 10, 12]])
>>> import torch
>>> A = torch.tensor([[1, 2, 3],[4, 5, 6]])
>>> B = torch.tensor([[2, 2, 2],[2, 2, 2]])
>>> A*B
tensor([[ 2, 4, 6],
[ 8, 10, 12]])