행렬 곱셈의 조건
두 행렬의 곱셈은 모든 경우에 가능한 것이 아니라, 반드시 특정 조건을 만족해야만 수행할 수 있습니다. 두 행렬 P와 Q가 있고, 각각의 차원이 P(a × b), Q(z × y)라고 가정해 보겠습니다. 이때 두 행렬의 곱셈이 성립하려면 P의 열 개수(b)와 Q의 행 개수(z)가 반드시 같아야 합니다. 조건이 만족되면 결과 행렬 R의 크기는 (a × y)가 됩니다.
행렬 곱셈 알고리즘
위 조건을 바탕으로 한 행렬 곱셈의 의사 코드(pseudocode)는 다음과 같습니다.
matrixMultiply(P, Q):
P의 차원은 (a × b), Q의 차원은 (z × y)라고 가정
시작
만약 b ≠ z 라면 프로그램 종료
그렇지 않으면 결과 행렬 R을 (a × y) 크기로 정의
i를 0부터 a-1까지 반복:
j를 0부터 y-1까지 반복:
R[i][j] = 0 으로 초기화
k를 0부터 z-1까지 반복:
R[i][j] = R[i][j] + (P[i][k] * Q[k][j])
종료핵심은 세 겹의 반복문입니다. 바깥쪽 두 반복문이 결과 행렬의 각 위치(i, j)를 순회하고, 가장 안쪽 반복문이 해당 위치의 값을 계산하기 위해 필요한 곱셈과 덧셈을 수행합니다.
행렬 정규화란?
행렬 정규화(matrix normalization)는 각 행(row)을 하나의 벡터로 보고, 그 벡터의 길이(크기)가 1이 되도록 만드는 과정입니다. 구체적으로는 각 요소를 해당 행 전체 제곱합의 제곱근으로 나누면 됩니다.
예를 들어 다음과 같은 2×3 행렬이 있다고 가정해 보겠습니다.
4 5 6 1 2 3
첫 번째 행의 제곱합은 4² + 5² + 6² = 77이므로 √77로 나누고, 두 번째 행의 제곱합은 1² + 2² + 3² = 14이므로 √14로 나눕니다. 따라서 정규화된 행렬은 다음과 같습니다.
4/√77 5/√77 6/√77 1/√14 2/√14 3/√14
C 언어 전체 구현 예제
아래는 사용자로부터 행렬을 입력받아 각 행의 제곱합을 계산한 뒤, 정규화된 행렬을 출력하는 완전한 C 프로그램입니다.
#include <stdio.h>
#include <math.h>
int main() {
int row, col, i, j;
int matrix[50][50] = {0};
long long square[50] = {0};
double norm[50][50], k;
printf("행렬의 크기를 입력하세요: ");
scanf("%d %d", &row, &col);
printf("%dX%d 크기의 행렬 요소를 입력하세요:\n", row, col);
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
scanf("%d", &matrix[i][j]);
}
}
printf("\n입력된 행렬 (%d행 %d열):\n", row, col);
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
/* 각 행의 제곱합 계산 */
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
square[i] += (long long)matrix[i][j] * matrix[i][j];
}
printf("%d번째 행의 제곱합: %lld\n", i, square[i]);
}
/* 행렬 정규화 */
for (i = 0; i < row; i++) {
k = 1.0 / sqrt((double)square[i]);
for (j = 0; j < col; j++) {
norm[i][j] = k * matrix[i][j];
}
}
printf("\n정규화된 행렬:\n");
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
printf("%.3lf ", norm[i][j]);
}
printf("\n");
}
return 0;
}실행 결과
행렬의 크기를 입력하세요: 2 3 2X3 크기의 행렬 요소를 입력하세요: 4 5 6 1 2 3 입력된 행렬 (2행 3열): 4 5 6 1 2 3 0번째 행의 제곱합: 77 1번째 행의 제곱합: 14 정규화된 행렬: 0.456 0.570 0.684 0.267 0.535 0.802
정리
이 예제에서 확인할 수 있듯이, 정규화된 각 행의 요소를 다시 제곱하여 더하면 약 1에 가까운 값이 나옵니다. 즉, 각 행이 길이 1인 단위 벡터(unit vector)로 변환된 것입니다. 이러한 정규화 기법은 머신러닝의 특성 스케일링, 컴퓨터 그래픽스의 방향 벡터 처리 등 다양한 분야에서 널리 활용되므로, 행렬 곱셈의 기본 원리와 함께 꼭 익혀두는 것이 좋습니다.