핵심 키워드
- #로지스틱 회귀 #다중 분류 #시그모이드 함수 #소프트맥스 함수
- 로지스틱 회귀 알고리즘을 배우고 이진 분류 문제에서 클래스 확률을 예측하자
럭키백의 확률
- 럭키 백
럭키백은 구성품을 모른 채 먼저 구매하고, 배송받은 다음에야 비로소 구성품을 알 수 있는 상품
마케팅 팀은 럭키백에 포함된 생선의 확률을 알려주는 방향으로 이벤트를 하며 이를 위해 생선의 확률이 필요
- 확률 계산하기
럭키백에 들어갈 수 있는 생선은 7개이며 길이, 높이, 두께 이외에도 대각선 길이와 무게도 사용
확률을 구하기 위해 k-최근접 이웃을 사용해 주변 이웃을 찾아 이웃의 클래스 비율을 확률로 출력하도록 함
예) 샘플 X 주위에 가장 가까운 이웃 샘플 10개를 표시
사각형이 3개, 삼각형이 5개, 원이 2개이므로 샘플 X가 사각형일 확률은 30%, 삼각형일 확률은 50%, 원일 확률을 20%
- 데이터 준비
k-최근접 이웃 분류기도 이와 동일한 방식으로 클래스 확률을 계산하여 제공하므로
데이터를 준비하기 k-최근접 이웃 분류기로 럭키백에 들어간 생선의 확률을 계산해보도록 함
판다스를 이용해 인터넷에서 read_csv() 함수로 CSV 파일을 데이터프레임으로 변환한 다음 head() 메소드로 처음 5개 행 출력
이 데이터프레임에서 Species 열을 타깃으로 만들고 나머지 5개 열은 특성이므로 입력 데이터로 사용하도록 함
이를 위해 데이터프레임에서 열을 선택하는 방법으로 데이터프레임에서 원하는 열을 리스트로 나열해 새로운 데이터프레임 반환
그리고 이를 to_numpy() 메소드로 넘파이 배열로 바꾸어 fish_input에 저장
이후 동일한 방식으로 타깃 데이터도 만듦
만들어진 데이터를 훈련 세트와 테스트 세트로 나눈 후, StandardScaler 클래스를 사용해 표준화 전처리를 해 데이터 준비 완료
- k-최근접 이웃의 다중 분류
KNeighborsClassifier 클래스 객체를 만들고 훈련 세트로 모델을 훈련한 다음 훈련 세트와 테스트 세트의 점수를 확인하도록 함
이 때 최근접 이웃 개수인 k를 3으로 지정하여 사용하도록 함
fish 데이터프레임에서 7개의 생선이 있었기 때문에 훈련 세트와 테스트 세트의 타깃 데이터에도 7개의 생선 종류가 들어감
이렇게 타깃 데이터에 2개 이상의 클래스가 포함된 문제를 다중 분류라고 부름
이진 분류를 사용했을 때는 양성 클래스와 음성 클래스를 각각 1과 0으로 지정하여 타깃 데이터를 만들었으나
다중 분류에서는 사이킷런을 사용해 편리하게 문자열로 된 타깃값을 그대로 사용할 수 있음
타깃값을 그대로 사이킷런 모델에 전달하면 자동으로 순서가 알파벳 순으로 매겨지며 정렬된 타깃값은 classes_ 속성에 저장됨
그러므로 classes_ 속성을 보게 되면 'Bream'이 첫 번째 클래스, 'Parkki'가 두 번째 클래스가 됨을 알 수 있음
predict() 메소드를 사용하여 테스트 세트에 있는 처음 5개 샘플의 타깃값을 예측하며
이 5개 샘플에 대한 예측이 어떤 확률로 만들어졌는지 알기 위해서는 predict_proba() 메소드를 사용해 클래스별 확률값을 반환
predict_proba() 메소드의 출력 순서도 classes_ 속성과 마찬가지이므로 첫 번째 열이 'Bream'에 대한 확률이 됨
하지만 이 모델의 경우 3개의 최근접 이웃을 사용하기 때문에 가능한 확률은 0/3, 1/3, 2/3, 3/3이 전부
만약 럭키백의 확률을 이렇게만 표시한다면 마케팅팀이 만족하지 않을 것이며 확률이라고 말하기가 어색함
그러므로 로지스틱 회귀로 그럴싸한 확률을 뽑아도록 하겠음
로지스틱 회귀
- 로지스틱 회귀
로지스틱 회귀는 이름은 회귀이지만 분류 모델이며 이 알고리즘은 선형 회귀와 동일하게 선형 방정식을 학습
여기서 a, b, c, d, e는 5개의 특성에 대한 가중치 혹은 계수를 뜻하며 z는 -∞ 부터 ∞ 까지로 어떤 값도 가능함
하지만 확률이 되려면 0 ~ 1 사이 값이 되어야 하므로 z가 아주 큰 음수일 때 0, z가 아주 큰 양수일 때 1이 되도록 바꿔야 함
이를 위해 시그모이드 함수(로지스틱 함수)를 사용
시그모이드 함수는 선형 방정식의 출력 z의 음수를 사용해 자연 상수 e를 거듭제곱하고 1을 더한 값의 역수를 취함
이렇게 계산하면 아래와 같은 그래프를 만들 수 있어 z를 0에서 1 사이의 값이 되게 하며
z가 무한한게 큰 음수일 경우 이 함수는 0에 가까워져 양성 클래스, z가 무한하게 큰 양수가 될 때는 1에 가까워져 음성 클래스
그리고 z가 0이 될 때는 0.5가 되므로 z가 어떤 값이 되더라고 절대로 0 ~ 1 사이의 범위를 벗어날 수 없어짐
- 로지스틱 회귀 (이진 분류)
훈련하기 전에 간단히 도미와 빙어 3개를 사용해서 이진 분류를 수행
이진 분류일 경우 시그모이드 함수의 출력이 0.5보다 크면 양성 클래스, 0.5보다 작으면 음성 클래스로 판단
넘파이 배열은 True, False 값을 전달하여 행을 선택할 수 있으며 이를 불리언 인덱싱이라고 함
이 방식과 비교 연산자를 사용하여 도미와 빙어의 행을 모두 True로 만들고 그 외는 모두 False 배열을 반환하고
도미와 빙어에 대한 비교 결과를 비트 OR 연산자를 사용해 합쳐 훈련 세트에서 도미와 빙어의 행만 골라냄
그리고 이 데이터를 가지고 로지스틱 회귀 모델을 훈련
Logistic Regression 클래스는 선형 모델이므로 sklearn.linear.model 패키지 아래에 존재하므로
이를 가지고 훈련한 모델을 사용해 처음 5개의 샘플을 예측하면 두 번째 샘플을 제외하고는 모두 도미로 예측
KNeighborsClassifier는 예측 확률을 predict_proba() 메소드에서 제공하므로 이를 사용해 처음 5개 샘플의 예측 확률을 출력
샘플마다 2개의 확률이 출력되며 첫 번째 열이 음성 클래스에 대한 확률이고 두 번째 열이 양성 클래스에 대한 확률임
그러므로 도미와 빙어에서 어떤 것이 양성 클래스인지 알기 위해 classes_ 속성을 확인하면 빙어가 양성 클래스임을 알 수 있음
- 로지스틱 회귀 계수 확인
lr.coef_와 lr.intercept_ 를 살펴 보면 로지스틱 회귀가 학습한 계수를 확인할 수 있으며
이를 통해 로지스틱 회귀 모델이 학습한 방정식을 알 수 있음
그 후 LogisticRegression 클래스의 decision_function() 메소드를 사용해 z 값을 출력한 후
이 z 값을 시그모이드 함수에 통과시키면 확률을 얻을 수 있으므로 사이파이 라이브러리의 시그모이드 함수인 expit()를 사용
이를 사용하면 decisions 배열의 값을 시그모이드 함수를 거친 확률로 변환해줌
출력값을 보면 predict_proba() 메소드 출력의 두 번째 열의 값과 동일한 것을 볼 수 있으므로
decision_function() 메소드는 양성 클래스에 대한 z값을 반환함을 알 수 있음
- 로지스틱 회귀 (다중 분류)
다중 분류는 LogisticRegression 클래스를 사용해 7개의 생선을 분류하는 것이며 기본적으로 반복적인 알고리즘을 사용
max_iter 매개변수에서 반복 횟수를 정하며 기본값은 100이지만 여기에서 준비한 데이터셋을 사용해 모델을 훈련하면
반복 횟수가 부족하다는 경고가 발생하므로 충분하게 훈련시키기 위해 반복 횟수를 1000으로 늘리도록 함
또한 LogisticRegression는 기본적으로 계수의 제곱을 규제하는 L2 규제를 사용하며 규제를 제어하는 매개변수는 C
C는 작을수록 규제가 커지며 기본값은 1이지만 여기에서는 좀 더 복잡한 모델을 만들기 위해 규제를 완화해 20으로 늘림
그 후 이를 사용해 LogisticRegression 클래스로 다중 분류 모델을 훈련한 후 정확도를 살펴보면
훈련 세트와 테스트 세트에 대한 점수가 높고 과대적합이나 과소적합으로 치우친 것 같아 보이지 않으므로
테스트 세트의 처음 5개 샘플에 대한 예측과 예측 확률을 출력하면 5개의 샘플에 대한 예측이므로 5개의 행이 출력됨
또 7개의 생선에 대한 확률을 계산했으므로 7개의 열이 출력됨
이를 통해 다중 분류는 샘플마다 클래스 개수만큼 확률을 출력함을 알 수 있음
다중 분류일 경우 7개의 선형 함수(방정식)를 만드므로 coef_와 intercept_의 크기를 출력해보면
7개의 선형 함수에 대한 계수와 절편의 개수를 출력하며
5개의 특성을 사용하므로 coef_ 배열의 열은 5개이며 행은 7개, intercept_도 7개가 됨
즉, 이 말은 이진 분류에서 보았던 z 값을 하나씩 계산한다는 것을 뜻하며 z값이 클래스마다 만들어지는 것을 뜻함
그리고 샘플을 7개의 함수를 다 통과시켜서 나온 값들 중에서 가장 높은 z 값을 출력하는 클래스가 예측 클래스가 됨
이를 통해 다중 분류는 한 클래스를 양성 클래스, 나머지 클래스를 음성 클래스로 하여 이진 분류를 각 7번 훈련함을 알 수 있음
이처럼 이진 분류를 여러 번 수행하여 분류하는 알고리즘을 OvR(One vs Rest)이라고 함
- 소프트맥스 함수
다중 분류의 경우, 확률을 계산하기 위해 시그모이드 함수를 사용하여 z를 0과 1 사이의 값으로 변환할 경우
7개의 z에 대한 시그모이드 함수의 합이 1이 되어야 확률이 될 수 있는데 그렇지 않으므로 소프트맥스 함수를 사용해 확률로 변환
먼저 7개의 z 값의 이름을 z1에서 z7이라고 붙인 후, z1 ~ z7까지 값을 사용해 지수 함수 e^z1 ~ e^z7을 계산해 모두 더함
그 다음 e^z1 ~ e^z7을 각각 e^z1 ~ e^z7을 계산해 모두 더한 값인 e_sum으로 나누어 주게됨
나누어진 값인 s1에서 s7까지 모두 더하면 분자와 분모가 같아지므로 1이 되어 확률을 구할 수 있음
z1 ~ z7까지의 값을 decision_function() 메소드로 구한 다음 사이파이의 softmax()를 사용해 확률로 바꾸도록 함
그리고 이를 앞서 구한 proba 배열과 비교하면 정확히 일치함을 알 수 있음
(즉, z를 구하여 찾아낸 확률 값과 predict_proba() 메소드를 사용해 찾아낸 예측 확률이 같음을 알 수 있음)
'ML > 혼자 공부하는 머신러닝 + 딥러닝' 카테고리의 다른 글
[혼공머신] 05. 트리 알고리즘 - 결정 트리 (0) | 2022.05.30 |
---|---|
[혼공머신] 04. 다양한 분류 알고리즘 - 확률적 경사 하강법 (0) | 2022.05.24 |
[혼공머신] 03. 회귀 알고리즘과 모델 규제 - 특성 공학과 규제 (0) | 2022.05.17 |
[혼공머신] 03. 회귀 알고리즘과 모델 규제 - 선형 회귀 (0) | 2022.05.16 |
[혼공머신] 03. 회귀 알고리즘과 모델 규제 - k-최근접 이웃 회귀 (0) | 2022.05.15 |