TL;DR — 행렬곱은 왼쪽 행과 오른쪽 열을 곱해 더해 결과 칸을 만들고, 전치는 값은 보존한 채 행·열 축의 역할을 바꿉니다. 곱셈 가능 여부와 축의 의미를 함께 확인해야 합니다.
왜 배우나요? — AI는 데이터를 배치로 쌓아 한꺼번에 변환합니다. 행렬곱과 전치의 축 의미를 알아야 shape만 맞고 뜻은 틀린 오류를 막을 수 있습니다.
AI 어디에 쓰이나요? — 신경망 선형층과 Transformer 어텐션의 에서 행렬곱과 전치가 함께 등장합니다.
행렬곱 — 데이터를 한꺼번에 변환할 때
행렬곱은 한 표의 행과 다른 표의 열을 짝지어, 곱하고 더해서 새 표를 만드는 연산입니다.
왼쪽 행렬의 한 행은 “무엇을 얼마나 반영할지”를 담고 있고, 오른쪽 행렬의 한 열은 “계산에 들어갈 값들”을 담고 있습니다. 이 둘을 같은 위치끼리 곱한 뒤 모두 더하면 결과 행렬의 한 칸이 됩니다.
그래서 행렬곱은 단순히 표끼리 곱하는 것이 아니라, 한쪽 표에 들어 있는 규칙을 이용해 다른 쪽 표의 데이터를 새 형태로 바꾸는 연산입니다.
[칸 하나]에서는 결과 의 첫 칸 하나가 어떻게 만들어지는지 봅니다 — 왼쪽 의 파란 1행 과 위쪽 의 주황 1열 이 의 첫 칸에서 실제로 교차합니다. 두 띠의 값을 짝지어 곱해 더하면 입니다.
[행 하나]로 넘기면 같은 파란 의 1행은 고정되고, 주황 띠가 의 두 열을 모두 가리킵니다. 그래서 의 1행 전체 가 채워집니다.
[전체]에서는 의 2행까지 똑같이 훑어 네 칸이 모두 차고 이 완성됩니다. '행과 열이 만나 곱해서 더한다' — 이 한 문장이 그림 세 장에 다 들어 있습니다.
한 줄 정리 — 행렬곱의 각 칸은 왼쪽 행렬의 한 행(row)과 오른쪽 행렬(column)의 한 열을 짝지어 곱해서 더한 값입니다.
: 왼쪽 행렬 ()
: 오른쪽 행렬 ()
: 곱 결과 ()
: 안쪽 차원 — 의 열 수 = 의 행 수
의 행 열 = 의 행과 의 열의 내적
행과 열을 짝지어 곱해 더한 값
왜 행렬곱이 딥러닝의 엔진일까
행렬곱이 왜 그토록 중요할까요? 신경망의 한 층(layer)이 하는 일이 정확히 이 행렬곱이기 때문입니다. 완전연결층(FC(fully connected) layer)의 핵심 계산은 인데, 입력 데이터를 행으로 쌓은 배치 행렬 에 가중치 행렬 를 곱하면 수백 개의 샘플이 동시에 다음 표현으로 바뀝니다. 데이터를 한 개씩 100번 변환하는 대신, 100개를 쌓아 곱셈 한 번으로 끝내는 것이죠 — 위 그림에서 의 행이 여러 개였던 것이 바로 이 '여러 데이터'에 해당합니다.
요즘 많이 들리는 Transformer의 어텐션(attention)도 속을 열어 보면 행렬곱입니다. 토큰들의 질의 행렬 와 키 행렬 를 곱한 한 방으로 '어떤 토큰이 어떤 토큰과 얼마나 관련 있는지'를 전부 계산합니다. "딥러닝은 결국 행렬곱을 아주 많이 하는 것"이라는 말이 과장이 아닌 이유입니다.
Transpose(전치) — 행과 열을 뒤집기
방금 에서 위에 붙은 작은 가 전치(transpose)입니다. 전치는 값은 보존한 채 표의 행과 열을 맞바꾸는 연산입니다. 학생×과목 성적표를 전치하면 과목×학생 표가 됩니다. 라 쓰고, 입니다.
행렬곱은 안쪽 차원이 맞아야 하지만, 차원이 맞는다는 사실만으로 계산의 의미가 맞지는 않습니다. 어텐션에서 를 쓰는 이유는 토큰별 키 벡터를 열 방향에 놓아 각 질의와 모든 키의 내적을 계산하려는 명확한 축 설계 때문입니다. shape 오류가 났다는 이유만으로 임의의 행렬을 전치하면 샘플·특성 축이 뒤바뀐 조용한 오류가 생길 수 있습니다.
곱과 전치가 만나면 곱을 전치할 때 순서가 뒤집히는 규칙이 성립합니다.
: 의 전치 —
: 의 전치
곱을 전치하면 각 행렬을 전치하고 순서를 뒤집는다
(AB) 뒤집기 = (B 뒤집기) 곱하기 (A 뒤집기)
전치 그림에서 의 파란 첫 행 이 의 파란 첫 열로 이동합니다. 값은 그대로지만 shape는 에서 로 바뀌고, 행과 열이 맡던 역할도 서로 바뀝니다. 따라서 이 화면은 전치가 단순한 shape 수리가 아니라 축 의미를 바꾸는 연산임을 보여 줍니다.
표기
코드로 넘어가기 전에 수학 표기와 코드 표기의 차이를 짚어 두면 헷갈리지 않습니다. 세 가지만 기억하면 됩니다.
- 곱셈 기호: 수학에서는 처럼 붙여 쓰거나 , 로 씁니다. 그런데 코드에서
A * B라고 쓰면 행렬곱이 아니라 같은 자리끼리 곱하는 성분별 곱이 되어 버립니다. 진짜 행렬곱은 numpy에서@기호(또는np.matmul)로 씁니다 —A @ B. - 전치: 수학의 는 코드에서
A.T입니다. - 첨자 시작 번호: 수학은 처럼 1부터 세지만, 코드(파이썬·numpy)는 0부터 셉니다. 그래서 수학의 '1행 1열'은 코드에서
C[0, 0]입니다. 위 그림의 가 코드에서는C[0, 0]이라는 뜻이죠. 이 한 칸 차이 때문에 실수가 잦으니 눈에 익혀 두면 좋습니다.
이제 아래 코드로 직접 확인해 봅시다.
A = ([[1, 2], [3, 4]])
B = ([[5, 6], [7, 8]])
(A @ B) # 행렬곱 C = AB (수학의 A×B ↔ 코드의 @)
((A @ B).) # 곱의 전치 (AB)^T (수학의 ^T ↔ 코드의 .T)
(B @ A) # B^T A^T — 순서를 뒤집으면 같은 결과[[19 22] [43 50]] [[19 43] [22 50]] [[19 43] [22 50]]
A @ B 한 줄이 위 공식 그대로입니다 — 예를 들어 결과의 첫 칸 C[0, 0]은 로, 그림의 [칸 하나]에서 본 값과 정확히 같습니다. 아래 두 줄은 를 눈으로 확인합니다: (A @ B).T와 B.T @ A.T가 똑같은 행렬 [[19 43] [22 50]]을 내므로, 곱을 전치하면 순서가 뒤집힌다는 규칙이 실제로 성립함을 볼 수 있습니다.
마무리하기
데이터를 다룰 때 행렬곱과 전치는 거의 매 순간에 숨어 있습니다.
- 배치 처리: 이미지 128장을 행으로 쌓은 에 가중치 를 곱하면 여러 샘플을 같은 규칙으로 변환합니다.
- 임베딩 조회: 단어 벡터를 뽑은 뒤 다음 층의 행렬곱으로 넘깁니다.
- shape 점검: 곱이 안 되면 먼저 각 축이 샘플·특성·출력 중 무엇인지 확인합니다. 의도한 축이 정말 뒤집혀 있을 때만
.T를 씁니다. 차원만 맞춘 전치는 실행되더라도 의미가 틀린 조용한 오류를 만들 수 있습니다.
기억할 한 문장: 행렬곱은 안쪽 차원뿐 아니라 그 차원이 뜻하는 특성 축까지 맞아야 올바른 계산입니다.