개요: 선형과 비선형
일반적인 모델이 다음과 같이 있다고 치자.
보통 그래프를 그리면 각 점을 따라서 모델이 잘 맞을 가능성이 크다.
그런데 데이터의 패턴이 이상하게 꺾인다면?
물론 비선형 모델을 도입할 수 있지만, 이거 말고도 방법이 있다.
Spline model
-
구간을 나눠서 직선을 피팅하는 방법
-
단점1: 미분이 안된다.
-
단점2: 각 구간별 직선이 로컬(local) 하게 적용된다.
즉, knot (갈라지는 점)에 따라 너무 모양이 많이 달라진다.
그래서, Spline을 강화시켜야 한다.
- knot의 갯수를 잘 조절해야 한다.
- 이를 smoothing scatterplot (산점도 평활화) 이라고 한다.
loess procedures
- local regression의 약자.
- 데이터의 어떤 점을 기준으로 그 근방의 값(local)에 대해 회귀
- g를 추정하는 방법 : 모수와 SSE를 이용한다.
- 대표적인 산점도 평활화 기법.
- 윈도우를 이용해 구간을 설정
- 함수를 피팅 (윈도우가 클 수록 차수가 늘어난다)
- 피팅된 선들의 평균을 구한다.
- 평균들을 연결!
그런데 윈도우가 너무 크면, 이상한 직선이 생길 수 있다.
이를 피하는 방법 : 가중치를 적게 주면 가능하다.
점 A와 가까운 곳 : 가중치를 늘린다.
점 A와 먼 곳 : 가중치를 줄인다.
가중치 = 거리의 절댓값의 역수.
knot (x_0)을 계속 이동시켜 전체적인 curve를 그리는 것이 목표
- 정확한 추정을 위해서.
기준과 만들기
- 좋은 선 : SSE가 최소화되는 선
- \beta_0, \beta_1의 관점에서 SSE 최소화
- 두가지 파라미터: \alpha, \lambda
- \alpha : 몇 개의 이웃을 반영할 것인지 (local의 영역을 결정)
- 이 값이 클수록 그래프가 smooth해진다.
- 너무 작으면 overfitting의 문제가 발생
- \lambda : 다항식의 차수 결정.
- 보통 1이 기본값이다.
- 자료의 양에 따라 두 파라미터를 조정하는 방법이 달라진다.
가중치함수
한 이웃에 있는 모든 점들은 knot (x_0)으로의 거리를 이용해 가중치를 가진다.
- 거리의 역수 = 가중치
- 거리가 멀수록 가중치가 낮아진다.
이때, 각 가중치를 만드는 가중치함수(weight function)가 있다.
W는 다음과 같은 성질을 가진다.
tri-cube weight function은 다음과 같다.
- 정규분포를 반으로 자른 모양이랑 비슷하다.
각 가중치와 SSE를 곱한 뒤, 전부 더한다.
loess의 단점
-
관측값 내에서만 그릴 수 있다. extrapolation(외삽법) 불가.
-
x와 y의 연관성을 파악하기 힘들다. 검정이 안됨.
-
전체적인 신뢰구간을 찾을 수 없다. 구간추정이 안됨.
(지역적인 신뢰구간은 구할 수 있다.)
-
변수가 많아지면 만들고, 보기 힘들다.
→ 말 그대로 탐색을 위한 기법!
예시문제 1: environmental
데이터 준비하기
데이터를 준비하고, loess을 만들어보자.
해답
load("environmental.Rdata")
ls()
str(data)
attach(data)
# loess fit
x = 2/3
y = 1
data_loess = loess(Ozone~Temperature,
span=x, degree=y)
scatterplot 그리기
해답
# 산점도 그리기
windows()
plot(Temperature, Ozone, pch=16,
main="Environmental Data",
xlab="온도(F)", ylab="Ozone(PPB)",
axes=F, xlim=c(55, 100), ylim=c(0, 180))
axis(1, seq(55, 100, by=5), seq(55, 100, by=5))
axis(2, seq(0, 180, by=20), seq(0, 180, by=20))
ord_temp = order(Temperature)
lines(Temperature[ord_temp], fitted(data_loess)[ord_temp], lwd=2)
detach(data)
결과해석 : 직선 fit vs loess fit
- loess fit
- 일반적인 직선보다 더 분포를 잘 반영한다.
- 단, loess는 정렬을 하지 않으면 데이터가 엉망이 된다.
- 이웃의 넓이에 따른 loess fit의 차이
- 구간이 넓으면 좀 더 smooth한 곡선이 그려진다.
loess의 신뢰구간
- 잭나이프법이나 부트스트래핑을 이용, 신뢰구간을 구하는 것
- 완벽한 신뢰구간을 구할 수 없는 loess 기법에서 자주 사용한다.
- 아래는 y값의 평균에 대한 신뢰구간이다.
sample_data = sample(data_loess$y, 30, replace=TRUE)
n = length(sample_data) # 반복횟수
x = 50000 # 부트스트랩 반복횟수
resamples = matrix(sample(sample_data, n*x, replace=TRUE))
means = apply(resamples, 1, mean) # 샘플별 평균
quantile(means, c(0.025, 0.975))
예시문제 2: galaxy
데이터 준비하기
데이터를 준비하고, loess을 만들어보자.
해답
##### environmental data
### 데이터 준비
dev.off()
rm(list=ls())
load("galaxy.Rdata")
str(data)
attach(data)
# loess fit
galaxy_loess = loess(Velocity~EastWest*NorthSouth, span=0.25, degree=2)
조건부 산점도
- conditional plot
coplot()을 사용한다.- 변수가 두 개 이상일 때 사용한다.
해답
# NorthSouth를 조건부로 loess fit 그리기
t1 = "East-West Coordinate (arcsec)"
t2 = "Given: North-South Coordinate (arcsec)"
windows()
coplot(Velocity~EastWest|NorthSouth,
panel = function(x, y, col, pch){
idx = order(x)
points(x, y, pch=pch, col=col)
lines(x[idx], predict(loess(y~x))[idx], lwd=2, col=4)
}, xlab=c(t1, t2), ylab="Velocity")
등고선 그리기
- 등고선(contour plot): 변수가 두 개 이상일 때 사용한다.
해답
# 등고선 그리기
sort_ew = sort(EastWest)
sort_ns = sort(NorthSouth)
pred_val = predict(galaxy_loess, expand.grid(data.frame(EastWest=sort_ew, NorthSouth=sort_ns)))
contour(sort_ew, sort_ns, pred_val,
nlevels=15, main="Contour plot of loess fit to Velocity", xlab=t1, ylab=t2)
detach(data)