# 제 8장: 선형 대수의 고급 주제 및 응용

## 8.1 행렬의 복소수 고유값 및 고유벡터

행렬이 복소수 고유값과 고유벡터를 가지는 경우는 여러 응용 문제에서 발생한다. 복소수 고유값을 가지는 행렬은 다음과 같은 특성을 갖는다.

### 8.1.1 복소수 고유값의 정의

정방 행렬 $ \mathbf{A} $의 고유값이 복소수일 때, $ \mathbf{A} $는 복소수 고유벡터와 함께 나타난다. 복소수 고유값 $ \lambda $와 고유벡터 $ \mathbf{v} $는 다음과 같은 관계를 만족한다:

$$
\mathbf{A} \mathbf{v} = \lambda \mathbf{v}
$$

여기서 $ \lambda $는 복소수일 수 있으며, $ \mathbf{v} $ 역시 복소수 벡터일 수 있다.

### 8.1.2 복소수 고유값과 고유벡터의 계산

복소수 고유값과 고유벡터는 행렬의 고유값 문제를 풀 때 얻어진다. 특히, 실수 행렬의 경우 복소수 고유값과 고유벡터를 가질 수 있으며, 이는 행렬의 분해와 분석에 중요한 역할을 한다.

### 8.1.3 C++ Eigen3를 이용한 복소수 고유값 및 고유벡터 계산

```cpp
#include <Eigen/Dense>
#include <Eigen/Eigenvalues>
#include <iostream>

int main() {
    // 복소수 행렬 정의
    Eigen::Matrix2cd A;
    A << std::complex<double>(0, -1), std::complex<double>(1, 0),
         std::complex<double>(-1, 0), std::complex<double>(0, 1);

    // 복소수 고유값과 고유벡터 계산
    Eigen::EigenSolver<Eigen::Matrix2cd> es(A);
    Eigen::Vector2cd eigenvalues = es.eigenvalues();
    Eigen::Matrix2cd eigenvectors = es.eigenvectors();

    std::cout << "Eigenvalues: \n" << eigenvalues << std::endl;
    std::cout << "Eigenvectors: \n" << eigenvectors << std::endl;

    return 0;
}
```

이 코드는 `EigenSolver`를 사용하여 복소수 행렬의 고유값과 고유벡터를 계산하고 출력한다.

## 8.2 행렬의 조건수 및 안정성

행렬의 조건수는 행렬의 역행렬이 얼마나 민감한지를 측정하는 값이다. 조건수가 큰 행렬은 역행렬의 계산이 불안정할 수 있다.

### 8.2.1 조건수 정의

행렬 $ \mathbf{A} $의 조건수 $ \kappa(\mathbf{A}) $는 다음과 같이 정의된다:

$$
\kappa(\mathbf{A}) = |\mathbf{A}| |\mathbf{A}^{-1}|
$$

여기서 $ |\cdot| $는 행렬의 노름(norm)이다. 조건수가 클수록 행렬의 역행렬 계산이 불안정해질 수 있다.

### 8.2.2 조건수의 의미

* **작은 조건수**: 행렬의 역행렬이 안정적으로 계산될 수 있음을 의미한다.
* **큰 조건수**: 계산이 불안정하거나 오류가 크게 발생할 수 있음을 의미한다.

### 8.2.3 C++ Eigen3를 이용한 조건수 계산

```cpp
#include <Eigen/Dense>
#include <iostream>

int main() {
    // 행렬 정의
    Eigen::Matrix2d A;
    A << 1, 2,
         3, 4;

    // 조건수 계산
    Eigen::JacobiSVD<Eigen::Matrix2d> svd(A);
    double condition_number = svd.singularValues()(0) / svd.singularValues()(1);

    std::cout << "Condition number: " << condition_number << std::endl;

    return 0;
}
```

이 코드는 `JacobiSVD`를 사용하여 행렬의 조건수를 계산한다. 조건수는 행렬의 특이값을 이용하여 간단히 계산할 수 있다.

## 8.3 행렬의 최소 제곱 해법

최소 제곱 문제는 과잉 결정 시스템에서 최적의 해를 찾는 방법이다. 선형 시스템의 해가 유일하지 않거나 해가 없을 때 사용된다.

### 8.3.1 최소 제곱 문제 정의

다음과 같은 형태의 문제를 고려한다:

$$
\text{최소화 } | \mathbf{A} \mathbf{x} - \mathbf{b} |\_2^2
$$

여기서 $ \mathbf{A} $는 $ m \times n $ 행렬, $ \mathbf{x} $는 $ n \times 1 $ 벡터, $ \mathbf{b} $는 $ m \times 1 $ 벡터이다. 이 문제는 $ \mathbf{A} \mathbf{x} \approx \mathbf{b} $를 만족하는 $ \mathbf{x} $를 찾는 것이다.

### 8.3.2 최소 제곱 해법의 계산

최소 제곱 해법은 일반적으로 다음과 같은 방법으로 해결된다:

* **정규 방정식**: $ (\mathbf{A}^T \mathbf{A}) \mathbf{x} = \mathbf{A}^T \mathbf{b} $
* **SVD**: $ \mathbf{A} = \mathbf{U} \mathbf{\Sigma} \mathbf{V}^T $를 이용하여 해를 구한다.

### 8.3.3 C++ Eigen3를 이용한 최소 제곱 해법

```cpp
#include <Eigen/Dense>
#include <iostream>

int main() {
    // 행렬 및 벡터 정의
    Eigen::MatrixXd A(3, 2);
    Eigen::VectorXd b(3);
    A << 1, 1,
         2, 2,
         3, 3;
    b << 1, 2, 3;

    // 최소 제곱 해법 계산
    Eigen::VectorXd x = A.colPivHouseholderQr().solve(b);

    std::cout << "Least squares solution: \n" << x << std::endl;

    return 0;
}
```

이 코드는 `colPivHouseholderQr`를 사용하여 최소 제곱 문제를 해결하고 최적의 해를 출력한다.

## 8.4 차원 축소 및 주성분 분석 (PCA)

차원 축소는 고차원 데이터를 저차원으로 변환하여 분석하는 방법이다. 주성분 분석(PCA)은 이러한 방법 중 하나이다.

### 8.4.1 PCA의 정의

PCA는 데이터의 분산을 최대화하는 방향으로 주성분을 찾는 방법이다. 데이터 행렬 $ \mathbf{X} $의 공분산 행렬 $ \mathbf{C} $의 고유벡터를 찾아 차원 축소를 수행한다.

$$
\mathbf{C} = \frac{1}{n-1} \mathbf{X}^T \mathbf{X}
$$

### 8.4.2 PCA의 계산

1. **공분산 행렬 계산**: $ \mathbf{C} = \frac{1}{n-1} \mathbf{X}^T \mathbf{X} $
2. **고유값 및 고유벡터 계산**: $ \mathbf{C} $의 고유값과 고유벡터를 구한다.
3. **주성분 선택**: 가장 큰 고유값에 대응하는 고유벡터를 선택한다.

### 8.4.3 C++ Eigen3를 이용한 PCA

```cpp
#include <Eigen/Dense>
#include <iostream>

int main() {
    // 데이터 행렬 정의
    Eigen::MatrixXd X(4, 2);
    X << 1, 2,
         2, 3,
         3, 4,
         4, 5;

    // 공분산 행렬 계산
    Eigen::MatrixXd C = (X.transpose() * X) / (X.rows() - 1);

    // 고유값과 고유벡터 계산
    Eigen::EigenSolver<Eigen::MatrixXd> es(C);
    Eigen::VectorXd eigenvalues = es.eigenvalues().real();
    Eigen::MatrixXd eigenvectors = es.eigenvectors().real();

    std::cout << "Eigenvalues: \n" << eigenvalues << std::endl;
    std::cout << "Eigenvectors: \n" << eigenvectors << std::endl;

    return 0;
}
```

이 코드는 PCA를 수행하기 위해 데이터 행렬의 공분산 행렬을 계산하고, 고유값 및 고유벡터를 구하여 주성분을 분석한다.

## 8.5 요약

이 장에서는 행렬의 복소수 고유값 및 고유벡터, 조건수와 안정성, 최소 제곱 해법, 그리고 차원 축소 및 PCA에 대해 다루었다. 이러한 고급 주제들은 다양한 응용 문제를 해결하고, 실전에서의 데이터 분석 및 시스템 모델링에 중요한 역할을 한다. 다음 장에서는 이러한 개념을 더욱 심화하고, 실제 응용 사례를 통해 이해를 확장하겠다.
