1 주성분 함수 (Estimated Functional Principal Components)
함수형 데이터 분석에서 가장 유용하고 빈번하게 사용되는 도구가 함수 주성분 분석(Functional Principal Component Analysis, FPCA)이다 (Kokoszka & Reimherr, 2017, Ch.1).
1.1 기저 전개 vs 주성분 전개: 핵심 차이
§1.1에서 다룬 기저 전개에서는 기저 함수 \(B_m\) 이 데이터와 무관하게 미리 결정된다 — B-spline이든 Fourier 기저든 수학적 편의성을 위해 선택된 “범용 기저”이다. 이 기저는 모든 종류의 곡선에 동일하게 적용된다.
반면, 추정 함수 주성분(Estimated Functional Principal Components, EFPC) \(\hat{v}_j\) 는 관측된 데이터로부터 학습된 기저이다. 중심화된 곡선 \(X_n - \bar{X}_N\) 을 최소 개수의 직교 기저로 근사하되, 근사 오차를 최소화하는 방향으로 기저를 결정한다:
\[ X_n(t) - \bar{X}_N(t) \approx \sum_{j=1}^{p} \hat{\xi}_{nj} \hat{v}_j(t) \]
여기서 \(p\) 는 사용하는 주성분의 수이며, 기저 전개의 \(M\) 보다 훨씬 작다.
이 차이를 비유로 설명하면 다음과 같다. 기저 전개가 “영어 알파벳 26자로 모든 텍스트를 표현”하는 것이라면, EFPC는 “이 특정 문서에서 가장 자주 등장하는 단어 10개만으로 문서의 핵심을 요약”하는 것이다. 알파벳은 범용적이지만 비효율적이고, 빈출 단어는 특화되어 있지만 효율적이다. EFPC가 “이 데이터에 최적화된 기저”인 이유가 이것이다.
1.2 EFPC의 구성 요소
EFPC 전개의 각 구성 요소를 정확히 정의한다:
- \(\hat{v}_j(t)\): \(j\) 번째 추정 함수 주성분 (EFPC). 평균으로부터의 편차에서 \(j\) 번째로 중요한 변동 패턴을 나타내는 함수이다.
- \(\hat{\xi}_{nj}\): 곡선 \(X_n\) 의 \(j\) 번째 EFPC에 대한 점수(score). 곡선 \(n\) 이 패턴 \(\hat{v}_j\) 를 얼마나 강하게, 어느 방향으로 따르는지를 하나의 스칼라로 수량화한다.
- \(p\): 사용하는 주성분의 수. 전체 변동의 충분한 비율(예: 95%)을 설명하도록 선택한다.
직관적으로, \(\hat{v}_1\) 은 “50개 곡선이 평균에서 벗어나는 가장 주된 방식”을 포착한다. 어떤 곡선은 이 패턴을 강하게 따르고(\(\hat{\xi}_{n1}\) 이 큰 양수), 어떤 곡선은 반대 방향으로 따르며(\(\hat{\xi}_{n1}\) 이 큰 음수), 어떤 곡선은 이 패턴과 무관하다(\(\hat{\xi}_{n1} \approx 0\)).
1.3 다변량 PCA와의 대응
FPCA의 구조는 다변량 PCA와 정확히 대응한다. 이 대응을 이해하면 FPCA의 직관이 명확해진다:
| 다변량 PCA | FPCA |
|---|---|
| 데이터: \(\mathbf{x}_n \in \mathbb{R}^p\) | 데이터: \(X_n(t) \in L^2[T_1, T_2]\) |
| 공분산 행렬 \(\hat{\mathbf{\Sigma}}\) (\(p \times p\)) | 공분산 함수 \(\hat{c}(t,s)\) |
| 고유벡터 \(\mathbf{e}_j \in \mathbb{R}^p\) | 고유함수 \(\hat{v}_j(t)\) |
| 고유값 \(\lambda_j\) | 고유값 \(\hat{\lambda}_j\) |
| 점수 \(z_{nj} = \mathbf{e}_j^T \mathbf{x}_n\) | 점수 \(\hat{\xi}_{nj} = \int \hat{v}_j(t) X_n(t) \, dt\) |
| \(\lambda_j / \sum_k \lambda_k\): 설명 분산 비율 | \(\hat{\lambda}_j / \sum_k \hat{\lambda}_k\): 설명 분산 비율 |
| \(\sum_j \lambda_j = \text{tr}(\hat{\mathbf{\Sigma}})\): 총 변동 | \(\sum_j \hat{\lambda}_j = \int \hat{c}(t,t)\,dt\): 총 변동 |
핵심 차이는 유한차원 \(\to\) 무한차원 확장이다: 벡터가 함수로, 행렬이 함수로, 내적 \(\mathbf{e}_j^T \mathbf{x}_n\) 이 적분 \(\int \hat{v}_j(t) X_n(t) \, dt\) 로 바뀐다. 그러나 논리적 구조 — 공분산의 고유분해를 통한 최적 차원 축소 — 는 동일하다.
1.4 직교성 (Orthonormality)
EFPC들은 직교정규 조건을 만족한다:
\[ \int \hat{v}_j(t) \hat{v}_i(t) \, dt = \begin{cases} 0 & \text{if } j \neq i \\ 1 & \text{if } j = i \end{cases} \]
이 조건이 왜 중요한가?
\(\langle \hat{v}_j, \hat{v}_i \rangle = 0\) (\(j \neq i\)): 직교성. 각 EFPC가 서로 중복되지 않는 독립적인 변동 방향을 포착한다는 의미이다. \(\hat{v}_1\) 이 설명하는 변동 패턴과 \(\hat{v}_2\) 가 설명하는 패턴은 완전히 다른 “축”에 있다. 따라서 두 성분이 같은 변동을 이중으로 세는 일이 없다.
\(\|\hat{v}_j\| = 1\): 정규화. 각 EFPC의 크기를 1로 고정하여, 변동의 크기 정보가 점수 \(\hat{\xi}_{nj}\) 에만 집중된다. 이를 통해 \(\hat{\xi}_{nj}\) 의 크기 자체가 곡선 \(n\) 이 패턴 \(j\) 를 따르는 정도를 직접 반영한다.
이 직교성은 해석에 제약도 부과한다. \(\hat{v}_2\) 는 “두 번째로 중요한 변동 패턴” 중에서 \(\hat{v}_1\) 과 직교하는 것만 될 수 있다. 따라서 \(\hat{v}_2\) 의 형태는 \(\hat{v}_1\) 에 의존하며, 독립적으로 해석하기 어려울 수 있다. 이는 다변량 PCA에서 두 번째 고유벡터가 첫 번째와 수직인 것과 동일한 제약이다.
1.5 분산 설명 비율
전체 곡선 변동(평균 주변)을 각 EFPC가 설명하는 비율은 해당 고유값의 상대 크기로 결정된다.
50개 랜덤 워크(§1.1~1.2의 예시) 데이터에서 EFPC를 계산하면 (Kokoszka & Reimherr, 2017, Ch.1):
| EFPC | 분산 설명 비율 | 누적 |
|---|---|---|
| \(\hat{v}_1\) | 약 81% | 81% |
| \(\hat{v}_2\) | 약 10% | 91% |
| \(\hat{v}_3\) | 약 4% | 95% |
| \(\hat{v}_4\) | 약 2% | 97% |
첫 번째 EFPC만으로 변동의 81%를 포착하며, 4개면 97%에 도달한다. 이는 \(p = 4\) (또는 심지어 \(p = 2\))로 차원 축소해도 곡선의 핵심 형태가 보존됨을 의미한다.
분산 설명 비율이 중요한 이유는, 이것이 정보 손실의 정량적 척도이기 때문이다. \(p = 2\) 를 선택하면 전체 변동의 약 9%를 버린다는 것을 명시적으로 알 수 있다. 이 비율이 허용 가능한지는 응용 맥락에 따라 다르다 — 탐색적 분석에서는 85%면 충분할 수 있지만, 예측 모형에서는 95% 이상이 필요할 수 있다.
1.6 EFPC의 형태: 브라운 운동과의 연결
50개 랜덤 워크의 EFPC \(\hat{v}_j\) 는 삼각함수(사인/코사인)와 유사한 형태를 보인다. 이것은 우연이 아니다.
브라운 운동의 공분산 함수 \(c(t, s) = \min(t, s)\) 의 이론적 고유함수는 닫힌 형태로 알려져 있다 (Ch.11에서 유도):
\[ v_j(t) = \sqrt{2} \sin\left((j - \tfrac{1}{2})\pi t\right), \quad \lambda_j = \frac{1}{(j - \tfrac{1}{2})^2 \pi^2} \]
EFPC \(\hat{v}_j\) 는 이 이론적 고유함수 \(v_j\) 의 추정량이다. 표본 크기 \(N\) 이 충분히 크면 \(\hat{v}_j \to v_j\) 로 수렴한다 (Ch.12에서 일치성이 증명된다). 따라서 EFPC의 삼각함수 형태는 브라운 운동의 공분산 구조에서 필연적으로 도출된다.
고유값 \(\lambda_j = 1/((j-1/2)^2\pi^2)\) 가 \(j\) 의 제곱에 반비례하여 급격히 감소하는 것은, 첫 번째 성분이 대부분의 분산을 설명하고 고차 성분의 기여가 빠르게 줄어든다는 것을 의미한다. 이것이 FPCA로 소수의 주성분만으로 효율적 차원 축소가 가능한 수학적 근거이다.
1.7 R 코드: EFPC 계산
library(fda)
N <- 50
W.mat <- matrix(0, ncol = N, nrow = 10000)
for (n in 1:N) { W.mat[, n] <- cumsum(rnorm(10000)) / 100 }
B25.basis <- create.bspline.basis(rangeval = c(0, 10000), nbasis = 25)
W.fd <- smooth.basis(y = W.mat, fdParobj = B25.basis)
W.pca <- pca.fd(W.fd$fd, nharm = 4)
plot(W.pca$harmonics, lwd = 3)
W.pca$varprop
# [1] 0.80513155 0.09509154 0.04099496 0.02119239pca.fd() 의 주요 인수와 반환값:
| 항목 | 설명 |
|---|---|
W.fd$fd |
입력: 함수 데이터 객체 (fd 클래스) |
nharm = 4 |
계산할 주성분 수 |
$harmonics |
반환: EFPC 함수 객체 (\(\hat{v}_1, \hat{v}_2, \hat{v}_3, \hat{v}_4\)) |
$varprop |
반환: 각 EFPC의 분산 설명 비율 벡터 |
$scores |
반환: \(N \times p\) 점수 행렬 (\(\hat{\xi}_{nj}\)) |
$values |
반환: 고유값 벡터 (\(\hat{\lambda}_j\)) |
그래프에서 \(\hat{v}_1\) (검은 실선)은 구간 중앙에서 단봉 형태로 최대값을 가지며, 이는 곡선들이 평균에서 벗어나는 가장 주된 방식이 “중앙부에서의 전체적 편이”임을 의미한다. \(\hat{v}_2\) (빨간 점선)는 한 번의 교차를 가지며, 이는 “구간 전반부와 후반부에서 반대 방향으로의 편이”라는 두 번째 변동 모드를 포착한다.
1.8 점수의 해석
점수 \(\hat{\xi}_{nj}\) 는 곡선 \(X_n\) 이 \(j\) 번째 EFPC 패턴을 어떤 크기와 방향으로 따르는지를 나타내는 스칼라이다.
- \(\hat{\xi}_{n1} > 0\): 곡선 \(n\) 이 \(\hat{v}_1\) 방향으로 평균보다 편이 (평균 + 양수 \(\times\) \(\hat{v}_1\) 형태)
- \(\hat{\xi}_{n1} < 0\): 곡선 \(n\) 이 \(\hat{v}_1\) 의 반대 방향으로 편이
- \(\hat{\xi}_{n1} \approx 0\): 곡선 \(n\) 에서 \(\hat{v}_1\) 패턴이 약함
점수의 분산은 해당 고유값과 같다: \(\text{Var}(\hat{\xi}_{nj}) \approx \hat{\lambda}_j\). 분산 설명 비율이 작은 EFPC의 점수일수록 값이 작다 — 이것이 고차 성분을 제거해도 정보 손실이 적은 이유이다.
점수 벡터 \((\hat{\xi}_{n1}, \hat{\xi}_{n2}, \ldots, \hat{\xi}_{np})\) 는 무한차원 함수 \(X_n(t)\) 를 \(p\) 차원 벡터로 축소한 것이며, 이후 분류, 군집 분석, 회귀 등 기존 다변량 기법의 입력으로 사용된다. 이것이 FPCA가 FDA에서 “만능 전처리 단계”인 이유이다.
2 BOA 주식 누적 수익률 분석
§1.4에서 Kokoszka & Reimherr (2017)는 §1.1~1.3에서 도입한 기저 전개, 표본 평균·공분산, EFPC를 실제 금융 데이터에 적용하여 FDA의 실용적 가치를 보여준다.
2.1 데이터 구조
Bank of America(BOA)는 미국 최대 금융기관 중 하나로, 100년 이상의 역사를 가진다. 분석 대상은 1997년 4월 9일부터 2007년 4월 2일까지의 분 단위 주가 데이터이다.
각 거래일의 구조:
| 항목 | 값 |
|---|---|
| 개장 시간 | 9:30 AM (EST) |
| 폐장 시간 | 4:00 PM |
| 거래 시간 | 6.5시간 |
| 관측 해상도 | 1분 |
| 일당 관측 수 | 390개 |
| 총 거래일 수 | 2,511일 (이상치 1일 제거 후 2,510일) |
여기서 \(t \in (0, 6.5)\) 이며, 하루를 하나의 함수 관측으로 간주한다. 즉 \(N = 2{,}510\) 개의 곡선이 있고, 각 곡선은 390개의 점으로 이루어져 있다.
2.2 누적 로그수익률 (Cumulative Log-Return)
분석에 사용하는 함수 관측은 원시 주가가 아니라 누적 로그수익률이다:
\[ R_n(t) := \log(P_n(t)) - \log(P_n(0)) \approx \frac{P_n(t) - P_n(0)}{P_n(0)} \]
여기서 \(P_n(t)\) 는 \(n\) 일의 시점 \(t\) 에서의 주가이다.
왜 원시 주가 대신 누적 로그수익률을 사용하는가?
- 정규화: 매일 \(R_n(0) = 0\) 에서 시작하므로, 2,510일의 곡선이 모두 공통 출발점을 가진다. 원시 주가는 10년간 크게 변동하므로 직접 비교가 불가능하다.
- 해석의 명확성: \(R_n(t)\) 는 “개장 시점에 투자했을 때 시점 \(t\) 까지의 수익률”이다. \(R_n(6.5) > 0\) 이면 그날 이익, \(< 0\) 이면 손실이다.
- 수학적 편의: 로그수익률은 정규분포에 더 가까우며, 기간별 수익률의 합산이 용이하다. 또한 근사식 \(\log(P/P_0) \approx (P - P_0)/P_0\) 에 의해 직관적 해석도 가능하다.
2.3 이상치 처리
2004년 8월 26일 데이터는 주식 분할(stock split)로 인해 비정상적 패턴을 보이므로 분석에서 제외한다. 주식 분할은 주가를 인위적으로 절반(또는 1/3 등)으로 낮추는 기업 이벤트로, 실질적 가치 변동이 아니다. 이런 이상치는 평균 함수와 공분산 추정을 크게 왜곡하므로, FDA 적용 전에 반드시 식별하고 제거해야 한다.
2.4 R 코드: 데이터 준비
library(fda)
BOA <- read.table("BOA.txt", header = TRUE)
Dates <- dimnames(BOA)[[1]]
BOA <- data.matrix(BOA)
Outlier <- which(Dates == "08/26/2004")
BOA <- BOA[-Outlier, ]
N <- dim(BOA)[1] # 2510
M <- dim(BOA)[2] # 390
Times <- seq(0, 6.5, length = M)
log_BOA <- log(BOA) - matrix(log(BOA)[, 1], nrow = N, ncol = M)
bspline_basis <- create.bspline.basis(rangeval = c(0, 6.5),
norder = 4, nbasis = 200)
log_BOA_f <- Data2fd(Times, t(log_BOA), basisobj = bspline_basis)
plot(log_BOA_f[1:10], xlab = "", ylab = "", lwd = 1.5)코드의 핵심 단계를 해설한다:
log(BOA) - matrix(log(BOA)[, 1], ...): 각 행(거래일)에서 첫 번째 열(개장 가격)의 로그를 빼서 누적 로그수익률을 계산한다.matrix(..., nrow=N, ncol=M)은 열 벡터를 행렬로 확장하여 element-wise 뺄셈을 가능하게 한다.nbasis = 200: BOA 데이터는 관측점이 390개이므로, §1.1의 랜덤 워크(25개 기저)보다 훨씬 많은 200개의 B-spline 기저를 사용한다. 이는 분 단위 주가 변동의 세밀한 패턴을 포착하기 위함이다.Data2fd():smooth.basis()의 편의 래퍼(wrapper)로, 시간 격자와 데이터 행렬을 바로 받아 함수 객체를 생성한다.t(log_BOA)는 데이터를 전치하여 열이 곡선을 나타내도록 한다.
2.5 평균 함수와 점별 신뢰 구간
muhat <- mean.fd(log_BOA_f)
sdhat <- sd.fd(log_BOA_f)
SE_hat_U <- fd(basisobj = bspline_basis)
SE_hat_L <- fd(basisobj = bspline_basis)
SE_hat_U$coefs <- 2 * sdhat$coefs / sqrt(N) + muhat$coefs
SE_hat_L$coefs <- -2 * sdhat$coefs / sqrt(N) + muhat$coefs
plot.fd(SE_hat_U, ylim = c(-0.002, 0.002), col = "red", lty = 2,
xlab = "", ylab = "")
plot.fd(SE_hat_L, add = TRUE, col = "red", lty = 2)
plot.fd(muhat, add = TRUE)신뢰 구간의 구성:
\[ \bar{X}_N(t) \pm 2 \cdot \frac{\text{SD}_X(t)}{\sqrt{N}} \]
이 구간은 각 시점 \(t\) 에서 독립적으로 구성되는 점별(pointwise) 95% 신뢰 구간이다. \(N = 2{,}510\) 이 매우 크므로 \(\sqrt{N} \approx 50\) 으로, 표준오차가 SD의 약 1/50로 줄어든다.
R 구현에서 주목할 점은 기저 계수에 대한 산술 연산으로 함수 수준의 조작을 수행한다는 것이다. muhat$coefs 에 2*sdhat$coefs/sqrt(N) 을 더하는 것이 곧 함수 \(\bar{X}_N(t) + 2\text{SD}_X(t)/\sqrt{N}\) 을 구성하는 것이다. 이것이 기저 전개의 실용적 힘이다 — 함수 연산이 벡터 연산으로 귀결된다.
2.6 평균 함수의 해석
BOA 누적 수익률의 평균 함수 \(\bar{R}_N(t)\) 는 다음과 같은 패턴을 보인다:
- 오전 초반(0~1시간): 급격한 상승 — 개장 직후 거래 활동이 집중되면서 수익률이 빠르게 형성된다
- 중반 이후(1~6.5시간): 완만한 수준 유지 — 일중 수익률이 대부분 오전에 결정된다
양의 평균 수익률은 주주가 양의 수익을 기대한다는 금융 이론과 정합한다. 다만 크기가 매우 작다 (약 0.001 수준) — 일중 수익률의 기대값은 미미하고, 곡선 간 변동(SD)이 평균보다 훨씬 크다. 이것이 주식 투자의 본질적 불확실성을 수학적으로 반영한다.
2.7 EFPC 분석: 브라운 운동과의 비교
BOA 누적 수익률의 처음 4개 EFPC를 브라운 운동의 이론적 고유함수와 나란히 비교하면, 형태가 거의 동일하다. 이것은 중요한 함의를 가진다.
금융에서 로그수익률(또는 주가)을 브라운 운동으로 모형화하는 것은 Black-Scholes 이론 이래 근본적인 가정이다:
\[ \frac{dP_n(t)}{P_n(t)} = \mu \, dt + \sigma \, dW(t) \]
여기서 \(W(t)\) 는 표준 브라운 운동이다. 이 모형 하에서 누적 로그수익률 \(R_n(t) = \log(P_n(t)/P_n(0))\) 의 공분산 구조는 \(\sigma^2 \min(t, s)\) 로, 브라운 운동과 같은 고유함수를 가진다.
EFPC가 이 이론적 고유함수와 일치한다는 것은, FDA가 데이터 기반으로 이 가정의 타당성을 검증하는 도구가 됨을 보여준다. 만약 EFPC가 삼각함수와 크게 다르다면, 브라운 운동 가정이 부적절하다는 실증적 증거가 된다.
2.8 공분산 히트맵
공분산 표면을 3D perspective plot에 히트맵을 추가하여 시각화한다:
library(plot3D)
BOA.cov <- var.fd(log_BOA_f)
grid <- seq(0, 6.5, length = 100)
BOA.cov.mat <- eval.bifd(grid, grid, BOA.cov)
persp3D(grid, grid, BOA.cov.mat, xlab = "s", ylab = "t", zlab = "c(s,t)")히트맵에서 빨간색은 높은 공분산, 파란색은 낮은 공분산을 나타낸다. BOA 데이터의 공분산 표면은 §1.2에서 분석한 50개 랜덤 워크의 공분산 표면과 유사한 패턴 — 대각선을 중심으로 한 삼각형 구조 — 을 보인다. 이는 EFPC 비교 결과와 일관된다: 누적 수익률의 공분산 구조가 브라운 운동의 \(c(t,s) = \min(t,s)\) 와 유사하다.
2.9 금융에서의 FDA 분석의 의의
이 예시가 보여주는 FDA의 분석적 가치를 정리한다:
- 모형 검증: 브라운 운동 가정의 실증적 타당성을 EFPC 비교로 확인할 수 있다. 이것은 단순히 “주가가 정규분포를 따르는가?”보다 풍부한 정보를 제공한다 — 공분산의 전체 구조를 비교하기 때문이다.
- 패턴 발견: 평균 함수의 일중 패턴(오전 급등 후 완만)은 시계열 분석에서는 포착하기 어려운 구조이다. FDA는 “하루”를 하나의 관측 단위로 취급함으로써 일중 구조를 자연스럽게 드러낸다.
- 차원 축소: 390개 시점의 주가 곡선을 4개의 점수 \((\hat{\xi}_{n1}, \ldots, \hat{\xi}_{n4})\) 로 요약하여 97% 이상의 변동을 보존한다. 이 점수를 이용해 특이 거래일 탐지, 시장 구조 변화 감지 등 후속 분석이 가능하다.
3 코드 예시: Python 구현
3.1 Step 1: 순수 Python으로 EFPC 원리 확인
import numpy as np
np.random.seed(42)
N, K = 50, 1000
t = np.linspace(0, 1, K)
walks = np.cumsum(np.random.randn(N, K), axis=1) / np.sqrt(K)
mean_func = walks.mean(axis=0)
centered = walks - mean_func[np.newaxis, :]
cov_matrix = centered.T @ centered / (N - 1) # (K, K)
eigenvalues, eigenvectors = np.linalg.eigh(cov_matrix)
idx = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[idx]
eigenvectors = eigenvectors[:, idx]
dt = t[1] - t[0]
eigenvectors_normalized = eigenvectors / np.sqrt(dt)
total_var = eigenvalues.sum()
var_explained = eigenvalues[:4] / total_var
print("분산 설명 비율 (상위 4):", var_explained)
print("누적:", np.cumsum(var_explained))
scores = centered @ eigenvectors[:, :4] * dt
print(f"\n점수 행렬 shape: {scores.shape}")
print(f"점수 분산 (이론: 고유값): {scores.var(axis=0, ddof=1)[:4]}")
print(f"고유값 (상위 4): {eigenvalues[:4]}")코드의 핵심 논리:
cov_matrix = centered.T @ centered / (N-1): 표본 공분산 행렬 (\(K \times K\)) 계산. 이것은 공분산 함수 \(\hat{c}(t_j, t_k)\) 를 격자점에서 평가한 것이다.np.linalg.eigh(): 대칭 행렬의 고유분해. 고유벡터가 이산 격자에서의 EFPC이다.eigenvectors / np.sqrt(dt): 정규화. 이산 내적 \(\sum_k v_j(t_k) v_i(t_k) \Delta t = \delta_{ij}\) 을 만족하도록 스케일링한다.- 점수 분산이 고유값과 일치하는지 검증한다 — 이것이 FPCA의 핵심 성질이다.
3.2 Step 2: scikit-fda 구현
import skfda
from skfda.preprocessing.dim_reduction import FPCA
import numpy as np
np.random.seed(42)
N, K = 50, 1000
walks = np.cumsum(np.random.randn(N, K), axis=1) / np.sqrt(K)
t_grid = np.linspace(0, 1, K)
fd = skfda.FDataGrid(data_matrix=walks, grid_points=t_grid)
fpca = FPCA(n_components=4)
fpca.fit(fd)
scores = fpca.transform(fd)
print("분산 설명 비율:", fpca.explained_variance_ratio_)
print("누적:", np.cumsum(fpca.explained_variance_ratio_))
print(f"\n점수 행렬 shape: {scores.shape}")
components = fpca.components_
print(f"EFPC 수: {len(components)}")FPCA 클래스는 fit() 으로 공분산 추정 + 고유분해를 수행하고, transform() 으로 각 곡선의 점수를 반환한다. components_ 는 EFPC 함수 객체를 담고 있다.
3.3 브라운 운동 이론값과 비교
import numpy as np
t = np.linspace(0, 1, 1000)
for j in range(1, 5):
v_theory = np.sqrt(2) * np.sin((j - 0.5) * np.pi * t)
lam_theory = 1.0 / ((j - 0.5)**2 * np.pi**2)
print(f"v_{j}: lambda_theory = {lam_theory:.6f}, "
f"lambda_hat = {fpca.explained_variance_ratio_[j-1] * sum(fpca.explained_variance_):.6f}")이 코드는 추정된 고유값과 브라운 운동의 이론적 고유값 \(\lambda_j = 1/((j-1/2)^2\pi^2)\) 를 직접 비교한다. 표본 크기가 충분하면 양자가 근사적으로 일치해야 한다.
4 왜 FPCA가 FDA의 핵심 도구인가
4.1 차원 축소의 최적성
FPCA는 주어진 \(p\) 개의 직교 기저 중 재구성 오차를 최소화하는 유일한 전개이다. 즉, \(p\) 개의 함수로 \(N\) 개 곡선을 근사할 때, 평균 제곱 오차
\[ \frac{1}{N} \sum_{n=1}^{N} \left\| X_n - \bar{X}_N - \sum_{j=1}^{p} \hat{\xi}_{nj} \hat{v}_j \right\|^2 \]
를 최소화하는 직교 함수 \(\hat{v}_1, \ldots, \hat{v}_p\) 가 바로 EFPC이다. B-spline이나 Fourier 기저는 이 의미에서 최적이 아니다 — 데이터 구조를 반영하지 않기 때문이다.
4.2 FDA 파이프라인에서의 위치
원시 데이터 → 기저 전개 → fd 객체 → FPCA → 점수 (p차원 벡터)
↓
분류, 회귀, 군집, 검정 ...
FPCA는 “무한차원 함수”와 “유한차원 통계 기법” 사이의 다리 역할을 한다. 무한차원 함수 데이터를 \(p\) 차원 점수 벡터로 변환하면, 기존의 분류(로지스틱 회귀), 군집(k-means), 회귀(선형 회귀) 등을 바로 적용할 수 있다. Ch.4의 함수 회귀에서도 FPCA 기반 추정이 중심적 역할을 한다.
5 응용 분야
| 분야 | 함수형 데이터 | EFPC의 역할 |
|---|---|---|
| 금융 | 일중 주가 곡선 | 수익률 곡선의 주요 변동 모드 추출, 이상 거래일 탐지 |
| 신경과학 | fMRI 시간 곡선 | 뇌 활성화의 주요 시간적 패턴 발견 |
| 분자 진단 | RT-PCR 증폭 곡선 | 정상/비정상 곡선 분류를 위한 특징 추출 |
| 기상학 | 일별 기온 곡선 | 기온 변동의 계절적·위도적 패턴 분해 |
| 스포츠 과학 | 동작 궤적 곡선 | 선수 간 동작 차이의 주요 모드 식별 |
6 관련 주제
선행 지식
FDA 시리즈
후속 주제
- FDA 1.5 — 확산 텐서 영상 (DTI) 분석
- FDA Ch.2 — 미분, 벌점 스무딩, 곡선 정렬
- FDA Ch.3 — 수학적 프레임워크 (\(L^2\) 공간, Karhunen-Loeve 전개)
- FDA Ch.4 — 스칼라-on-함수 회귀