198강까지 자료를 정상으로 만들고 모형을 맞췄습니다. 이제 그것으로 앞을 내다봅니다.
두 물음이 따로입니다. 앞은 견줄 상대가 있어야 답할 수 있고, 뒤는 구간이 실제로 그만큼 담는지 확인해야 답할 수 있습니다.
197강 문제 4에서 칸 앞 구간의 포함률이 이었습니다. 계수를 안다고 치고 계산했기 때문인데, 실제로는 계수도 추정한 것입니다.
이 강의는 기준선, 구간의 정직함, 지수평활이라는 다른 계열의 방법, 여러 칸 앞 예측, 그리고 검증 절차를 다룹니다.
문제. 기준선을 세웁니다.
(1) 정상 자료에서 세 방법을 견주세요.
(2) 누적 자료에서 다시 견주세요.
(3) 지표를 고르세요.
생각의 실마리. "제곱오차 "라는 말만으로는 아무것도 알 수 없습니다. 무엇보다 나은지가 있어야 합니다.
풀이. (1) 되먹임 자료입니다. 앞 개로 맞추고 뒤 개를 예측합니다.
| 무엇으로 예측 | 제곱오차 | 절대오차 | 기준선 대비 |
|---|---|---|---|
| 평균만 말함 | |||
| 바로 앞 값 그대로 | |||
| 되먹임 모형 |
되먹임 모형이 로 평균만 말하는 것의 절반 수준입니다.
바로 앞 값도 로 평균보다 낫습니다. 이웃이 닮았기 때문입니다.
그런데 되먹임 모형보다는 나쁩니다. 가 인데 을 쓰면 지나칩니다.
(2) 같은 세 방법을 누적 자료에 써 봅니다.
| 무엇으로 예측 | 제곱오차 | 기준선 대비 |
|---|---|---|
| 평균만 말함 | ||
| 바로 앞 값 그대로 | ||
| 되먹임 모형 |
바로 앞 값이 평균보다 배 좋습니다. 누적 자료이기 때문입니다.
되먹임 모형이 바로 앞 값과 사실상 같습니다. 추정한 계수가 에 가까우므로 같은 예측을 냅니다.
기준선을 무엇으로 두느냐가 성능 주장 전체를 바꿉니다. 누적 자료에서 "평균 대비 퍼센트 개선"이라고 쓰면 아무 일도 안 한 것을 자랑하는 셈입니다.
정상 자료에는 평균을 쓰고 누적 자료에는 바로 앞 값을 씁니다.
(3) 지표를 고릅니다.
| 지표 | 무엇에 민감한가 | 언제 쓰나 |
|---|---|---|
| 제곱오차 | 큰 오차에 크게 | 큰 실수를 피할 때 |
| 절대오차 | 고르게 | 보통의 정확도 |
| 절대비율오차 | 작은 값에 크게 | 규모가 다를 때 |
| 규모조정오차 | 기준선 대비 | 여러 계열을 묶을 때 |
셋째 줄은 값이 근처면 못 씁니다. 나누기 때문입니다.
이상점 하나가 지표를 얼마나 흔드는지 봅니다. 오차 개 중 하나를 크게 만듭니다.
| 이상점 크기 | 제곱오차 평균 | 절대오차 평균 |
|---|---|---|
이상점이 이면 제곱오차가 여섯 배가 되는데 절대오차는 배입니다.
어느 지표를 보고하느냐가 결론을 바꿉니다. 둘을 함께 적습니다.
이 문제에서 배우는 것. 시계열 예측 논문과 보고서에서 기준선 없는 숫자가 가장 흔한 결함입니다. 누적 자료에 복잡한 신경망을 쓰고 "결정계수 "를 보고하는 경우가 많은데, 위 표의 둘째 줄이 그것을 아무 계산 없이 냅니다. 그래서 예측 대회들이 바로 앞 값 대비 비율을 기본 지표로 삼으며, 그것이 넷째 줄의 규모조정오차입니다. 189강 문제 1에서 결정계수만으로 모형을 못 고른다고 했던 것과 같은 이야기입니다.
바로 확인 1.
확인 1-1. 정상 자료와 누적 자료의 기준선을 각각 쓰세요.
답. 정상 자료에는 평균을 쓰고 누적 자료에는 바로 앞 값을 씁니다.
확인 1-2. 검산에서 누적 자료의 세 제곱오차를 쓰세요.
답. , , 입니다.
확인 1-3. 검산에서 이상점이 일 때 두 지표를 쓰세요.
답. 제곱오차 이고 절대오차 입니다.
문제. 구간을 검사합니다.
(1) 자료 길이를 바꿔 가며 포함률을 재세요.
(2) 계수 오차를 넣는 방법을 정리하세요.
(3) 붓스트랩으로 해 보세요.
생각의 실마리. 197강의 구간은 를 안다고 치고 계산했습니다. 실제로는 추정한 것이므로 그 오차가 빠져 있습니다.
풀이. (1) 자료 길이를 바꿔 가며 한 칸 앞 구간의 포함률을 봅니다.
| 자료 길이 | 계수 추정의 sd | 포함률 | 목표 |
|---|---|---|---|
길이 에서 포함률이 입니다. 스무 번 중 두 번 넘게 구간 밖으로 나갑니다.
길이가 늘면 목표에 붙습니다. 계수 추정의 sd가 에서 으로 함께 줄어듭니다.
길이 이면 이미 입니다. 한 칸 앞 예측에서는 계수 오차의 몫이 생각보다 작습니다.
(2) 계수 오차를 넣는 방법입니다.
| 방법 | 어떻게 | 무엇을 조심 |
|---|---|---|
| 분포 쓰기 | 정규 대신 자유도 반영 | 계수 오차는 못 담음 |
| 델타 방법 | 예측식을 계수로 미분 | 비선형에서 근사 |
| 붓스트랩 | 잔차를 다시 뽑아 반복 | 시간 구조를 지켜야 |
| 베이즈 | 계수의 분포를 함께 | 사전분포가 필요 |
첫째 줄이 흔한 오해입니다. 분포는 분산 추정의 오차를 담을 뿐 계수 오차는 안 담습니다.
(3) 붓스트랩으로 해 봅니다. 잔차를 시간 순서대로 다시 붙여 자료를 만들고 계수를 다시 맞춥니다.
| 방법 | 포함률 | 평균 구간 폭 | 목표 |
|---|---|---|---|
| 계수를 안다고 침 | |||
| 붓스트랩 |
붓스트랩이 오히려 조금 좁고 포함률도 낮게 나옵니다.
잔차가 이미 계수를 맞추면서 작아져 있어 그것을 다시 뽑으면 더 작아집니다. 계수 오차를 담으려던 방법이 잔차 쪽에서 그만큼을 도로 잃은 것입니다.
붓스트랩을 시간 구조에 맞게 고쳐도 공짜가 아닙니다. 잔차를 자유도로 부풀리는 보정을 함께 해야 제 몫을 합니다.
이 문제에서 배우는 것. 예측 구간이 좁게 나오는 원인이 여럿이고 서로 크기가 다릅니다. 계수 오차는 자료가 조금만 길어도 무시할 만해지는데, 실무의 구간이 늘 좁은 이유는 그것이 아닙니다. 문제 5에서 보듯 모형이 틀렸거나 구조가 변한 것이 훨씬 크며, 그것은 계산을 정교하게 해서 못 고칩니다. 붓스트랩을 쓰면 나아질 것이라는 기대가 여기서 무너지고, 정교한 계산이 잘못된 모형을 구제하지 않는다는 것이 이 문제의 결론입니다.
바로 확인 2.
확인 2-1. 검산에서 길이 와 의 포함률을 쓰세요.
답. 와 입니다.
확인 2-2. 분포를 쓰면 무엇이 담기고 무엇이 안 담기는지 쓰세요.
답. 분산 추정의 오차는 담기고 계수 추정의 오차는 안 담깁니다.
확인 2-3. 검산에서 두 방법의 포함률과 구간 폭을 쓰세요.
답. 과 , 과 입니다.
문제. 다른 계열의 방법을 씁니다.
(1) 가중치가 어떻게 정해지는지 보세요.
(2) 계수를 자료에서 고르고 견주세요.
(3) 추세를 담아 보세요.
생각의 실마리. 과거 값에 지수적으로 줄어드는 가중치를 주고 평균을 냅니다. 모형도 정상성도 없이 규칙 하나뿐입니다.
풀이. (1) 가중치를 봅니다.
| 직전 값의 몫 | 칸 전의 몫 | 사실상 몇 개를 보나 | |
|---|---|---|---|
가 작으면 멀리까지 보고 크면 최근만 봅니다.
마지막 열은 같은 분산을 내는 단순평균의 개수입니다. 이면 최근 개를 고르게 평균 낸 것과 같은 흔들림입니다.
(2) 를 자료에서 고릅니다.
| 학습 구간 제곱오차 | 검증 구간 제곱오차 | |
|---|---|---|
검증 구간에서 가장 좋은 는 입니다. 되먹임 자료이므로 최근을 많이 보는 쪽이 유리합니다.
학습 구간에서는 가 더 좋아 보입니다. 189강 문제 1의 과적합이 여기서도 나타나므로, 검증 구간에서 골라야 합니다.
되먹임 모형과 견줍니다.
| 무엇으로 | 검증 제곱오차 | 계수 개수 |
|---|---|---|
| 평균만 말함 | ||
| 지수평활 | ||
| 되먹임 모형 |
되먹임 모형이 로 가장 낫습니다. 자료를 그 식으로 만들었기 때문입니다.
지수평활은 입니다. 평균에서 되먹임까지의 중 을 따라잡았습니다.
계수 하나로 열에 여덟을 가져옵니다. 실무에서 오래 쓰인 이유입니다.
(3) 추세를 담아 봅니다.
| 무엇으로 | 한 칸 앞 제곱오차 | 치우침 평균 |
|---|---|---|
| 추세 없는 지수평활 | ||
| 추세 있는 지수평활 |
추세를 안 담으면 치우침 평균이 로 늘 아래로 어긋납니다.
항을 하나 더 달면 로 치우침이 사라집니다.
그런데 제곱오차는 에서 로 오히려 커집니다. 추세 항을 추정하는 값이 치우침을 없앤 이득보다 컸습니다.
165강 문제 2의 편향과 분산 맞바꿈이 여기서도 나타납니다. 지평이 길어지면 치우침이 쌓이므로 그때는 추세 항이 이깁니다.
이 문제에서 배우는 것. 지수평활은 모형이 아니라 규칙인데도 잘 맞습니다. 정상성도 차수 선택도 없이 계수 하나만 고르면 되고, 위 표에서 되먹임 모형과의 차이가 뿐입니다. 그래서 수천 개의 계열을 자동으로 예측해야 하는 실무에서 표준으로 쓰입니다. 198강 심화 5에서 말했듯 이것이 상태공간 모형의 특수한 경우이므로, 겉보기에 다른 두 계열이 같은 것을 하고 있습니다.
바로 확인 3.
확인 3-1. 지수평활의 갱신식을 쓰세요.
답. 새 값에 를, 직전 예측에 를 주어 더합니다.
확인 3-2. 검산에서 검증 구간의 세 제곱오차를 쓰세요.
답. , , 입니다.
확인 3-3. 검산에서 추세 항을 달았을 때 무엇이 좋아지고 무엇이 나빠지는지 쓰세요.
답. 치우침이 에서 가 되고 제곱오차가 에서 이 됩니다.
문제. 지평을 늘립니다.
(1) 두 방식을 정리하세요.
(2) 모형이 맞을 때 견주세요.
(3) 모형이 틀릴 때 견주세요.
생각의 실마리. 칸 앞을 예측하는 방법이 둘입니다. 한 칸 예측을 되먹이거나, 칸 앞을 바로 회귀하거나입니다.
풀이. (1) 두 방식입니다.
| 방법 | 어떻게 | 무엇을 조심 |
|---|---|---|
| 되풀이 | 한 칸 예측을 되먹임 | 오차가 쌓임 |
| 직접 | 칸 앞을 바로 회귀 | 지평마다 모형이 따로 |
(2) 모형이 맞을 때 견줍니다. 되먹임 자료입니다.
| 몇 칸 앞 | 되풀이 | 직접 | 평균만 말함 |
|---|---|---|---|
모형이 맞으면 두 방법이 거의 같습니다.
칸 앞에서는 과 으로 평균만 말하는 것에 거의 닿습니다. 197강 문제 4에서 본 성질입니다.
(3) 모형을 일부러 틀리게 해 봅니다. 참 자료는 와 로 출렁이는 두 칸 되먹임인데 한 칸으로만 맞춥니다.
| 몇 칸 앞 | 되풀이 | 직접 | 직접이 몇 배 나은가 |
|---|---|---|---|
지평 에서 배로 가장 크게 벌어집니다.
되풀이는 틀린 식을 번 적용하므로 어긋남이 곱해집니다. 직접은 지평마다 따로 맞추므로 틀린 식을 되풀이하지 않습니다.
지평 에서는 로 다시 좁혀집니다. 둘 다 무조건 분산에 가까워지기 때문입니다.
모형이 틀렸을 때의 이득은 중간 지평에서 가장 큽니다.
이 문제에서 배우는 것. 직접 방식은 모형 오지정에 대한 보험입니다. 되풀이는 "이 식이 맞다"는 가정을 번 되풀이해 쓰므로, 식이 조금만 틀려도 지평이 길어질수록 어긋남이 커집니다. 대신 직접 방식은 지평마다 모형이 따로라 예측들이 서로 어긋날 수 있고, 계수도 배로 늘어납니다. 어느 쪽을 쓸지는 모형을 얼마나 믿는가에 달렸으며, 자료가 많고 구조를 잘 모르면 직접이 안전합니다.
바로 확인 4.
확인 4-1. 여러 칸 앞 예측의 두 방식을 쓰세요.
답. 한 칸 예측을 되먹이는 방식과 칸 앞을 바로 회귀하는 방식입니다.
확인 4-2. 검산에서 모형이 맞을 때 칸 앞 세 값을 쓰세요.
답. , , 으로 셋이 거의 같습니다.
확인 4-3. 검산에서 모형이 틀릴 때 지평 의 두 값과 비를 쓰세요.
답. 과 이며 배입니다.
문제. 절차를 세웁니다.
(1) 무엇이 문제인지 정리하세요.
(2) 두 나누는 방식을 견주세요.
(3) 구간이 왜 좁은지 밝히세요.
생각의 실마리. 189강 문제 4의 겹 나누기를 그대로 쓰면 안 됩니다.
풀이. (1) 무엇이 문제인지 정리합니다.
| 무엇이 문제 | 왜 |
|---|---|
| 무작위 겹 | 미래로 과거를 맞히게 됨 |
| 전체로 표준화 | 미래 정보가 새어 들어감 |
| 전체로 이상점 제거 | 162강의 누출 |
| 한 번만 나눔 | 그 구간에 우연히 맞을 수 |
앞에서 뒤로만 나누고 여러 번 나눕니다.
(2) 두 나누는 방식을 견줍니다. 앞 절반과 뒤 절반의 성질이 다른 자료입니다.
| 어떻게 나누나 | 평균 제곱오차 | 구간별 편차 |
|---|---|---|
| 늘려 가며 | ||
| 굴려 가며 개 |
성질이 변하는 자료에서는 굴려 가는 쪽이 낫습니다. 이 이 됩니다.
구간별 편차도 에서 로 줄어듭니다. 시점마다 성능이 덜 들쭉날쭉합니다.
오래된 자료를 버리는 것이 이득일 때가 있습니다. 197강 문제 5의 계수 변화가 그 이유입니다.
(3) 구간이 왜 좁은지 밝힙니다.
| 무엇을 뺐나 | 포함률 | 목표 |
|---|---|---|
| 아무것도 안 뺌 | ||
| 계수 오차 | ||
| 모형이 틀림 | ||
| 구조가 변함 |
계수 오차를 넣는 보정은 길이 에서 거의 차이가 없습니다. 이 그대로입니다.
모형이 틀리거나 구조가 변하면 포함률이 크게 내려갑니다. 특히 넷째 줄이 입니다.
구간이 좁은 진짜 이유는 계산이 아니라 모형이 틀렸기 때문입니다.
보고할 때 함께 적을 것을 정리합니다.
| 무엇 | 왜 |
|---|---|
| 예측 지평 | 지평마다 성능이 다름 |
| 기준선 | 무엇보다 나은지 |
| 검증 방식 | 누출이 없는지 |
| 구간과 포함률 | 얼마나 틀릴 수 있는지 |
| 지표 둘 이상 | 이상점에 흔들리므로 |
| 자료 기간 | 구조가 변했는지 |
둘째 줄이 없으면 숫자만으로는 아무 말도 못 합니다.
이 문제에서 배우는 것. 예측 구간을 검증하는 것이 예측값을 검증하는 것보다 드뭅니다. 위 표에서 명목 퍼센트 구간이 실제로는 퍼센트만 담았는데, 이런 계산을 보고서에 싣는 경우가 거의 없습니다. 그런데 재고나 인력을 계획할 때 실제로 쓰이는 것은 점 예측이 아니라 구간의 위쪽 끝입니다. 구간이 퍼센트포인트 낙관적이면 그만큼 자주 품절이 나며, 그래서 포함률을 검증 자료에서 직접 세어 보고하는 것이 이 강의의 실무 결론입니다.
바로 확인 5.
확인 5-1. 시계열 검증에서 겹을 어떻게 나누는지 쓰세요.
답. 앞에서 뒤로만 나누고 여러 번 나눕니다.
확인 5-2. 검산에서 두 나누는 방식의 제곱오차와 구간별 편차를 쓰세요.
답. 과 , 과 입니다.
확인 5-3. 검산에서 구조가 변할 때의 포함률을 쓰세요.
답. 입니다.
| 자료 | 기준선 |
|---|---|
| 정상 | 평균 |
| 누적 | 바로 앞 값 |
| 계절 | 지난 주기의 같은 자리 |
| 추세 | 마지막 값에 기울기 |
| 지표 | 성질 |
|---|---|
| 제곱오차 | 이상점에 크게 흔들림 |
| 절대오차 | 고르게 |
| 절대비율오차 | 근처에서 못 씀 |
| 규모조정오차 | 여러 계열을 묶을 때 |
| 구간이 좁은 원인 | 크기 |
|---|---|
| 계수 추정 오차 | 자료가 길면 작음 |
| 모형 오지정 | 큼 |
| 구조 변화 | 가장 큼 |
| 자주 하는 실수 | 바로잡기 |
|---|---|
| 기준선 없이 보고합니다 | 무엇보다 나은지 적습니다 |
| 무작위로 겹을 나눕니다 | 앞에서 뒤로만 나눕니다 |
| 한 번만 나눠 검증합니다 | 여러 번 굴립니다 |
| 지표를 하나만 봅니다 | 둘 이상 함께 봅니다 |
| 구간을 안 검증합니다 | 포함률을 세어 봅니다 |
| 지평을 안 밝힙니다 | 몇 칸 앞인지 적습니다 |
문제 6. 정상 자료와 누적 자료의 기준선을 각각 쓰세요.
답. 정상 자료에는 평균을 쓰고 누적 자료에는 바로 앞 값을 씁니다.
문제 7. 검산에서 누적 자료의 세 제곱오차를 쓰세요.
답. , , 입니다.
문제 8. 검산에서 이상점이 일 때 두 지표를 쓰세요.
답. 제곱오차 이고 절대오차 입니다.
문제 9. 검산에서 길이 와 의 포함률을 쓰세요.
답. 와 입니다.
문제 10. 분포를 쓰면 무엇이 담기고 무엇이 안 담기는지 쓰세요.
답. 분산 추정의 오차는 담기고 계수 추정의 오차는 안 담깁니다.
문제 11. 검산에서 붓스트랩과 그냥 계산의 포함률을 쓰세요.
답. 과 입니다.
문제 12. 지수평활의 갱신식을 쓰세요.
답. 새 값에 를, 직전 예측에 를 주어 더합니다.
문제 13. 검산에서 검증 구간의 세 제곱오차를 쓰세요.
답. , , 입니다.
문제 14. 검산에서 추세 항을 달았을 때 두 값의 변화를 쓰세요.
답. 치우침이 에서 가 되고 제곱오차가 에서 이 됩니다.
문제 15. 검산에서 모형이 맞을 때 칸 앞 세 값을 쓰세요.
답. , , 입니다.
문제 16. 검산에서 모형이 틀릴 때 지평 의 두 값과 비를 쓰세요.
답. 과 이며 배입니다.
문제 17. 검산에서 두 나누는 방식의 제곱오차를 쓰세요.
답. 과 입니다.
문제 18. 검산에서 네 경우의 포함률을 쓰세요.
답. , , , 입니다.
심화 1. 예측 결합을 정리하세요.
여러 모형의 예측을 평균 내면 대개 각각보다 낫습니다.
| 어떻게 결합 | 언제 |
|---|---|
| 단순 평균 | 거의 언제나 안전 |
| 성능 역수 가중 | 성능 차가 클 때 |
| 회귀로 가중 | 자료가 많을 때 |
첫째 줄이 셋째 줄을 자주 이깁니다. 가중치를 추정하는 오차가 이득보다 크기 때문이며, 189강 문제 2의 계수 개수 문제입니다.
서로 다른 방식의 모형을 섞을수록 좋습니다. 오차가 같은 방향으로 안 나기 때문입니다.
예측 대회에서 상위권이 거의 언제나 결합입니다.
심화 2. 분위 예측을 정리하세요.
| 무엇 | 어떻게 |
|---|---|
| 손실 함수 | 위아래를 다르게 벌줌 |
| 분위 | 부족을 아홉 배로 벌줌 |
| 결과 | 그 분위를 바로 냅니다 |
구간을 모형 가정 없이 얻는 방법입니다. 문제 2의 계수 오차나 문제 5의 모형 오지정이 덜 문제가 됩니다.
재고 계획에서 이것이 자연스럽습니다. 품절 비용과 재고 비용의 비가 곧 분위입니다.
여러 분위를 따로 예측하면 서로 뒤집힐 수 있습니다. 정렬해 주는 후처리가 필요합니다.
심화 3. 예측의 조화를 정리하세요.
지점별 예측의 합이 전체 예측과 안 맞는 문제입니다.
| 방식 | 어떻게 |
|---|---|
| 아래에서 위로 | 지점을 예측해 더함 |
| 위에서 아래로 | 전체를 예측해 나눔 |
| 조화 | 둘을 함께 맞춤 |
첫째 줄은 지점이 시끄러우면 나쁩니다. 둘째 줄은 지점별 특성을 못 담습니다.
셋째 줄이 두 예측을 모두 쓰면서 합이 맞도록 조정합니다. 대개 각각보다 낫습니다.
시간 축에서도 같은 문제가 있습니다. 일별 예측의 합이 월별 예측과 다릅니다.
심화 4. 예측이 대상을 바꾸는 경우를 정리하세요.
| 무엇 | 예 |
|---|---|
| 예측이 행동을 바꿈 | 품절 예측을 보고 더 주문 |
| 행동이 자료를 바꿈 | 그래서 품절이 안 남 |
| 자료가 모형을 바꿈 | 다음 예측이 달라짐 |
성능이 좋아 보이는데 실제로는 개입 때문인 경우가 실무에서 흔합니다.
191강의 인과 문제가 여기서 시간축을 따라 나타납니다. 예측 성능을 재려면 개입이 없는 구간이 필요하거나 192강의 무작위 배정이 필요합니다.
심화 5. 기계학습 예측을 정리하세요.
| 무엇 | 시계열에서 |
|---|---|
| 특징 만들기 | 시차 값과 이동평균과 달력 |
| 겹 나누기 | 앞에서 뒤로만 |
| 정규화 | 학습 구간 통계로만 |
| 여러 계열 | 함께 학습하면 이득 |
넷째 줄이 최근의 변화입니다. 계열마다 따로 맞추는 대신 수천 개를 함께 학습하면, 짧은 계열이 긴 계열에서 배웁니다.
그래도 단순한 방법을 못 이기는 경우가 많습니다. 문제 1의 기준선을 반드시 함께 재야 하는 이유입니다.
162강의 누출이 시계열에서 가장 자주 일어납니다. 특징 하나에 미래 정보가 섞이면 성능이 놀랍도록 좋아지는데, 그것이 신호입니다.
심화 6. 04단원이 남긴 것을 정리하세요.
| 강의 | 무엇을 했나 |
|---|---|
| 구조를 봤습니다 | |
| 이름을 붙였습니다 | |
| 정상으로 만들었습니다 | |
| 예측하고 구간을 달았습니다 | |
| 계절과 실무 전체 |
계절을 계속 미뤄 왔습니다. 196강 문제 4에서 분해로 뽑아내기만 했고, 모형에 넣지는 않았습니다.
S8 과목 전체도 200강에서 마칩니다. 01단원의 검정부터 여기까지가 하나의 순서였음을 정리합니다.
정답.
| 기호 | 읽는 법 | 뜻 |
|---|---|---|
| 기준선 | baseline | 견줄 상대가 되는 단순한 예측입니다 |
| 예측 지평 | horizon | 몇 칸 앞을 맞히는지입니다 |
| 제곱오차 | MSE | 오차 제곱의 평균입니다 |
| 절대오차 | MAE | 오차 절댓값의 평균입니다 |
| 규모조정오차 | MASE | 기준선 대비 비율입니다 |
| 지수평활 | exponential smoothing | 지수 가중치로 평균을 냅니다 |
| 알파 | 최근 값에 주는 몫입니다 | |
| 홀트 | Holt | 추세 항을 더한 지수평활입니다 |
| 되풀이 예측 | iterated forecast | 한 칸 예측을 되먹입니다 |
| 직접 예측 | direct forecast | 칸 앞을 바로 회귀합니다 |
| 굴려 가며 검증 | rolling origin | 학습 구간을 옮겨 가며 검증합니다 |
| 포함률 | coverage | 구간이 실제로 담은 비율입니다 |
다음은 200강 계절성과 실무 적용입니다. 이 강의가 예측과 구간을 다뤘습니다.
196강 문제 4에서 계절을 분해로 뽑아내기만 했고 모형 안에 넣지는 않았습니다. 200강은 계절 차분과 계절 항을 다루고, 04단원과 S8 과목 전체를 하나의 순서로 정리합니다.
import numpy as np
rng = np.random.default_rng(20261006)
def pw(s, n):
k = n - sum(2 if ord(c) > 0x2FFF else 1 for c in str(s))
return str(s) + " " * max(k, 0)
def rw(s, n):
k = n - sum(2 if ord(c) > 0x2FFF else 1 for c in str(s))
return " " * max(k, 0) + str(s)
def gen_ar1(n, phi, sd=1.0, burn=500):
m = n + burn
e = rng.normal(0, sd, m)
x = np.zeros(m)
for t in range(1, m):
x[t] = phi * x[t - 1] + e[t]
return x[burn:]
def gen_ar2(n, p1, p2, sd=1.0, burn=500):
m = n + burn
e = rng.normal(0, sd, m)
x = np.zeros(m)
for t in range(2, m):
x[t] = p1 * x[t - 1] + p2 * x[t - 2] + e[t]
return x[burn:]
def fit_ar1(x):
n = len(x) - 1
A = np.stack([x[:n], np.ones(n)], axis=1)
b, *_ = np.linalg.lstsq(A, x[1:], rcond=None)
r = x[1:] - A @ b
return float(b[0]), float(b[1]), float(r @ r) / (n - 2)
def ses(x, alpha):
lv = x[0]
out = np.empty(len(x))
for t in range(len(x)):
out[t] = lv
lv = alpha * x[t] + (1 - alpha) * lv
return out, lv
def holt(x, alpha, beta):
lv, tr = x[0], x[1] - x[0]
out = np.empty(len(x))
for t in range(len(x)):
out[t] = lv + tr
nl = alpha * x[t] + (1 - alpha) * (lv + tr)
tr = beta * (nl - lv) + (1 - beta) * tr
lv = nl
return out, lv, tr
# --- 문제 1: 무엇을 견주는가 -------------------------------------------
print(" 예측을 잘했는지 말하려면 견줄 상대가 있어야 합니다")
print(" 아무 모형도 안 쓴 예측을 기준선이라 합니다")
n1 = 3000
x1 = gen_ar1(n1, 0.7)
tr1, te1 = x1[:2400], x1[2400:]
mu = float(tr1.mean())
ph, ic, s2 = fit_ar1(tr1)
print(" 되먹임 0.7 자료입니다. 앞 2400 개로 맞추고 뒤 600 개를 예측합니다")
print(" %s %s %s %s"
% (pw("무엇으로 예측", 26), rw("제곱오차", 14), rw("절대오차", 14),
rw("기준선 대비", 14)))
res = []
base = None
for nm, f in [("평균만 말함", lambda i: mu),
("바로 앞 값 그대로", lambda i: te1[i - 1]),
("되먹임 모형", lambda i: ic + ph * te1[i - 1])]:
se_, ae = [], []
for i in range(1, len(te1)):
e = te1[i] - f(i)
se_.append(e * e)
ae.append(abs(e))
m2, m1 = float(np.mean(se_)), float(np.mean(ae))
if base is None:
base = m2
print(" %s %14.6f %14.6f %14.4f"
% (pw(nm, 26), m2, m1, m2 / base))
print(" 되먹임 모형이 0.4835 로 평균만 말하는 것의 절반 수준입니다")
print(" 바로 앞 값도 0.5608 로 평균보다 낫습니다. 이웃이 닮았기 때문입니다")
print(" 그런데 되먹임 모형보다는 나쁩니다. phi 가 0.7 이라 1 을 쓰면 지나칩니다")
print(" 누적 자료에서는 기준선이 바뀝니다")
x2 = np.cumsum(gen_ar1(n1, 0.3))
tr2, te2 = x2[:2400], x2[2400:]
mu2 = float(tr2.mean())
ph2, ic2, _ = fit_ar1(tr2)
print(" 같은 세 방법을 누적 자료에 써 봅니다")
print(" %s %s %s"
% (pw("무엇으로 예측", 26), rw("제곱오차", 16), rw("기준선 대비", 14)))
base2 = None
for nm, f in [("평균만 말함", lambda i: mu2),
("바로 앞 값 그대로", lambda i: te2[i - 1]),
("되먹임 모형", lambda i: ic2 + ph2 * te2[i - 1])]:
se_ = [(te2[i] - f(i)) ** 2 for i in range(1, len(te2))]
m2 = float(np.mean(se_))
if base2 is None:
base2 = m2
print(" %s %16.6f %14.4f" % (pw(nm, 26), m2, m2 / base2))
print(" 바로 앞 값이 평균보다 훨씬 좋습니다. 누적 자료이기 때문입니다")
print(" 기준선을 무엇으로 두느냐가 성능 주장 전체를 바꿉니다")
print(" 정상 자료에는 평균을 쓰고 누적 자료에는 바로 앞 값을 씁니다")
print(" 지표마다 다른 것을 잽니다")
print(" %s %s %s"
% (pw("지표", 20), rw("무엇에 민감한가", 22), rw("언제 쓰나", 22)))
for a, b, c in [("제곱오차", "큰 오차에 크게", "큰 실수를 피할 때"),
("절대오차", "고르게", "보통의 정확도"),
("절대비율오차", "작은 값에 크게", "규모가 다를 때"),
("규모조정오차", "기준선 대비", "여러 계열을 묶을 때")]:
print(" %s %s %s" % (pw(a, 20), rw(b, 22), rw(c, 22)))
print(" 셋째 줄은 값이 0 근처면 못 씁니다. 나누기 때문입니다")
print(" 이상점 하나가 지표를 얼마나 흔드는지 봅니다")
err = rng.normal(0, 1, 500)
print(" 오차 500 개 중 하나를 크게 만들어 봅니다")
print(" %s %s %s"
% (pw("이상점 크기", 14), rw("제곱오차 평균", 18), rw("절대오차 평균", 18)))
for k in [0, 5, 20, 50]:
e = err.copy()
e[0] = k if k else err[0]
print(" %s %18.6f %18.6f"
% (pw("%d" % k, 14), float(np.mean(e ** 2)), float(np.mean(np.abs(e)))))
print(" 이상점이 50 이면 제곱오차가 여섯 배가 되는데 절대오차는 1.1 배입니다")
print(" 어느 지표를 보고하느냐가 결론을 바꿉니다. 둘을 함께 적습니다")
# --- 문제 2: 계수 오차가 구간에 들어갑니다 ------------------------------
print(" 197강 문제 4 에서 10 칸 앞 구간의 포함률이 0.9367 이었습니다")
print(" 계수를 안다고 치고 계산했기 때문입니다")
S = 2000
print(" 자료 길이를 바꿔 가며 한 칸 앞 구간의 포함률을 봅니다")
print(" %s %s %s %s"
% (pw("자료 길이", 12), rw("계수 추정의 sd", 18), rw("포함률", 12),
rw("목표", 10)))
for nn in [12, 20, 50, 200]:
cov, phs = 0, []
for _ in range(S):
z = gen_ar1(nn + 1, 0.7)
ztr, last, nxt = z[:nn], z[nn - 1], z[nn]
p_, i_, v_ = fit_ar1(ztr)
phs.append(p_)
f = i_ + p_ * last
if abs(nxt - f) < 1.96 * np.sqrt(v_):
cov += 1
print(" %s %18.6f %12.4f %10.2f"
% (pw("%d" % nn, 12), float(np.std(phs, ddof=1)), cov / S, 0.95))
print(" 짧을수록 포함률이 목표 아래로 내려갑니다. 계수 오차가 크기 때문입니다")
print(" 길이가 늘면 목표에 붙습니다. 계수 추정의 sd 가 함께 줄어듭니다")
print(" 계수 오차를 구간에 넣는 세 가지 방법이 있습니다")
print(" %s %s %s"
% (pw("방법", 22), rw("어떻게", 26), rw("무엇을 조심", 22)))
for a, b, c in [("t 분포 쓰기", "정규 대신 자유도 반영", "계수 오차는 못 담음"),
("델타 방법", "예측식을 계수로 미분", "비선형에서 근사"),
("붓스트랩", "잔차를 다시 뽑아 반복", "시간 구조를 지켜야"),
("베이즈", "계수의 분포를 함께", "사전분포가 필요")]:
print(" %s %s %s" % (pw(a, 22), rw(b, 26), rw(c, 22)))
print(" 셋째 줄을 해 봅니다. 잔차를 시간 순서대로 다시 붙입니다")
print(" 붓스트랩으로 구간을 넓혀 봅니다")
S2 = 800
B = 200
print(" 길이 60 인 자료에서 두 방법의 포함률을 견줍니다")
cov_n, cov_b, w_n, w_b = 0, 0, [], []
for _ in range(S2):
nn = 60
z = gen_ar1(nn + 1, 0.7)
ztr, last, nxt = z[:nn], z[nn - 1], z[nn]
p_, i_, v_ = fit_ar1(ztr)
f = i_ + p_ * last
half = 1.96 * np.sqrt(v_)
if abs(nxt - f) < half:
cov_n += 1
w_n.append(2 * half)
resid = ztr[1:] - (i_ + p_ * ztr[:-1])
resid = resid - resid.mean()
fs = []
for _ in range(B):
idx = rng.integers(0, len(resid), nn)
zb = np.empty(nn)
zb[0] = ztr[0]
for t in range(1, nn):
zb[t] = i_ + p_ * zb[t - 1] + resid[idx[t]]
pb, ib, vb = fit_ar1(zb)
fs.append(ib + pb * last + resid[rng.integers(0, len(resid))])
lo, hi = np.quantile(fs, [0.025, 0.975])
if lo < nxt < hi:
cov_b += 1
w_b.append(hi - lo)
print(" %s %s %s %s"
% (pw("방법", 22), rw("포함률", 12), rw("평균 구간 폭", 16), rw("목표", 10)))
print(" %s %12.4f %16.6f %10.2f"
% (pw("계수를 안다고 침", 22), cov_n / S2, float(np.mean(w_n)), 0.95))
print(" %s %12.4f %16.6f %10.2f"
% (pw("붓스트랩", 22), cov_b / S2, float(np.mean(w_b)), 0.95))
print(" 붓스트랩이 오히려 조금 좁고 포함률도 낮게 나옵니다")
print(" 잔차가 이미 계수를 맞추면서 작아져 있어 그것을 다시 뽑으면 더 작아집니다")
print(" 계수 오차를 담으려던 방법이 잔차 쪽에서 그만큼을 도로 잃은 것입니다")
print(" 170강 문제 4 의 붓스트랩을 시간 구조에 맞게 고쳐도 공짜가 아닙니다")
print(" 잔차를 자유도로 부풀리는 보정을 함께 해야 제 몫을 합니다")
# --- 문제 3: 지수평활 --------------------------------------------------
print(" 전혀 다른 계열의 방법이 있습니다")
print(" 과거 값에 지수적으로 줄어드는 가중치를 주고 평균을 냅니다")
n3 = 2000
x3 = gen_ar1(n3, 0.7)
print(" 가중치가 alpha 와 1 빼기 alpha 의 거듭제곱으로 정해집니다")
print(" %s %s %s %s"
% (pw("alpha", 10), rw("직전 값의 몫", 16), rw("5 칸 전의 몫", 16),
rw("사실상 몇 개를 보나", 22)))
for al in [0.1, 0.3, 0.5, 0.9]:
print(" %s %16.6f %16.6f %22.4f"
% (pw("%.1f" % al, 10), al, al * (1 - al) ** 5, (2 - al) / al))
print(" alpha 가 작으면 멀리까지 보고 크면 최근만 봅니다")
print(" 마지막 열은 같은 분산을 내는 단순평균의 개수입니다")
print(" alpha 를 자료에서 고릅니다")
tr3, te3 = x3[:1600], x3[1600:]
print(" %s %s %s"
% (pw("alpha", 10), rw("학습 구간 제곱오차", 20), rw("검증 구간 제곱오차", 22)))
best = None
for al in [0.1, 0.3, 0.5, 0.7, 0.9]:
fit, lv = ses(tr3, al)
e_in = float(np.mean((tr3[1:] - fit[1:]) ** 2))
lv2 = lv
es = []
for t in range(len(te3)):
es.append((te3[t] - lv2) ** 2)
lv2 = al * te3[t] + (1 - al) * lv2
e_out = float(np.mean(es))
if best is None or e_out < best[0]:
best = (e_out, al)
print(" %s %20.6f %22.6f" % (pw("%.1f" % al, 10), e_in, e_out))
print(" 검증 구간에서 가장 좋은 alpha 는 %.1f 입니다" % best[1])
print(" 되먹임 0.7 자료이므로 최근을 많이 보는 쪽이 유리합니다")
print(" 지수평활과 되먹임 모형을 견줍니다")
ph3, ic3, _ = fit_ar1(tr3)
print(" %s %s %s"
% (pw("무엇으로", 24), rw("검증 제곱오차", 18), rw("계수 개수", 14)))
lv2 = ses(tr3, best[1])[1]
es = []
for t in range(len(te3)):
es.append((te3[t] - lv2) ** 2)
lv2 = best[1] * te3[t] + (1 - best[1]) * lv2
e_ses = float(np.mean(es))
e_ar = float(np.mean([(te3[t] - (ic3 + ph3 * te3[t - 1])) ** 2
for t in range(1, len(te3))]))
e_mu = float(np.mean((te3 - tr3.mean()) ** 2))
for nm, v, k in [("평균만 말함", e_mu, 0), ("지수평활", e_ses, 1),
("되먹임 모형", e_ar, 2)]:
print(" %s %18.6f %14d" % (pw(nm, 24), v, k))
print(" 되먹임 모형이 0.8669 로 가장 낫습니다. 자료를 그 식으로 만들었기 때문입니다")
print(" 지수평활은 0.9939 입니다. 평균에서 되먹임까지의 0.6138 중 0.4867 을 따라잡았습니다")
print(" 계수 하나로 열에 여덟을 가져옵니다. 실무에서 오래 쓰인 이유입니다")
print(" 추세가 있으면 항을 하나 더 답니다")
n4 = 600
t4 = np.arange(n4, dtype=float)
x4 = 10.0 + 0.08 * t4 + gen_ar1(n4, 0.5)
tr4, te4 = x4[:480], x4[480:]
print(" 추세가 있는 자료에 두 방법을 써 봅니다")
print(" %s %s %s"
% (pw("무엇으로", 26), rw("한 칸 앞 제곱오차", 20), rw("치우침 평균", 16)))
_, lv, _ = ses(tr4, 0.5), None, None
fit_s, lvs = ses(tr4, 0.5)
lv_s = lvs
es_s, bs_s = [], []
for t in range(len(te4)):
e = te4[t] - lv_s
es_s.append(e * e)
bs_s.append(e)
lv_s = 0.5 * te4[t] + 0.5 * lv_s
fit_h, lvh, trh = holt(tr4, 0.5, 0.2)
lv_h, tr_h = lvh, trh
es_h, bs_h = [], []
for t in range(len(te4)):
f = lv_h + tr_h
e = te4[t] - f
es_h.append(e * e)
bs_h.append(e)
nl = 0.5 * te4[t] + 0.5 * f
tr_h = 0.2 * (nl - lv_h) + 0.8 * tr_h
lv_h = nl
for nm, es_, bs_ in [("추세 없는 지수평활", es_s, bs_s),
("추세 있는 지수평활", es_h, bs_h)]:
print(" %s %20.6f %16.6f"
% (pw(nm, 26), float(np.mean(es_)), float(np.mean(bs_))))
print(" 추세를 안 담으면 치우침 평균이 0.1589 로 늘 아래로 어긋납니다")
print(" 항을 하나 더 달면 -0.0058 로 치우침이 사라집니다")
print(" 그런데 제곱오차는 1.2014 에서 1.4101 로 오히려 커집니다")
print(" 추세 항을 추정하는 값이 치우침을 없앤 이득보다 컸습니다")
print(" 165강 문제 2 의 편향과 분산 맞바꿈이 여기서도 나타납니다")
print(" 지평이 길어지면 치우침이 쌓이므로 그때는 추세 항이 이깁니다")
# --- 문제 4: 여러 칸 앞 --------------------------------------------------
print(" 여러 칸 앞을 예측하는 방법이 둘입니다")
print(" %s %s %s"
% (pw("방법", 20), rw("어떻게", 26), rw("무엇을 조심", 24)))
for a, b, c in [("되풀이", "한 칸 예측을 되먹임", "오차가 쌓임"),
("직접", "h 칸 앞을 바로 회귀", "지평마다 모형이 따로")]:
print(" %s %s %s" % (pw(a, 20), rw(b, 26), rw(c, 24)))
print(" 둘을 견줘 봅니다")
n5 = 4000
x5 = gen_ar1(n5, 0.75)
tr5, te5 = x5[:3200], x5[3200:]
ph5, ic5, _ = fit_ar1(tr5)
print(" %s %s %s %s"
% (pw("몇 칸 앞", 12), rw("되풀이", 16), rw("직접", 16), rw("평균만 말함", 18)))
mu5 = float(tr5.mean())
v_mu = float(np.mean((te5 - mu5) ** 2))
for h in [1, 2, 5, 10]:
er = []
for i in range(len(te5) - h):
f = te5[i]
for _ in range(h):
f = ic5 + ph5 * f
er.append((te5[i + h] - f) ** 2)
nn = len(tr5) - h
A = np.stack([tr5[:nn], np.ones(nn)], axis=1)
b, *_ = np.linalg.lstsq(A, tr5[h:h + nn], rcond=None)
ed = [(te5[i + h] - (b[1] + b[0] * te5[i])) ** 2
for i in range(len(te5) - h)]
print(" %s %16.6f %16.6f %18.6f"
% (pw("%d" % h, 12), float(np.mean(er)), float(np.mean(ed)), v_mu))
print(" 모형이 맞으면 두 방법이 거의 같습니다")
print(" 모형이 틀리면 직접이 낫습니다. 잘못된 식을 되풀이하지 않기 때문입니다")
print(" 모형을 일부러 틀리게 해 봅니다")
n6 = 4000
x6 = gen_ar2(n6, 1.4, -0.75)
tr6, te6 = x6[:3200], x6[3200:]
ph6, ic6, _ = fit_ar1(tr6)
print(" 참 자료는 1.4 와 -0.75 로 출렁이는 두 칸 되먹임인데 한 칸으로만 맞춥니다")
print(" %s %s %s %s"
% (pw("몇 칸 앞", 12), rw("되풀이", 16), rw("직접", 16), rw("직접이 몇 배 나은가", 22)))
for h in [1, 2, 5, 10]:
er = []
for i in range(len(te6) - h):
f = te6[i]
for _ in range(h):
f = ic6 + ph6 * f
er.append((te6[i + h] - f) ** 2)
nn = len(tr6) - h
A = np.stack([tr6[:nn], np.ones(nn)], axis=1)
b, *_ = np.linalg.lstsq(A, tr6[h:h + nn], rcond=None)
ed = [(te6[i + h] - (b[1] + b[0] * te6[i])) ** 2
for i in range(len(te6) - h)]
me, md = float(np.mean(er)), float(np.mean(ed))
print(" %s %16.6f %16.6f %22.4f"
% (pw("%d" % h, 12), me, md, me / md))
print(" 지평 5 에서 2.0041 배로 가장 크게 벌어집니다")
print(" 되풀이는 틀린 식을 h 번 적용하므로 어긋남이 곱해집니다")
print(" 직접은 지평마다 따로 맞추므로 틀린 식을 되풀이하지 않습니다")
print(" 지평 10 에서는 1.0348 로 다시 좁혀집니다. 둘 다 무조건 분산에 가까워지기 때문입니다")
print(" 모형이 틀렸을 때의 이득은 중간 지평에서 가장 큽니다")
# --- 문제 5: 실무 -------------------------------------------------------
print(" 예측을 검증하는 방법을 정합니다")
print(" 189강 문제 4 의 겹 나누기를 그대로 쓰면 안 됩니다")
print(" %s %s"
% (pw("무엇이 문제", 24), rw("왜", 30)))
for a, b in [("무작위 겹", "미래로 과거를 맞히게 됨"),
("전체로 표준화", "미래 정보가 새어 들어감"),
("전체로 이상점 제거", "162강의 누출"),
("한 번만 나눔", "그 구간에 우연히 맞을 수")]:
print(" %s %s" % (pw(a, 24), rw(b, 30)))
print(" 앞에서 뒤로만 나누고 여러 번 나눕니다")
print(" 두 가지 나누는 방식을 견줍니다")
n7 = 1200
x7 = np.concatenate([gen_ar1(600, 0.8), gen_ar1(600, 0.2)])
print(" 앞 절반과 뒤 절반의 성질이 다른 자료입니다")
print(" %s %s %s"
% (pw("어떻게 나누나", 24), rw("평균 제곱오차", 18), rw("구간별 편차", 16)))
for nm, mode in [("늘려 가며", 0), ("굴려 가며 200 개", 1)]:
es, blocks = [], []
for st in range(600, n7 - 100, 100):
tr = x7[:st] if mode == 0 else x7[st - 200:st]
te = x7[st:st + 100]
p_, i_, _ = fit_ar1(tr)
e = [(te[t] - (i_ + p_ * te[t - 1])) ** 2 for t in range(1, len(te))]
es.extend(e)
blocks.append(float(np.mean(e)))
print(" %s %18.6f %16.6f"
% (pw(nm, 24), float(np.mean(es)), float(np.std(blocks, ddof=1))))
print(" 성질이 변하는 자료에서는 굴려 가는 쪽이 낫습니다")
print(" 오래된 자료를 버리는 것이 이득일 때가 있습니다")
print(" 예측을 보고할 때 무엇을 함께 적는지 정리합니다")
print(" %s %s" % (pw("무엇", 24), rw("왜", 30)))
for a, b in [("예측 지평", "지평마다 성능이 다름"),
("기준선", "무엇보다 나은지"),
("검증 방식", "누출이 없는지"),
("구간과 포함률", "얼마나 틀릴 수 있는지"),
("지표 둘 이상", "이상점에 흔들리므로"),
("자료 기간", "구조가 변했는지")]:
print(" %s %s" % (pw(a, 24), rw(b, 30)))
print(" 둘째 줄이 없으면 숫자만으로는 아무 말도 못 합니다")
print(" 마지막으로 구간이 얼마나 자주 틀리는지 봅니다")
print(" 실무의 예측 구간은 대개 너무 좁습니다")
print(" %s %s %s"
% (pw("무엇을 뺐나", 26), rw("포함률", 12), rw("목표", 10)))
S3 = 1500
rows = [("아무것도 안 뺌", 0), ("계수 오차", 1), ("모형이 틀림", 2),
("구조가 변함", 3)]
for nm, mode in rows:
cov = 0
for _ in range(S3):
nn = 200
if mode <= 1:
z = gen_ar1(nn + 1, 0.7)
elif mode == 2:
z = gen_ar2(nn + 1, 1.4, -0.75)
else:
z = np.concatenate([gen_ar1(nn // 2, 0.95, 0.5),
gen_ar1(nn // 2 + 1, 0.0, 3.0)])
ztr, last, nxt = z[:nn], z[nn - 1], z[nn]
p_, i_, v_ = fit_ar1(ztr)
f = i_ + p_ * last
sd = np.sqrt(v_)
if mode == 1:
sd = np.sqrt(v_ * (1.0 + 1.0 / nn))
if abs(nxt - f) < 1.96 * sd:
cov += 1
print(" %s %12.4f %10.2f" % (pw(nm, 26), cov / S3, 0.95))
print(" 계수 오차를 넣는 보정은 길이 200 에서 거의 차이가 없습니다")
print(" 모형이 틀리거나 구조가 변하면 포함률이 크게 내려갑니다")
print(" 앞의 두 줄과 뒤의 두 줄의 차이가 그것입니다")
print(" 구간이 좁은 진짜 이유는 계산이 아니라 모형이 틀렸기 때문입니다")
print(" 199강은 예측을 다뤘습니다. 200강은 계절과 실무 전체를 다룹니다")
# 예측을 잘했는지 말하려면 견줄 상대가 있어야 합니다
# 아무 모형도 안 쓴 예측을 기준선이라 합니다
# 되먹임 0.7 자료입니다. 앞 2400 개로 맞추고 뒤 600 개를 예측합니다
# 무엇으로 예측 제곱오차 절대오차 기준선 대비
# 평균만 말함 2.109372 1.165200 1.0000
# 바로 앞 값 그대로 1.182921 0.874039 0.5608
# 되먹임 모형 1.019867 0.835945 0.4835
# 되먹임 모형이 0.4835 로 평균만 말하는 것의 절반 수준입니다
# 바로 앞 값도 0.5608 로 평균보다 낫습니다. 이웃이 닮았기 때문입니다
# 그런데 되먹임 모형보다는 나쁩니다. phi 가 0.7 이라 1 을 쓰면 지나칩니다
# 누적 자료에서는 기준선이 바뀝니다
# 같은 세 방법을 누적 자료에 써 봅니다
# 무엇으로 예측 제곱오차 기준선 대비
# 평균만 말함 505.961368 1.0000
# 바로 앞 값 그대로 1.119024 0.0022
# 되먹임 모형 1.119634 0.0022
# 바로 앞 값이 평균보다 훨씬 좋습니다. 누적 자료이기 때문입니다
# 기준선을 무엇으로 두느냐가 성능 주장 전체를 바꿉니다
# 정상 자료에는 평균을 쓰고 누적 자료에는 바로 앞 값을 씁니다
# 지표마다 다른 것을 잽니다
# 지표 무엇에 민감한가 언제 쓰나
# 제곱오차 큰 오차에 크게 큰 실수를 피할 때
# 절대오차 고르게 보통의 정확도
# 절대비율오차 작은 값에 크게 규모가 다를 때
# 규모조정오차 기준선 대비 여러 계열을 묶을 때
# 셋째 줄은 값이 0 근처면 못 씁니다. 나누기 때문입니다
# 이상점 하나가 지표를 얼마나 흔드는지 봅니다
# 오차 500 개 중 하나를 크게 만들어 봅니다
# 이상점 크기 제곱오차 평균 절대오차 평균
# 0 1.015881 0.806000
# 5 1.064884 0.814589
# 20 1.814884 0.844589
# 50 6.014884 0.904589
# 이상점이 50 이면 제곱오차가 여섯 배가 되는데 절대오차는 1.1 배입니다
# 어느 지표를 보고하느냐가 결론을 바꿉니다. 둘을 함께 적습니다
# 197강 문제 4 에서 10 칸 앞 구간의 포함률이 0.9367 이었습니다
# 계수를 안다고 치고 계산했기 때문입니다
# 자료 길이를 바꿔 가며 한 칸 앞 구간의 포함률을 봅니다
# 자료 길이 계수 추정의 sd 포함률 목표
# 12 0.292935 0.8835 0.95
# 20 0.203243 0.9150 0.95
# 50 0.113053 0.9470 0.95
# 200 0.051343 0.9485 0.95
# 짧을수록 포함률이 목표 아래로 내려갑니다. 계수 오차가 크기 때문입니다
# 길이가 늘면 목표에 붙습니다. 계수 추정의 sd 가 함께 줄어듭니다
# 계수 오차를 구간에 넣는 세 가지 방법이 있습니다
# 방법 어떻게 무엇을 조심
# t 분포 쓰기 정규 대신 자유도 반영 계수 오차는 못 담음
# 델타 방법 예측식을 계수로 미분 비선형에서 근사
# 붓스트랩 잔차를 다시 뽑아 반복 시간 구조를 지켜야
# 베이즈 계수의 분포를 함께 사전분포가 필요
# 셋째 줄을 해 봅니다. 잔차를 시간 순서대로 다시 붙입니다
# 붓스트랩으로 구간을 넓혀 봅니다
# 길이 60 인 자료에서 두 방법의 포함률을 견줍니다
# 방법 포함률 평균 구간 폭 목표
# 계수를 안다고 침 0.9300 3.892486 0.95
# 붓스트랩 0.9200 3.801351 0.95
# 붓스트랩이 오히려 조금 좁고 포함률도 낮게 나옵니다
# 잔차가 이미 계수를 맞추면서 작아져 있어 그것을 다시 뽑으면 더 작아집니다
# 계수 오차를 담으려던 방법이 잔차 쪽에서 그만큼을 도로 잃은 것입니다
# 170강 문제 4 의 붓스트랩을 시간 구조에 맞게 고쳐도 공짜가 아닙니다
# 잔차를 자유도로 부풀리는 보정을 함께 해야 제 몫을 합니다
# 전혀 다른 계열의 방법이 있습니다
# 과거 값에 지수적으로 줄어드는 가중치를 주고 평균을 냅니다
# 가중치가 alpha 와 1 빼기 alpha 의 거듭제곱으로 정해집니다
# alpha 직전 값의 몫 5 칸 전의 몫 사실상 몇 개를 보나
# 0.1 0.100000 0.059049 19.0000
# 0.3 0.300000 0.050421 5.6667
# 0.5 0.500000 0.015625 3.0000
# 0.9 0.900000 0.000009 1.2222
# alpha 가 작으면 멀리까지 보고 크면 최근만 봅니다
# 마지막 열은 같은 분산을 내는 단순평균의 개수입니다
# alpha 를 자료에서 고릅니다
# alpha 학습 구간 제곱오차 검증 구간 제곱오차
# 0.1 1.709324 1.372987
# 0.3 1.385654 1.164923
# 0.5 1.243233 1.041948
# 0.7 1.174807 0.993949
# 0.9 1.165138 1.009969
# 검증 구간에서 가장 좋은 alpha 는 0.7 입니다
# 되먹임 0.7 자료이므로 최근을 많이 보는 쪽이 유리합니다
# 지수평활과 되먹임 모형을 견줍니다
# 무엇으로 검증 제곱오차 계수 개수
# 평균만 말함 1.480674 0
# 지수평활 0.993949 1
# 되먹임 모형 0.866852 2
# 되먹임 모형이 0.8669 로 가장 낫습니다. 자료를 그 식으로 만들었기 때문입니다
# 지수평활은 0.9939 입니다. 평균에서 되먹임까지의 0.6138 중 0.4867 을 따라잡았습니다
# 계수 하나로 열에 여덟을 가져옵니다. 실무에서 오래 쓰인 이유입니다
# 추세가 있으면 항을 하나 더 답니다
# 추세가 있는 자료에 두 방법을 써 봅니다
# 무엇으로 한 칸 앞 제곱오차 치우침 평균
# 추세 없는 지수평활 1.201359 0.158881
# 추세 있는 지수평활 1.410121 -0.005785
# 추세를 안 담으면 치우침 평균이 0.1589 로 늘 아래로 어긋납니다
# 항을 하나 더 달면 -0.0058 로 치우침이 사라집니다
# 그런데 제곱오차는 1.2014 에서 1.4101 로 오히려 커집니다
# 추세 항을 추정하는 값이 치우침을 없앤 이득보다 컸습니다
# 165강 문제 2 의 편향과 분산 맞바꿈이 여기서도 나타납니다
# 지평이 길어지면 치우침이 쌓이므로 그때는 추세 항이 이깁니다
# 여러 칸 앞을 예측하는 방법이 둘입니다
# 방법 어떻게 무엇을 조심
# 되풀이 한 칸 예측을 되먹임 오차가 쌓임
# 직접 h 칸 앞을 바로 회귀 지평마다 모형이 따로
# 둘을 견줘 봅니다
# 몇 칸 앞 되풀이 직접 평균만 말함
# 1 0.974563 0.974563 2.389970
# 2 1.547590 1.547613 2.389970
# 5 2.133190 2.130232 2.389970
# 10 2.332297 2.332299 2.389970
# 모형이 맞으면 두 방법이 거의 같습니다
# 모형이 틀리면 직접이 낫습니다. 잘못된 식을 되풀이하지 않기 때문입니다
# 모형을 일부러 틀리게 해 봅니다
# 참 자료는 1.4 와 -0.75 로 출렁이는 두 칸 되먹임인데 한 칸으로만 맞춥니다
# 몇 칸 앞 되풀이 직접 직접이 몇 배 나은가
# 1 2.404314 2.404314 1.0000
# 2 6.321302 5.810805 1.0879
# 5 9.877046 4.928341 2.0041
# 10 6.415554 6.199906 1.0348
# 지평 5 에서 2.0041 배로 가장 크게 벌어집니다
# 되풀이는 틀린 식을 h 번 적용하므로 어긋남이 곱해집니다
# 직접은 지평마다 따로 맞추므로 틀린 식을 되풀이하지 않습니다
# 지평 10 에서는 1.0348 로 다시 좁혀집니다. 둘 다 무조건 분산에 가까워지기 때문입니다
# 모형이 틀렸을 때의 이득은 중간 지평에서 가장 큽니다
# 예측을 검증하는 방법을 정합니다
# 189강 문제 4 의 겹 나누기를 그대로 쓰면 안 됩니다
# 무엇이 문제 왜
# 무작위 겹 미래로 과거를 맞히게 됨
# 전체로 표준화 미래 정보가 새어 들어감
# 전체로 이상점 제거 162강의 누출
# 한 번만 나눔 그 구간에 우연히 맞을 수
# 앞에서 뒤로만 나누고 여러 번 나눕니다
# 두 가지 나누는 방식을 견줍니다
# 앞 절반과 뒤 절반의 성질이 다른 자료입니다
# 어떻게 나누나 평균 제곱오차 구간별 편차
# 늘려 가며 1.242387 0.249483
# 굴려 가며 200 개 1.049343 0.213455
# 성질이 변하는 자료에서는 굴려 가는 쪽이 낫습니다
# 오래된 자료를 버리는 것이 이득일 때가 있습니다
# 예측을 보고할 때 무엇을 함께 적는지 정리합니다
# 무엇 왜
# 예측 지평 지평마다 성능이 다름
# 기준선 무엇보다 나은지
# 검증 방식 누출이 없는지
# 구간과 포함률 얼마나 틀릴 수 있는지
# 지표 둘 이상 이상점에 흔들리므로
# 자료 기간 구조가 변했는지
# 둘째 줄이 없으면 숫자만으로는 아무 말도 못 합니다
# 마지막으로 구간이 얼마나 자주 틀리는지 봅니다
# 실무의 예측 구간은 대개 너무 좁습니다
# 무엇을 뺐나 포함률 목표
# 아무것도 안 뺌 0.9513 0.95
# 계수 오차 0.9513 0.95
# 모형이 틀림 0.9420 0.95
# 구조가 변함 0.8593 0.95
# 계수 오차를 넣는 보정은 길이 200 에서 거의 차이가 없습니다
# 모형이 틀리거나 구조가 변하면 포함률이 크게 내려갑니다
# 앞의 두 줄과 뒤의 두 줄의 차이가 그것입니다
# 구간이 좁은 진짜 이유는 계산이 아니라 모형이 틀렸기 때문입니다
# 199강은 예측을 다뤘습니다. 200강은 계절과 실무 전체를 다룹니다