P2-3.6 선형대수를 NumPy로 확인하기¶
Section ID:
P2-3.6Version:v2026.07.20
P2-3.1에서는 스칼라(scalar), 벡터(vector), 행렬(matrix)의 모양을 봤습니다. P2-3.2에서는 벡터 공간(vector space)과 위치(position)의 직관을 봤고, P2-3.3에서는 행렬 곱(matrix multiplication)을 가중합(weighted sum)의 재사용으로 읽었습니다. P2-3.5에서는 파이썬 실행 환경을 Google Colab과 로컬 PC로 나누어 봤습니다.
이제 같은 내용을 작은 코드로 확인합니다. 여기서는 NumPy(넘파이)를 사용합니다. NumPy는 파이썬(Python)에서 배열(array)을 만들고 계산하는 대표적인 라이브러리입니다.
- 수식으로 봅니다.
- 배열로 만듭니다.
shape를 확인합니다.- 계산 결과를 확인합니다.
여기서는 NumPy 문법을 많이 외우기보다 선형대수 기호가 코드에서 어떤 모양으로 나타나는지 확인하는 데 집중합니다.
여기서는 NumPy, 배열(array), shape, 위치별 곱(element-wise multiplication), 행렬 곱(matrix multiplication)을 다시 정리합니다. 3.1에서 데이터 모양을 읽고 3.3에서 행렬 곱 구조를 읽었다면, 이제 그 계산이 코드와 출력에서 어떻게 보이는지 정리합니다.
여기서는 NumPy 전체 기능을 익히기보다 수식에서 본 선형대수 구조를 코드와 shape로 다시 확인하는 데 집중합니다. 벡터, 행렬, *, @, 배치 계산을 실제 출력으로 확인해 두면, 뒤에서 Pandas 데이터와 모델 입력 배열을 볼 때도 수식과 코드가 같은 구조라는 점을 더 쉽게 읽을 수 있습니다.
독자 기준으로는 코드가 되긴 되는데 지금 어느 절 개념을 확인하는가가 흐려지기 쉽습니다. 그래서 이 절에서는 각 예제가 P2-3.1의 모양(shape), P2-3.2의 벡터 비교, P2-3.3의 행렬 곱 중 무엇을 다시 확인하는지 함께 읽습니다.
| 지금 이 절에서 잡을 것 | 바로 다음에 이어질 질문 | 이후 다시 쓰이는 위치 |
|---|---|---|
| 수식과 NumPy 배열이 대응된다는 감각 | 이후 장에서 표 데이터와 모델 입력 배열이 어떻게 이어지는지 봅니다. | Part 3에서 X, y, train/test 분할 결과를 shape로 읽을 때 다시 씁니다. |
*와 @를 shape와 함께 구분하는 습관 | P2-12.1, P2-12.3, P2-13.1의 데이터 처리와 시각화 실습에서도 출력 모양을 함께 확인합니다. | Part 4의 선형층, Part 5의 임베딩·로짓 계산을 읽을 때 다시 등장합니다. |
| 배치 계산을 행렬 단위로 읽는 시선 | P2-4.1과 P2-5.1의 변화율·확률 설명, 이후 배열 변환 흐름으로 이어집니다. | 머신러닝 입력 행렬과 미니배치(batch) 설명을 따라갈 때 바탕이 됩니다. |
먼저 보는 개념 대응표¶
이 절의 예제는 앞 절의 개념을 다음처럼 다시 확인합니다.
| 코드 장면 | 다시 확인하는 앞 절 개념 | 독자가 먼저 볼 것 |
|---|---|---|
벡터 만들기와 shape | P2-3.1의 스칼라·벡터·행렬 모양 | 값보다 모양이 먼저 보이는가 |
벡터 a, b 비교 | P2-3.2의 위치와 가까움 직관 | 같은 길이의 벡터인가 |
a + b, 2 * a | P2-3.2의 벡터 공간 최소 연산 | 덧셈과 스칼라배가 코드에서 어떻게 보이는가 |
*와 @ 구분 | P2-3.3의 행렬 곱과 가중합 | 같은 위치 계산인지, 곱하고 더하는 계산인지 |
| 배치 행렬 계산 | P2-3.3의 여러 벡터를 한꺼번에 처리하는 관점 | 입력 행렬과 출력 행렬의 shape가 어떻게 바뀌는가 |
이 표를 먼저 붙잡으면 각 코드 블록이 단순 문법 예제가 아니라 앞 절 개념을 재확인하는 자리라는 점이 더 분명해집니다.
핵심 기준: 선형대수를 NumPy로 확인하기¶
- NumPy 배열(array)로 벡터와 행렬을 만들 수 있습니다.
.shape로 데이터 모양을 확인할 수 있습니다.- 벡터 덧셈과 스칼라배를 코드로 확인할 수 있습니다.
*와@의 차이를 설명할 수 있습니다.- 여러 샘플을 행렬로 묶어 같은 가중치 행렬을 적용하는 계산을 읽을 수 있습니다.
- 수식, shape, 코드 결과를 함께 보는 습관을 만들 수 있습니다.
세 가지 기준¶
| 기준 | 왜 중요한가 | 이 절에서 필요한 이해 수준 |
|---|---|---|
| NumPy는 수식의 배열 구조를 코드로 옮긴다 | 벡터와 행렬을 실제로 만들고 출력해 봐야 shape와 연산 차이를 확인할 수 있기 때문입니다. | NumPy를 배열 계산 도구로 이해합니다. |
| shape를 값보다 먼저 본다 | 계산 가능 여부와 입력·출력 구조를 가장 빨리 확인할 수 있기 때문입니다. | .shape로 길이와 행열 수를 먼저 읽는다고 이해합니다. |
*와 @를 구분한다 | 위치별 곱과 행렬 곱을 혼동하면 수식과 코드 해석이 함께 어긋나기 때문입니다. | *는 위치별 계산, @는 행렬 곱이라고 이해합니다. |
실행 환경¶
이 절의 코드는 NumPy가 설치된 파이썬 환경에서 실행할 수 있습니다.
실행 환경은 먼저 P2-3.5의 실행 환경을 먼저 구분한다를 기준으로 확인합니다. 파이썬을 아직 설치하지 않았다면 Google Colab 코드 셀에서 실행할 수 있고, 로컬 PC를 사용한다면 개인 PC 터미널에서 실행할 수 있습니다.
Colab 코드 셀에서는 다음처럼 NumPy를 준비할 수 있습니다.
문제 상황: Colab에서 본문의 NumPy 예제를 실행하기 전에 패키지를 준비합니다. 입력(input): 노트북 코드 셀의 %pip install numpy 명령입니다. 기대 출력(output): 현재 Colab 커널에 NumPy가 설치됩니다. 확인할 개념: Colab 코드 셀의 설치 명령과 Python 코드 실행은 서로 다른 단계라는 점을 봅니다.
로컬 PC 터미널에서는 다음 명령을 사용합니다.
그다음 파이썬 코드에서는 NumPy를 다음처럼 불러옵니다.
문제 상황: 패키지를 준비한 뒤 Python 코드 안에서 NumPy를 실제로 불러옵니다. 입력(input): import numpy as np 문장입니다. 기대 출력(output): 출력은 없지만 이후 예제에서 np 이름을 사용할 준비가 됩니다. 확인할 개념: 설치 명령과 import 문장은 실행 위치와 역할이 다르다는 점을 봅니다.
여기서 np는 NumPy를 짧게 부르기 위한 관례적인 별칭(alias)입니다.
이 절의 전체 예제 코드는 다음 파일로도 받을 수 있습니다.
프로젝트 루트에서 실행한다면 개인 PC의 터미널에서 다음 명령을 사용할 수 있습니다.
이 파일은 본문에 나오는 벡터 덧셈, 스칼라배, 위치별 곱, 행렬 곱, 배치 계산을 한 번에 출력합니다.
벡터와 행렬 만들기¶
벡터(vector)는 값의 목록으로 만들 수 있습니다.
이 예제는 P2-3.1에서 본 벡터는 1차원 배열처럼 읽을 수 있다는 점을 코드로 확인하는 자리입니다.
문제 상황: 수식에서 본 벡터를 NumPy 1차원 배열로 만들고 모양을 확인합니다. 입력(input): 값 두 개를 담은 배열 x입니다. 기대 출력(output): 벡터 값과 shape (2,)가 출력됩니다. 확인할 개념: 벡터는 NumPy에서 1차원 배열로 나타나며, shape로 길이를 확인할 수 있다는 점을 봅니다.
출력은 다음처럼 볼 수 있습니다.
(2,)는 값이 2개인 1차원 배열이라는 뜻입니다. 수식으로 쓰면 다음 벡터와 대응됩니다.
행렬(matrix)은 행(row)과 열(column)을 가진 2차원 배열로 만들 수 있습니다.
이 예제는 P2-3.1의 행렬은 여러 벡터를 모은 2차원 구조라는 설명을 다시 확인하는 자리입니다.
문제 상황: 수식에서 본 가중치 행렬을 NumPy 2차원 배열로 만들고 모양을 확인합니다. 입력(input): 2행 2열 배열 W입니다. 기대 출력(output): 행렬 값과 shape (2, 2)가 출력됩니다. 확인할 개념: 행렬은 NumPy에서 2차원 배열로 나타나며, 행과 열 수를 shape로 읽는다는 점을 봅니다.
출력은 다음처럼 볼 수 있습니다.
(2, 2)는 2행 2열이라는 뜻입니다.
shape을 먼저 확인한다¶
AI 코드에서 계산이 맞지 않을 때는 값보다 shape을 먼저 확인해야 할 때가 많습니다.
이 습관은 P2-3.2에서 말한 같은 공간에서만 비교한다는 기준을 코드 수준으로 옮긴 것입니다. 길이와 모양이 다르면 비교와 곱셈 자체가 성립하지 않을 수 있습니다.
문제 상황: 입력 벡터와 가중치 행렬이 계산 가능한 모양인지 먼저 점검합니다. 입력(input): 벡터 x와 행렬 W입니다. 기대 출력(output): x와 W의 shape가 출력됩니다. 확인할 개념: 선형대수 계산을 코드로 옮길 때는 값보다 shape을 먼저 확인해야 한다는 점을 봅니다.
출력은 다음과 같습니다. x shape: (2,), W shape: (2, 2)입니다.
이 정보는 x는 값이 몇 개인가, W는 몇 개 입력을 받아 몇 개 출력을 만드는가, 이 둘은 곱할 수 있는 모양인가라는 질문에 답하게 해 줍니다.
P2-3.3의 관점으로 읽으면, x는 입력값 2개를 가진 벡터이고 W는 입력 2개를 받아 출력 2개를 만드는 가중치 행렬(weight matrix)입니다.
벡터 덧셈과 스칼라배 확인하기¶
벡터 덧셈(vector addition)은 같은 위치의 값끼리 더합니다.
이 예제는 P2-3.2의 벡터 공간 최소 연산을 코드로 다시 확인하는 자리입니다. 즉 벡터는 비교만 하는 대상이 아니라, 더하고 크기를 바꿔 새 표현을 만들 수 있는 계산 대상입니다.
문제 상황: 두 벡터를 같은 위치끼리 더하는 기본 계산을 확인합니다. 입력(input): 길이 3 벡터 a, b입니다. 기대 출력(output): 위치별 합 [5 7 9]가 출력됩니다. 확인할 개념: 벡터 덧셈은 같은 위치의 값끼리 더하는 계산이라는 점을 봅니다.
출력은 다음과 같습니다.
수식으로는 다음과 같습니다.
스칼라배(scalar multiplication)는 배열의 각 값에 같은 숫자를 곱합니다.
문제 상황: 하나의 스칼라 값을 벡터 전체에 곱하는 계산을 확인합니다. 입력(input): 벡터 a와 스칼라 2입니다. 기대 출력(output): [2 4 6]이 출력됩니다. 확인할 개념: 스칼라배는 벡터 각 위치에 같은 숫자를 적용하는 계산이라는 점을 봅니다.
출력은 다음과 같습니다.
수식으로는 다음과 같습니다.
이 두 계산은 P2-3.2에서 말한 벡터 공간의 최소 계산과 연결됩니다.
*는 위치별 곱이다¶
NumPy에서 배열끼리 *를 사용하면 보통 위치별 곱(element-wise multiplication)이 됩니다.
이 예제는 P2-3.4에서 다시 보게 될 비교 질문과도 연결됩니다. 지금은 같은 위치의 값끼리 곱하는 연산이 어떤 모양인지 먼저 익히고, 뒤에서는 이와 다른 내적(dot product)이나 유사도 계산을 구분해 읽게 됩니다.
문제 상황: * 연산자가 행렬 곱이 아니라 위치별 곱으로 작동하는 예를 확인합니다. 입력(input): 길이 3 벡터 a, b입니다. 기대 출력(output): 위치별 곱 [ 4 10 18]이 출력됩니다. 확인할 개념: NumPy의 *는 같은 위치끼리 곱하는 element-wise 연산이라는 점을 봅니다.
출력은 다음과 같습니다.
수식으로는 다음과 같습니다.
여기서 중요한 점은 *가 행렬 곱이 아니라는 것입니다. 같은 위치끼리 곱하는 계산입니다. 즉 *는 위치별 곱이고 @는 행렬 곱입니다.
@는 행렬 곱이다¶
NumPy에서 @는 행렬 곱(matrix multiplication)에 사용합니다.
이 예제는 P2-3.3의 핵심을 코드로 되살리는 자리입니다. @는 같은 위치끼리 곱하는 연산이 아니라, 곱하고 더해 새 벡터를 만드는 가중합 구조입니다.
문제 상황: 입력 벡터와 가중치 행렬로 가중합 기반의 행렬 곱을 계산합니다. 입력(input): 길이 2 벡터 x와 2 x 2 행렬 W입니다. 기대 출력(output): 출력 벡터 y와 그 shape가 출력됩니다. 확인할 개념: @는 위치별 곱이 아니라 곱하고 더해 새 벡터를 만드는 행렬 곱이라는 점을 확인합니다.
출력은 다음과 같습니다.
이 계산은 P2-3.3에서 본 가중합과 같습니다.
첫 번째 출력은 다음 계산입니다.
두 번째 출력은 다음 계산입니다.
즉 @는 “곱하고 더해서 새 벡터를 만드는 계산”입니다.
여러 샘플을 한꺼번에 계산하기¶
여러 입력 샘플(sample)을 행렬로 묶으면 같은 가중치 행렬을 한 번에 적용할 수 있습니다.
문제 상황: 여러 샘플을 행렬로 묶어 같은 가중치 행렬을 한 번에 적용하는 배치 계산을 확인합니다. 입력(input): 2 x 2 입력 행렬 X와 2 x 2 가중치 행렬 W입니다. 기대 출력(output): X, W, Y의 shape과 배치 계산 결과 행렬이 출력됩니다. 확인할 개념: 여러 샘플을 한꺼번에 계산할 때도 핵심은 행렬 shape의 호환성이라는 점을 봅니다.
출력은 다음과 같습니다.
수식으로는 다음과 같습니다.
여기서 첫 번째 행은 첫 번째 샘플의 출력이고, 두 번째 행은 두 번째 샘플의 출력입니다. 즉 입력 샘플 2개가 있고, 각 샘플은 값 2개를 가지며, 같은 W를 적용한 뒤, 출력 샘플도 2개가 되고 각 출력은 값 2개를 가집니다.
이것이 배치(batch) 계산의 가장 작은 예시입니다.
shape 오류를 의도적으로 생각해 보기¶
다음 계산은 바로 맞지 않습니다.
문제 상황: 입력 벡터 길이와 가중치 행렬 입력 방향 크기가 다를 때 어떤 문제가 생기는지 확인합니다. 입력(input): 길이 3 벡터 bad_x와 2 x 2 행렬 W입니다. 기대 출력(output): 행렬 곱 시도에서 shape 불일치 오류가 납니다. 확인할 개념: 선형대수 코드는 값이 아니라 모양이 맞아야 실행된다는 점을 다시 확인합니다.
bad_x의 shape은 (3,)이고, W의 shape은 (2, 2)입니다. 입력값은 3개인데 가중치 행렬은 입력 2개를 받는 모양입니다. 즉 bad_x shape: (3,), W shape: (2, 2)입니다.
따라서 어떤 입력값과 어떤 가중치를 곱해야 하는지 맞지 않습니다. 실제 NumPy는 이런 경우 shape이 맞지 않는다는 오류를 냅니다.
오류 메시지를 외우는 것보다 중요한 것은 왼쪽의 마지막 크기와 오른쪽의 입력 방향 크기가 맞는지, 내가 곱하려는 것이 위치별 곱인지 행렬 곱인지, 출력 shape은 무엇이 되어야 하는지를 묻는 일입니다.
사례 및 예시¶
사례 1. shape을 확인하지 않으면 왜 같은 코드가 갑자기 안 맞을까¶
학습자가 NumPy 예제를 따라 하다가 *와 @를 섞거나, 벡터 길이와 행렬 크기를 맞추지 못해 오류를 만나는 경우가 많습니다. 숫자만 보면 비슷해 보여도, NumPy는 값보다 먼저 모양(shape)이 맞는지를 기준으로 계산 가능 여부를 판단합니다.
예를 들어 길이 2의 벡터 x와 2 x 2 행렬 W는 x @ W로 곱할 수 있습니다. 하지만 입력 벡터 길이가 3으로 바뀌었는데 가중치 행렬은 그대로 두면, 어떤 값과 어떤 가중치를 조합해야 할지 정할 수 없어 계산이 막힙니다.
이 사례는 왜 값부터 보지 말고 shape부터 보라는 말을 반복하는지를 보여 줍니다. 선형대수 수식에서는 기호가 간단해 보여도, 코드에서는 각 벡터와 행렬이 실제로 몇 개의 값으로 이루어졌는지 확인해야 같은 계산을 재현할 수 있습니다.
즉 NumPy 실습의 핵심은 문법 외우기보다 수식의 구조를 shape로 다시 확인하는 데 있습니다. *는 위치별 곱인지, @는 행렬 곱인지, 입력과 출력 차원이 어떻게 이어지는지를 읽는 기준이 뒤의 모델 계산으로 그대로 이어집니다.
체크리스트¶
- NumPy 배열(array)로 벡터와 행렬을 만들 수 있다.
.shape로 벡터와 행렬의 모양을 확인할 수 있다.- 벡터 덧셈과 스칼라배를 코드와 수식으로 연결할 수 있다.
- NumPy의
*가 위치별 곱(element-wise multiplication)임을 설명할 수 있다. - NumPy의
@가 행렬 곱(matrix multiplication)임을 설명할 수 있다. x @ W에서 입력 shape, 가중치 shape, 출력 shape을 읽을 수 있다.- 여러 샘플을 행렬로 묶어 같은 가중치 행렬을 적용하는 배치(batch) 계산을 설명할 수 있다.
- NumPy에서 문법 자체보다 수식, shape, 출력이 서로 맞는지 함께 보는 습관을 설명할 수 있다.
*와@를 구분하고, 값보다 shape를 먼저 보는 기준을 적용할 수 있다.
출처와 참고 자료¶
- 이 절의 예제 코드: p2_3_6_numpy_linear_algebra.py
- NumPy Developers, NumPy documentation, 확인 날짜: 2026-07-19.
- NumPy Developers, NumPy quickstart, 확인 날짜: 2026-07-19.
- NumPy Developers,
numpy.array, 배열 생성 API의 인자와 예제를 확인할 수 있습니다. 확인 날짜: 2026-07-19. - NumPy Developers,
numpy.ndarray.shape, 배열 차원을 튜플로 확인하는shape속성을 확인할 수 있습니다. 확인 날짜: 2026-07-19. - NumPy Developers,
numpy.matmul, 행렬 곱과 shape 불일치 오류 조건을 확인할 수 있습니다. 확인 날짜: 2026-07-19. - Charles R. Harris et al., Array Programming with NumPy, Nature, 2020, 확인 날짜: 2026-07-19.