한빛 마켓의 새로운 이벤트인 '한빛 럭키백' 출시! 그런데 고객들이 구매에 대한 판단을 하려면 럭키백에 포함된 생선의 확률을 알려줘야겠네... 그냥 분류만 하는 건 앞에서 해봤는데, 그 분류에 대한 확률도 구할 수 있는 걸까?
= 럭키백에 들어가는 생선은 7개. 럭키백에 들어간 생선의 크기, 무게, 길이 등이 주어졌을 때, 7개 생선에 대한 확률을 출력해야 함!
k-최근접 이웃 모델은 가까운 이웃 중 가장 많은 것을 타깃으로 채택했었다. 그렇다면, 그 '가까운 이웃'들의 비율이 있을 것이다. → 실제로 이 분류기에서 확률계산 기능을 제공함!
.unique()
: 중복되는 거 빼고 고유한 값들 보여주는 함수KNeighborsClassifier
모델 훈련시키기 (2장과 동일).classes_
: KNeighborsClassifier에서 정렬된 타깃값은 여기에 저장되어있음..predict_proba()
: 예측에 대한 확률값을 계산해주는 메소드.np.round
: 소수점 첫째자리에서 반올림해주는 넘파이 함수.decimals
: 반올림(round)의 자릿수를 지정해주는 매개변수.➡️ 이게 바로 '예측 확률'임. 근데 이 경우는 가능한 확률이 0, 1/3, 2/3, 3/3 밖에 없어서 제대로 된 확률스러운(?) 느낌이 없음. 좀 더 연속적인 확률로 나타내는 방법 없을까?
- 시그모이드 함수(또는 로지스틱 함수)
: 자연상수 를 로 거듭제곱하고 1을 더한 값에, 역수를 취하면,
아래와 같은 그래프를 얻을 수 있음. 가 0일 때는 0.5가 됨.- >0 : 양성 / <0 : 음성 → 이렇게 반 잘라서 생각하기도 편함.
(=0은 보통 음성에 포함시킴. 사이킷런에서도 그러함.)
불리언 인덱싱
으로 Bream, Smelt 행만 골라내면 됨.LogisticRegression()
: 로지스틱 회귀모델 (역시 linear_model 패키지 아래에 있음).predict_proba
)❗이진분류에서는, 1열이 음성 클래스이고 2열이 양성 클래스임
= 앞에서 사이킷런은 문자열 그대로 쓸 땐 알파벳순으로 한다고 했었으니,
빙어가 양성이 되겠네 (if. 도미를 양성으로 쓰고 싶으면, 2장에서 했듯이 0/1 지정해주면 됨)
= 위의 예측 결과와 비교해보면, Bream 4개 / Smelt 1개니까 맞아떨어지네 ㅇㅇ
.decision_function()
: LogisticRegression()에서 값을 출력하는 메소드expit()
: 사이파이 라이브러리에서 제공하는 시그모이드 함수decision_function
의 반환값은 양성클래스에 대한 z값이란 걸 알 수 있음. (음성 = 1-양성 으로 사후 계산)⭐자, 이제 그럼 우리의 진짜 문제를 위해, 다중분류로 넘어와보자.
max_iter
: 충분한 훈련을 위해 반복횟수를 지정하는 매개변수 (기본값=100)C
: (릿지의 alpha
처럼) 규제의 양을 조절하는 매개변수. (기본값=1)predict
: 5개의 특성을 바탕으로 판단했을 때 7개의 생선 중 무엇일지 ㅇㅇ.predict_proba
: 위의 예측 결과가 어떤 확률 속에서 나왔는지 ㅇㅇ.❗다중분류에서는, 클래스 개수만큼 확률을 출력함.
= 위의 예측결과와 비교해보면 각각 가장 높은 확률이랑 맞아떨어짐 ㅇㅇ
= (해석) 첫번째 샘플은 Bream일 확률 0 / Parkki일 확률 0.014 / Perch일 확률 0.841 / Pike일 확률 0 / Roach일 확률 0.136 / Smelt일 확률 0.007 / Whitefish일 확률 0.003 이었던 것이다.
❗근데 다중분류는, 이진분류(샘플당 값 1개)와 달리, 값이 여러 개라서 다 합치면 1을 넘어갈 수 있음 = 한 샘플 내의 7개 값을 다 합치면 1이 되도록 적당히 압축 필요
➡️ 그게 바로, 소프트맥스 함수 !!! (그래서 여기선 시그모이드 X)
softmax()
: 여러 개의 선형방정식의 출력값()을 0~1 사이로 압축하고, 총합이 1이 되게 만드는 함수. → 여기 넣어서 확률 구해보니 [22]에서 구했던 것과 동일^^char_arr = np.array(['a', 'b', 'c', 'd', 'e'])
print(char_arr[[True, False, True, False, False]])
---------------------------------------------------------------
['a' 'c'] # 이렇게 True 위치의 원소만 뽑아냄!
alpha
가 커질수록 규제가 커졌지만, C
는 반대로 작을수록 규제가 커지니 사용할 때 헷갈리지 않게 주의! (최적의 C
값도 역시 직접 찾아야 함)axis
는 소프트맥스 계산의 단위를 각 행마다 하기 위해서 설정해주는 거임.[설명]
로지스틱 회귀는 선형방정식에서 출력된 값을 특정 함수에 집어넣어 '확률'처럼 보이게 할 수 있다. 이진분류는 0~1 사이의 값으로 압축시켜주는 시그모이드 함수를 쓴다. 다중분류는 값이 여러 개라서 시그모이드로 할 수 없고, 그걸 다 압축시켜주는 소프트맥스 함수를 써야한다.
179p. 넘파이로 안 바꾸면 어떻게 되나요? 그냥 리스트 형태로 나오나?
182p. 4번째 샘플 불러올 때, 왜 [3:4]로 불러오는 거죠..?
kn.neighbors()
는 2차원 배열을 넣어줘야해서 그런 거임! (310p 참고) ⏯️
190-191p 과정 이해 잘 안 되면 이 그림을 기억하자. 이런 식으로 각 샘플마다 7개의 방정식 적용돼서 z값이 7개가 나오는 것이다..! 🆗
갑자기 처음 보는 지수함수가 등장하고.. 설상가상으로 더 복잡한 소프트맥스 함수까지 나와서 당황스러웠다ㅠ 다행히 강의랑 같이 보면서 천천히 이해할 수 있었다,,, 결국 지수함수 자체가 중요한 건 아니고, "다중회귀식의 결과값(z)을 적당히 계산해주니까 0~1사이의 값이 나와서, 그걸 확률로 보겠다"는 식의 논리인 것 같다..!
'럭키백' 이벤트 출시 = 분류모델에서 '분류'뿐만 아니라 분류의 근거가 되는 '확률'까지 필요한 상황 → ① k-최근접 이웃 분류모델에서 .predict_proba
로 확률 출력 가능! → but 확률 치고 너무 불연속적인 수치.. → ② 새로운 알고리즘, 로지스틱 회귀모델을 사용 = 결과값(z)을 0~1 사이의 값으로 재구성해서 확률처럼 보이게 출력 가능!! → 이진분류는 시그모이드 함수 활용, z가 0보다 크면 양성 클래스! → 다중분류는 소프트맥스 함수 활용, z가 가장 큰 클래스 채택!