Scikit-learn

2 minute read

1. 머신러닝 단계에 포함되어야 할 사항

  • Hold out: Training, Test Split
    • 데이터가 많다는 가정 하에 수행
    • 데이터가 작다면 Cross Validation 사용, stratify 사용해서 y값 비율 맞춤
  • EDA: Split 전 합친 데이터로
  • 오버피팅 방지
    • 데이터 추가
    • 차원축소 (차원의 저주 막기 위함)
    • Feature selection
    • Ensemble

2. Hold out

iris 데이터를 가져와보자.

from sklearn.datasets import load_iris
import pandas as pd

data = load_iris()
iris = pd.DataFrame(data.data, columns=data.feature_names)
iris['target'] = data.target

sklearn은 train_test_split이라는 Hold out 방식을 제공하며, stratify를 사용해 y값의 비율을 맞춰줄 수 있다. 데이터 양이 많다면 큰 문제 없지만 데이터가 작다면 stratify를 사용해주는 것이 좋다.

from sklearn.model_selection import train_test_split

train, test = train_test_split(iris, stratify=iris.target)

실제로는 다음과 같은 방식으로 많이 사용할 것이다.

X_train, X_test, y_train, y_test = train_test_split(iris.iloc[:, :-1], iris.iloc[:,-1])

3. 모델 성능 비교

사이킷런의 교차검증은 cross_val_score로 쉽게 반복할 수 있다.

from sklearn.model_selection import cross_val_score
from sklearn.neighbors import KNeighborsClassifier

cross_val_score(KNeighborsClassifier(), X_train, y_train, cv=10, n_jobs=-1)
# (회귀분석모형, 독립변수 데이터, 종속변수 데이터, cv=교차검증 생성기 객체 or 숫자)

Classification 모델에서는 accuracy를 주로 사용하며, Regression 모델에서는 r2_score를 주로 사용한다.

# 분류의 다양한 스코어링 기법 체크
from sklearn.metrics import classification_report
classification_report(y_true, y_pred)

4. DummyClassifier

DummyClassifier를 사용한다면 기계학습을 쓰지 않을 수도 있다. 단, testset이 작아 편차가 크면 할 때마다 성능은 다르게 나올 수 있다.

from sklearn.dummy import DummyClassifier
du = DummyClassifier()
du.fit(X_train, y_train)
du.score(X_test, y_test)

5. Encoding

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(X_train, y_train) # ValueError

현재 인코딩이 되지 않은 상태이기 때문에 에러가 발생한다.

(1) 판다스에서 Encoding

label encoding

다음과 같이 map을 활용해 라벨인코딩할 수 있다.

iris.species.map({'virginica':0, 'setosa':1, 'versicolor':2})

카테고리 type으로 만들어 라벨인코딩하는 것도 가능하다.

iris.species = iris.species.astype('category')
iris.species.cat.codes

one-hot encoding

# 방법 1
iris.species.str.get_dummies()
# 방법 2
pd.get_dummies(iris.species)

(2) Scikit-learn에서 Encoding

label encoding

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit_transform(iris.species)

le.inverse_transform([2])

inverse_transform 기능은 사이킷에서만 지원하는 기능으로, 인코딩한 결과를 반대로 이야기해준다.

le.fit_transform(iris[['species']])

위의 코드처럼 Fancy Indexing을 할 경우 1차원으로 넣어달라고 Warning이 발생한다. 1차원으로 넣어주자.

one-hot encoding

from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()
ohe.fit_transform(iris[['species']]).toarray()

OneHotEncoder는 반대로 2차원으로 넣어줘야 에러가 발생하지 않으며 toarray()까지 해줘야 값이 제대로 나올 수 있다.

6. Learning Curve

from sklearn.model_selection import learning_curve
import sklearn_evaluation

train_size,train_score,test_score = learning_curve(KNeighborsClassifier(), iris.iloc[:, :-1], iris.species, cv=10)

sklearn_evaluation.plot.learning_curve(train_score, test_score, train_size)

train_score는 train 가지고만 한 것으로 언더피팅을 확인하기 위해 사용한다.

image

해당 그래프는 iris 데이터를 활용해서 learning curve가 괜찮게 나온 상태이다. 만약 cross-validataion score가 계속 올라가지 않고 떨어지거나 한다면 문제가 있다고 판단할 수 있다.

7. 하이퍼파라미터 찾기

  • GridSearchCV
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
import pandas as pd

knn = KNeighborsClassifier()
grid = GridSearchCV(KNeighborsClassifier(), {'n_neighbors':range(2,20)}, cv=10)
# 파라미터들은 knn.get_params()으로 확인
grid.fit(iris.iloc[:,:-1], iris.iloc[:, -1])
pd.DataFrame(grid.cv_results_).T
grid.best_params_
grid.best_index_
grid.best_score_

Leave a comment