댕구리댕댕구리 2022. 10. 25. 02:27
728x90
반응형
SMALL

1. 데이터 인코딩

  • LabelEncoder를 객체로 생성한 후에 fit(), transform()을 호출
from sklearn.preprocessing import LabelEncoder

items = ['TV','냉장고','전자레인지','컴퓨터','선풍기', '선풍기']

encoder = LabelEncoder()
encoder.fit(items)
items_label = encoder.transform(items)

print('변환변 레이블 : ', items_label)

# classes_ : 0번부터 순서대로 변환된 인코딩 값에 대한 원본값을 가짐
print('원본 레이블 : ', encoder.classes_)

# inverse_transform : 인코딩된 레이블을 다시 디코딩
print('디코딩한 레이블 : ', encoder.inverse_transform([4,3,1,1,0,2,4]))

  • 레이블 인코딩은 tree 기반 모델 성능에 영향을 주지 않아 괜찮지만, 선형 회귀에서는 가중치가 부가되거 더 중요하게 인식할 수 있어 사용하면 안됨

 

2. 원핫인코딩

  • 피처 값의 유형에 따라 새로운 피처를 추가해 고유 값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시
  • 출력값 해석 : TV는 0으로 인코딩 되었기에, 0번 자리에 1이 표시
from sklearn.preprocessing import OneHotEncoder
import numpy as np 

items = ['TV','냉장고','냉장고','전자레인지','컴퓨터','선풍기', '선풍기']

# LabelEncoder 작업 진행
encoder = LabelEncoder()
encoder.fit(items)
items_label = encoder.transform(items)

# 2차원 데이터로 변경
items_label = items_label.reshape(-1, 1)

# 원핫 인코딩 적용
oh_encoder = OneHotEncoder()
oh_encoder.fit(items_label)
oh_labels = oh_encoder.transform(items_label)

print('원핫 인코딩 데이터')
print(oh_labels.toarray())

print('원핫 인코딩 데이터 차원')
print(oh_labels.shape)

# OneHotEncoding을 더 쉽게 지원하는 get_dummies()

import pandas as pd
df = pd.DataFrame({'item': ['TV','냉장고','전자레인지','컴퓨터','선풍기','선풍기','믹서','믹서']})

pd.get_dummies(df)

 

3. 피처 스케일링과 정규화

  • 표준화 : 데이터의 피처 각각이 평균이 0이고, 분산이 1인 경우 가우시안 정규 분포를 가진 값으로 변환하는 것을 의미
    • 새로운 데이터 x_new의 값에서 피처 x의 평균을 빼고 x의 표준편차로 나눈 값
  • 정규화 : 데이터의 값 범위가 1 ~ 1000000 정도 된다면 변수를 모두 동일한 크기 단위로 비교하기 위해 값을 최소 0 / 최대 1의 값으로 변환
    • 새로운 데이터 x_new의 값에서 피처 x의 최솟값을 뺀 값을 피처 x의 최댓값과 최솟값의 차이로 나눈 값으로 변환

 

3 - 1. 표준화 - StandardScaler

  • sklearn에서 구현한 RBF 커널을 이용하는 SVM, 선형 회귀, 로지스틱 회귀는  데이터가 가우시안 분포를 가지고 있다고 가정하고 구현됐기 때문에 사전에 표준화 작업을 하는 것이 성능 향상에 도움
from sklearn.datasets import load_iris
import pandas as pd

iris = load_iris()
iris_data = iris.data
df = pd.DataFrame(data = iris_data, columns= iris.feature_names)

print('feature들의 평균 값')
print(df.mean())

print('\n feature들의 분산값')
print(df.var())

from sklearn.preprocessing import StandardScaler

stand = StandardScaler()
stand.fit(df)
iris_scaled = stand.transform(df)

# StandardScaler 작업시 스케일 변환된 numpy ndarray 형식으로 반환돼 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(data = iris_scaled, columns = iris.feature_names)


print('feature들의 평균 값')
print(iris_df_scaled.mean())

print('\n feature들의 분산 값')
print(iris_df_scaled.var())

3 - 2. MinMaxScaler

  • 데이터값을 0과 1사이의 범위 값으로 변환(음수 값이 있으며 -1에서 1값으로 변환)
  • 데이터의 분포가 가우시안 분포가 아닐 경우에 적용
from sklearn.preprocessing import MinMaxScaler

min = MinMaxScaler()
min.fit(df)
iris_scaled = min.transform(df)

# MinMaxScaler 작업시 스케일 변환된 numpy ndarray 형식으로 반환돼 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(data = iris_scaled, columns = iris.feature_names)


print('feature들의 최소값')
print(iris_df_scaled.min())

print('\n feature들의 최대값')
print(iris_df_scaled.max())

 

4. 학습 데이터와 테스트 데이터의 스케일링 변환 시 유의점

  • 학습 데이터로만 fit을 수행해야하며, 테스트 데이터에는 학습데이터에서 fit()을 수행한 결과를 transform()해야함
  • 만약 학습, 테스트 값 둘다 fit()을 진행하게 된다면 서로 다른 원본 값이 동일한 값으로 변할 수도 있음
  • 머신러닝 모델은 학습 데이터를 기반으로 학습이 되기 때문에 반드시 test 데이터는 학습 데이터의 기준에 적용되어야함
from sklearn.preprocessing import MinMaxScaler

train_array = np.arange(0, 11).reshape(-1 ,1)
test_array = np.arange(0, 6).reshape(-1 ,1)

min_scaler = MinMaxScaler()

min_scaler.fit(train_array)
train_scaled = min_scaler.transform(train_array)
print('원본 train_array 데이터: ', np.round(train_array.reshape(-1), 2))
print('Scaled된 train_array 데이터: ', np.round(train_scaled.reshape(-1), 2))


test_scaled = min_scaler.transform(test_array)
print('원본 test_array 데이터: ', np.round(test_array.reshape(-1), 2))
print('Scaled된 test_array 데이터: ', np.round(test_scaled.reshape(-1), 2))

  • 가능하다면 전체 데이터의 스케일링을 적용한 뒤에 학습과 테스트 데이터 분리

 

05. 사이킷런으로 수행하는 타이타닉 생존자

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

# 타이타닉 데이터는 kaggle에서 다운
df = pd.read_csv('각자 파일 경로/train.csv')
df

 

5 - 1. NULL값 채우기

df['Age'].fillna(df['Age'].mean(), inplace = True)
df['Cabin'].fillna('N', inplace = True)
df['Embarked'].fillna('N', inplace = True)

df.isnull().sum()

 

5 - 2. 값 분포 확인

print('Age 컬럼의 값 분포 \n', df['Age'].value_counts())
print('Cabin 컬럼의 값 분포 \n', df['Cabin'].value_counts())
print('Embarked 컬럼의 값 분포 \n', df['Embarked'].value_counts())

 

  • Cabin 속성에서 중복이 발생하기 때문에 앞글자만 추출
df['Cabin'] = df['Cabin'].str[:1]
print(df['Cabin'].head())

 

5 - 3. 중간확인 - 어떤 유형의 승객 생존 확률이 높은지

df.groupby(['Sex', 'Survived'])['Survived'].count()

 

sns.barplot(x = 'Sex', y = 'Survived', data = df)

 

sns.barplot(x = 'Pclass', y = 'Survived', hue = 'Sex',data = df)

 

 

# 입력 age에 따른 구분 값을 반환하는 함수 설정. DataFrame의 apply lambda 식에 사용

def get_category(age):
  cat = ''
  if age <= -1: cat = 'Unkown'
  elif age <= 5: cat = 'Baby'
  elif age <= 12: cat = 'Child'
  elif age <= 18: cat = 'Teenager'
  elif age <= 25: cat = 'Student'
  elif age <= 35: cat = 'Young Adult'
  elif age <= 60: cat = 'Adult'
  else : cat = 'Elderly'

  return cat

# 막대 그래프의 크기 설정
plt.figure(figsize = (10, 10))

# X축의 값을 순차적으로 표현하기 위한 설정
group_names = ['Unkown','Baby','Child','Teenager','Student','Young Adult','Adult','Elderly']

# lambda 식에 위헤서 생성한 get_category() 함수를 반환값으로 지정
# get_category(x)는 입력값으로 'Age' 칼럼 값을 받아서 해당하는 cat 반환

df['Age_cat'] = df['Age'].apply(lambda x : get_category(x))
sns.barplot(x = 'Age_cat', y = 'Survived', hue = 'Sex', data = df, order = group_names)
df.drop('Age_cat', axis = 1, inplace = True)

# 문자열 LabelEncoder화

from sklearn.preprocessing import LabelEncoder
label = LabelEncoder()

def encode_features(dataDF):
  features = ['Cabin', 'Sex','Embarked']
  for i in features:
     le= label.fit(dataDF[i])
     dataDF[i] = le.transform(dataDF[i])

  return dataDF

df = encode_features(df)
df.head()

print(df['Cabin'].value_counts())

 

5 - 4. EDA 함수 총정리

def fillna(df):
  df['Age'].fillna(df['Age'].mean(), inplace = True)
  df['Cabin'].fillna('N', inplace = True)
  df['Embarked'].fillna('N', inplace = True)
  df['Fare'].fillna(0, inplace = True)
  return df


def drop_features(df):
  df.drop(['PassengerId','Name','Ticket'], axis = 1, inplace = True)
  return df


def format_features(df):
  features = ['Cabin', 'Sex','Embarked']
  for i in features:
     le= label.fit(df[i])
     df[i] = le.transform(df[i])

  return df


def transform_features(df):
  df = fillna(df)
  df = drop_features(df)
  df = format_features(df)
  return df

 

5 - 5. 데이터 재로드 후 전처리 함수 적용

import warnings
warnings.filterwarnings('ignore')

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

df = pd.read_csv('개인 파일 경로/train.csv')

df = transform_features(df)

X = df.drop(columns = ['Survived'])
y = df[['Survived']]

X_train, X_val, y_train, y_val = train_test_split(X, y, test_size = 0.2, random_state = 11)

dt_clf = DecisionTreeClassifier(random_state = 11)
rf_clf = RandomForestClassifier(random_state = 11)
lr_clf = LogisticRegression()

# DecisionTreeClassifier의 학습 / 예측 / 평가
dt_clf.fit(X_train, y_train)
predict_1 = dt_clf.predict(X_val)
print('DecisionTreeClassifier 정확도 : ' , accuracy_score(y_val, predict_1))

# RandomForestClassifier 학습 / 예측 / 평가
rf_clf.fit(X_train, y_train)
predict_2 = rf_clf.predict(X_val)
print('RandomForestClassifier 정확도 : ' , accuracy_score(y_val, predict_2))

# LogisticRegression 학습 / 예측 / 평가
lr_clf.fit(X_train, y_train)
predict_3 = lr_clf.predict(X_val)
print('LogisticRegression 정확도 : ' , accuracy_score(y_val, predict_3))

 

5 - 6. 교차 검증 - KFold, cross_val_score(), GridSearchCV / 폴드 수 = 5개

5 - 6 - 1. KFold

from sklearn.model_selection import KFold


def exec_kfold(clf, folds = 5):
  kfold = KFold(n_splits = folds)
  scores = []

  # KFold 교차 검증 수행
  for iter_count, (train_index, test_index) in enumerate(kfold.split(X)):
    # X 데이터에서 교차 검증별로 학습과 검증 데이터를 가리키는 index 생성
    X_train, X_val = X.values[train_index], X.values[test_index]
    y_train, y_val = y.values[train_index], y.values[test_index]

    clf.fit(X_train, y_train)
    predictions = clf.predict(X_val)
    accuracy = accuracy_score(y_val, predictions)

    scores.append(accuracy)
    print('교차 검증 {0} 정확도: {1:.4f}'.format(iter_count, accuracy))
  

  mean_score = np.mean(scores)
  print('평균 정확도: {0:.4f}'.format(mean_score))

exec_kfold(dt_clf, folds = 5)

 

5 - 6 - 2. cross_val_score()

  • KFold와 성능 차이가 있는 이유는 StratifiedKFold를 사용해 폴드 세트를 구분하기 때문이다.
from sklearn.model_selection import cross_val_score

scores = cross_val_score(dt_clf, X, y, cv = 5)
for iter_count, accuracy in enumerate(scores):
  print("교차 검증 {0} 정확고 : {1:.4f}".format(iter_count, accuracy))

print("평균 정확도 : {0:.4f}".format(np.mean(scores)))

 

5 - 6 - 3. GridSearchCV

from sklearn.model_selection import GridSearchCV

parameters = {'max_depth' : [2, 3, 5, 10],
              'min_samples_split' : [2, 3, 5],
              'min_samples_leaf' : [1, 5, 8]}

grid_clf = GridSearchCV(dt_clf, param_grid = parameters, scoring = 'accuracy', cv = 5)
grid_clf.fit(X_train, y_train)

print("최적의 파라미터 : ", grid_clf.best_params_)
print("최고의 정확도 : {0:.4f}".format(grid_clf.best_score_))

best_clf = grid_clf.best_estimator_

# GridSearchCV의 최적 하이퍼 파라미터로 학습된 Estimator로 예측 및 수행 평가 수행
dpredictions = best_clf.predict(X_val)
accuracy = accuracy_score(y_val, dpredictions)

print('테스트 세트에서의 정확도 : {0:.4f}'.format(accuracy))


 

 

03. 데이터 전처리.ipynb

Colaboratory notebook

colab.research.google.com

참고자료

 

파이썬 머신러닝 완벽 가이드 - YES24

『파이썬 머신러닝 완벽 가이드』는 이론 위주의 머신러닝 책에서 탈피해 다양한 실전 예제를 직접 구현해 보면서 머신러닝을 체득할 수 있도록 만들었다. 캐글과 UCI 머신러닝 리포지토리에서

www.yes24.com

 

 

728x90
반응형
LIST