머신러닝

머신 러닝(with Google Colab) - 4일차(1)

aisw7984 2024. 10. 16. 17:50
반응형

이전까지 우리가 사용한 분류는 목표로 하는것을 1로 두고 0과 1을 분류하는 이진분류의 형태였다.

좀더 나아가서 각 목표별 확률을 나누어 분류를 할 수 있는 방법을 알아보자


우선 데이터를 준비해 보자

import pandas as pd
fish = pd.read_csv('https://bit.ly/fish_csv_data')
print(pd.unique(fish['Species']))
fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
fish_target = fish['Species'].to_numpy()

from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_=\
train_test_split(fish_input, fish_target,random_state=42)

 

앞서 사용했던 분류모델인 KNeighborsClassifier 을 사용해보자(이웃수 =3)

#KNN 이용 이웃 분류기의 확률 예측
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier(n_neighbors=3)
kn.fit(train_scaled, train_target)
print("훈련세트 정확도:",kn.score(train_scaled, train_target))
print("테스트 세트 정확도:",kn.score(test_scaled, test_target))
#사이킷런으로 문자열이 입력되면 알파벳순으로 정렬됨
print(kn.classes_)
#샘플 예측
print(kn.predict(test_scaled[:5]))

KNeighborsClassifier의 객체에는 classes_하는 매서드가 있다. classes_ 객체가 가진 클래스들의 이름을 알려주는데, 사이킷런에서 문자는 자동으로 순서대로 정렬된다. 즉 데이터를 입력했을때 클레스와 순서가 다르게 된다.

테스트에서 5개를 추출해서 예측해보면 다음과 같다.

훈련세트 정확도: 0.8907563025210085
테스트 세트 정확도: 0.85
['Bream' 'Parkki' 'Perch' 'Pike' 'Roach' 'Smelt' 'Whitefish']
['Perch' 'Smelt' 'Pike' 'Perch' 'Perch']

사이킷런에 포함된 분류모델은 predict_proba() 매서드를 통해 클래스별 확률을 알 수 있다. 추가로 numpy의 round()는 값을 decimals매개변수로 주어진 수에 따라 소숫점 아래 자리수를 정할 수 있다.

import numpy as np
#predict_proba : 클래스별 확률값
proba = kn.predict_proba(test_scaled[:5])
print(np.round(proba,decimals=4))
#4번째 샘플의 최근접 확인
distances, indexs = kn.kneighbors(test_scaled[3:4])
print(train_target[indexs])
[[0.     0.     1.     0.     0.     0.     0.    ]
 [0.     0.     0.     0.     0.     1.     0.    ]
 [0.     0.     0.     1.     0.     0.     0.    ]
 [0.     0.     0.6667 0.     0.3333 0.     0.    ]
 [0.     0.     0.6667 0.     0.3333 0.     0.    ]]
[['Roach' 'Perch' 'Perch']]

결과를 확인해보면 행 마다 앞서 classes_ 를 통해 확인했던 순서대로 확률이 적혀있다.

사용한 모델이 최근접 이웃이기때문에 근처에 이웃이 누가 많이 있는가를 보여준다.

4번째 행을 보면 Rerch와 Roach가 확률에 잡힌는데 이웃수를 3으로 잡았기 떄문에 Rerch= 2  Roach=1 이라는것을 알수 있다.


로지스틱 회귀

로지스틱 회귀는 이름으로만 본다면 회귀를 다룰것 같지만 분류 모델이다. 이 알고리즘이 선형 방정식을 통해 학습을 하기 때문에 회귀라고 불린다. 로지스틱 회귀는 시그모이드 함수(로지스틱 함수)를 사용하는데 이에 관한 자세한 정보는 검색을 통해 알아보자

여러개의 정보중에 특정한 정보들만 선택하고 싶을때 사용하는 것이 불리언 인덱싱이다. 만약 주어진 데이터에서 도미(Bream)와 빙어(Smelt)의 데이터만 사용하려고 한다면 다음과 같이 사용하면 된다.

bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt')
train_bream_smelt = train_scaled[bream_smelt_indexes]
target_bream_smelt = train_target[bream_smelt_indexes]

 

로지스틱 회귀 모델은 sklearn.linear_model 패키지에 LogistcRegression 클래스에 포함되어 있다.

객체를 생성하고 위에 처럼 예측해보자

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(train_bream_smelt, target_bream_smelt)
print(lr.predict(train_bream_smelt[:5]))
print(lr.predict_proba(train_bream_smelt[:5]))
['Bream' 'Smelt' 'Bream' 'Bream' 'Bream']
[[0.99760007 0.00239993]
 [0.02737325 0.97262675]
 [0.99486386 0.00513614]
 [0.98585047 0.01414953]
 [0.99767419 0.00232581]]

예측의 결과와 확률을 보면 알수 있드시 도미를 0 빙어를1로 보고 예측한 것을 알수 있다. 


로지스틱 회귀로 다중 분류 수행하기

LogisticRegression() 의 괄호 안에는 C와 max_iter 이라는 매개변수가 들어 갈 수 있다.

C는  규제를 제어하는 변수인데 alpha와 비슷하지만 반대로 작을수록 규제가 크다는 점이 있다.(기본값1)

max_iter는 매개변수의 반복 횟수를 지정하는 것인데 너무 적을경우 훈련이 되지 않으므로 적당한 값을 넣어주어야 한다,(기본값 100)

이를 생각하고 다시 로지스틱 함수를 사용해 보자

lr = LogisticRegression(C=20, max_iter=1000)
lr.fit(train_scaled, train_target)
print(lr.score(train_scaled,train_target))
print(lr.score(test_scaled,test_target))
print(lr.predict(test_scaled[:5]))
#예측확률 출력
print(np.round(lr.predict_proba(test_scaled[:5]),decimals=3))
=>
0.9327731092436975
0.925
['Perch' 'Smelt' 'Pike' 'Roach' 'Perch']
[[0.    0.014 0.842 0.    0.135 0.007 0.003]
 [0.    0.003 0.044 0.    0.007 0.946 0.   ]
 [0.    0.    0.034 0.934 0.015 0.016 0.   ]
 [0.011 0.034 0.305 0.006 0.567 0.    0.076]
 [0.    0.    0.904 0.002 0.089 0.002 0.001]]

확률적 경사 하강법

지속적으로 데이터를 학습해야 하는 상황이 온다면 앞선 방법을 쓰게 되면 프로그램을 실행시키는데 부담이 되고 계발자 입장에서도 힘들 것이다. 이를 해결하기 위한 방법으로 점진적 합습이 있는데 이런 대표적 합습법이 확률적 경사 하강법이 있다.

확률적 경사 하강법은 훈련 세트에서 랜덤하게 하나의 샘플을 골라서 경사를 내려가고 이를 반복한다. 훈련세트를 한번 모두 사용하는 과정을 에포크 라고 한다. 이러한 에포크가 누적이 되서 확률적 경사 하강법을 구성한다.

위와 같은 확률적 경사 하강법이 내려가는 경사는 손실함수 라고 할수 있다. 손실 함수는 머신러닝 알고리즘의 정확도를 알려주는 지표중 하나로 적을수록 좋다. 손실함수는 여러 종류가 있을 수 있는데  기본적으로 손실함수를 구하는 것은 머신렁러닝 라이브러리에 포함이 되어있기떄문에  손실함수에 대한 자세한 계산법은 따로 알아 보자. 

간단히 정리하면 확률적 경사 하강법은 손실함수를 랜덤한 샘플을 골라 누적해서 오차를 줄여나가는 방법이라 볼 수 있다.

반응형