본문 바로가기
코딩/데이터분석(Pandas, ML, etc)

파이썬 머신러닝 라이브러리 Scikit-learn(사이킷런) 사용법

by 나홀로코더 2022. 1. 30.
반응형

요즘 머신러닝에 관심이 생겨 공부를 하는 중이다.

 

이 글은 파이썬의 머신러닝 라이브러리 중 대표 격인 사이킷런에서 제공하는 아래 페이지를 우리말로 옮긴 것이며, 필자처럼 이 분야에 익숙하지 않은 사람들을 위한 추가 설명을 박스로 덧붙였다. 필자도 이제 막 배워가고 있는 입장이므로 정확하지 않은 내용이 포함되어 있을 수도 있다.

 

https://scikit-learn.org/stable/getting_started.html 

 

Getting Started

The purpose of this guide is to illustrate some of the main features that scikit-learn provides. It assumes a very basic working knowledge of machine learning practices (model fitting, predicting, ...

scikit-learn.org

 


 

Scikit-learn은 지도 학습 및 비지도 학습을 지원하는 오픈 소스 머신러닝 라이브러리이다.  또한 모델 피팅, 데이터 전처리, 모델 선택, 모델 평가를 위한 다양한 도구와 기타 여러 유틸리티를 제공한다.

 

- 지도/비지도 학습: 머신러닝은 크게 지도 학습과 비지도 학습으로 나뉜다. 구분 기준은 학습 데이터에 label이 있는지 없는지이다. 예를 들어 신용카드 부정 거래 탐지 모델을 학습시키는 경우에, 학습 데이터에 이미 부정거래 여부에 관한 데이터(label)가 포함되어 있는 경우에는 지도 학습이 되는 것이고, 그렇지 않은 경우에는 비지도 학습이 되는 것이다.

 

피팅 및 예측: 추정기 기본

 

Scikit-learn은 추정기(estimator)라고 하는 수십 가지 머신러닝 알고리즘과 모델을 제공한다. 각 추정기는 fit 메서드를 이용해서 데이터에 적합(피팅)시킬 수 있다.

 

다음은 매우 기본적인 데이터에 RandomForestClassifier를 적합시키는 예이다.

 

>>> from sklearn.ensemble import RandomForestClassifier 
>>> clf = RandomForestClassifier(random_state=0) 
>>> X = [[ 1, 2, 3], # 2개의 샘플 데이터(3개의 특징)
... [11, 12, 13]] 
>>> y = [0, 1] # 각 샘플의 분류
>>> clf.fit(X, y) 
RandomForestClassifier(random_state=0)

 

- 피팅과 예측
머신러닝이 복잡해 보이지만 크게 보면 피팅과 예측으로 나누어 볼 수 있는 것 같다. 피팅은 학습 데이터를 머신러닝 모델, 즉 추정기(estimator)에 넘겨 주어 모델을 데이터에 적합(피팅)시키는 것이다. 영어로는 fit을 사용한다.
이렇게 데이터에 적합시킨 모델을 이용해서 새로운 데이터에 대한 예측을 하는 것이다. 
앞서 신용카드의 예를 들면, 신용카드 부정거래에 관한 학습 데이터를 학습한 모델에다가 새 데이터를 넣어 보면 해당 거래가 부정거래일지 아닐지를 예측해 알려 주는 것이다.

 

fit 메서드는 일반적으로 2개의 입력값을 받는다.

 

- 샘플 행렬 X

X의 크기는 일반적으로 (샘플의 개수, 특징의 개수)이다.

 

- 목표 값 y

회귀 작업의 경우 실수, 분류 작업의 경우 정수를 받는다. 비지도 학습의 경우 y를 지정할 필요가 없다. y는 일반적으로 i번째 항목이 샘플 행렬 X의 i번째 샘플(행)에 해당하는 1차원 배열(array, list)이다.

 

일부 추정기는 희소 행렬 같은 다른 형식과 함께 작동하지만 X와 y는 일반적으로 numpy 배열 또는 이에 상응하는 배열 같은 데이터이다.

 

추정기가 적합(피팅)되면 새 데이터의 목표 값을 예측하는 데 사용할 수 있다. 추정기를 다시 학습시킬 필요가 없다.

 

>>> clf.predict(X) # 학습 데이터의 분류를 예측
array([0, 1]) 
>>> clf.predict([[4, 5, 6], [14, 15, 16]]) # 새로운 데이터의 분류를 
array([0, 1])

 

반응형

 

변환기 및 전처리기

 

머신러닝은 종종 서로 다른 부분으로 구성된다. 일반적인 파이프라인은 데이터를 전처리하는 단계와 목푯 값을 예측하는 단계로 구성된다.

 

scikit-learn에서 전처리기와 변환기는 추정기와 동일한 API를 따른다(실제로 모두 동일한 BaseEstimator 클래스에서 상속됨). 변환기 객체에는 예측 메서드가 없고 새로 변환된 샘플 행렬 X를 출력하는 변환 메서드가 있다.

 

>>> from sklearn.preprocessing import StandardScaler 
>>> X = [[0, 15], 
... [1, -10]] 
>>> StandardScaler().fit(X).transform(X) 
array([[-1., 1.], 
	[ 1., -1.]])

 

- 변환기와 전처리기:
학습 데이터를 모델에 적합시키기 전에 학습 데이터를 전처리해 머신러닝에 적합한 형태로 변형해야 할 필요가 있을 수 있다. 실제 코딩을 할 때는 순서상 앞에서 설명한 피팅 및 예측보다 먼저 이루어지는 작업이다.
예를들어 학습 데이터의 특징1은 1~10 사이의 값을 가지는 반면 특징2는 1000 이상의 큰 값을 가지는 경우, 모델에 따라 특징2의 영향을 더 크게 받게 될 수 있다. 만일 그렇다면 데에터를 전처리해 주는 것이다.(예. 특징1과 특징2가 모두 0과 1사이의 값을 가지도록 변환)

 

파이프라인: 전처리기 및 추정기 연결

 

변환기와 추정기(예측기)는 파이프라인으로 결합될 수 있다. 파이프라인은 일반 추정기와 동일한 API를 제공한다. 즉 적합 및 예측을 사용할 수 있다. 파이프라인을 사용하면 훈련(학습) 데이터에서 테스트(예측) 데이터의 일부가 공개되는 것, 즉 데이터 누출을 방지할 수 있다.

 

다음 예에서는 Iris 데이터 세트를 불러와 이를 훈련(학습) 세트와 테스트(예측) 세트로 분할하고 테스트 데이터에 대한 파이프라인의 정확도 점수를 계산한다.

 

 

>>> from sklearn.preprocessing import StandardScaler
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.pipeline import make_pipeline
>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split
>>> from sklearn.metrics import accuracy_score
...
>>> # 파이프라인 객체 생성
>>> pipe = make_pipeline(
...     StandardScaler(),
...     LogisticRegression()
... )
...
>>> # iris 데이터셋을 불러와 훈련/테스트 세트로 분할
>>> X, y = load_iris(return_X_y=True)
>>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
...
>>> # 파이프라인 피팅
>>> pipe.fit(X_train, y_train)
Pipeline(steps=[('standardscaler', StandardScaler()),
                ('logisticregression', LogisticRegression())])
>>> # 이제 다른 추정들처럼 사용
>>> accuracy_score(pipe.predict(X_test), y_test)
0.97...

 

- 정확도 점수: 여기에서 정확도 점수가 0.97로 계산되었다. 머신러닝에서는 피팅과 예측 이후에 항상 그 결과를 평가하는 절차가 따라 온다. 평가 결과가 좋지 않으면 모델을 바꾸거나 모델에 넘겨 주는 변수에 변화를 줘 가면서 더 나은 결과가 나오게 만든다.
여기에서 정확도 점수란, 테스트(예측) 데이터(X)를 모델에 넘겨줘서 예측된 결과가 실제 데이터(y)와 얼마나 일치하는지를 계산한 것이다.

 

반응형

 

모델 평가

 

모델을 일부 데이터에 적합(피팅)시켰더라도 새 데이터에 대해 잘 예측하는 것은 아니다. 이는 직접 평가해야 한다. 데이터 세트를 훈련 세트와 테스트 세트로 분할하는 train_test_split 메서드를 방금 보았지만 scikit-learn은 모델 평가를 위한 다른 많은 도구(특히 교차 검증을 위한)를 제공한다.

 

여기서는 cross_validate 메서드를 사용하여 5중 교차 검증 절차를 수행하는 방법을 간략하게 보여준다.

 

>>> from sklearn.datasets import make_regression
>>> from sklearn.linear_model import LinearRegression
>>> from sklearn.model_selection import cross_validate
...
>>> X, y = make_regression(n_samples=1000, random_state=0)
>>> lr = LinearRegression()
...
>>> result = cross_validate(lr, X, y)  # defaults to 5-fold CV
>>> result['test_score']  # r_squared score is high because dataset is easy
array([1., 1., 1., 1., 1.])

 

자동 변수 검색

 

모든 추정기는 매개변수(하이퍼 매개변수)가 있다. 추정기의 일반화 능력은 종종 몇 가지 매개변수에 크게 의존한다. 예를 들어 RandomForestRegressor에는 트리의 수를 결정하는 n_estimators 매개변수와 각 트리의 최대 깊이를 결정하는 max_depth 매개변수가 있다. 종종 이러한 매개변수의 정확한 값을 무엇으로 해야 할지 명확하지 않다.

 

Scikit-learn은 (교차 검증을 통해) 최상의 매개변수 조합을 자동으로 찾는 도구를 제공한다. 다음 예에서는 RandomizedSearchCV 개체를 사용하여 랜덤포레스트의 매개 변수를 무작위로 검색한다. 검색이 끝나면 RandomizedSearchCV는 최적의 매개변수 세트가 적용된 RandomForestRegressor로 작동한다.

 

>>> from sklearn.datasets import fetch_california_housing
>>> from sklearn.ensemble import RandomForestRegressor
>>> from sklearn.model_selection import RandomizedSearchCV
>>> from sklearn.model_selection import train_test_split
>>> from scipy.stats import randint
...
>>> X, y = fetch_california_housing(return_X_y=True)
>>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
...
>>> # 검색할 매개변수를 정의
>>> param_distributions = {'n_estimators': randint(1, 5),
...                        'max_depth': randint(5, 10)}
...
>>> # searchCV 객체를 생성하고 데이터에 피팅
>>> search = RandomizedSearchCV(estimator=RandomForestRegressor(random_state=0),
...                             n_iter=5,
...                             param_distributions=param_distributions,
...                             random_state=0)
>>> search.fit(X_train, y_train)
RandomizedSearchCV(estimator=RandomForestRegressor(random_state=0), n_iter=5,
                   param_distributions={'max_depth': ...,
                                        'n_estimators': ...},
                   random_state=0)
>>> search.best_params_
{'max_depth': 9, 'n_estimators': 4}

>>> # 서치 객체를 일반적인 추정기처럼 사용
>>> # 검색된 매개변수인 max_depth=9과 n_estimators=4를 
>>> search.score(X_test, y_test)


0.73...

 

실제로는 거의 항상 단일 추정기 대신 파이프라인을 검색한다. 파이프라인을 사용하지 않고 전체 데이터 세트에 전처리 단계를 적용한 다음 모든 종류의 교차 검증을 수행하면 학습 데이터와 테스트 데이터 간의 독립성에 대한 기본 가정을 깨는 것이기 때문이다. 전체 데이터 세트를 사용하여 데이터를 사전 처리했기 때문에 테스트 세트에 대한 일부 정보를 훈련 세트에서 사용할 수 있다. 이것은 추정기의 일반화 능력을 과대평가하는 결과를 낳는다. 교차 검증 및 검색에 파이프라인을 사용하면 이 일반적인 함정에서 크게 벗어날 수 있다.

반응형

댓글