Chapter 6

내적과 투영

같은 방향 성분을 숫자로 재기
핵심 질문

두 벡터가 수직이면 내적은 왜 0일까?

내적과 투영

핵심 질문

두 벡터가 얼마나 같은 방향을 보는지 숫자로 잴 수 있을까?

교과서 설명

두 벡터 , 의 내적은 다음과 같다.

두 벡터의 길이를 같은 기준으로 비교하면, 내적은 방향이 비슷할수록 커지고 수직이면 이 된다.

내적은 한 벡터를 다른 벡터 방향으로 비추어 보는 투영과도 연결된다. 가 길이 인 방향 벡터라면, 가 그 방향으로 얼마나 뻗어 있는지를 말한다.

이 생각은 점들의 배열에도 그대로 쓸 수 있다. 두 배열을 벡터처럼 보면 내적은 같은 위치끼리 곱해서 더하는 계산이다.

두 배열의 방향만 비교하고 싶다면 길이의 영향을 나누어 볼 수 있다. 영벡터가 아닌 배열에 대해

처럼 생각하면 된다. 값이 에 가까우면 방향이 비슷하고, 에 가까우면 서로 지워지는 방향이며, 에 가까우면 반대 방향이다.

두 파동이 서로 잘 맞으면 이 합이 크게 남고, 서로 엇갈려 있으면 양수와 음수가 지워져 작아진다. 이런 관계를 직교라고 부른다.

투영 공식의 유도

내적 공식 는 “한 벡터가 다른 벡터 방향으로 얼마나 그림자를 드리우는가”를 수식화한 것이다. 가 영벡터가 아닐 때, 방향의 단위벡터를

라고 하면, 방향으로 가진 길이는 다. 이를 내적으로 쓰면

이고, 양쪽에 를 곱하면

가 된다. 그래서 일 때 이므로 내적도 이다.

배열 내적에서도 같은 해석이 가능하다. 길이 인 배열 , 의 벡터로 보면

이다. 서로 다른 주파수의 기본 파동들이 직교한다는 말은, 이 배열 내적이 이 된다는 뜻이다. DFT는 이 직교성을 복소수 회전값까지 확장해서 사용한다.

직관 비유

바람이 부는 방향으로 자전거를 타면 쉽게 간다. 바람과 자전거 방향이 같을수록 도움을 많이 받고, 수직이면 거의 도움을 받지 않는다. 이 “같은 방향 성분”을 재는 것이 내적이다.

예제

두 번째 벡터가 가로 방향이므로 첫 번째 벡터의 가로 성분이 크게 반영된다.

배열 내적 예시는 다음과 같다.

첫 번째 위치에서는 이 더해지고, 세 번째 위치에서는 이 더해져 서로 지워진다. DFT는 이 내적 아이디어를 여러 검사 파동에 대해 반복한다.

DFT를 준비하기 위해 코사인 배열끼리 직접 비교해 보자. 길이 에서 상수 파동과 한 번 출렁이는 코사인파는 다음처럼 점수가 이 된다.

서로 다른 주파수는 이렇게 양수와 음수가 지워지는 경우가 많다. 이 “지워짐”이 DFT에서 맞지 않는 주파수가 작게 나오는 이유다.

손풀이 체크

  1. 는?

    답 보기

    13+24=111\cdot3+2\cdot4=11

  2. 은?

    답 보기

    1+01+0=01+0-1+0=0

  3. 내적이 이면 두 방향은 어떤 관계라고 볼 수 있을까?

    답 보기

    서로 같은 방향 성분이 남지 않는 직교 관계로 볼 수 있다.

다음으로 이어지는 생각

복소수 곱셈은 벡터를 회전하고 늘리는 움직임처럼 볼 수 있다.

이번 장에서 기억할 3문장

  1. 내적은 두 벡터가 같은 방향으로 얼마나 겹치는지 재는 숫자다.
  2. 수직인 두 벡터의 같은 방향 성분은 없으므로 내적은 0이 된다.
  3. DFT도 신호와 검사 파동이 얼마나 잘 맞는지 재는 내적 관점으로 볼 수 있다.

C++ Practice

C++로 확인하기

내적 xy=x[n]y[n]x\cdot y=\sum x[n]y[n]과 직교를 배열로 확인하기

#include <iostream>
#include <vector>

using namespace std;

int dot(const vector<int>& a, const vector<int>& b) {
    int result = 0;
    for (int i = 0; i < static_cast<int>(a.size()); ++i) {
        result += a[i] * b[i];
    }
    return result;
}

int main() {
    vector<int> a = {1, 0, -1, 0};
    vector<int> b = {0, 1, 0, -1};
    vector<int> c = {1, 1, 1, 1};

    cout << "a dot b = " << dot(a, b) << "\n";
    cout << "a dot c = " << dot(a, c) << "\n";
}

연습: aa 또는 bb의 값을 바꿔서 ab=0a\cdot b=0이 되는 경우를 찾아보자.