2019. 8. 6. 00:03ㆍ분석 Python/Scikit Learn (싸이킷런)
내가 모델링을 할 때 다음과 같은 실수를 한 적이 있다.
예를 들어 어떤 데이터를 열심히 전처리를 하고 나서, 모델링을 한다고 했을 때, 보통 모델만 저장하고 전 처리할 때 값을 저장을 안 한 경우가 있다.
그래서 다른 새로운 데이터가 들어왔을 때 다시 전처리 함수를 적용하는 경우가 있는데, 이러면 train과 test로 학습시킨 게 어긋나기 때문에 문제가 생긴다.
그리고 만약 어떤 칼럼에서 특정 값이 train에는 없는데, test에만 있어도 문제가 발생할 것이다.
하지만 이때 test에 있는 것을 가져와야 하는지... 어차피 다 0으로 처리되니까 상관없을 것 같기도 하지만 고민이 되는 사항이다.
아무튼 이번 포스팅은 전처리를 하고 나서 저장해서 어떻게 쓸 수 있을지에 대해 고민해본 것을 써보려고 한다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import preprocessing
data_file = "./../../Data/Churn.csv"
data = pd.read_csv(data_file)
data["churn"] = data["churn"].astype(str)
data.drop(["phone number"] , axis = 1 , inplace= True)
data.head(2)
요런 데이터가 있다고 하자.
이런 것이 있다고 했을 때 일반적으로 object로 나온 부분은 category이기 때문에 onehot 처리를 해줄 것이고, int나 float는 숫자니 표준화를 해줄 것이다.
데이터를 잘 봐야 하는데, area code 같은 경우에는 int지만 category이므로 같이 onehot을 해줘야 한다.
churn 같은 경우에는 타깃이니 내버려두자.
원래는 각각 따로따로 처리해서 진행을 하였다.
따로따로 처리하면 장점은 변수 하나하나당 섬세하게 작업을 할 수 있다는 장점이 있을 것 같다.
category_col = ["state","international plan" , "voice mail plan" ,'area code' ]
numeric_col = list(set(data.columns.tolist()).difference(col))
onehot_encoder_dict = {}
for i in category_col :
print(i)
onehot_encoder = preprocessing.OneHotEncoder()
label = onehot_encoder.fit(data[i].values.reshape(-1,1))
colnames = i + "_"+ onehot_encoder.categories_[0].astype(str).astype(object)
dt = pd.DataFrame(label.transform(data[i].values.reshape(-1,1)).toarray(), columns = colnames)
data.drop([i],axis = 1 , inplace = True)
data = pd.concat([data , dt], axis = 1 )
onehot_encoder_dict[i] = onehot_encoder
numeric_col.remove("churn")
from sklearn.preprocessing import StandardScaler
numeric_process_dict = {}
for i in numeric_col :
print(i)
scaler = StandardScaler()
scaler.fit(data[i].values.reshape(-1,1))
numeric_process_dict[i] = scaler
data[i] = scaler.transform(data[i].values.reshape(-1,1))
이런 식으로 처리를 해주면 된다 여기서 중요한 것은 모델을 만든 후에 dict에 넣은 것이다
이유는 나중에 다시 또 쓰기 위해서!
그래서 위에 같이 전처리를 진행해주면 되는데, 찾아보니 동시에 한꺼번에 하는 것도 있어서 공유한다.
한꺼번에 하면 좋은 점이 많은데, 단점으로는 인풋의 순서를 잘 기억해야 한다는 점이다.
꼬이는 순간 다른 데이터가 되어버린다!
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
numeric_features = numeric_col
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())])
categorical_features = category_col
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant', fill_value='missing')),
('onehot', OneHotEncoder(handle_unknown='ignore'))])
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)])
clf = Pipeline(steps=[('preprocessor', preprocessor),])
data_file = "./../../Data/Churn.csv"
data = pd.read_csv(data_file)
data["churn"] = data["churn"].astype(str)
data.drop(["phone number" ,"churn"] , axis = 1 , inplace= True)
clf.fit(data)
Allprocess2= {}
Allprocess2["Numeric_Onehot"] = clf
test2 = pd.DataFrame(data.iloc[0,:]).T
clf = Allprocess2["Numeric_Onehot"]
pd.DataFrame(clf.transform(test2).toarray())
말하고자 했던 것은 모델뿐만 아니라 encoding 값을 만든 함수도 따로 저장을 해서 새로운 데이터에 적용을 하는 것이 올바른 적용 방법이다
'분석 Python > Scikit Learn (싸이킷런)' 카테고리의 다른 글
[ Python ] Cross Validation 병렬로 돌리고 BoxPlot 시각화 (0) | 2019.11.07 |
---|---|
[ Python ] scikitplot 다양한 metric plot 제공 (0) | 2019.10.19 |
sklearn Pipeline을 이용해 다양한 Regression모델 모델링하기 (0) | 2019.06.15 |
sklearn Pipeline을 이용해 다양한 Classification모델들 모델링하기 (0) | 2019.06.15 |
Sklearn SVM + OneVsRestClassifer Gridsearch (0) | 2019.06.15 |