단원에서 답이 새 자료에서도 맞는지를 재는 눈금을 다 만들었습니다. 이제 그 눈금으로 실제 방법들을 재 봅니다. 첫 번째는 가장 오래되고 가장 단순한 것입니다.
강부터 강까지 학습은 모수를 정하는 일이었습니다. 이 방법에는 모수가 없습니다.
가정을 거의 안 하는 대가로 무엇을 치르는지, 그리고 강의 저주가 왜 이 방법에 가장 세게 걸리는지를 봅니다.
문제. 모수 없는 학습을 봅니다.
() 모수 방법과 무엇이 다른지 정리하세요.
() 를 바꿔 가며 재세요.
() 가 유효 자유도와 어떻게 이어지는지 보세요.
생각의 실마리. 학습이란 결국 새 점에서 무엇을 답할지 정하는 일입니다. 미리 함수를 정해 두지 않고 물어볼 때 그 자리에서 정해도 됩니다.
풀이. () 정리합니다.
| 무엇 | 모수를 두는 방법 | 이웃 방법 |
|---|---|---|
| 학습 때 하는 일 | 모수를 맞춤 | 자료를 저장만 함 |
| 예측 때 하는 일 | 식에 넣음 | 가까운 점을 찾음 |
| 학습 비용 | 큼 | |
| 예측 비용 | 작음 | 표본에 비례 |
| 기억해야 할 것 | 모수만 | 자료 전부 |
학습을 예측 시점으로 미루는 것이라 게으른 학습이라 합니다.
() 를 바꿔 가며 잽니다. 표본 에 잡음 표준편차 입니다.
| 학습 오차 | 검증 오차 | 가장 좋은 자리인가 | |
|---|---|---|---|
| 아니오 | |||
| 아니오 | |||
| 예 | |||
| 아니오 | |||
| 아니오 | |||
| 아니오 |
가 이면 학습 오차가 정확히 입니다. 자기 자신이 가장 가까운 이웃이기 때문입니다. 그런데 검증 오차는 로 의 일곱 배입니다.
가 표본과 같으면 어디서나 전체 평균을 냅니다. 학습 오차와 검증 오차가 둘 다 근처로 같아집니다.
학습 오차는 단조로 커지고 검증 오차는 U자를 그립니다. 강의 편향과 분산이 하나로 조절됩니다.
() 가 유효 자유도와 어떻게 이어지는지 봅니다. 이웃 평균은 관측 하나에 의 무게를 주므로 모자 행렬의 대각합이 입니다.
| 유효 자유도 나누기 | 학습 오차 | 잡음만으로 예상되는 값 | |
|---|---|---|---|
마지막 열은 편향이 일 때의 값입니다. 가 작을 때는 실제와 거의 같고( 대 ), 가 커지면 실제가 훨씬 큽니다( 대 ). 그 차이가 편향입니다.
강 문제 의 유효 자유도가 모수 없는 방법에서도 정의됩니다. 모수를 안 세도 자유도는 셀 수 있습니다.
이 문제에서 배우는 것. 모수가 없다고 복잡도가 없는 것이 아닙니다. 가 곧 복잡도 손잡이이고, 유효 자유도가 로 정확히 정해집니다. 강의 "복잡도는 세는 것이 아니라 재는 것"이 여기서 다시 확인됩니다.
확인 1-1. 게으른 학습이 무엇인지 한 문장으로 쓰세요.
답. 학습을 예측 시점으로 미루고 자료를 저장만 하는 방식입니다.
확인 1-2. 검산에서 과 의 검증 오차를 쓰세요.
답. 와 입니다.
확인 1-3. 최근접이웃의 유효 자유도를 쓰세요.
답. 나누기 입니다.
문제. 성능을 정하는 것들을 봅니다.
() 변수의 눈금이 무엇을 바꾸는지 재세요.
() 거리 재는 법을 바꿔 보세요.
() 차원의 저주를 이웃 방법에서 확인하세요.
생각의 실마리. 이 방법에서 유일하게 자료를 보는 창이 거리입니다. 거리가 잘못 정의되면 다른 모든 것이 무의미해집니다.
풀이. 먼저 무엇이 성능을 정하는지 정리합니다.
| 무엇 | 무엇을 바꾸나 | 어디서 봤나 |
|---|---|---|
| 편향과 분산 | 문제 | |
| 거리 재는 법 | 어느 점이 이웃인가 | 이 문제 |
| 변수의 눈금 | 거리의 뜻 | 이 문제 |
| 차원 | 이웃이 멀어짐 | 강 |
| 가중치 | 가까운 점을 더 봄 | 문제 |
() 두 변수가 똑같이 중요한데 한쪽 눈금만 키웁니다.
| 둘째 변수의 배율 | 정확도 | 표준화 후 정확도 | 차 |
|---|---|---|---|
배율 에서 정확도가 에서 로 떨어집니다. 거리가 둘째 변수에만 끌려다니므로 첫째 변수는 사실상 무시됩니다.
표준화하면 어느 배율에서나 정확히 같은 값이 나옵니다. 강 문제 에서 벌점도 눈금에 딸린다고 했습니다. 같은 이유입니다.
() 거리 재는 법을 바꿔 봅니다.
| 거리 | 정확도 | 언제 쓰나 |
|---|---|---|
| 유클리드 | 기본값 | |
| 맨해튼 | 차원이 높을 때 | |
| 체비쇼프 | 한 축만 중요할 때 | |
| 코사인 | 크기보다 방향 |
코사인이 가장 높습니다. 참 경계가 으로 원점을 지나는 직선이기 때문입니다. 원점을 지나면 갈래가 방향만으로 정해지고, 코사인은 방향만 봅니다.
거리를 고르는 것이 곧 어떤 구조를 가정하는지 고르는 것입니다. "가정을 안 하는 방법"이라 했지만 거리를 고르는 순간 가정이 들어갑니다.
() 차원의 저주를 확인합니다. 아무 정보 없는 잡음 변수를 더해 갑니다.
| 잡음 변수 수 | 정확도 | 가장 가까운 이웃 거리 | 가장 먼 이웃 거리 |
|---|---|---|---|
잡음 변수를 개 더하면 정확도가 에서 으로 내려갑니다. 참 정보는 하나도 안 지웠는데도 그렇습니다.
가까운 이웃과 먼 이웃의 거리 비가 배에서 배로 줄어듭니다. 강 문제 에서 본 거리의 집중이 그대로 나타납니다.
이웃 방법은 변수 선택이 특히 중요합니다. 선형 모형은 쓸모없는 변수에 계수 을 주면 그만이지만, 이웃 방법은 그 변수가 거리에 그대로 들어갑니다.
이 문제에서 배우는 것. 이웃 방법에서 거리는 모형입니다. 눈금을 안 맞추면 한 변수만 보는 모형이 되고, 잡음 변수를 그대로 두면 강의 저주에 정면으로 걸립니다.
확인 2-1. 이웃 방법에서 표준화가 왜 필수인지 쓰세요.
답. 눈금이 큰 변수가 거리를 독차지해 다른 변수를 무시하게 되기 때문입니다.
확인 2-2. 검산에서 배율 일 때 표준화 전과 후의 정확도를 쓰세요.
답. 과 입니다.
확인 2-3. 검산에서 잡음 변수 개일 때의 정확도를 쓰세요.
답. 입니다.
문제. 가까운 이웃을 더 무겁게 셉니다.
() 무게 주는 방법을 정리하세요.
() 커널 폭을 바꿔 가며 재세요.
() 경계 편향을 국소 선형 회귀로 고치세요.
생각의 실마리. 이웃 평균은 번째 이웃과 번째 이웃을 똑같이 셉니다. 거리가 열 배 차이 나도 무게가 같습니다. 이상합니다.
풀이. () 정리합니다.
| 무게 주는 법 | 식 | 성질 |
|---|---|---|
| 고르게 | 나누기 | 경계에서 튐 |
| 거리의 역수 | 나누기 | 가까운 점에 몰림 |
| 가우스 커널 | 마이너스 제곱 | 매끄러움 |
| 삼각형 커널 | 빼기 나누기 | 폭 밖은 |
가중 평균으로 쓰면 이것이 나다라야 왓슨 커널 회귀입니다.
() 커널 폭 를 바꿔 가며 잽니다.
| 학습 오차 | 검증 오차 | 무게를 나눠 갖는 유효 개수 | |
|---|---|---|---|
가 와 같은 역할을 합니다. 작으면 분산이 크고 크면 편향이 큽니다.
다만 는 연속이고 는 정수입니다. 표본 에서 는 가지뿐이지만 는 얼마든지 곱게 돌릴 수 있습니다.
마지막 열이 커널판 유효 이웃 수입니다. 이고, 강의 유효 표본 크기와 같은 식입니다.
두 방법의 최선을 견줍니다.
| 무엇 | 최근접 최선 | 커널 회귀 최선 |
|---|---|---|
| 가장 좋은 검증 오차 | ||
| 그때의 손잡이 | ||
| 양 끝 점 오차 |
커널 회귀가 전체에서도 경계에서도 낫습니다. 그래도 둘 다 양 끝 오차가 전체 오차의 두 배가 넘습니다.
경계에서는 한쪽에만 점이 있어 평균이 안쪽으로 끌립니다. 이것을 경계 편향이라 합니다.
() 국소 선형 회귀로 고칩니다. 점마다 무게를 주고 직선을 다시 맞춘 뒤 그 자리의 값을 씁니다.
| 커널 회귀 양 끝 | 국소 선형 양 끝 | 국소 선형이 몇 배 나은가 | |
|---|---|---|---|
폭이 좁으면 국소 선형이 오히려 조금 나쁩니다. 계수 둘을 적은 점으로 맞추느라 분산이 커지기 때문입니다.
폭이 넓어질수록 커널 회귀의 경계 편향이 커져 국소 선형이 앞섭니다. 에서 열 배 넘게 낫습니다.
에서 배율이 다시 줄어드는 것은 폭이 너무 넓어 국소 선형도 굽은 곳을 직선으로 못 따라가기 때문입니다.
국소 선형은 경계에서 기울기까지 맞추므로 안쪽으로 안 끌립니다. 강의 최소제곱을 무게를 주고 점마다 다시 푸는 것이고, 강의 가중최소제곱이 여기서 다시 쓰입니다.
이 문제에서 배우는 것. 최근접에서 커널 회귀로, 다시 국소 선형으로 가는 것은 국소적으로 무엇을 맞추느냐의 차이입니다. 상수를 맞추면 커널 회귀이고 직선을 맞추면 국소 선형입니다. 차수를 올릴수록 경계는 좋아지고 분산은 커집니다.
확인 3-1. 나다라야 왓슨 커널 회귀가 무엇인지 한 문장으로 쓰세요.
답. 거리에 따라 무게를 준 가중 평균으로 예측하는 방법입니다.
확인 3-2. 검산에서 의 검증 오차와 유효 이웃 수를 쓰세요.
답. 과 입니다.
확인 3-3. 검산에서 일 때 국소 선형이 몇 배 나은지 쓰세요.
답. 배입니다.
문제. 분류에서 무엇을 하는지 봅니다.
() 확률 추정의 질을 재세요.
() 판정 경계의 모양을 보세요.
() 로지스틱 회귀와 견주세요.
생각의 실마리. 이웃 개 중 양성이 몇 개인지 세면 그것이 곧 확률 추정입니다. 그런데 개 중 몇 개이므로 값이 가지뿐입니다.
풀이. () 확률 추정의 질을 잽니다.
| 정확도 | 확률 추정의 제곱오차 | 확률이 몇 가지 값인가 | |
|---|---|---|---|
이면 확률이 아니면 입니다. 확률 추정으로는 못 씁니다. 제곱오차가 으로 의 서른두 배입니다.
이 자료에서는 정확도가 가장 높은 와 확률이 가장 정확한 가 둘 다 입니다. 그러나 두 눈금은 다른 것을 재므로 언제나 같지는 않습니다. 강에서 이 둘을 나눠 재는 법을 봅니다.
() 판정 경계의 모양을 봅니다. 경계를 가로지르는 직선 위에서 예측 갈래가 몇 번 바뀌는지 셉니다.
| 경계 근처 뒤집힘 횟수 | 경계의 매끄러움 | |
|---|---|---|
| 거침 | ||
| 거침 | ||
| 매끄러움 | ||
| 매끄러움 | ||
| 매끄러움 |
가 작으면 경계가 들쭉날쭉합니다. 잡음 점 하나가 자기 주변에 작은 섬을 만듭니다.
를 키우면 경계가 매끄러워지고 결국 직선에 가까워집니다. 강의 복잡도 손잡이가 여기서는 입니다.
() 로지스틱 회귀와 견줍니다. 참 경계의 모양을 셋으로 바꿔 가며 잽니다.
| 참 경계 | 이웃 방법 정확도 | 로지스틱 정확도 |
|---|---|---|
| 직선 | ||
| 원 | ||
| 배타적 논리합 |
직선 경계에서는 로지스틱이 낫습니다. 참 모양을 미리 알고 있으므로 표본을 그 모양 하나에 다 씁니다.
원과 배타적 논리합에서는 이웃 방법이 이깁니다. 배타적 논리합에서 로지스틱은 으로 동전 던지기보다 못합니다. 직선으로는 원리적으로 못 나누는 배치이기 때문입니다.
가정을 안 하는 대가가 표본을 더 쓰는 것입니다. 직선 문제에서 이웃 방법이 퍼센트포인트 뒤지는 것이 그 값입니다.
이 문제에서 배우는 것. 모수 방법과 이웃 방법의 차이는 가정을 어디에 두느냐입니다. 가정이 맞으면 모수 방법이 이기고, 틀리면 크게 집니다. 참 모양을 모를 때 이웃 방법이 안전한 선택입니다.
확인 4-1. 을 확률 추정에 못 쓰는 이유를 쓰세요.
답. 확률이 아니면 두 값밖에 안 나오기 때문입니다.
확인 4-2. 검산에서 과 의 확률 제곱오차를 쓰세요.
답. 과 입니다.
확인 4-3. 검산에서 배타적 논리합 경계의 두 정확도를 쓰세요.
답. 과 입니다.
문제. 실무의 걸림돌을 정리합니다.
() 문제와 대응을 정리하세요.
() 갈래가 치우쳤을 때를 재세요.
() 자료를 줄이면 얼마나 잃는지 보세요.
생각의 실마리. 이 방법의 학습 비용은 인데 예측 비용이 표본에 비례합니다. 자료가 커질수록 정확해지지만 동시에 느려집니다.
풀이. () 정리합니다.
| 문제 | 무엇이 곤란한가 | 어떻게 하나 |
|---|---|---|
| 예측이 느림 | 표본마다 거리 계산 | KD 트리나 근사 탐색 |
| 자료를 다 들고 있어야 함 | 메모리 | 대표점만 남김 |
| 눈금에 민감 | 거리의 뜻이 바뀜 | 표준화 필수 |
| 결측값 | 거리를 못 잼 | 대치하거나 부분 거리 |
| 갈래가 치우침 | 다수 갈래가 이김 | 강 가중치 |
() 갈래가 치우쳤을 때를 잽니다.
| 양성 비율 | 정확도 | 양성 재현율 | 전부 음성이라 할 때 정확도 |
|---|---|---|---|
양성이 퍼센트면 전부 음성이라 해도 정확도가 입니다. 이웃 방법의 과 큰 차이가 없습니다.
그런데 재현율은 에서 으로 무너집니다. 양성 개 이웃 중 다수가 되려면 개가 양성이어야 하는데, 양성이 퍼센트면 그런 자리가 거의 없습니다.
재현율이 무너지는 것을 정확도만 보면 못 잡습니다. 강과 강에서 이 문제를 정면으로 다룹니다.
() 거리 계산을 줄이는 방법을 정리합니다.
| 방법 | 거리 계산 횟수 | 표본 일 때 |
|---|---|---|
| 전수 탐색 | ||
| KD 트리 (낮은 차원) | ||
| KD 트리 (높은 차원) | 에 가까움 | 근처 |
| 국소 민감 해싱 | 상수에 가까움 | 수백 |
강의 저주가 KD 트리에도 걸립니다. 차원이 크면 가지치기가 안 되어 전수 탐색과 같아집니다.
자료 자체를 줄이면 어떻게 되는지 잽니다. 무작위로 남기는 것과 경계 근처만 남기는 것을 견줍니다.
| 남긴 비율 | 남긴 개수 | 무작위로 남김 | 경계 근처만 남김 |
|---|---|---|---|
기대와 반대로 경계 근처만 남기는 쪽이 더 나쁩니다. 퍼센트에서 으로 동전 던지기에 가깝습니다.
이웃 방법은 다수결이므로 경계 근처만 남기면 표가 반반이 됩니다. 경계에서 먼 점이 다수결의 무게추 노릇을 하고 있었던 것입니다.
무작위로 줄이면 퍼센트까지는 거의 안 잃습니다. 에서 입니다.
강의 서포트 벡터는 다수결이 아니라 경계 자체를 그으므로 다릅니다. 같은 자료를 어떻게 쓰느냐에 따라 어느 점이 중요한지가 달라집니다.
이 문제에서 배우는 것. "중요한 점"은 자료의 성질이 아니라 방법의 성질입니다. 이웃 방법에서는 멀리 있는 점도 표를 던지므로 중요하고, 서포트 벡터 머신에서는 경계 근처만 중요합니다.
확인 5-1. 갈래가 치우쳤을 때 정확도만 보면 안 되는 이유를 쓰세요.
답. 전부 음성이라 해도 정확도가 높게 나오기 때문입니다.
확인 5-2. 검산에서 양성 비율 일 때 재현율을 쓰세요.
답. 입니다.
확인 5-3. 검산에서 퍼센트를 무작위로 남길 때와 경계 근처만 남길 때의 정확도를 쓰세요.
답. 과 입니다.
| 유형 | 무엇을 묻나 | 어디를 보나 |
|---|---|---|
| 와 편향 분산 | 가 크면 편향 | 문제 |
| 유효 자유도 | 나누기 | 문제 |
| 표준화 | 눈금이 거리를 정함 | 문제 |
| 거리의 선택 | 거리가 곧 가정 | 문제 |
| 차원의 저주 | 잡음 변수가 치명적 | 문제 |
| 커널 회귀 | 무게를 준 평균 | 문제 |
| 경계 편향 | 국소 선형이 고침 | 문제 |
| 확률 추정 | 가지 값 | 문제 |
| 모수 방법과의 대비 | 가정이 맞느냐 | 문제 |
| 자료 줄이기 | 먼 점도 표를 던짐 | 문제 |
세 방법을 한자리에 모읍니다.
| 방법 | 국소적으로 무엇을 맞추나 | 손잡이 | 경계에서 |
|---|---|---|---|
| 최근접 | 상수 (고른 무게) | (정수) | 나쁨 |
| 커널 회귀 | 상수 (준 무게) | (연속) | 나쁨 |
| 국소 선형 | 직선 | (연속) | 좋음 |
| 국소 이차 | 포물선 | (연속) | 더 좋고 더 흔들림 |
문제 6. 게으른 학습이 무엇인지 한 문장으로 쓰세요.
답. 학습을 예측 시점으로 미루고 자료를 저장만 하는 방식입니다.
문제 7. 검산에서 과 의 검증 오차를 쓰세요.
답. 와 입니다.
문제 8. 최근접이웃의 유효 자유도를 쓰세요.
답. 나누기 입니다.
문제 9. 검산에서 배율 일 때 표준화 전과 후의 정확도를 쓰세요.
답. 과 입니다.
문제 10. 검산에서 코사인 거리의 정확도를 쓰고 왜 가장 높은지 쓰세요.
답. 이며 참 경계가 원점을 지나는 직선이기 때문입니다.
문제 11. 검산에서 잡음 변수 개일 때의 정확도를 쓰세요.
답. 입니다.
문제 12. 검산에서 의 검증 오차와 유효 이웃 수를 쓰세요.
답. 과 입니다.
문제 13. 검산에서 일 때 국소 선형이 몇 배 나은지 쓰세요.
답. 배입니다.
문제 14. 검산에서 과 의 확률 제곱오차를 쓰세요.
답. 과 입니다.
문제 15. 검산에서 배타적 논리합 경계의 두 정확도를 쓰세요.
답. 과 입니다.
문제 16. 검산에서 양성 비율 일 때 재현율을 쓰세요.
답. 입니다.
문제 17. 검산에서 퍼센트를 무작위로 남길 때와 경계 근처만 남길 때의 정확도를 쓰세요.
답. 과 입니다.
문제 18. 이웃 방법에서 경계에서 먼 점이 왜 중요한지 쓰세요.
답. 다수결의 무게추 노릇을 하기 때문입니다.
심화 1. 최근접이웃의 수렴 속도를 정리하세요.
참 함수가 리프시츠이고 가 차원에 고르게 퍼져 있으면 번째 이웃까지의 거리가 이렇습니다.
| 무엇 | 크기 |
|---|---|
| 편향 제곱 | r_{k}^{2}\approx(k/n)^ |
| 분산 | |
| 최적 | n^ |
| 최적 오차 | n^ |
강 심화 의 비모수 수렴 속도가 그대로 나옵니다. 이면 이고 이면 입니다. 차원이 지수 자리에 있는 것이 저주의 수학적 형태입니다.
심화 2. 의 점근 오류율을 정리하세요.
표본이 무한히 많으면 가장 가까운 이웃이 자기 자신과 같은 자리에 오므로, 그 이웃의 라벨은 참 확률로 뽑힌 라벨입니다.
| 무엇 | 값 |
|---|---|
| 베이즈 오류율 | |
| 최근접 극한 | |
| 관계 | R^{*}\leq R_{1\text{NN}}\leq 2R^ |
은 아무리 자료가 많아도 최적의 두 배를 못 넘습니다. 그리고 그것이 상한입니다. 를 에 따라 천천히 키우면(, ) 베이즈 오류율에 수렴합니다.
심화 3. 커널 회귀의 편향과 분산을 유도하세요.
내부 점에서 테일러 전개하면 이렇습니다.
| 항 | 무엇에 딸리나 |
|---|---|
| 편향 | 과 이차 도함수 |
| 분산 | 와 밀도의 역수 |
| 최적 | n^ |
| 최적 오차 | n^ |
편향에 항이 있는 것이 문제입니다. 밀도 가 기울어진 자리에서 편향이 생기고, 경계는 밀도가 갑자기 끊기는 자리이므로 이 항이 폭발합니다. 국소 선형은 이 항이 사라집니다. 문제 의 표가 그 결과입니다.
심화 4. 거리 학습이 무엇인지 정리하세요.
표준화는 각 변수를 자기 표준편차로 나누는 것뿐입니다. 더 나가면 행렬을 학습합니다.
| 무엇이 되나 | |
|---|---|
| 유클리드 | |
| 대각 | 변수별 가중 |
| 일반 | 회전까지 포함 |
| 저랭크 | 차원 축소를 겸함 |
로 쓰면 로 변환한 뒤 유클리드 거리를 재는 것과 같습니다. 같은 갈래는 가깝게 다른 갈래는 멀게 을 학습하는 것이 거리 학습이고, S의 표현 학습이 이 생각을 신경망으로 밀어붙인 것입니다.
심화 5. 이웃 방법과 커널 방법의 관계를 정리하세요.
| 방법 | |
|---|---|
| 최근접 | 가까운 개에 |
| 커널 회귀 | K_{h}/\sum K_ |
| 국소 선형 | 부호가 음수일 수도 있음 |
| 릿지 | x^{\top}(X^{\top}X+n\lambda I)^{-1}X^ |
넷이 모두 선형 평활자입니다. 무게가 에 딸리느냐 아니냐가 다를 뿐이고, 강 심화 의 하나씩 빼기 공식이 넷 모두에 그대로 적용됩니다. 셋째 줄에서 무게가 음수가 될 수 있다는 것이 국소 선형이 경계에서 잘 되는 대가입니다.
심화 6. 이웃 방법을 언제 첫 후보로 삼을지 정리하세요.
| 상황 | 이웃 방법이 좋은가 | 왜 |
|---|---|---|
| 변수가 적고 표본이 많음 | 예 | 저주가 약하고 밀도가 촘촘 |
| 참 경계 모양을 모름 | 예 | 가정을 안 함 |
| 변수가 수백 개 | 아니오 | 강의 저주 |
| 예측이 실시간이어야 함 | 아니오 | 표본에 비례하는 비용 |
| 설명이 필요함 | 절반 | 이웃을 보여 줄 수는 있음 |
마지막 줄이 실무에서 자주 쓰입니다. "이 판정은 과거의 이 세 건과 비슷해서입니다"라는 설명은 계수를 보여 주는 것보다 이해하기 쉽습니다. 강의 모형 해석에서 이 방식이 다시 나옵니다.
정답.
| 기호 | 읽는 법 | 뜻 |
|---|---|---|
| 최근접이웃 | k-nearest neighbors | 가까운 개의 답을 씁니다 |
| 게으른 학습 | lazy learning | 학습을 예측 시점으로 미룹니다 |
| 커널 회귀 | Nadaraya-Watson | 거리로 무게를 준 평균입니다 |
| 커널 폭 | bandwidth | 얼마나 넓게 볼지 정합니다 |
| 국소 선형 회귀 | local linear regression | 점마다 직선을 다시 맞춥니다 |
| 경계 편향 | boundary bias | 끝에서 평균이 안쪽으로 끌립니다 |
| 선형 평활자 | linear smoother | 예측이 의 가중합입니다 |
| 거리 학습 | metric learning | 거리 재는 행렬을 배웁니다 |
| KD 트리 | k-d tree | 공간을 쪼개 탐색을 줄입니다 |
| 베이즈 오류율 | Bayes error rate | 어떤 방법도 못 내려가는 자리입니다 |
다음은 216강 나이브 베이즈입니다. 이 강의가 가정을 거의 안 하는 쪽 끝을 봤습니다. 다음 강의는 가정을 아주 세게 하는 쪽 끝으로 가서, 틀린 것이 뻔한 가정이 왜 잘 작동하는지를 봅니다.
import numpy as np
rng = np.random.default_rng(20261115)
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 d2(A, B):
return ((A[:, None, :] - B[None, :, :]) ** 2).sum(axis=2)
def knn_reg(Xa, ya, Xb, k):
idx = np.argsort(d2(Xb, Xa), axis=1)[:, :k]
return ya[idx].mean(axis=1)
def knn_clf(Xa, ya, Xb, k):
idx = np.argsort(d2(Xb, Xa), axis=1)[:, :k]
return (ya[idx].mean(axis=1) > 0.5).astype(float)
# --- 문제 1: 배우지 않는 학습 -------------------------------------------
print(" 214강까지는 모수를 정하는 것이 학습이었습니다")
print(" 이번에는 모수가 없는 방법을 봅니다")
print(" %s %s %s"
% (pw("무엇", 20), rw("모수를 두는 방법", 24), rw("이웃 방법", 24)))
for a, b, c in [("학습 때 하는 일", "모수를 맞춤", "자료를 저장만 함"),
("예측 때 하는 일", "식에 넣음", "가까운 점을 찾음"),
("학습 비용", "큼", "0"),
("예측 비용", "작음", "표본에 비례"),
("기억해야 할 것", "모수만", "자료 전부")]:
print(" %s %s %s" % (pw(a, 20), rw(b, 24), rw(c, 24)))
print(" 학습을 예측 시점으로 미루는 것이라 게으른 학습이라 합니다")
print(" 가장 단순한 형태부터 봅니다. k 를 바꿔 가며 잽니다")
n1 = 200
x1 = rng.uniform(-3, 3, (n1, 1))
f1 = 1.2 * x1[:, 0] + np.sin(2 * x1[:, 0])
y1 = f1 + rng.normal(0, 0.4, n1)
xv = np.linspace(-3, 3, 2000).reshape(-1, 1)
fv = 1.2 * xv[:, 0] + np.sin(2 * xv[:, 0])
print(" %s %s %s %s"
% (pw("k", 8), rw("학습 오차", 14), rw("검증 오차", 14),
rw("가장 좋은 자리인가", 24)))
ks0 = [1, 3, 10, 30, 100, 200]
tes0 = [float(np.mean((fv - knn_reg(x1, y1, xv, k)) ** 2)) for k in ks0]
kb0 = int(np.argmin(tes0))
for i, k in enumerate(ks0):
tr = float(np.mean((y1 - knn_reg(x1, y1, x1, k)) ** 2))
print(" %s %14.6f %14.6f %s"
% (pw(str(k), 8), tr, tes0[i],
rw("예" if i == kb0 else "아니오", 24)))
print(" k 가 1 이면 학습 오차가 0 입니다. 자기 자신이 가장 가까운 이웃입니다")
print(" k 가 표본과 같으면 어디서나 전체 평균을 냅니다")
print(" k 를 키우면 학습 오차는 단조로 커지고 검증 오차는 U 자를 그립니다")
print(" 210강의 편향과 분산이 k 하나로 조절됩니다")
print(" k 가 유효 자유도와 어떻게 이어지는지 봅니다")
print(" %s %s %s %s"
% (pw("k", 8), rw("유효 자유도 n 나누기 k", 24), rw("학습 오차", 14),
rw("잡음만으로 예상되는 값", 24)))
for k in [1, 3, 10, 30, 100]:
tr = float(np.mean((y1 - knn_reg(x1, y1, x1, k)) ** 2))
print(" %s %24.6f %14.6f %24.6f"
% (pw(str(k), 8), n1 / k, tr, 0.16 * (1.0 - 1.0 / k)))
print(" 마지막 열은 잡음만 있고 편향이 0 일 때의 학습 오차입니다")
print(" k 가 작을 때는 둘이 거의 같고 k 가 커지면 실제가 더 큽니다")
print(" 그 차이가 편향입니다")
print(" k 이웃 평균은 관측 하나에 1 나누기 k 의 무게를 줍니다")
print(" 모자 행렬의 대각합이 n 나누기 k 이므로 유효 자유도가 그 값입니다")
print(" 214강 문제 1 의 유효 자유도가 모수 없는 방법에서도 정의됩니다")
# --- 문제 2: 무엇이 성능을 정하는가 -------------------------------------
print(" 이웃 방법의 성능을 정하는 것 세 가지를 봅니다")
print(" %s %s %s"
% (pw("무엇", 20), rw("무엇을 바꾸나", 22), rw("어디서 봤나", 22)))
for a, b, c in [("k", "편향과 분산", "문제 1"),
("거리 재는 법", "어느 점이 이웃인가", "이 문제"),
("변수의 눈금", "거리의 뜻", "이 문제"),
("차원", "이웃이 멀어짐", "213강"),
("가중치", "가까운 점을 더 봄", "문제 3")]:
print(" %s %s %s" % (pw(a, 20), rw(b, 22), rw(c, 22)))
print(" 변수의 눈금이 다르면 어떻게 되는지 봅니다")
n2 = 400
Z = rng.uniform(-1, 1, (n2, 2))
y2 = (Z[:, 0] + Z[:, 1] > 0).astype(float)
Zt = rng.uniform(-1, 1, (600, 2))
yt2 = (Zt[:, 0] + Zt[:, 1] > 0).astype(float)
print(" 두 변수가 똑같이 중요한데 한쪽 눈금만 키웁니다")
print(" %s %s %s %s"
% (pw("둘째 변수의 배율", 20), rw("정확도", 14), rw("표준화 후 정확도", 20),
rw("차", 12)))
for sc in [1.0, 10.0, 100.0, 1000.0]:
A = Z * np.array([1.0, sc])
B = Zt * np.array([1.0, sc])
a1 = float(np.mean(knn_clf(A, y2, B, 10) == yt2))
sd = A.std(axis=0)
a2 = float(np.mean(knn_clf(A / sd, y2, B / sd, 10) == yt2))
print(" %s %14.6f %20.6f %12.6f"
% (pw("%.0f" % sc, 20), a1, a2, a2 - a1))
print(" 배율을 키우면 거리가 둘째 변수에만 끌려다닙니다")
print(" 표준화하면 어느 배율에서나 같은 값이 나옵니다")
print(" 211강 문제 5 에서 벌점도 눈금에 딸린다고 했습니다. 같은 이유입니다")
print(" 거리 재는 법을 바꿔 봅니다")
print(" %s %s %s"
% (pw("거리", 22), rw("정확도", 14), rw("언제 쓰나", 26)))
Zs = Z / Z.std(axis=0)
Zts = Zt / Zt.std(axis=0)
def acc_metric(kind, k=10):
if kind == "manhattan":
D = np.abs(Zts[:, None, :] - Zs[None, :, :]).sum(axis=2)
elif kind == "cheby":
D = np.abs(Zts[:, None, :] - Zs[None, :, :]).max(axis=2)
elif kind == "cosine":
A = Zs / np.linalg.norm(Zs, axis=1, keepdims=True)
B = Zts / np.linalg.norm(Zts, axis=1, keepdims=True)
D = 1.0 - B @ A.T
else:
D = d2(Zts, Zs)
idx = np.argsort(D, axis=1)[:, :k]
return float(np.mean((y2[idx].mean(axis=1) > 0.5) == yt2))
for nm, kind, why in [("유클리드", "euclid", "기본값"),
("맨해튼", "manhattan", "차원이 높을 때"),
("체비쇼프", "cheby", "한 축만 중요할 때"),
("코사인", "cosine", "크기보다 방향")]:
print(" %s %14.6f %s" % (pw(nm, 22), acc_metric(kind), rw(why, 26)))
print(" 코사인이 가장 높습니다. 참 경계가 원점을 지나는 직선이기 때문입니다")
print(" 원점을 지나면 갈래가 방향만으로 정해지고 코사인은 방향만 봅니다")
print(" 거리를 고르는 것이 곧 어떤 구조를 가정하는지 고르는 것입니다")
print(" 나머지 셋은 서로 비슷합니다. 경계가 직선이라 어느 것이든 잘 잡습니다")
print(" 213강의 차원 문제를 이웃 방법에서 다시 확인합니다")
print(" %s %s %s %s"
% (pw("잡음 변수 수", 14), rw("정확도", 14), rw("가장 가까운 이웃 거리", 24),
rw("가장 먼 이웃 거리", 22)))
for m in [0, 2, 10, 50]:
A = np.hstack([Zs, rng.normal(0, 1, (n2, m))])
B = np.hstack([Zts, rng.normal(0, 1, (600, m))])
D = np.sqrt(d2(B, A))
idx = np.argsort(D, axis=1)
ac = float(np.mean((y2[idx[:, :10]].mean(axis=1) > 0.5) == yt2))
print(" %s %14.6f %24.6f %22.6f"
% (pw(str(m), 14), ac, float(D[np.arange(600), idx[:, 0]].mean()),
float(D[np.arange(600), idx[:, -1]].mean())))
print(" 잡음 변수를 50 개 더하면 정확도가 0.95 에서 0.73 으로 내려갑니다")
print(" 가까운 이웃과 먼 이웃의 거리 차가 줄어듭니다. 213강 문제 2 그대로입니다")
print(" 이웃 방법은 변수 선택이 특히 중요합니다")
# --- 문제 3: 가중치를 주면 커널 회귀 ------------------------------------
print(" 가까운 이웃을 더 무겁게 세면 어떻게 되는지 봅니다")
print(" %s %s %s"
% (pw("무게 주는 법", 22), rw("식", 26), rw("성질", 22)))
for a, b, c in [("고르게", "1 나누기 k", "경계에서 튐"),
("거리의 역수", "1 나누기 d", "가까운 점에 몰림"),
("가우스 커널", "exp 마이너스 d 제곱", "매끄러움"),
("삼각형 커널", "1 빼기 d 나누기 h", "폭 밖은 0")]:
print(" %s %s %s" % (pw(a, 22), rw(b, 26), rw(c, 22)))
print(" 가중 평균으로 쓰면 이것이 나다라야 왓슨 커널 회귀입니다")
def nw(Xa, ya, Xb, h):
D = d2(Xb, Xa)
W = np.exp(-D / (2 * h * h))
return (W @ ya) / W.sum(axis=1)
print(" 커널 폭 h 를 바꿔 가며 잽니다")
print(" %s %s %s %s"
% (pw("h", 10), rw("학습 오차", 14), rw("검증 오차", 14),
rw("무게를 나눠 갖는 유효 개수", 30)))
for h in [0.02, 0.1, 0.3, 1.0, 3.0]:
tr = float(np.mean((y1 - nw(x1, y1, x1, h)) ** 2))
te = float(np.mean((fv - nw(x1, y1, xv, h)) ** 2))
W = np.exp(-d2(x1, x1) / (2 * h * h))
eff = float(np.mean(W.sum(axis=1) ** 2 / (W ** 2).sum(axis=1)))
print(" %s %14.6f %14.6f %30.6f"
% (pw("%.2f" % h, 10), tr, te, eff))
print(" h 가 k 와 같은 역할을 합니다. 작으면 분산이 크고 크면 편향이 큽니다")
print(" 다만 h 는 연속이고 k 는 정수입니다. 손잡이가 더 곱습니다")
print(" 마지막 열이 커널판 유효 이웃 수입니다. 163강의 유효 표본 크기입니다")
print(" 두 방법을 나란히 견줍니다")
print(" %s %s %s"
% (pw("무엇", 26), rw("k 최근접 최선", 20), rw("커널 회귀 최선", 20)))
ks = [1, 2, 3, 5, 8, 12, 20, 30, 50, 100]
hs = [0.02, 0.05, 0.1, 0.2, 0.3, 0.5, 1.0, 2.0, 3.0]
ke = [float(np.mean((fv - knn_reg(x1, y1, xv, k)) ** 2)) for k in ks]
he = [float(np.mean((fv - nw(x1, y1, xv, h)) ** 2)) for h in hs]
print(" %s %20.6f %20.6f"
% (pw("가장 좋은 검증 오차", 26), min(ke), min(he)))
print(" %s %20.6f %20.6f"
% (pw("그때의 손잡이", 26), ks[int(np.argmin(ke))], hs[int(np.argmin(he))]))
bd_k = knn_reg(x1, y1, xv, ks[int(np.argmin(ke))])
bd_h = nw(x1, y1, xv, hs[int(np.argmin(he))])
edge = np.r_[np.arange(100), np.arange(1900, 2000)]
print(" %s %20.6f %20.6f"
% (pw("양 끝 200 점 오차", 26),
float(np.mean((fv[edge] - bd_k[edge]) ** 2)),
float(np.mean((fv[edge] - bd_h[edge]) ** 2))))
print(" 가운데서는 둘이 비슷합니다. 경계 근처에서 차이가 납니다")
print(" 경계에서는 한쪽에만 점이 있어 평균이 안쪽으로 끌립니다")
print(" 이것을 경계 편향이라 하고 국소 선형 회귀가 고칩니다")
print(" 국소 선형 회귀로 경계 편향을 고칩니다")
def loclin(Xa, ya, Xb, h):
out = np.zeros(len(Xb))
for i in range(len(Xb)):
d = Xa[:, 0] - Xb[i, 0]
w = np.exp(-(d ** 2) / (2 * h * h))
A = np.stack([np.ones_like(d), d], axis=1)
M = A.T @ (w[:, None] * A)
b = A.T @ (w * ya)
out[i] = np.linalg.solve(M + 1e-10 * np.eye(2), b)[0]
return out
print(" 폭을 넓혀 가며 두 방법의 양 끝 오차를 견줍니다")
print(" %s %s %s %s"
% (pw("h", 10), rw("커널 회귀 양 끝", 20), rw("국소 선형 양 끝", 20),
rw("국소 선형이 몇 배 나은가", 28)))
for h in [0.1, 0.2, 0.3, 0.5, 1.0]:
a = float(np.mean((fv[edge] - nw(x1, y1, xv, h)[edge]) ** 2))
b = float(np.mean((fv[edge] - loclin(x1, y1, xv, h)[edge]) ** 2))
print(" %s %20.6f %20.6f %28.6f"
% (pw("%.1f" % h, 10), a, b, a / b))
print(" 폭이 좁으면 국소 선형이 계수 둘을 적은 점으로 맞추느라 오히려 나쁩니다")
print(" 폭이 넓어질수록 커널 회귀의 경계 편향이 커져 국소 선형이 앞섭니다")
print(" h 가 0.5 이면 국소 선형이 열 배 넘게 낫습니다")
print(" h 가 1.0 에서 배율이 다시 줄어드는 것은 굽은 곳을 직선으로 못 따라가서입니다")
print(" 국소 선형은 경계에서 기울기까지 맞추므로 안쪽으로 안 끌립니다")
print(" 207강의 최소제곱을 무게를 주고 점마다 다시 푸는 것입니다")
print(" 188강의 가중최소제곱이 여기서 다시 쓰입니다")
# --- 문제 4: 분류와 확률 추정 -------------------------------------------
print(" 분류에서 이웃 방법이 무엇을 하는지 봅니다")
print(" k 이웃 중 양성 비율이 곧 확률 추정입니다")
n4 = 600
X4 = rng.normal(0, 1, (n4, 2))
p4 = 1.0 / (1.0 + np.exp(-(1.5 * X4[:, 0] - X4[:, 1])))
y4 = (rng.uniform(0, 1, n4) < p4).astype(float)
X4t = rng.normal(0, 1, (2000, 2))
p4t = 1.0 / (1.0 + np.exp(-(1.5 * X4t[:, 0] - X4t[:, 1])))
y4t = (rng.uniform(0, 1, 2000) < p4t).astype(float)
print(" %s %s %s %s"
% (pw("k", 8), rw("정확도", 14), rw("확률 추정의 제곱오차", 24),
rw("확률이 몇 가지 값인가", 24)))
for k in [1, 5, 15, 50, 150]:
idx = np.argsort(d2(X4t, X4), axis=1)[:, :k]
ph = y4[idx].mean(axis=1)
ac = float(np.mean((ph > 0.5) == y4t))
br = float(np.mean((ph - p4t) ** 2))
print(" %s %14.6f %24.6f %24d"
% (pw(str(k), 8), ac, br, k + 1))
print(" k 가 1 이면 확률이 0 아니면 1 입니다. 확률 추정으로 못 씁니다")
print(" 이 자료에서는 정확도가 가장 높은 k 와 확률이 가장 정확한 k 가 같습니다")
print(" 그러나 두 눈금은 다른 것을 재므로 언제나 같지는 않습니다")
print(" 226강에서 이 둘을 나눠 재는 법을 봅니다")
print(" 이웃 방법의 판정 경계가 어떻게 생겼는지 봅니다")
print(" %s %s %s"
% (pw("k", 8), rw("경계 근처 뒤집힘 횟수", 26), rw("경계의 매끄러움", 22)))
gx = np.linspace(-2.5, 2.5, 400)
line = np.stack([gx, np.zeros_like(gx)], axis=1)
for k in [1, 5, 15, 50, 150]:
idx = np.argsort(d2(line, X4), axis=1)[:, :k]
lab = (y4[idx].mean(axis=1) > 0.5).astype(int)
flips = int(np.sum(np.abs(np.diff(lab))))
print(" %s %26d %s"
% (pw(str(k), 8), flips,
rw("거침" if flips > 5 else "매끄러움", 22)))
print(" k 가 작으면 경계가 들쭉날쭉합니다. 잡음 하나가 섬을 만듭니다")
print(" k 를 키우면 경계가 매끄러워지고 결국 직선에 가까워집니다")
print(" 214강의 복잡도 손잡이가 여기서는 k 입니다")
print(" 이웃 방법과 로지스틱 회귀를 견줍니다")
print(" %s %s %s"
% (pw("참 경계", 22), rw("이웃 방법 정확도", 22), rw("로지스틱 정확도", 22)))
def logit_fit(X, y, steps=3000, lr=0.3):
A = np.hstack([X, np.ones((len(X), 1))])
w = np.zeros(A.shape[1])
for _ in range(steps):
p = 1.0 / (1.0 + np.exp(-A @ w))
w -= lr * (A.T @ (p - y)) / len(y)
return w
def logit_acc(Xa, ya, Xb, yb):
w = logit_fit(Xa, ya)
A = np.hstack([Xb, np.ones((len(Xb), 1))])
return float(np.mean(((A @ w) > 0) == yb))
for nm, gen in [("직선", lambda Z: (1.5 * Z[:, 0] - Z[:, 1])),
("원", lambda Z: (1.2 - (Z ** 2).sum(axis=1))),
("배타적 논리합", lambda Z: (Z[:, 0] * Z[:, 1] * 3.0))]:
Xa = rng.normal(0, 1, (600, 2))
ya = (rng.uniform(0, 1, 600) < 1 / (1 + np.exp(-gen(Xa)))).astype(float)
Xb = rng.normal(0, 1, (2000, 2))
yb = (rng.uniform(0, 1, 2000) < 1 / (1 + np.exp(-gen(Xb)))).astype(float)
idx = np.argsort(d2(Xb, Xa), axis=1)[:, :15]
ak = float(np.mean((ya[idx].mean(axis=1) > 0.5) == yb))
print(" %s %22.6f %22.6f"
% (pw(nm, 22), ak, logit_acc(Xa, ya, Xb, yb)))
print(" 직선 경계에서는 로지스틱이 낫습니다. 참 모양을 알고 있기 때문입니다")
print(" 원과 배타적 논리합에서는 이웃 방법이 이깁니다. 모양을 안 가정합니다")
print(" 가정을 안 하는 대가가 표본을 더 쓰는 것입니다")
# --- 문제 5: 실무에서 쓰기 ---------------------------------------------
print(" 실무에서 이웃 방법을 쓸 때의 문제를 정리합니다")
print(" %s %s %s"
% (pw("문제", 22), rw("무엇이 곤란한가", 24), rw("어떻게 하나", 26)))
for a, b, c in [("예측이 느림", "표본마다 거리 계산", "KD 트리나 근사 탐색"),
("자료를 다 들고 있어야 함", "메모리", "대표점만 남김"),
("눈금에 민감", "거리의 뜻이 바뀜", "표준화 필수"),
("결측값", "거리를 못 잼", "대치하거나 부분 거리"),
("갈래가 치우침", "다수 갈래가 이김", "227강 가중치")]:
print(" %s %s %s" % (pw(a, 22), rw(b, 24), rw(c, 26)))
print(" 갈래가 치우쳤을 때 무슨 일이 나는지 잽니다")
print(" %s %s %s %s"
% (pw("양성 비율", 12), rw("정확도", 14), rw("양성 재현율", 16),
rw("전부 음성이라 할 때 정확도", 30)))
for pr in [0.5, 0.2, 0.05, 0.01]:
m = 2000
Xa = rng.normal(0, 1, (m, 2))
sc = 1.5 * Xa[:, 0] - Xa[:, 1]
thr = np.quantile(sc, 1 - pr)
ya = (sc > thr).astype(float)
Xb = rng.normal(0, 1, (2000, 2))
sb = 1.5 * Xb[:, 0] - Xb[:, 1]
yb = (sb > thr).astype(float)
idx = np.argsort(d2(Xb, Xa), axis=1)[:, :15]
ph = (ya[idx].mean(axis=1) > 0.5).astype(float)
ac = float(np.mean(ph == yb))
rc = float(np.sum((ph == 1) & (yb == 1)) / max(np.sum(yb == 1), 1))
print(" %s %14.6f %16.6f %30.6f"
% (pw("%.2f" % pr, 12), ac, rc, float(np.mean(yb == 0))))
print(" 양성이 1 퍼센트면 전부 음성이라 해도 정확도가 99 퍼센트입니다")
print(" 재현율이 무너지는 것을 정확도만 보면 못 잡습니다")
print(" 226강과 227강에서 이 문제를 정면으로 다룹니다")
print(" 거리 계산을 줄이는 방법의 효과를 봅니다")
print(" %s %s %s"
% (pw("방법", 24), rw("거리 계산 횟수", 20), rw("표본 10000 일 때", 22)))
for a, b, c in [("전수 탐색", "n", "10000"),
("KD 트리 (낮은 차원)", "log n", "13"),
("KD 트리 (높은 차원)", "n 에 가까움", "10000 근처"),
("국소 민감 해싱", "상수에 가까움", "수백")]:
print(" %s %s %s" % (pw(a, 24), rw(b, 20), rw(c, 22)))
print(" 213강의 저주가 KD 트리에도 걸립니다. 차원이 크면 전수 탐색과 같아집니다")
print(" 대표점만 남기면 얼마나 잃는지 잽니다")
print(" 무작위로 남기는 것과 경계 근처만 남기는 것을 견줍니다")
mar = np.abs(1.5 * X4[:, 0] - X4[:, 1])
ordm = np.argsort(mar)
print(" %s %s %s %s"
% (pw("남긴 비율", 12), rw("남긴 개수", 12), rw("무작위로 남김", 18),
rw("경계 근처만 남김", 20)))
for fr in [1.0, 0.5, 0.2, 0.05]:
m = int(n4 * fr)
kk = min(15, m)
s1 = rng.permutation(n4)[:m]
i1 = np.argsort(d2(X4t, X4[s1]), axis=1)[:, :kk]
a1 = float(np.mean((y4[s1][i1].mean(axis=1) > 0.5) == y4t))
s2 = ordm[:m]
i2 = np.argsort(d2(X4t, X4[s2]), axis=1)[:, :kk]
a2 = float(np.mean((y4[s2][i2].mean(axis=1) > 0.5) == y4t))
print(" %s %12d %18.6f %20.6f"
% (pw("%.2f" % fr, 12), m, a1, a2))
print(" 기대와 반대로 경계 근처만 남기는 쪽이 더 나쁩니다")
print(" 이웃 방법은 다수결이므로 경계 근처만 남기면 표가 반반이 됩니다")
print(" 경계에서 먼 점이 다수결의 무게추 노릇을 하고 있었던 것입니다")
print(" 무작위로 줄이면 20 퍼센트까지는 거의 안 잃습니다")
print(" 220강의 서포트 벡터는 다수결이 아니라 경계 자체를 그으므로 다릅니다")
print(" 같은 자료를 어떻게 쓰느냐에 따라 어느 점이 중요한지가 달라집니다")
print(" 215강은 가정을 안 하는 방법을 봤습니다. 216강은 가정을 세게 하는 쪽을 봅니다")
# 214강까지는 모수를 정하는 것이 학습이었습니다
# 이번에는 모수가 없는 방법을 봅니다
# 무엇 모수를 두는 방법 이웃 방법
# 학습 때 하는 일 모수를 맞춤 자료를 저장만 함
# 예측 때 하는 일 식에 넣음 가까운 점을 찾음
# 학습 비용 큼 0
# 예측 비용 작음 표본에 비례
# 기억해야 할 것 모수만 자료 전부
# 학습을 예측 시점으로 미루는 것이라 게으른 학습이라 합니다
# 가장 단순한 형태부터 봅니다. k 를 바꿔 가며 잽니다
# k 학습 오차 검증 오차 가장 좋은 자리인가
# 1 0.000000 0.170465 아니오
# 3 0.110292 0.061439 아니오
# 10 0.160101 0.025579 예
# 30 0.215402 0.079669 아니오
# 100 0.508307 0.368308 아니오
# 200 3.674264 3.644459 아니오
# k 가 1 이면 학습 오차가 0 입니다. 자기 자신이 가장 가까운 이웃입니다
# k 가 표본과 같으면 어디서나 전체 평균을 냅니다
# k 를 키우면 학습 오차는 단조로 커지고 검증 오차는 U 자를 그립니다
# 210강의 편향과 분산이 k 하나로 조절됩니다
# k 가 유효 자유도와 어떻게 이어지는지 봅니다
# k 유효 자유도 n 나누기 k 학습 오차 잡음만으로 예상되는 값
# 1 200.000000 0.000000 0.000000
# 3 66.666667 0.110292 0.106667
# 10 20.000000 0.160101 0.144000
# 30 6.666667 0.215402 0.154667
# 100 2.000000 0.508307 0.158400
# 마지막 열은 잡음만 있고 편향이 0 일 때의 학습 오차입니다
# k 가 작을 때는 둘이 거의 같고 k 가 커지면 실제가 더 큽니다
# 그 차이가 편향입니다
# k 이웃 평균은 관측 하나에 1 나누기 k 의 무게를 줍니다
# 모자 행렬의 대각합이 n 나누기 k 이므로 유효 자유도가 그 값입니다
# 214강 문제 1 의 유효 자유도가 모수 없는 방법에서도 정의됩니다
# 이웃 방법의 성능을 정하는 것 세 가지를 봅니다
# 무엇 무엇을 바꾸나 어디서 봤나
# k 편향과 분산 문제 1
# 거리 재는 법 어느 점이 이웃인가 이 문제
# 변수의 눈금 거리의 뜻 이 문제
# 차원 이웃이 멀어짐 213강
# 가중치 가까운 점을 더 봄 문제 3
# 변수의 눈금이 다르면 어떻게 되는지 봅니다
# 두 변수가 똑같이 중요한데 한쪽 눈금만 키웁니다
# 둘째 변수의 배율 정확도 표준화 후 정확도 차
# 1 0.955000 0.955000 0.000000
# 10 0.950000 0.955000 0.005000
# 100 0.728333 0.955000 0.226667
# 1000 0.711667 0.955000 0.243333
# 배율을 키우면 거리가 둘째 변수에만 끌려다닙니다
# 표준화하면 어느 배율에서나 같은 값이 나옵니다
# 211강 문제 5 에서 벌점도 눈금에 딸린다고 했습니다. 같은 이유입니다
# 거리 재는 법을 바꿔 봅니다
# 거리 정확도 언제 쓰나
# 유클리드 0.953333 기본값
# 맨해튼 0.958333 차원이 높을 때
# 체비쇼프 0.961667 한 축만 중요할 때
# 코사인 0.988333 크기보다 방향
# 코사인이 가장 높습니다. 참 경계가 원점을 지나는 직선이기 때문입니다
# 원점을 지나면 갈래가 방향만으로 정해지고 코사인은 방향만 봅니다
# 거리를 고르는 것이 곧 어떤 구조를 가정하는지 고르는 것입니다
# 나머지 셋은 서로 비슷합니다. 경계가 직선이라 어느 것이든 잘 잡습니다
# 213강의 차원 문제를 이웃 방법에서 다시 확인합니다
# 잡음 변수 수 정확도 가장 가까운 이웃 거리 가장 먼 이웃 거리
# 0 0.953333 0.089120 3.557055
# 2 0.921667 0.538808 5.061705
# 10 0.826667 2.384804 7.280707
# 50 0.730000 7.672673 12.684290
# 잡음 변수를 50 개 더하면 정확도가 0.95 에서 0.73 으로 내려갑니다
# 가까운 이웃과 먼 이웃의 거리 차가 줄어듭니다. 213강 문제 2 그대로입니다
# 이웃 방법은 변수 선택이 특히 중요합니다
# 가까운 이웃을 더 무겁게 세면 어떻게 되는지 봅니다
# 무게 주는 법 식 성질
# 고르게 1 나누기 k 경계에서 튐
# 거리의 역수 1 나누기 d 가까운 점에 몰림
# 가우스 커널 exp 마이너스 d 제곱 매끄러움
# 삼각형 커널 1 빼기 d 나누기 h 폭 밖은 0
# 가중 평균으로 쓰면 이것이 나다라야 왓슨 커널 회귀입니다
# 커널 폭 h 를 바꿔 가며 잽니다
# h 학습 오차 검증 오차 무게를 나눠 갖는 유효 개수
# 0.02 0.075798 0.074509 3.222655
# 0.10 0.148408 0.015971 12.406854
# 0.30 0.181257 0.031444 35.312024
# 1.00 0.496256 0.334150 104.496099
# 3.00 2.309404 2.161305 187.016926
# h 가 k 와 같은 역할을 합니다. 작으면 분산이 크고 크면 편향이 큽니다
# 다만 h 는 연속이고 k 는 정수입니다. 손잡이가 더 곱습니다
# 마지막 열이 커널판 유효 이웃 수입니다. 163강의 유효 표본 크기입니다
# 두 방법을 나란히 견줍니다
# 무엇 k 최근접 최선 커널 회귀 최선
# 가장 좋은 검증 오차 0.026228 0.015971
# 그때의 손잡이 8.000000 0.100000
# 양 끝 200 점 오차 0.056949 0.037131
# 가운데서는 둘이 비슷합니다. 경계 근처에서 차이가 납니다
# 경계에서는 한쪽에만 점이 있어 평균이 안쪽으로 끌립니다
# 이것을 경계 편향이라 하고 국소 선형 회귀가 고칩니다
# 국소 선형 회귀로 경계 편향을 고칩니다
# 폭을 넓혀 가며 두 방법의 양 끝 오차를 견줍니다
# h 커널 회귀 양 끝 국소 선형 양 끝 국소 선형이 몇 배 나은가
# 0.1 0.037131 0.039648 0.936527
# 0.2 0.056067 0.019126 2.931448
# 0.3 0.128730 0.013312 9.670212
# 0.5 0.347712 0.032426 10.723391
# 1.0 0.696108 0.184830 3.766202
# 폭이 좁으면 국소 선형이 계수 둘을 적은 점으로 맞추느라 오히려 나쁩니다
# 폭이 넓어질수록 커널 회귀의 경계 편향이 커져 국소 선형이 앞섭니다
# h 가 0.5 이면 국소 선형이 열 배 넘게 낫습니다
# h 가 1.0 에서 배율이 다시 줄어드는 것은 굽은 곳을 직선으로 못 따라가서입니다
# 국소 선형은 경계에서 기울기까지 맞추므로 안쪽으로 안 끌립니다
# 207강의 최소제곱을 무게를 주고 점마다 다시 푸는 것입니다
# 188강의 가중최소제곱이 여기서 다시 쓰입니다
# 분류에서 이웃 방법이 무엇을 하는지 봅니다
# k 이웃 중 양성 비율이 곧 확률 추정입니다
# k 정확도 확률 추정의 제곱오차 확률이 몇 가지 값인가
# 1 0.671000 0.167870 2
# 5 0.724000 0.032079 6
# 15 0.744000 0.011932 16
# 50 0.757500 0.005209 51
# 150 0.754000 0.009502 151
# k 가 1 이면 확률이 0 아니면 1 입니다. 확률 추정으로 못 씁니다
# 이 자료에서는 정확도가 가장 높은 k 와 확률이 가장 정확한 k 가 같습니다
# 그러나 두 눈금은 다른 것을 재므로 언제나 같지는 않습니다
# 226강에서 이 둘을 나눠 재는 법을 봅니다
# 이웃 방법의 판정 경계가 어떻게 생겼는지 봅니다
# k 경계 근처 뒤집힘 횟수 경계의 매끄러움
# 1 15 거침
# 5 11 거침
# 15 3 매끄러움
# 50 1 매끄러움
# 150 1 매끄러움
# k 가 작으면 경계가 들쭉날쭉합니다. 잡음 하나가 섬을 만듭니다
# k 를 키우면 경계가 매끄러워지고 결국 직선에 가까워집니다
# 214강의 복잡도 손잡이가 여기서는 k 입니다
# 이웃 방법과 로지스틱 회귀를 견줍니다
# 참 경계 이웃 방법 정확도 로지스틱 정확도
# 직선 0.748000 0.771500
# 원 0.674500 0.579500
# 배타적 논리합 0.743000 0.491000
# 직선 경계에서는 로지스틱이 낫습니다. 참 모양을 알고 있기 때문입니다
# 원과 배타적 논리합에서는 이웃 방법이 이깁니다. 모양을 안 가정합니다
# 가정을 안 하는 대가가 표본을 더 쓰는 것입니다
# 실무에서 이웃 방법을 쓸 때의 문제를 정리합니다
# 문제 무엇이 곤란한가 어떻게 하나
# 예측이 느림 표본마다 거리 계산 KD 트리나 근사 탐색
# 자료를 다 들고 있어야 함 메모리 대표점만 남김
# 눈금에 민감 거리의 뜻이 바뀜 표준화 필수
# 결측값 거리를 못 잼 대치하거나 부분 거리
# 갈래가 치우침 다수 갈래가 이김 227강 가중치
# 갈래가 치우쳤을 때 무슨 일이 나는지 잽니다
# 양성 비율 정확도 양성 재현율 전부 음성이라 할 때 정확도
# 0.50 0.990500 0.999004 0.498000
# 0.20 0.987000 0.956298 0.805500
# 0.05 0.994500 0.887640 0.955500
# 0.01 0.997500 0.583333 0.994000
# 양성이 1 퍼센트면 전부 음성이라 해도 정확도가 99 퍼센트입니다
# 재현율이 무너지는 것을 정확도만 보면 못 잡습니다
# 226강과 227강에서 이 문제를 정면으로 다룹니다
# 거리 계산을 줄이는 방법의 효과를 봅니다
# 방법 거리 계산 횟수 표본 10000 일 때
# 전수 탐색 n 10000
# KD 트리 (낮은 차원) log n 13
# KD 트리 (높은 차원) n 에 가까움 10000 근처
# 국소 민감 해싱 상수에 가까움 수백
# 213강의 저주가 KD 트리에도 걸립니다. 차원이 크면 전수 탐색과 같아집니다
# 대표점만 남기면 얼마나 잃는지 잽니다
# 무작위로 남기는 것과 경계 근처만 남기는 것을 견줍니다
# 남긴 비율 남긴 개수 무작위로 남김 경계 근처만 남김
# 1.00 600 0.744000 0.744000
# 0.50 300 0.748500 0.741000
# 0.20 120 0.735500 0.672500
# 0.05 30 0.699000 0.521000
# 기대와 반대로 경계 근처만 남기는 쪽이 더 나쁩니다
# 이웃 방법은 다수결이므로 경계 근처만 남기면 표가 반반이 됩니다
# 경계에서 먼 점이 다수결의 무게추 노릇을 하고 있었던 것입니다
# 무작위로 줄이면 20 퍼센트까지는 거의 안 잃습니다
# 220강의 서포트 벡터는 다수결이 아니라 경계 자체를 그으므로 다릅니다
# 같은 자료를 어떻게 쓰느냐에 따라 어느 점이 중요한지가 달라집니다
# 215강은 가정을 안 하는 방법을 봤습니다. 216강은 가정을 세게 하는 쪽을 봅니다