벡터의 정규화 정의
벡터의 정규화는 주어진 벡터를 동일한 방향을 유지하면서 그 크기를 1로 만드는 작업이다. 이를 통해 벡터를 단위 벡터로 변환할 수 있다. 정규화는 컴퓨터 그래픽스, 물리 시뮬레이션, 데이터 과학 등 여러 응용 분야에서 필수적인 연산 중 하나로 사용된다.
수학적으로, 임의의 벡터 \mathbf{v}의 정규화는 다음과 같이 정의된다:
여기서:
- \mathbf{v}는 정규화할 벡터이다.
- \mathbf{\hat{v}}는 \mathbf{v}의 정규화된 벡터이다.
- \|\mathbf{v}\|는 벡터 \mathbf{v}의 크기(또는 노름)로, 다음과 같이 계산된다:
즉, 벡터의 각 성분의 제곱의 합에 대한 제곱근이 벡터의 크기가 된다.
벡터 크기의 계산
벡터 \mathbf{v}의 크기, 즉 노름은 벡터의 유클리드 거리로 정의된다. n-차원 벡터 \mathbf{v} = [v_1, v_2, \cdots, v_n]의 크기는 다음과 같다:
이때, 벡터의 정규화는 \mathbf{v}의 각 성분을 벡터의 크기로 나눈 값으로 정의된다.
Eigen을 활용한 벡터 정규화
Eigen 라이브러리는 C++에서 수학적 벡터와 행렬 연산을 효율적으로 수행할 수 있도록 설계된 라이브러리다. 이를 통해 벡터의 정규화를 간단하게 구현할 수 있다. 다음은 Eigen 라이브러리에서 벡터 정규화를 수행하는 예제 코드이다.
#include <Eigen/Dense>
#include <iostream>
int main() {
// Eigen 벡터 선언 및 초기화
Eigen::Vector3d v(3.0, 4.0, 0.0);
// 벡터 정규화
Eigen::Vector3d v_normalized = v.normalized();
// 결과 출력
std::cout << "정규화된 벡터: " << v_normalized.transpose() << std::endl;
return 0;
}
위 예제에서 Eigen::Vector3d
는 3차원 실수 벡터를 정의하며, normalized()
함수는 벡터의 정규화된 값을 반환한다. 주어진 벡터 \mathbf{v} = [3, 4, 0]의 크기는 \|\mathbf{v}\| = 5이므로, 정규화된 벡터는 \mathbf{\hat{v}} = [\frac{3}{5}, \frac{4}{5}, 0]이 된다.
정규화 벡터의 성질
정규화된 벡터는 다음과 같은 중요한 성질을 가진다:
- 크기: 정규화된 벡터의 크기는 항상 1이다. 즉, 벡터 \mathbf{\hat{v}}는 항상 단위 벡터로 변환된다. 이를 수식으로 나타내면:
-
방향: 정규화된 벡터 \mathbf{\hat{v}}는 원래 벡터 \mathbf{v}와 동일한 방향을 가진다. 즉, 방향은 유지되지만 크기만 변한다.
-
스칼라 곱: 두 벡터 \mathbf{v_1}와 \mathbf{v_2}가 있을 때, 이 벡터들을 각각 정규화한 후 스칼라 곱(내적)을 계산하면, 원래 벡터 간의 코사인 유사도와 동일하다:
여기서 \theta는 두 벡터 사이의 각도이다. 이는 두 벡터 간의 유사도를 측정하는 데 유용하게 사용된다.
특수한 경우의 벡터 정규화
-
영벡터의 정규화: 영벡터 \mathbf{0}는 모든 성분이 0인 벡터를 의미한다. 영벡터의 정규화는 수학적으로 정의되지 않는다. 벡터의 크기가 0이기 때문에, 이를 나눌 수 없기 때문이다. 이러한 경우 정규화 함수는 예외 처리를 해야 한다.
-
정규화의 안정성: 실수 계산에서는 부동소수점 연산의 불확실성으로 인해 벡터의 정규화가 완벽하게 수행되지 않을 수 있다. 특히, 벡터의 크기가 매우 작거나 매우 큰 경우에는 정규화 과정에서 오차가 발생할 수 있으므로, 수치적으로 안정한 방법이 필요할 수 있다.
Eigen 라이브러리에서의 주의 사항
Eigen 라이브러리에서 normalized()
함수는 정규화된 벡터를 반환하지만, 원래 벡터 자체를 변경하지 않는다. 만약 원래 벡터 자체를 정규화하고자 한다면 normalize()
함수를 사용해야 한다. 아래는 이를 사용하는 예제이다.
#include <Eigen/Dense>
#include <iostream>
int main() {
// Eigen 벡터 선언 및 초기화
Eigen::Vector3d v(3.0, 4.0, 0.0);
// 벡터 자체를 정규화
v.normalize();
// 결과 출력
std::cout << "자체 정규화된 벡터: " << v.transpose() << std::endl;
return 0;
}
이 경우 벡터 v는 함수 호출 이후 정규화된 상태로 변환된다. 즉, 원래 벡터는 더 이상 [3, 4, 0]이 아니고, [\frac{3}{5}, \frac{4}{5}, 0]로 바뀐다.
다차원 벡터 정규화
다차원 벡터에 대해서도 동일한 방법으로 정규화를 적용할 수 있다. 예를 들어, n-차원 벡터 \mathbf{v} = [v_1, v_2, \cdots, v_n]의 정규화는 다음과 같다:
Eigen 라이브러리는 이러한 다차원 벡터를 효율적으로 처리할 수 있다. 예를 들어, 4차원 벡터를 정규화하려면 다음과 같이 코드를 작성할 수 있다.
#include <Eigen/Dense>
#include <iostream>
int main() {
// 4차원 벡터 선언 및 초기화
Eigen::Vector4d v(1.0, 2.0, 3.0, 4.0);
// 벡터 정규화
Eigen::Vector4d v_normalized = v.normalized();
// 결과 출력
std::cout << "정규화된 4차원 벡터: " << v_normalized.transpose() << std::endl;
return 0;
}
이 코드는 \mathbf{v} = [1, 2, 3, 4]인 4차원 벡터를 정규화하여 그 결과를 출력한다.
벡터 정규화의 실제 응용
정규화된 벡터는 여러 분야에서 중요한 역할을 한다. 특히, 벡터의 방향 정보를 필요로 하는 다양한 응용에서 많이 사용된다. 아래에서는 몇 가지 대표적인 응용 사례를 소개한다.
컴퓨터 그래픽스에서의 응용
컴퓨터 그래픽스에서 벡터 정규화는 표면의 법선 벡터 계산, 빛의 반사 계산, 물체의 회전과 같은 다양한 작업에서 필수적이다. 예를 들어, 법선 벡터는 표면의 기울기를 나타내는데, 이 벡터가 정규화되지 않으면 빛의 반사와 같은 계산에서 오류가 발생할 수 있다. 표면 법선 벡터를 정규화하면 표면의 기하학적 특성을 보다 정확하게 계산할 수 있다.
다음은 3D 그래픽스에서 법선 벡터를 정규화하는 예시이다.
#include <Eigen/Dense>
#include <iostream>
int main() {
// 임의의 3차원 벡터 정의
Eigen::Vector3d normal_vector(3.0, 1.0, 2.0);
// 법선 벡터 정규화
Eigen::Vector3d normalized_normal = normal_vector.normalized();
// 결과 출력
std::cout << "정규화된 법선 벡터: " << normalized_normal.transpose() << std::endl;
return 0;
}
이 코드에서는 법선 벡터를 정규화하여 결과를 출력한다. 정규화된 벡터는 그래픽스 렌더링 엔진에서 빛과 표면 간의 상호작용을 계산할 때 사용된다.
물리 시뮬레이션에서의 응용
물리 시뮬레이션에서는 물체의 속도 벡터나 가속도 벡터를 정규화하여 운동의 방향을 추적하거나, 물체 간의 충돌 및 반사 방향을 계산할 때 사용된다. 예를 들어, 충돌이 발생했을 때 물체가 반사하는 방향은 충돌 지점에서의 법선 벡터에 따라 결정되며, 이 벡터가 정규화되어야 물리적으로 정확한 계산이 가능하다.
다음은 물체의 속도 벡터를 정규화하는 예시이다.
#include <Eigen/Dense>
#include <iostream>
int main() {
// 물체의 속도 벡터 정의
Eigen::Vector3d velocity(5.0, -3.0, 2.0);
// 속도 벡터 정규화
Eigen::Vector3d normalized_velocity = velocity.normalized();
// 결과 출력
std::cout << "정규화된 속도 벡터: " << normalized_velocity.transpose() << std::endl;
return 0;
}
이 코드는 물체의 속도 벡터를 정규화하여 그 방향만을 추출하고, 이후 물체의 운동 방향을 추적하거나 계산하는 데 사용할 수 있다.
머신 러닝에서의 응용
머신 러닝에서는 데이터의 각 특성(feature)을 정규화하거나 표준화하는 과정이 필수적이다. 벡터 정규화는 주로 텍스트 데이터나 이미지 데이터의 특징 벡터(feature vector)를 유사도 분석에 사용할 때 적용된다. 예를 들어, 텍스트 데이터에서 단어의 빈도를 나타내는 벡터(벡터 공간 모델)를 정규화하여 코사인 유사도를 계산할 수 있다.
두 문서 벡터 \mathbf{v_1}과 \mathbf{v_2}의 코사인 유사도는 다음과 같이 계산된다:
이때 벡터를 정규화하면 크기가 1로 통일되므로, 코사인 유사도는 단순히 내적으로 계산할 수 있다.
Eigen에서 다차원 벡터를 활용한 응용 예시
다차원 벡터는 일반적으로 데이터 분석에서 중요한 역할을 한다. 예를 들어, 이미지나 텍스트 데이터에서 고차원 특징 벡터를 사용해 유사도를 계산할 때 벡터의 정규화는 필수적이다. 다음은 Eigen을 사용해 5차원 벡터를 정규화하고, 이를 활용해 두 벡터 간의 코사인 유사도를 계산하는 예제이다.
#include <Eigen/Dense>
#include <iostream>
int main() {
// 5차원 벡터 선언 및 초기화
Eigen::VectorXd v1(5);
v1 << 1.0, 2.0, 3.0, 4.0, 5.0;
Eigen::VectorXd v2(5);
v2 << 5.0, 4.0, 3.0, 2.0, 1.0;
// 벡터 정규화
Eigen::VectorXd v1_normalized = v1.normalized();
Eigen::VectorXd v2_normalized = v2.normalized();
// 코사인 유사도 계산
double cosine_similarity = v1_normalized.dot(v2_normalized);
// 결과 출력
std::cout << "정규화된 벡터 1: " << v1_normalized.transpose() << std::endl;
std::cout << "정규화된 벡터 2: " << v2_normalized.transpose() << std::endl;
std::cout << "코사인 유사도: " << cosine_similarity << std::endl;
return 0;
}
이 예제에서는 두 개의 5차원 벡터 \mathbf{v_1}과 \mathbf{v_2}를 정규화한 후, 그 사이의 코사인 유사도를 계산한다. 정규화된 벡터는 크기가 1이므로 유사도를 계산할 때 내적만으로 충분하다.