단원은 라벨 없이 무엇을 할 수 있는지 봤습니다. 이제 다시 라벨이 있습니다. 다만 이번에는 모형을 만드는 것이 아닙니다.
"정확도 퍼센트"라는 말은 대개 아무 뜻이 없습니다. 양성이 퍼센트인 문제에서 아무것도 안 잡아도 그 값이 나오기 때문입니다.
이 강의는 네 칸짜리 표에서 모든 지표를 꺼내고, 문턱을 옮길 때 무엇이 맞바뀌는지 보고, 순위가 맞는 것과 확률이 맞는 것이 다르다는 것까지 봅니다.
문제. 지표들을 세웁니다.
() 각 지표가 무엇을 놓치는지 정리하세요.
() 갈래가 치우치면 정확도가 왜 무의미한지 보세요.
() 혼동행렬의 네 칸을 보세요.
생각의 실마리. 판정 결과는 네 가지뿐입니다. 맞게 양성, 틀리게 양성, 틀리게 음성, 맞게 음성입니다. 모든 지표가 이 네 수의 조합입니다.
풀이. () 정리합니다.
| 무엇 | 무엇을 세나 | 무엇을 놓치나 |
|---|---|---|
| 정확도 | 맞힌 비율 | 치우침을 못 봄 |
| 정밀도 | 양성이라 한 것 중 맞은 것 | 안 잡은 것을 못 봄 |
| 재현율 | 실제 양성 중 잡은 것 | 헛경보를 못 봄 |
| F1 | 둘의 조화평균 | 음성을 아예 안 봄 |
| AUC | 순위의 질 | 문턱을 안 정함 |
() 갈래가 치우치면 정확도가 왜 무의미한지 봅니다. 아무것도 안 잡고 전부 음성이라 답합니다.
| 양성 비율 | 전부 음성이라 할 때 정확도 | 재현율 | F1 |
|---|---|---|---|
양성이 퍼센트면 아무것도 안 잡고도 정확도가 입니다.
재현율과 F1은 입니다. 이 셋을 함께 봐야 하고, 강 문제 와 강 문제 에서 본 그 문제입니다.
() 혼동행렬의 네 칸을 봅니다. 양성 비율이 인 자료입니다.
| 문턱 | 참양성 | 거짓양성 | 거짓음성 | 참음성 |
|---|---|---|---|---|
문턱을 올리면 참양성과 거짓양성이 함께 줄어듭니다. 참양성이 에서 로, 거짓양성이 에서 로 줄어듭니다.
네 칸의 합은 언제나 입니다. 어느 칸으로 옮길지만 정하고, 강의 모든 지표가 이 네 칸에서 나옵니다.
이 문제에서 배우는 것. 지표 하나는 네 칸을 하나의 수로 뭉갠 것입니다. 뭉개는 방식마다 무엇을 버리는지 다르고, 버린 것이 중요하면 그 지표를 쓰면 안 됩니다.
확인 1-1. F1이 무엇을 아예 안 보는지 쓰세요.
답. 참음성 칸을 안 봅니다.
확인 1-2. 검산에서 양성 비율 일 때 전부 음성이라 한 정확도를 쓰세요.
답. 입니다.
확인 1-3. 검산에서 문턱 과 의 거짓양성 수를 쓰세요.
답. 개와 개입니다.
문제. 문턱의 효과를 봅니다.
() 지표들이 어떻게 움직이는지 재세요.
() 목적마다 다른 문턱이 나오는 것을 보세요.
() 비용에서 문턱을 유도하세요.
생각의 실마리. 모형이 주는 것은 확률 하나이고, 문턱은 우리가 정하는 것입니다. 모형을 안 바꾸고도 성능이 완전히 달라집니다.
풀이. () 지표들이 어떻게 움직이는지 잽니다.
| 문턱 | 정확도 | 정밀도 | 재현율 | F1 |
|---|---|---|---|---|
정밀도는 에서 로 오르고 재현율은 에서 로 내립니다. 언제나 반대로 움직입니다.
F1은 문턱 에서 로 가장 큽니다. 정확도는 에서 으로 가장 큽니다. 두 자리가 다릅니다.
() 목적마다 다른 문턱이 나오는 것을 봅니다.
| 무엇을 최대로 | 고른 문턱 | 그때의 값 |
|---|---|---|
| 정확도 | ||
| F1 | ||
| 재현율 아래 정밀도 | ||
| 거짓양성 아래 재현율 |
네 목적이 네 문턱을 고릅니다. 에서 까지 세 배 차이입니다.
하나가 옳은 것이 아닙니다. 무엇을 원하는지 먼저 정해야 문턱이 정해집니다.
() 비용에서 문턱을 유도합니다. 놓치는 비용을 , 헛경보 비용을 이라 하면 기대 비용을 최소로 하는 문턱이 이렇습니다.
| 놓침 대 헛경보 비용비 | 이론 문턱 | 실제로 가장 싼 문턱 | 그때 비용 |
|---|---|---|---|
이론 문턱과 실제로 가장 싼 문턱이 거의 같습니다. 비용비 에서 와 입니다.
확률이 잘 맞을수록 더 가깝습니다. 확률이 틀리면 이론 문턱이 안 맞고, 그래서 문제 의 보정이 필요합니다.
강 문제 에서 문턱을 옮기는 근거가 이것이었습니다.
이 문제에서 배우는 것. 문턱은 모형의 일부가 아니라 결정의 일부입니다. 같은 모형으로 재현율 짜리 시스템도 정밀도 짜리 시스템도 만들 수 있고, 어느 쪽을 원하는지는 자료가 아니라 사람이 정합니다.
확인 2-1. 정밀도와 재현율이 왜 반대로 움직이는지 쓰세요.
답. 문턱을 올리면 양성이라 하는 수가 줄어 잡는 것도 함께 줄기 때문입니다.
확인 2-2. 검산에서 F1이 가장 큰 문턱과 그 값을 쓰세요.
답. 이고 입니다.
확인 2-3. 비용비가 일 때 이론 문턱을 쓰세요.
답. 나누기 더하기 비용비입니다.
문제. 곡선을 봅니다.
() 네 곡선을 정리하세요.
() 갈래 비율이 무엇을 바꾸는지 재세요.
() 곡선의 왼쪽 끝을 보세요.
생각의 실마리. 문턱 하나를 고르지 말고 다 훑어 그리면, 모형 자체의 성질을 봅니다. 다만 무엇을 축에 두느냐가 다른 그림을 만듭니다.
풀이. () 정리합니다.
| 곡선 | 가로축 | 세로축 | 무엇에 딸리나 |
|---|---|---|---|
| ROC | 거짓양성률 | 재현율 | 갈래 비율에 안 딸림 |
| PR | 재현율 | 정밀도 | 갈래 비율에 딸림 |
| 이득 곡선 | 본 비율 | 잡은 비율 | 실무에서 읽기 쉬움 |
| 보정 곡선 | 예측 확률 | 실제 비율 | 확률의 질 |
첫 줄과 둘째 줄의 차이가 이 문제의 핵심입니다. 거짓양성률은 이라 음성 전체로 나누고, 정밀도는 라 양성이라 한 것으로 나눕니다.
() 갈래 비율이 무엇을 바꾸는지 잽니다.
| 양성 비율 | ROC 아래 넓이 | PR 아래 넓이 | 아무렇게나 할 때 PR |
|---|---|---|---|
ROC 아래 넓이는 에서 사이에 머뭅니다.
PR 아래 넓이는 에서 로 크게 떨어집니다.
아무렇게나 할 때의 PR 아래 넓이가 곧 양성 비율입니다. 기준선이 에서 로 움직이므로, PR 값을 볼 때는 기준선과 함께 봐야 합니다.
같은 AUC라도 실무 성능이 다를 수 있습니다. 양성이 인 자료에 점수 두 가지를 만듭니다.
| 점수 | ROC 아래 넓이 | PR 아래 넓이 | 상위 개 중 양성 |
|---|---|---|---|
| A | |||
| B |
B는 맨 위쪽 개만 흐트러뜨렸습니다. ROC 아래 넓이가 에서 로 만 떨어집니다.
그런데 상위 개 중 양성 수가 에서 으로 줄어듭니다. PR 아래 넓이는 에서 으로 크게 떨어집니다.
사람이 상위 몇 개만 확인하는 상황이면 PR 쪽을 봐야 합니다.
() 곡선의 왼쪽 끝을 봅니다.
| 거짓양성률 근처 | 그때 재현율 | 무엇을 뜻하나 |
|---|---|---|
| 정상 중 을 틀림 | ||
| 정상 중 을 틀림 | ||
| 정상 중 을 틀림 | ||
| 정상 중 을 틀림 |
거짓양성률 에서 재현율이 뿐입니다. 헛경보를 거의 안 내려면 양성의 퍼센트만 잡습니다.
곡선의 왼쪽 끝이 실무에서 가장 중요한 자리입니다. 그런데 AUC는 곡선 전체의 평균이라 왼쪽 끝을 따로 못 봅니다.
이 문제에서 배우는 것. ROC는 갈래 비율에 안 딸려서 모형끼리 견주기 좋고, PR은 드문 쪽을 찾는 실무 성능을 보여 줍니다. 그리고 둘 다 곡선 전체를 하나로 뭉갠 값이라 필요한 구간을 따로 봐야 합니다.
확인 3-1. ROC가 갈래 비율에 안 딸리는 이유를 쓰세요.
답. 두 축이 각각 양성 전체와 음성 전체로 나눈 값이기 때문입니다.
확인 3-2. 검산에서 양성 비율 일 때 두 곡선 아래 넓이를 쓰세요.
답. 과 입니다.
확인 3-3. 검산에서 거짓양성률 일 때의 재현율을 쓰세요.
답. 입니다.
문제. 보정을 봅니다.
() 순위와 보정을 구분하세요.
() 단조 변환으로 확인하세요.
() 보정 곡선을 그리고 고쳐 보세요.
생각의 실마리. AUC는 순위만 봅니다. 확률을 제곱하든 세제곱근을 씌우든 순위가 안 바뀌면 AUC가 같습니다. 그런데 비용 계산에는 확률 값이 필요합니다.
풀이. () 정리합니다.
| 무엇 | 무엇을 요구하나 | 어디에 쓰나 |
|---|---|---|
| 순위 | 누가 더 위험한가 | 상위 몇 개를 고를 때 |
| 보정 | 이면 퍼센트 | 비용 계산과 결합 |
| 정확도 | 문턱 넘김만 | 판정만 필요할 때 |
| AUC | 순위만 | 문턱 전에 |
() 단조 변환으로 확인합니다.
| 점수를 어떻게 바꾸나 | AUC | 브라이어 점수 | 평균 예측 확률 |
|---|---|---|---|
| 그대로 | |||
| 제곱 | |||
| 세제곱근 | |||
| 로 압축 |
네 경우 모두 AUC가 로 같습니다. 순위가 안 바뀌기 때문입니다.
브라이어 점수는 에서 까지 크게 다릅니다. 실제 양성 비율이 인데 평균 예측 확률이 에서 까지 흩어집니다.
강의 로그손실도 같은 성질을 가집니다.
() 보정 곡선을 그립니다. 강의 나이브 베이즈와 로지스틱을 견줍니다. 상관이 아주 높은 변수 둘을 일부러 넣었습니다.
| 예측 확률 구간 | 나이브 실제 비율 | 로지스틱 실제 비율 | 구간 가운데 |
|---|---|---|---|
| 에서 | |||
| 에서 | |||
| 에서 | |||
| 에서 | |||
| 에서 |
나이브 베이즈는 에서 이라 한 것의 실제 비율이 입니다. 이라 했는데 실제로는 입니다.
로지스틱은 으로 훨씬 가깝습니다. 강 문제 에서 본 과신이 그림으로 나타납니다.
| 무엇 | AUC | 브라이어 점수 |
|---|---|---|
| 나이브 베이즈 | ||
| 로지스틱 |
AUC 차이가 이고 브라이어 차이가 입니다. 두 지표가 같은 방향을 가리킵니다.
그런데 확률 쪽은 보정으로 고칠 수 있습니다. 순위는 못 고칩니다.
| 무엇 | AUC | 브라이어 점수 | 평균 예측 확률 |
|---|---|---|---|
| 나이브 그대로 | |||
| 플랫 보정 뒤 |
AUC는 로 정확히 같고 브라이어 점수만 에서 으로 좋아집니다.
평균 예측 확률도 에서 로 실제 비율 에 가까워집니다.
단조 변환이므로 순위가 그대로이기 때문입니다. 강 심화 의 플랫 보정이 이것입니다.
이 문제에서 배우는 것. 순위와 확률은 따로 재고 따로 고칩니다. AUC가 좋아도 확률이 틀릴 수 있고, 확률이 틀리면 문제 의 비용 문턱이 안 맞습니다. 확률을 쓸 것이면 보정 곡선을 반드시 봐야 합니다.
확인 4-1. 단조 변환이 AUC를 안 바꾸는 이유를 쓰세요.
답. 순위가 그대로이기 때문입니다.
확인 4-2. 검산에서 나이브 베이즈가 에서 이라 한 것의 실제 비율을 쓰세요.
답. 입니다.
확인 4-3. 검산에서 플랫 보정 전후의 브라이어 점수를 쓰세요.
답. 와 입니다.
문제. 실제로 씁니다.
() 갈래가 셋 이상일 때를 정리하세요.
() 평가 자체가 흔들리는 것을 재세요.
() 실무 절차를 정리하세요.
생각의 실마리. 갈래가 셋이면 혼동행렬이 이 됩니다. 하나의 수로 뭉개는 방식이 또 여럿이고, 어느 것을 쓰느냐로 결론이 바뀝니다.
풀이. () 정리합니다.
| 방법 | 어떻게 묶나 | 언제 쓰나 |
|---|---|---|
| 마이크로 평균 | 네 칸을 다 더한 뒤 | 전체 정확도가 중요 |
| 매크로 평균 | 갈래마다 재고 평균 | 드문 갈래도 똑같이 |
| 가중 평균 | 갈래 크기로 가중 | 마이크로와 비슷 |
| 갈래별로 보고 | 안 묶음 | 가장 정직함 |
갈래 비율이 과 와 인 자료에서 잽니다.
| 갈래 | 몇 개 | 정밀도 | 재현율 |
|---|---|---|---|
| 무엇 | 정밀도 | 재현율 |
|---|---|---|
| 마이크로 평균 | ||
| 매크로 평균 |
마이크로 평균은 정밀도와 재현율이 정확히 같습니다. 갈래가 하나씩만 예측되면 거짓양성의 합과 거짓음성의 합이 같기 때문이고, 그 값이 곧 정확도입니다.
매크로 정밀도는 으로 마이크로의 보다 훨씬 낮습니다. 갈래 의 정밀도가 인데 크기와 무관하게 똑같이 세기 때문입니다.
드문 갈래가 중요하면 매크로를 봐야 합니다.
() 평가 자체가 흔들리는 것을 잽니다.
| 검증 자료 크기 | AUC 평균 | AUC 표준편차 | 가장 큰 값 빼기 작은 값 |
|---|---|---|---|
검증 자료가 개면 가장 큰 값과 작은 값의 차가 입니다. 개면 로 여덟 배 좁아집니다.
두 모형의 AUC 차가 그보다 작으면 아무 말도 못 합니다. 강 문제 에서 본 교차검증의 분산과 같은 이야기입니다.
() 실무 절차를 정리합니다.
| 순서 | 무엇을 하나 |
|---|---|
| 무엇이 비싼지 정하기 | 놓침인가 헛경보인가 |
| 지표를 그것에 맞추기 | 정확도는 대개 아님 |
| 곡선을 보고 문턱 고르기 | 강의 불균형까지 |
| 확률이 필요하면 보정 | AUC로는 못 봄 |
| 흔들림을 함께 보고 | 차가 흔들림보다 큰가 |
마지막 줄이 자주 빠집니다. 소수점 셋째 자리 차이는 대개 잡음입니다.
이 문제에서 배우는 것. 평가는 모형만큼이나 설계가 필요한 일입니다. 어느 지표를 어느 자료에서 어떻게 재고 차이가 뜻있는지까지 정해야 합니다.
확인 5-1. 마이크로 평균의 정밀도와 재현율이 같아지는 이유를 쓰세요.
답. 갈래를 하나씩만 예측하면 거짓양성 합과 거짓음성 합이 같기 때문입니다.
확인 5-2. 검산에서 마이크로와 매크로 정밀도를 쓰세요.
답. 과 입니다.
확인 5-3. 검산에서 검증 자료 개와 개의 AUC 표준편차를 쓰세요.
답. 와 입니다.
| 유형 | 무엇을 묻나 | 어디를 보나 |
|---|---|---|
| 정확도의 함정 | 치우치면 무의미 | 문제 |
| 혼동행렬 | 네 칸에서 다 나옴 | 문제 |
| 정밀도와 재현율 | 반대로 움직임 | 문제 |
| 목적별 문턱 | 넷이 다 다름 | 문제 |
| 비용 문턱 | 비용비 | 문제 |
| ROC 대 PR | 갈래 비율에 딸리나 | 문제 |
| 곡선의 왼쪽 끝 | AUC로는 못 봄 | 문제 |
| 순위와 보정 | 단조 변환 | 문제 |
| 마이크로와 매크로 | 드문 갈래를 어떻게 | 문제 |
| 평가의 흔들림 | 차가 뜻있는가 | 문제 |
핵심 식을 한자리에 모읍니다.
| 지표 | 갈래 비율에 딸리나 | 문턱이 필요한가 | 확률의 질을 보나 |
|---|---|---|---|
| 정확도 | 예 | 예 | 아니오 |
| F1 | 예 | 예 | 아니오 |
| ROC 아래 넓이 | 아니오 | 아니오 | 아니오 |
| PR 아래 넓이 | 예 | 아니오 | 아니오 |
| 브라이어 점수 | 예 | 아니오 | 예 |
문제 6. F1이 무엇을 아예 안 보는지 쓰세요.
답. 참음성 칸을 안 봅니다.
문제 7. 검산에서 양성 비율 일 때 전부 음성이라 한 정확도를 쓰세요.
답. 입니다.
문제 8. 검산에서 문턱 과 의 거짓양성 수를 쓰세요.
답. 개와 개입니다.
문제 9. 검산에서 F1이 가장 큰 문턱과 그 값을 쓰세요.
답. 이고 입니다.
문제 10. 비용비가 일 때 이론 문턱을 쓰세요.
답. 나누기 더하기 비용비입니다.
문제 11. 검산에서 비용비 일 때 이론 문턱과 실제로 가장 싼 문턱을 쓰세요.
답. 와 입니다.
문제 12. 검산에서 양성 비율 일 때 두 곡선 아래 넓이를 쓰세요.
답. 과 입니다.
문제 13. 검산에서 점수 A와 B의 상위 개 중 양성 수를 쓰세요.
답. 개와 개입니다.
문제 14. 검산에서 거짓양성률 일 때의 재현율을 쓰세요.
답. 입니다.
문제 15. 검산에서 제곱과 세제곱근으로 바꿨을 때의 AUC를 쓰세요.
답. 둘 다 입니다.
문제 16. 검산에서 플랫 보정 전후의 브라이어 점수를 쓰세요.
답. 와 입니다.
문제 17. 검산에서 마이크로와 매크로 정밀도를 쓰세요.
답. 과 입니다.
문제 18. 검산에서 검증 자료 개와 개의 AUC 표준편차를 쓰세요.
답. 와 입니다.
심화 1. AUC가 무엇의 확률인지 정리하세요.
| 무엇 | 값 |
|---|---|
| 무작위 양성 하나와 음성 하나 | 양성이 더 높을 확률 |
| 아무렇게나 하면 | |
| 완벽하면 | |
| 뒤집으면 | 1-\text |
만 휘트니 U 통계량을 표본 수로 나눈 것과 같습니다. 강의 순위합 검정이 여기서 다시 나오고, 그래서 AUC의 표준오차도 그 이론으로 계산할 수 있습니다.
심화 2. F1의 가 무엇을 조절하는지 정리하세요.
| 무엇을 더 중시 | 언제 | |
|---|---|---|
| 정밀도 | 헛경보가 비쌀 때 | |
| 똑같이 | 기본 | |
| 재현율 | 놓치면 큰일일 때 | |
| 재현율만 | 극단 |
는 "재현율 한 단위를 정밀도 몇 단위와 바꿀 것인가"입니다. 문제 의 비용비와 같은 것을 다른 말로 적은 것이고, 비용을 안다면 F가 아니라 비용을 직접 최소화하는 것이 낫습니다.
심화 3. ROC와 PR이 왜 같은 순위에서 다른 그림을 주는지 설명하세요.
| 무엇 | 분모 | 양성이 드물면 |
|---|---|---|
| 거짓양성률 | 음성 전체 | 분모가 큼 |
| 정밀도 | 양성이라 한 것 | 분모가 작음 |
거짓양성 건이 음성 개 중이면 거짓양성률이 로 무시할 만합니다. 그런데 양성이라 한 것이 개이고 그중 참양성이 개면 정밀도가 입니다.
같은 건을 한쪽은 무시하고 한쪽은 치명적으로 봅니다. 그래서 드문 갈래에서는 PR을 봅니다.
심화 4. 보정 방법들을 정리하세요.
| 방법 | 무엇을 맞추나 | 필요한 것 |
|---|---|---|
| 플랫 보정 | 로짓에 로지스틱 하나 | 검증 자료 조금 |
| 등위 회귀 | 단조 계단 함수 | 검증 자료 많이 |
| 온도 조정 | 로짓을 상수로 나눔 | 값 하나 |
| 베타 보정 | 세 모수 | 검증 자료 조금 |
둘째 줄이 가장 유연하고 가장 과적합하기 쉽습니다. 검증 자료가 적으면 플랫이 안전하고, 신경망에서는 온도 조정 하나로 대개 충분합니다. 에서 다시 나옵니다.
심화 5. 평가 자료를 나눌 때의 함정을 정리하세요.
| 함정 | 무엇이 새나 | 어디서 봤나 |
|---|---|---|
| 문턱을 검증에서 고르고 같은 데서 보고 | 낙관 | 강 문제 |
| 개체가 양쪽에 | 누출 | 강 문제 |
| 시간 순서를 안 지킴 | 미래를 봄 | 강 |
| 여러 지표 중 좋은 것만 보고 | 여러 번 보기 | 강 문제 |
넷째 줄이 이 강의에 특히 해당합니다. 지표를 열 개 재고 가장 좋은 것을 보고하면 강의 후보 수 효과가 그대로 일어납니다. 무엇을 볼지 미리 정해야 합니다.
심화 6. 두 모형의 차이가 뜻있는지 검정하는 법을 정리하세요.
| 방법 | 무엇을 하나 | 언제 |
|---|---|---|
| 맥니마 검정 | 서로 다르게 틀린 쌍만 셈 | 같은 자료 두 모형 |
| 붓스트랩 | AUC 차의 분포 | 어떤 지표든 |
| 델롱 검정 | AUC 차의 분산을 이론으로 | AUC 전용 |
| 교차검증 반복 | 겹마다 차를 봄 | 자료가 적을 때 |
첫 줄이 가장 강력합니다. 두 모형이 똑같이 맞히거나 똑같이 틀린 것은 정보가 없으므로 빼고, 갈린 쌍만 셉니다. 강의 짝지은 검정이 여기서 쓰입니다.
정답.
| 기호 | 읽는 법 | 뜻 |
|---|---|---|
| 혼동행렬 | confusion matrix | 실제와 예측의 네 칸 표입니다 |
| 정밀도 | precision | 양성이라 한 것 중 맞은 비율입니다 |
| 재현율 | recall | 실제 양성 중 잡은 비율입니다 |
| 거짓양성률 | false positive rate | 음성 중 틀리게 양성이라 한 비율입니다 |
| ROC 곡선 | receiver operating characteristic | 거짓양성률 대 재현율 곡선입니다 |
| PR 곡선 | precision-recall curve | 재현율 대 정밀도 곡선입니다 |
| 브라이어 점수 | Brier score | 예측 확률의 제곱오차입니다 |
| 보정 곡선 | calibration curve | 예측 확률과 실제 비율을 견줍니다 |
| 플랫 보정 | Platt scaling | 로짓에 로지스틱을 다시 맞춥니다 |
| 마이크로 평균 | micro average | 네 칸을 다 더한 뒤 계산합니다 |
다음은 227강 불균형 데이터 다루기입니다. 이 강의가 치우친 자료를 어떻게 재는지를 봤습니다. 다음 강의는 어떻게 다룰지를 봅니다.
import numpy as np
rng = np.random.default_rng(20270131)
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 counts(y, pred):
tp = int(np.sum((pred == 1) & (y == 1)))
fp = int(np.sum((pred == 1) & (y == 0)))
fn = int(np.sum((pred == 0) & (y == 1)))
tn = int(np.sum((pred == 0) & (y == 0)))
return tp, fp, fn, tn
def prf(y, pred):
tp, fp, fn, tn = counts(y, pred)
pr = tp / max(tp + fp, 1)
rc = tp / max(tp + fn, 1)
f1 = 0.0 if pr + rc == 0 else 2 * pr * rc / (pr + rc)
return pr, rc, f1
def roc_points(score, y):
o = np.argsort(-score)
ys = y[o]
tp = np.cumsum(ys == 1)
fp = np.cumsum(ys == 0)
P = max(int((y == 1).sum()), 1)
N = max(int((y == 0).sum()), 1)
return fp / N, tp / P
def auc_roc(score, y):
o = np.argsort(score)
r = np.empty(len(score))
r[o] = np.arange(1, len(score) + 1)
n1 = float((y == 1).sum())
n0 = float((y == 0).sum())
if n1 == 0 or n0 == 0:
return 0.5
return float((r[y == 1].sum() - n1 * (n1 + 1) / 2) / (n1 * n0))
def auc_pr(score, y):
o = np.argsort(-score)
ys = y[o]
tp = np.cumsum(ys == 1)
pr = tp / np.arange(1, len(ys) + 1)
P = max(int((y == 1).sum()), 1)
return float(np.sum(pr * (ys == 1)) / P)
def logit_fit(X, y, steps=4000, lr=0.4):
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_p(w, X):
return 1.0 / (1.0 + np.exp(-(np.hstack([X, np.ones((len(X), 1))]) @ w)))
# --- 문제 1: 정확도 하나로는 안 됩니다 ----------------------------------
print(" 05단원은 라벨 없이 무엇을 할 수 있는지 봤습니다")
print(" 이번에는 다시 라벨이 있고 잘했는지 재는 법을 봅니다")
print(" %s %s %s"
% (pw("무엇", 22), rw("무엇을 세나", 24), rw("무엇을 놓치나", 26)))
for a, b, c in [("정확도", "맞힌 비율", "치우침을 못 봄"),
("정밀도", "양성이라 한 것 중 맞은 것", "안 잡은 것을 못 봄"),
("재현율", "실제 양성 중 잡은 것", "헛경보를 못 봄"),
("F1", "둘의 조화평균", "음성을 아예 안 봄"),
("AUC", "순위의 질", "문턱을 안 정함")]:
print(" %s %s %s" % (pw(a, 22), rw(b, 24), rw(c, 26)))
print(" 정확도 하나만 보면 안 되는 이유를 수치로 봅니다")
print(" 갈래가 치우치면 정확도가 왜 무의미한지 봅니다")
print(" %s %s %s %s"
% (pw("양성 비율", 12), rw("전부 음성이라 할 때 정확도", 30),
rw("재현율", 14), rw("F1", 14)))
for pr in [0.5, 0.2, 0.05, 0.01]:
n = 10000
y = (rng.uniform(0, 1, n) < pr).astype(float)
pred = np.zeros(n)
a = float(np.mean(pred == y))
p_, r_, f_ = prf(y, pred)
print(" %s %30.6f %14.6f %14.6f"
% (pw("%.2f" % pr, 12), a, r_, f_))
print(" 양성이 1 퍼센트면 아무것도 안 잡고도 정확도가 99 퍼센트입니다")
print(" 재현율과 F1 은 0 입니다. 이 셋을 함께 봐야 합니다")
print(" 215강 문제 5 와 218강 문제 5 에서 본 그 문제입니다")
print(" 혼동행렬의 네 칸을 봅니다")
n1 = 4000
X1 = rng.normal(0, 1, (n1, 3))
s1 = 1.2 * X1[:, 0] - X1[:, 1] + 0.5 * X1[:, 2] - 1.5
p1 = 1.0 / (1.0 + np.exp(-s1))
y1 = (rng.uniform(0, 1, n1) < p1).astype(float)
w1 = logit_fit(X1, y1)
X1t = rng.normal(0, 1, (4000, 3))
s1t = 1.2 * X1t[:, 0] - X1t[:, 1] + 0.5 * X1t[:, 2] - 1.5
p1t = 1.0 / (1.0 + np.exp(-s1t))
y1t = (rng.uniform(0, 1, 4000) < p1t).astype(float)
ph = logit_p(w1, X1t)
print(" 양성 비율이 %.4f 인 자료입니다" % float(y1t.mean()))
print(" %s %s %s %s %s"
% (pw("문턱", 10), rw("참양성", 12), rw("거짓양성", 12),
rw("거짓음성", 12), rw("참음성", 12)))
for t in [0.2, 0.35, 0.5, 0.7]:
tp, fp, fn, tn = counts(y1t, (ph > t).astype(float))
print(" %s %12d %12d %12d %12d"
% (pw("%.2f" % t, 10), tp, fp, fn, tn))
print(" 문턱을 올리면 참양성과 거짓양성이 함께 줄어듭니다")
print(" 네 칸의 합은 언제나 같습니다. 어느 칸으로 옮길지만 정합니다")
print(" 226강의 모든 지표가 이 네 칸에서 나옵니다")
# --- 문제 2: 문턱을 옮기면 무엇이 맞바뀌는가 ----------------------------
print(" 문턱을 옮기며 지표들이 어떻게 움직이는지 봅니다")
print(" %s %s %s %s %s"
% (pw("문턱", 10), rw("정확도", 14), rw("정밀도", 14),
rw("재현율", 14), rw("F1", 14)))
for t in [0.1, 0.2, 0.3, 0.5, 0.7, 0.9]:
pred = (ph > t).astype(float)
p_, r_, f_ = prf(y1t, pred)
print(" %s %14.6f %14.6f %14.6f %14.6f"
% (pw("%.2f" % t, 10), float(np.mean(pred == y1t)), p_, r_, f_))
print(" 정밀도는 오르고 재현율은 내립니다. 언제나 반대로 움직입니다")
print(" F1 은 어느 자리에서 가장 큽니다")
print(" 정확도가 가장 큰 자리와 F1 이 가장 큰 자리가 다릅니다")
print(" 무엇을 최대로 할지에 따라 문턱이 달라집니다")
ths = np.linspace(0.02, 0.98, 97)
best = {}
for nm, fn_ in [("정확도", lambda pd: float(np.mean(pd == y1t))),
("F1", lambda pd: prf(y1t, pd)[2]),
("재현율 0.8 아래 정밀도",
lambda pd: prf(y1t, pd)[0] if prf(y1t, pd)[1] >= 0.8
else 0.0),
("거짓양성 100 아래 재현율",
lambda pd: prf(y1t, pd)[1]
if counts(y1t, pd)[1] <= 100 else 0.0)]:
vals = [fn_((ph > t).astype(float)) for t in ths]
k = int(np.argmax(vals))
best[nm] = (float(ths[k]), float(vals[k]))
print(" %s %s %s"
% (pw("무엇을 최대로", 28), rw("고른 문턱", 16), rw("그때의 값", 16)))
for nm in ["정확도", "F1", "재현율 0.8 아래 정밀도", "거짓양성 100 아래 재현율"]:
print(" %s %16.6f %16.6f"
% (pw(nm, 28), best[nm][0], best[nm][1]))
print(" 네 목적이 네 문턱을 고릅니다. 하나가 옳은 것이 아닙니다")
print(" 무엇을 원하는지 먼저 정해야 문턱이 정해집니다")
print(" 비용을 넣으면 문턱이 공식으로 나옵니다")
print(" 놓치는 비용을 C1 헛경보 비용을 C0 이라 두면")
print(" %s %s %s %s"
% (pw("놓침 대 헛경보 비용비", 24), rw("이론 문턱", 16),
rw("실제로 가장 싼 문턱", 24), rw("그때 비용", 16)))
for ratio in [1.0, 3.0, 10.0, 50.0]:
theo = 1.0 / (1.0 + ratio)
costs = []
for t in ths:
tp, fp, fn, tn = counts(y1t, (ph > t).astype(float))
costs.append(ratio * fn + 1.0 * fp)
k = int(np.argmin(costs))
print(" %s %16.6f %24.6f %16.0f"
% (pw("%.0f" % ratio, 24), theo, float(ths[k]), costs[k]))
print(" 이론 문턱은 1 나누기 1 더하기 비용비입니다")
print(" 실제로 가장 싼 문턱이 그 근처입니다. 확률이 잘 맞을수록 더 가깝습니다")
print(" 216강 문제 1 에서 문턱을 옮기는 근거가 이것이었습니다")
# --- 문제 3: ROC 곡선과 PR 곡선 ----------------------------------------
print(" 문턱을 다 훑어 그린 곡선을 봅니다")
print(" %s %s %s %s"
% (pw("곡선", 16), rw("가로축", 20), rw("세로축", 18),
rw("무엇에 딸리나", 24)))
for a, b, c, d in [("ROC", "거짓양성률", "재현율", "갈래 비율에 안 딸림"),
("PR", "재현율", "정밀도", "갈래 비율에 딸림"),
("이득 곡선", "본 비율", "잡은 비율", "실무에서 읽기 쉬움"),
("보정 곡선", "예측 확률", "실제 비율", "확률의 질")]:
print(" %s %s %s %s"
% (pw(a, 16), rw(b, 20), rw(c, 18), rw(d, 24)))
print(" 첫 줄과 둘째 줄의 차이가 이 문제의 핵심입니다")
print(" 갈래 비율을 바꿔 가며 두 곡선 아래 넓이를 잽니다")
print(" %s %s %s %s"
% (pw("양성 비율", 12), rw("ROC 아래 넓이", 20), rw("PR 아래 넓이", 20),
rw("아무렇게나 할 때 PR", 24)))
for pr in [0.5, 0.2, 0.05, 0.01]:
m = 6000
Xs = rng.normal(0, 1, (m, 2))
sc = 1.5 * Xs[:, 0] - Xs[:, 1]
thr = np.quantile(sc, 1 - pr)
yy = (sc + rng.normal(0, 1.2, m) > thr).astype(float)
sc2 = sc + rng.normal(0, 0.5, m)
print(" %s %20.6f %20.6f %24.6f"
% (pw("%.2f" % pr, 12), auc_roc(sc2, yy), auc_pr(sc2, yy),
float(yy.mean())))
print(" ROC 아래 넓이는 0.889313 에서 0.945351 사이에 머뭅니다")
print(" PR 아래 넓이는 0.894602 에서 0.335805 로 크게 떨어집니다")
print(" 아무렇게나 할 때의 PR 아래 넓이가 곧 양성 비율입니다. 기준선이 움직입니다")
print(" 같은 AUC 라도 실무 성능이 다를 수 있음을 봅니다")
m3 = 5000
pr3 = 0.01
Xs3 = rng.normal(0, 1, (m3, 2))
sc3 = 1.5 * Xs3[:, 0] - Xs3[:, 1]
thr3 = np.quantile(sc3, 1 - pr3)
y3 = (sc3 + rng.normal(0, 0.8, m3) > thr3).astype(float)
sA = sc3 + rng.normal(0, 0.6, m3)
sB = sc3.copy()
o = np.argsort(-sB)
sB[o[:50]] = sB[o[:50]] - 3.0 * rng.uniform(0, 1, 50)
print(" 양성이 %.4f 인 자료에 점수 두 가지를 만듭니다" % float(y3.mean()))
print(" %s %s %s %s"
% (pw("점수", 16), rw("ROC 아래 넓이", 20), rw("PR 아래 넓이", 20),
rw("상위 50 개 중 양성", 22)))
for nm, sc in [("A", sA), ("B", sB)]:
top = np.argsort(-sc)[:50]
print(" %s %20.6f %20.6f %22d"
% (pw(nm, 16), auc_roc(sc, y3), auc_pr(sc, y3),
int(y3[top].sum())))
print(" B 는 맨 위쪽만 흐트러뜨렸습니다. ROC 아래 넓이는 거의 안 변합니다")
print(" 그런데 상위 50 개 중 양성 수가 크게 다릅니다")
print(" 사람이 상위 몇 개만 확인하는 상황이면 PR 쪽을 봐야 합니다")
print(" ROC 곡선의 몇 점을 직접 봅니다")
fpr, tpr = roc_points(ph, y1t)
print(" %s %s %s"
% (pw("거짓양성률 근처", 20), rw("그때 재현율", 18), rw("무엇을 뜻하나", 26)))
for target in [0.01, 0.05, 0.1, 0.3]:
k = int(np.searchsorted(fpr, target))
k = min(k, len(fpr) - 1)
print(" %s %18.6f %s"
% (pw("%.2f" % target, 20), float(tpr[k]),
rw("정상 %d 중 1 을 틀림" % int(round(1 / max(target, 1e-9))), 26)))
print(" 곡선의 왼쪽 끝이 실무에서 가장 중요한 자리입니다")
print(" 헛경보를 거의 안 내면서 얼마나 잡는지를 봅니다")
print(" AUC 는 곡선 전체의 평균이라 왼쪽 끝을 따로 못 봅니다")
# --- 문제 4: 확률이 맞는가 ---------------------------------------------
print(" 순위가 맞는 것과 확률이 맞는 것은 다릅니다")
print(" %s %s %s"
% (pw("무엇", 22), rw("무엇을 요구하나", 26), rw("어디에 쓰나", 24)))
for a, b, c in [("순위", "누가 더 위험한가", "상위 몇 개를 고를 때"),
("보정", "0.7 이면 70 퍼센트", "비용 계산과 결합"),
("정확도", "문턱 넘김만", "판정만 필요할 때"),
("AUC", "순위만", "문턱 전에")]:
print(" %s %s %s" % (pw(a, 22), rw(b, 26), rw(c, 24)))
print(" 점수를 단조 변환해도 AUC 는 안 변합니다. 보정은 완전히 달라집니다")
print(" 단조 변환으로 확인합니다")
print(" %s %s %s %s"
% (pw("점수를 어떻게 바꾸나", 24), rw("AUC", 16), rw("브라이어 점수", 20),
rw("평균 예측 확률", 20)))
for nm, q in [("그대로", ph), ("제곱", ph ** 2), ("세제곱근", ph ** (1 / 3)),
("0.5 로 압축", 0.5 + (ph - 0.5) * 0.2)]:
br = float(np.mean((q - y1t) ** 2))
print(" %s %16.6f %20.6f %20.6f"
% (pw(nm, 24), auc_roc(q, y1t), br, float(q.mean())))
print(" 네 경우 모두 AUC 가 같습니다. 순위가 안 바뀌기 때문입니다")
print(" 브라이어 점수는 크게 다릅니다. 실제 양성 비율은 %.6f 입니다"
% float(y1t.mean()))
print(" 203강의 로그손실도 같은 성질을 가집니다")
print(" 보정 곡선을 그려 봅니다")
print(" 216강의 나이브 베이즈와 로지스틱을 견줍니다")
def nb_fit(X, y):
ms, vs, ps = [], [], []
for c in [0.0, 1.0]:
Z = X[y == c]
ms.append(Z.mean(axis=0))
vs.append(Z.var(axis=0) + 1e-9)
ps.append(len(Z) / len(y))
return np.array(ms), np.array(vs), np.array(ps)
def nb_p(X, ms, vs, ps):
L = []
for c in range(2):
L.append((-0.5 * np.log(2 * np.pi * vs[c])
- (X - ms[c]) ** 2 / (2 * vs[c])).sum(axis=1)
+ np.log(ps[c]))
L = np.stack(L, axis=1)
m = L.max(axis=1, keepdims=True)
E = np.exp(L - m)
return E[:, 1] / E.sum(axis=1)
Xc = np.hstack([X1, X1[:, [0]] + rng.normal(0, 0.05, (n1, 1)),
X1[:, [0]] + rng.normal(0, 0.05, (n1, 1))])
Xct = np.hstack([X1t, X1t[:, [0]] + rng.normal(0, 0.05, (4000, 1)),
X1t[:, [0]] + rng.normal(0, 0.05, (4000, 1))])
ms, vs, ps = nb_fit(Xc, y1)
pn = nb_p(Xct, ms, vs, ps)
wc = logit_fit(Xc, y1)
pgl = logit_p(wc, Xct)
print(" %s %s %s %s"
% (pw("예측 확률 구간", 18), rw("나이브 실제 비율", 22),
rw("로지스틱 실제 비율", 22), rw("구간 가운데", 16)))
for lo, hi in [(0.0, 0.2), (0.2, 0.4), (0.4, 0.6), (0.6, 0.8), (0.8, 1.01)]:
a = (pn >= lo) & (pn < hi)
b = (pgl >= lo) & (pgl < hi)
va = float(y1t[a].mean()) if a.sum() > 0 else 0.0
vb = float(y1t[b].mean()) if b.sum() > 0 else 0.0
print(" %s %22.6f %22.6f %16.6f"
% (pw("%.1f 에서 %.1f" % (lo, hi), 18), va, vb, (lo + hi) / 2))
print(" 로지스틱의 실제 비율이 구간 가운데에 훨씬 가깝습니다")
print(" 나이브 베이즈는 216강 문제 2 에서 본 대로 과신합니다")
print(" %s %s %s"
% (pw("무엇", 22), rw("AUC", 16), rw("브라이어 점수", 20)))
for nm, q in [("나이브 베이즈", pn), ("로지스틱", pgl)]:
print(" %s %16.6f %20.6f"
% (pw(nm, 22), auc_roc(q, y1t), float(np.mean((q - y1t) ** 2))))
print(" AUC 차이가 0.033375 이고 브라이어 차이가 0.028621 입니다")
print(" 두 지표가 같은 방향을 가리킵니다. 나이브가 순위도 확률도 조금 나쁩니다")
print(" 그런데 확률 쪽은 보정으로 고칠 수 있습니다. 순위는 못 고칩니다")
print(" 보정하면 나아지는지 봅니다")
sp = rng.permutation(4000)
ca, cb = sp[:2000], sp[2000:]
def platt(sc_tr, y_tr, sc_te, steps=3000, lr=0.5):
a, b = 1.0, 0.0
for _ in range(steps):
p = 1.0 / (1.0 + np.exp(-(a * sc_tr + b)))
ga = float(np.mean((p - y_tr) * sc_tr))
gb = float(np.mean(p - y_tr))
a -= lr * ga
b -= lr * gb
return 1.0 / (1.0 + np.exp(-(a * sc_te + b)))
lg = np.log(np.clip(pn, 1e-9, 1 - 1e-9) / np.clip(1 - pn, 1e-9, 1 - 1e-9))
pc = platt(lg[ca], y1t[ca], lg[cb])
print(" %s %s %s %s"
% (pw("무엇", 24), rw("AUC", 16), rw("브라이어 점수", 20),
rw("평균 예측 확률", 20)))
for nm, q in [("나이브 그대로", pn[cb]), ("플랫 보정 뒤", pc)]:
print(" %s %16.6f %20.6f %20.6f"
% (pw(nm, 24), auc_roc(q, y1t[cb]), float(np.mean((q - y1t[cb]) ** 2)),
float(q.mean())))
print(" 실제 양성 비율은 %.6f 입니다" % float(y1t[cb].mean()))
print(" 보정은 AUC 를 거의 안 바꾸고 브라이어 점수만 고칩니다")
print(" 단조 변환이므로 순위가 그대로이기 때문입니다")
print(" 216강 심화 4 의 플랫 보정이 이것입니다")
# --- 문제 5: 실무에서 쓰기 ---------------------------------------------
print(" 갈래가 셋 이상이면 어떻게 재는지 정리합니다")
print(" %s %s %s"
% (pw("방법", 22), rw("어떻게 묶나", 24), rw("언제 쓰나", 26)))
for a, b, c in [("마이크로 평균", "네 칸을 다 더한 뒤", "전체 정확도가 중요"),
("매크로 평균", "갈래마다 재고 평균", "드문 갈래도 똑같이"),
("가중 평균", "갈래 크기로 가중", "마이크로와 비슷"),
("갈래별로 보고", "안 묶음", "가장 정직함")]:
print(" %s %s %s" % (pw(a, 22), rw(b, 24), rw(c, 26)))
print(" 세 갈래 문제에서 두 평균이 얼마나 다른지 봅니다")
n5 = 3000
pi5 = np.array([0.8, 0.15, 0.05])
z5 = rng.choice(3, n5, p=pi5)
cen5 = np.array([[0.0, 0.0], [2.5, 0.0], [0.0, 2.5]])
X5 = cen5[z5] + rng.normal(0, 1.1, (n5, 2))
pred5 = np.argmin(((X5[:, None, :] - cen5[None, :, :]) ** 2).sum(axis=2),
axis=1)
pred5 = np.where(rng.uniform(0, 1, n5) < 0.15, rng.choice(3, n5), pred5)
print(" 갈래 비율이 0.80 과 0.15 와 0.05 입니다")
print(" %s %s %s %s"
% (pw("갈래", 10), rw("몇 개", 12), rw("정밀도", 14), rw("재현율", 14)))
prs, rcs = [], []
for j in range(3):
tp = int(np.sum((pred5 == j) & (z5 == j)))
fp = int(np.sum((pred5 == j) & (z5 != j)))
fn = int(np.sum((pred5 != j) & (z5 == j)))
p_ = tp / max(tp + fp, 1)
r_ = tp / max(tp + fn, 1)
prs.append(p_)
rcs.append(r_)
print(" %s %12d %14.6f %14.6f"
% (pw(str(j), 10), int((z5 == j).sum()), p_, r_))
print(" %s %s %s"
% (pw("무엇", 22), rw("정밀도", 16), rw("재현율", 16)))
print(" %s %16.6f %16.6f"
% (pw("마이크로 평균", 22), float(np.mean(pred5 == z5)),
float(np.mean(pred5 == z5))))
print(" %s %16.6f %16.6f"
% (pw("매크로 평균", 22), float(np.mean(prs)), float(np.mean(rcs))))
print(" 마이크로는 큰 갈래에 끌려갑니다. 매크로는 드문 갈래를 똑같이 셉니다")
print(" 드문 갈래가 중요하면 매크로를 봐야 합니다")
print(" 평가 자체가 흔들리는 것도 봅니다")
print(" %s %s %s %s"
% (pw("검증 자료 크기", 16), rw("AUC 평균", 18), rw("AUC 표준편차", 20),
rw("가장 큰 값 빼기 작은 값", 26)))
for m in [100, 500, 2000, 8000]:
vals = []
for _ in range(60):
idx = rng.integers(0, 4000, m)
vals.append(auc_roc(ph[idx], y1t[idx]))
vals = np.array(vals)
print(" %s %18.6f %20.6f %26.6f"
% (pw(str(m), 16), float(vals.mean()), float(vals.std()),
float(vals.max() - vals.min())))
print(" 검증 자료가 100 개면 가장 큰 값과 작은 값의 차가 0.177062 입니다")
print(" 8000 개면 0.020779 로 여덟 배 좁아집니다")
print(" 두 모형의 AUC 차가 그보다 작으면 아무 말도 못 합니다")
print(" 212강 문제 2 에서 본 교차검증의 분산과 같은 이야기입니다")
print(" 실무 절차를 정리합니다")
print(" %s %s"
% (pw("순서", 26), rw("무엇을 하나", 36)))
for a, b in [("무엇이 비싼지 정하기", "놓침인가 헛경보인가"),
("지표를 그것에 맞추기", "정확도는 대개 아님"),
("곡선을 보고 문턱 고르기", "227강의 불균형까지"),
("확률이 필요하면 보정", "AUC 로는 못 봄"),
("흔들림을 함께 보고", "차가 흔들림보다 큰가")]:
print(" %s %s" % (pw(a, 26), rw(b, 36)))
print(" 마지막 줄이 자주 빠집니다. 소수점 셋째 자리 차이는 대개 잡음입니다")
print(" 226강은 재는 법을 봤습니다. 227강은 치우친 자료를 다룹니다")
# 05단원은 라벨 없이 무엇을 할 수 있는지 봤습니다
# 이번에는 다시 라벨이 있고 잘했는지 재는 법을 봅니다
# 무엇 무엇을 세나 무엇을 놓치나
# 정확도 맞힌 비율 치우침을 못 봄
# 정밀도 양성이라 한 것 중 맞은 것 안 잡은 것을 못 봄
# 재현율 실제 양성 중 잡은 것 헛경보를 못 봄
# F1 둘의 조화평균 음성을 아예 안 봄
# AUC 순위의 질 문턱을 안 정함
# 정확도 하나만 보면 안 되는 이유를 수치로 봅니다
# 갈래가 치우치면 정확도가 왜 무의미한지 봅니다
# 양성 비율 전부 음성이라 할 때 정확도 재현율 F1
# 0.50 0.504300 0.000000 0.000000
# 0.20 0.801000 0.000000 0.000000
# 0.05 0.946700 0.000000 0.000000
# 0.01 0.990600 0.000000 0.000000
# 양성이 1 퍼센트면 아무것도 안 잡고도 정확도가 99 퍼센트입니다
# 재현율과 F1 은 0 입니다. 이 셋을 함께 봐야 합니다
# 215강 문제 5 와 218강 문제 5 에서 본 그 문제입니다
# 혼동행렬의 네 칸을 봅니다
# 양성 비율이 0.2530 인 자료입니다
# 문턱 참양성 거짓양성 거짓음성 참음성
# 0.20 836 972 176 2016
# 0.35 641 482 371 2506
# 0.50 464 236 548 2752
# 0.70 229 55 783 2933
# 문턱을 올리면 참양성과 거짓양성이 함께 줄어듭니다
# 네 칸의 합은 언제나 같습니다. 어느 칸으로 옮길지만 정합니다
# 226강의 모든 지표가 이 네 칸에서 나옵니다
# 문턱을 옮기며 지표들이 어떻게 움직이는지 봅니다
# 문턱 정확도 정밀도 재현율 F1
# 0.10 0.590750 0.376433 0.940711 0.537701
# 0.20 0.713000 0.462389 0.826087 0.592908
# 0.30 0.768750 0.533030 0.693676 0.602834
# 0.50 0.804000 0.662857 0.458498 0.542056
# 0.70 0.790500 0.806338 0.226285 0.353395
# 0.90 0.756000 0.973684 0.036561 0.070476
# 정밀도는 오르고 재현율은 내립니다. 언제나 반대로 움직입니다
# F1 은 어느 자리에서 가장 큽니다
# 정확도가 가장 큰 자리와 F1 이 가장 큰 자리가 다릅니다
# 무엇을 최대로 할지에 따라 문턱이 달라집니다
# 무엇을 최대로 고른 문턱 그때의 값
# 정확도 0.510000 0.804250
# F1 0.330000 0.606803
# 재현율 0.8 아래 정밀도 0.220000 0.480213
# 거짓양성 100 아래 재현율 0.650000 0.280632
# 네 목적이 네 문턱을 고릅니다. 하나가 옳은 것이 아닙니다
# 무엇을 원하는지 먼저 정해야 문턱이 정해집니다
# 비용을 넣으면 문턱이 공식으로 나옵니다
# 놓치는 비용을 C1 헛경보 비용을 C0 이라 두면
# 놓침 대 헛경보 비용비 이론 문턱 실제로 가장 싼 문턱 그때 비용
# 1 0.500000 0.510000 783
# 3 0.250000 0.230000 1472
# 10 0.090909 0.110000 2149
# 50 0.019608 0.030000 2708
# 이론 문턱은 1 나누기 1 더하기 비용비입니다
# 실제로 가장 싼 문턱이 그 근처입니다. 확률이 잘 맞을수록 더 가깝습니다
# 216강 문제 1 에서 문턱을 옮기는 근거가 이것이었습니다
# 문턱을 다 훑어 그린 곡선을 봅니다
# 곡선 가로축 세로축 무엇에 딸리나
# ROC 거짓양성률 재현율 갈래 비율에 안 딸림
# PR 재현율 정밀도 갈래 비율에 딸림
# 이득 곡선 본 비율 잡은 비율 실무에서 읽기 쉬움
# 보정 곡선 예측 확률 실제 비율 확률의 질
# 첫 줄과 둘째 줄의 차이가 이 문제의 핵심입니다
# 갈래 비율을 바꿔 가며 두 곡선 아래 넓이를 잽니다
# 양성 비율 ROC 아래 넓이 PR 아래 넓이 아무렇게나 할 때 PR
# 0.50 0.889313 0.894602 0.502500
# 0.20 0.900846 0.757913 0.244333
# 0.05 0.920974 0.588604 0.088333
# 0.01 0.945351 0.335805 0.024167
# ROC 아래 넓이는 0.889313 에서 0.945351 사이에 머뭅니다
# PR 아래 넓이는 0.894602 에서 0.335805 로 크게 떨어집니다
# 아무렇게나 할 때의 PR 아래 넓이가 곧 양성 비율입니다. 기준선이 움직입니다
# 같은 AUC 라도 실무 성능이 다를 수 있음을 봅니다
# 양성이 0.0170 인 자료에 점수 두 가지를 만듭니다
# 점수 ROC 아래 넓이 PR 아래 넓이 상위 50 개 중 양성
# A 0.978591 0.522985 30
# B 0.967159 0.400753 23
# B 는 맨 위쪽만 흐트러뜨렸습니다. ROC 아래 넓이는 거의 안 변합니다
# 그런데 상위 50 개 중 양성 수가 크게 다릅니다
# 사람이 상위 몇 개만 확인하는 상황이면 PR 쪽을 봐야 합니다
# ROC 곡선의 몇 점을 직접 봅니다
# 거짓양성률 근처 그때 재현율 무엇을 뜻하나
# 0.01 0.149209 정상 100 중 1 을 틀림
# 0.05 0.360672 정상 20 중 1 을 틀림
# 0.10 0.502964 정상 10 중 1 을 틀림
# 0.30 0.807312 정상 3 중 1 을 틀림
# 곡선의 왼쪽 끝이 실무에서 가장 중요한 자리입니다
# 헛경보를 거의 안 내면서 얼마나 잡는지를 봅니다
# AUC 는 곡선 전체의 평균이라 왼쪽 끝을 따로 못 봅니다
# 순위가 맞는 것과 확률이 맞는 것은 다릅니다
# 무엇 무엇을 요구하나 어디에 쓰나
# 순위 누가 더 위험한가 상위 몇 개를 고를 때
# 보정 0.7 이면 70 퍼센트 비용 계산과 결합
# 정확도 문턱 넘김만 판정만 필요할 때
# AUC 순위만 문턱 전에
# 점수를 단조 변환해도 AUC 는 안 변합니다. 보정은 완전히 달라집니다
# 단조 변환으로 확인합니다
# 점수를 어떻게 바꾸나 AUC 브라이어 점수 평균 예측 확률
# 그대로 0.835078 0.135361 0.253058
# 제곱 0.835078 0.159336 0.121273
# 세제곱근 0.835078 0.234736 0.561290
# 0.5 로 압축 0.835078 0.208158 0.450612
# 네 경우 모두 AUC 가 같습니다. 순위가 안 바뀌기 때문입니다
# 브라이어 점수는 크게 다릅니다. 실제 양성 비율은 0.253000 입니다
# 203강의 로그손실도 같은 성질을 가집니다
# 보정 곡선을 그려 봅니다
# 216강의 나이브 베이즈와 로지스틱을 견줍니다
# 예측 확률 구간 나이브 실제 비율 로지스틱 실제 비율 구간 가운데
# 0.0 에서 0.2 0.097022 0.081512 0.100000
# 0.2 에서 0.4 0.275391 0.309553 0.300000
# 0.4 에서 0.6 0.362018 0.483034 0.500000
# 0.6 에서 0.8 0.443213 0.633846 0.700000
# 0.8 에서 1.0 0.651568 0.854305 0.905000
# 로지스틱의 실제 비율이 구간 가운데에 훨씬 가깝습니다
# 나이브 베이즈는 216강 문제 2 에서 본 대로 과신합니다
# 무엇 AUC 브라이어 점수
# 나이브 베이즈 0.801359 0.164107
# 로지스틱 0.834734 0.135486
# AUC 차이가 0.033375 이고 브라이어 차이가 0.028621 입니다
# 두 지표가 같은 방향을 가리킵니다. 나이브가 순위도 확률도 조금 나쁩니다
# 그런데 확률 쪽은 보정으로 고칠 수 있습니다. 순위는 못 고칩니다
# 보정하면 나아지는지 봅니다
# 무엇 AUC 브라이어 점수 평균 예측 확률
# 나이브 그대로 0.809874 0.158074 0.302515
# 플랫 보정 뒤 0.809874 0.142426 0.251535
# 실제 양성 비율은 0.256500 입니다
# 보정은 AUC 를 거의 안 바꾸고 브라이어 점수만 고칩니다
# 단조 변환이므로 순위가 그대로이기 때문입니다
# 216강 심화 4 의 플랫 보정이 이것입니다
# 갈래가 셋 이상이면 어떻게 재는지 정리합니다
# 방법 어떻게 묶나 언제 쓰나
# 마이크로 평균 네 칸을 다 더한 뒤 전체 정확도가 중요
# 매크로 평균 갈래마다 재고 평균 드문 갈래도 똑같이
# 가중 평균 갈래 크기로 가중 마이크로와 비슷
# 갈래별로 보고 안 묶음 가장 정직함
# 세 갈래 문제에서 두 평균이 얼마나 다른지 봅니다
# 갈래 비율이 0.80 과 0.15 와 0.05 입니다
# 갈래 몇 개 정밀도 재현율
# 0 2388 0.951945 0.696817
# 1 467 0.505510 0.785867
# 2 145 0.222433 0.806897
# 무엇 정밀도 재현율
# 마이크로 평균 0.716000 0.716000
# 매크로 평균 0.559963 0.763194
# 마이크로는 큰 갈래에 끌려갑니다. 매크로는 드문 갈래를 똑같이 셉니다
# 드문 갈래가 중요하면 매크로를 봐야 합니다
# 평가 자체가 흔들리는 것도 봅니다
# 검증 자료 크기 AUC 평균 AUC 표준편차 가장 큰 값 빼기 작은 값
# 100 0.833261 0.043992 0.177062
# 500 0.834078 0.018838 0.078147
# 2000 0.834677 0.008880 0.045680
# 8000 0.835026 0.004343 0.020779
# 검증 자료가 100 개면 가장 큰 값과 작은 값의 차가 0.177062 입니다
# 8000 개면 0.020779 로 여덟 배 좁아집니다
# 두 모형의 AUC 차가 그보다 작으면 아무 말도 못 합니다
# 212강 문제 2 에서 본 교차검증의 분산과 같은 이야기입니다
# 실무 절차를 정리합니다
# 순서 무엇을 하나
# 무엇이 비싼지 정하기 놓침인가 헛경보인가
# 지표를 그것에 맞추기 정확도는 대개 아님
# 곡선을 보고 문턱 고르기 227강의 불균형까지
# 확률이 필요하면 보정 AUC 로는 못 봄
# 흔들림을 함께 보고 차가 흔들림보다 큰가
# 마지막 줄이 자주 빠집니다. 소수점 셋째 자리 차이는 대개 잡음입니다
# 226강은 재는 법을 봤습니다. 227강은 치우친 자료를 다룹니다