본문 바로가기

AI가 뭐길래 왜 어려운 거죠?

[ML] Preprocessing_ModelTuning(ft.아무_생각_없음)

느낀 점 

히이이이이ㅣㅣ 아무 생각 없다

 


Section2_Sprint2_Note3&Note4
  • Preprocessing
    • 특성과 전처리의 관계
    • 결측치 처리
    • 수치형 변수 전처리
    • 범주형 변수 전처리
  • Model Tuning
    • 하이퍼파라미터 튜닝
    • 특성 선택

요약 : 전처리 과정이 제일 복잡하고도 복잡하다.
  • 특성과 전처리의 관계
    • 각기 다른 모델 유형에 따른 각기 다른 전처리 특성
    • 선형 회귀 기반 모델 (LInear / Logistic Regression)등 → 대수적 연산으로 예측이 이루어지는 경우
    • ** 대수적 연산 : y = a*x + b 
      1. 입력 특성들의 크기 / 범위 / 분포에 영향을 받는다. 
        • 입력 값 자체가 직접 대수적 연산에 사용되므로, 입력 값들의 대소관계 뿐만 아니라 값의 분포나 크기, 범위 자체도 모델의 성능에 직접적인 영향을 준다. 
        • 입력 값(특성)들을 변환(표준화, 스케일링 등)하여 모델의 성능이 가장 높은 분포와 범위로 바꿔준다. 
        • 트리 기반 모델과 가장 큰 차이점이다. 
      2. 결측치 반드시 채워야 한다. 
        • 정상적인 수치형 값이 아닌 값들이 하나라도 포함되어 있으면 학습 및 예측이 이루어지는 대수적 연산이 불가능해진다.
        • 모든 값들이 수치형이고 결측치가 아닌 값들로 바꿔줘야 한다.  
      3. 비선형적 특성이나 특성 간 상호작용 등으로 미리 처리해야 한다. 
        • 각 입력 특성이 독립적으로 타겟과 선형적 관계가 있다고 가정하는 모델이므로 비선형적 특성들에 대해서 미리 선형관계를 갖도록 값들을 변환해줘야 한다. 
        • 예시) 어떤 특성의 log값 또는 sqrt값이 타겟 특성과 선형일 것으로 예상되는 경우, 해당 특성에 log또는 sqr를 씌우는 전처리 필요
    • 트리 기반 모델 (Decision Tree / RandomForest, GBDT 등) → 매 단계마다 특정 특성의 cut-line을 정해주어 학습
      1. 입력 특성들의 크기 / 범위 / 분포에 영향을 받지 않는다. 
        • 예측 시 cut-line에 따라서 데이터를 분기해주는 모델이므로, 입력 특성들의 값/분포에 영향 받지 않고 대소관계에만 영향을 받는다. 
        • 수치의 대소 관계에 영향을 주지 않는 전처리 과정도 모델의 성능에 전혀 영향을 주지 않는다. 
      2. 결측치를 반드시 채울 필요없다. 
        • 라이브러리의 구현에 따라 다르지만**, 기본적으로 결측 상태 그래도 결측치를 처리할 수있다. 
        • 결측치 집단을 하나의 집단으로 분기할 수 있기 때문이다. 
        • 결측치를 비현실적인 값으로 채워주더라도 모델이 잘 작동한다.
        • ** xgboost는 해당 방법을 디폴트로 지원하지만, sklearn은 결측치를 모델 내에서 자체 처리하지 않음 
      3. 특성과 타겟 간의 비선형적 관계나 특성 간 상호작용이 자동 반영될 수 있다.
        •  해당 모델을 특성과 타겟 간의 선형적 관계를 가정하지 않으므로 관계를 가정하는 전처리를 하지 않아도 여러 형태의 관계를 유연하게 모델링할 수 있다.
        • 여러 번 분기해 내려가는 과정에서, 각 특성들 간의 상호작용이 자동 반영된다.
        • 예시) 열이 38도 이상이고 밀접접촉자가 있는 데이터의 경우만 코로나 확진하는 분류 모델 제작가능 

 

  • 결측치 처리
    • 어떤 상황에는 특정 값이 결측되었다는 사실 자체가 어떠한 정보를 줄 수 있다.
    • 트리 기반 모델은 기본적으로 결측치 핸들링 필요없지만, 대수적 연산으로 구성된 모델의 경우 결측치 처리 필수
    • 단일 대표값으로 채우기
      • 각 데이터의 결측치가 해당 데이터의 다른 특성들과 전혀 무관하게 랜덤으로 발생했다는 가정으로
      • 데이터가 충분히 크거나 데이터 크기에 비해 결측치가 많지 않을 때(10% 내외), 가장 쉬운 선택지로 사용 가능
      • sklearn의 SimpleImputer(strategy= mean/median/most_frequent/constant)
    • 다른 특성들로부터 조건부로 채우기
      • 미리 알고 있는 특성 간의 상관관계 정보 또는 데이터로부터 파악한 정보 기반으로 결측치를 조건부로 채운다.
      • 예시) 키의 결측치를 해당 성별의 평균치로 채우거나, 몸무게의 결측치를 해당 성별과 유사한 키를 갖는 사람들의 평균 몸무게로 채운다. 
      • 데이터가 충분하지 않을 수록 결측치를 채워주는 것이 중요하다. 이의 경우, 데이터 자체 또는 데이터 설명서를 꼼꼼히 파악하여 특정 특성에서의 결측 발생이 다른 특성과 영향을 주고받지는 않는지 면밀한 검토 필요
from sklearn.impute import SimpleImputer # 단일 대표값 채우기
imputer = SimpleImputer(strategy='median')
imputer.fit_transform(x_train)

 

  • 수치형 변수 전처리 (Scaling & Normalization)
    • 수치형 특성 값들의 분포 스케일만 변화시키는 변환 : Min-Max Scaling / Standardization
    • Min-Max Scaling
      • 모든 값들을 0과 1 사이의 값으로 스케일링한다.
      • 해당 특성의 이상치가 정상치로부터 크게 벗어나지 않았을 때 또는 특성 값들의 분포가 전체 범위에서 균등 분포(uniform distribution)을 보일 때 주로 사용함
      • 예시) 사람들의 나이 정보, DL에서의 이미지 데이터의 경우
      • 변환 후, 평균이 0이 되지 않고 일부 너무 크거나 작은 이상치의 영향을 크게 받는 문제가 존재함

  • Standardization
    • 해당 특성의 평균을 0, 표준편차를 1로 조정한다. 
    • Min-Max보다 이상치에 덜 민감하여 해당 특성의 이상치 분포를 정확히 파악하기 어려울 때 사용함
    • 값들을 평행이동 및 크기 조정하여 평균과 표준오파만 조정해줄 뿐, 분포 자체를 정규분포의 모양으로 바꿔주지 않음

  • 수치형 특성 값들의 분포 스케일과 분포의 형태까지도 변화시키는 변환 : Clipping / Log / Bucketing / Rank 
  • 형태를 변화시킨다는 것은 각 값들 간의 상대적인 거리들까지도 변화시킬 수 있다는 것이다. 
  • Clipping
    • 특정 범위를 넘어서는 값들을 해당 경계값으로 변환한다. 
    • 정상 범위에서 비정상적으로 값이 튀는 이상치가 있을 때 시도해볼 수 있는 기법
    • 분포 전체의 모양을 변환시키지는 않으며 이상치에만 영향을 준다. 

  • Log 변환
    • 다수의 값들이 굉장히 제한된 범위 내에서만 존재하고 특정 값들이 굉장히 큰 형태의 분포에서 자주 적용됨
    • 예시) 인터넷 기사의 댓글 수 분포 - 소수의 기사에만 많은 댓글을 얻는다. 
    • 모든 값들이 음수가 아닐 때만 적용 가능함. 음수는 적절한 값을 더하여 양수로 우선 변환해줘야 적용 가능함 

  • Bucketing
    • 수치형 변수를 범주형과 같이 다루는 방법
    • 각 값들이 속하는 범위를 미리 지정해주고, 각 값들이 어떤 범위에 속하는지를 숫자로 나타내는 방법
    • (quantile) 각 범위 내에 동일한 수의 데이터가 들어가도록 범위를 쪼갤 수 있다. 
    • (uniform) 각 범위를 동일한 간격을 갖도록 쪼갤 수 있다. 
    • 그 외, 기존 사전 지식에 따라 범위를 쪼갤 수 있다. 
    • 특정 특성이 중요하나 타겟과 비선형 관계를 가질 것으로 예측될 때, 범위를 나누어 선형관계를 갖도록 한다. 혹은 OneHotEncoding 형태로 변경하여 완전히 범주형 데이터처럼 다룰 수도 있따. 
    • 특정 특성에 댛나 사전지식이  있을 경우에도 효과적이다. 

  • Rank 변환
    • 값들이 해당 값들의 전체 데이터에서의 순위 혹은 percentile로 변환한다.
    • 값들 간의 거리 정보를 복구할 수 없는 형태로, 대소 관계만 남긴다. 
    • 이상치에 민감하지 않고 어떠한 분포를 갖는 특성이든 균등 분포(uniform distribution)로 변환시켜 준다.
    • 모든 데이터를 가지고 있는 경우, pandas의 rank 기능 이용
    • pandas/rank는 기존에 없던 데이터가 들어왔을 때, 변환이 불가하므로 sklearn의 QuantileTransformer 사용
    • 특성 값의 분포에 따라 mapping의 형태가 달라지지만, 변환된 결과는 결국 균등 분포를 띄게 된다. 

  • 모델 특성에 따른 수치형 변수 변환이 적용된다. 즉, 대수 연산으로 학습 및 예측이 이뤄지는 모델의 경우 수치형 변수 변환이 필요하지만, 트리 기반 모델의 경우 각 분할 단계별로 특정 특성이 특정 범위 내에 있으면 동일한 집단으로 간주하기 때문에 이와 같은 전처리를 해주지 않아도 잘 학습한다. 
from sklearn.preprocessing import MinMaxScaler			# MinMaxScaler
scaler = MinMaxScaler()
scaler.fit_transform()
from skelarn.preprocessing import StandardScaler		# StandardScaler
df['특성명'] = df['특성명'].clip(lower=0, upper=150)		# clipping
df['특성명'] = np.loglp(df['특성명'])				# Log 변환
from sklearn.preprocessing import KBinsDiscretizer		# Bucketing
kbd = KBinsDiscretizer(n_bins=8, encode='ordinal', strategy='uniform')
kbd.fit_transform()
from sklearn.preprocessing import QuantileTransformer		# sklearn/rank 변환
df['특성명'] = df['특성명'].rank(pct=True)			# pandas/rank 변환
# pct=True : percentile 반환 / False : rank 자체 반환

 

  • 범주형 변수 전처리 (Encoding)
    • 수치형 변수로 바꿔주는 전처리 과정
    • OneHotEncoding
      • 각 범주형 특성 값들을 각 값들에 대해 (해당 여부)의 1과 0 값으로 인코딩
      • 명목형 변수는 해당 방식으로 통해 변환해줄 수 있다. 
      • 카디널리티가 너무 클 경우, 차원이 너무 커지므로 적절하지 못하다.
      • 트리 기반 모델에서는 특성의 정보를 분산시키고 비효율적인 트리를 만들 수 있으므로 잘 사용하지 않는다. 
    • OrdinalEncoding
      • 각 범주형 특성 값들을 단순히 서로 다른 정수값들로 인코딩
      • 순서형 변수는 해당 방식을 통해 변환해줄 수 있다.
      • 각 범주형 데이터가 양적 대소 관계를 갖는 것 처럼 간주되므로 선형/로지스틱 회귀 모델의 명목형 변수에는 잘 사용하지 않는다. 
      • 트리 기반 모델에서는 분기 과정을 통해 양적 대소 관계가 점차 사라지므로, OneHot보다 효율적으로 작동됨
    • CountEncoding(Frequency Encoding)
      • 각 카테고리의 등장 빈도가 중요한 정보가 되는 데이터셋의 경우, 각 카테고리 값들의 등장 빈도로 범주형 값을 대체한다. 
      • 구현이나 해석이 쉬우며, 특성의 차원을 늘리지 않아도 되고 특성 빈도에 대한 정보를 모델에게 명시적으로 제공할 수 있다. 
      • 동일한 빈도를 갖는 서로 다른 특성값이 구분되지 않고, 학습이 완료된 후에 입력으로 들어로는 새로운 특성값에 대해 대응하기 어렵다. 
    • TargetEncoding(Mean Encoding)
      • 각 범주형 특성 값들을 해당 특성을 갖는 데이터의 타겟 값의 평균으로 인코딩하는 방법
      • 해석이 쉬우며 특성의 차원을 늘리지 않아도 되고, 특성값과 타겟값의 직접적인 관계를 모델링하여 모델에게 중요한 정보를 제공할 수 있다. 
      • 동일한 평균 타겟 값을 갖는 서로 다른 특성값이 구분되지 않고, 과적합 문제가 발생할 수 있다. 
      • 과적합의 문제를 해결하기 위해, 특성별 조겁부 타겟 평균 값뿐만 아니라 해당 특성의 출현 빈도까지 함께 고려하여 범주형 값을 인코딩 한다. 
!pip3 install category_encoders==2.5.1
from category_encoders import OneHotEncoder, OrdinalEncdoer
onehot_encoder = OneHotEncoder()
ordinal_encoder = OrdinalEncoder()
onehot_encoded = onehot_encoder.fit_transform()
ordinal_encoded = ordinal_encoder.fit_transform()
from category_encoders import CountEncoder
from category_encoders import TargetEncoder

 

< 표 요약 >

 

1. 결측치 처리

  단일 대표값 다른 특성들로부터 조건부
다른 특성들과의 관계 전혀 무관하게 랜덤으로 발생 미리 알고 있는 특성 간의 상관관계 정보 또는 데이터로부터 파악한 정보 기반
데이터 크기 데이터가 충분히 크거나 데이터 크기에 비해
결측치가 많지 않을 때(10% 내외)
데이터 크기가 부족한 경우 
함수 선언 from sklearn.impute import SimpleImputer 데이터 자체 또는 설명서를 꼼꼼히 파악하여
특정 특성의 결측치와 다른 특성과의 관계(영향) 검토 필요
예시 mean / median / most_frequent / constant 키의 결측치를 해당 성별의 평균치로 채우거나, 
몸무게의 결측치를 해당 성별과 유사한 키를
갖는 사람들의 평균 몸무게로 대체

 

2. 수치형 변수 전처리

    (1) 값 분포의 스케일만 변화시키는 변환

  MinMaxScaling Standardization
함수 선언 from sklearn.preprocessing import MinMaxScaler from sklearn.preprocessing
import StandardScaler
방법 모든 값들을 0과 1사이의 값으로 스케일링 해당 특성의 평균을 0, 표준편차를 1로 조정
경우 해당 특성의 이상치가 정상치로부터
크게 벗어나지 않았을 때,또는
특성 값들의 분포가 전체 범위에서
균등 분포를 보일 때 주로 사용
해당 특성의 이상치 분포를
정확히 파악하기 어려울 때, 또는 
파악하기 이전에 주로 사용
예시 사람들의 나이 정보, DL에서의 이미지 데이터 -
장점 간단히 적용할 수 있음 -
단점 변환 후, 평균이 0이 되지 않고 일부 너무 크거나
작은 이상치의 영향을 크게 받음
값들을 평행이동 및 크기 조정하여
평균과 표준편차만 조정해줄 뿐,
분포 자체를 정규분포의 모양으로
바꿔주지 않음

    (2) 값 분포의 스케일과 형태를 변화시키는 변환

  Clipping Log 변환 Bucketing Rank 변환
함수 선언 df['특성명'].clip() np.loglp(df['특성명']) from sklearn.preprocessing 
import KBinsDiscretizer
from sklearn.preprocessing 
import QuantileTransformer /
df['특성명'].rank()
방법 특정 범위를 넘어서는 
값들을 해당 경계값으로
변환
skewed된 분포를
정규 분포로 변환
수치형 변수를 범주형과 같이 다루는 방법 /
각 값들이 속하는 범위를 미리 지정하여 각 값들이 어떤 범위에 속하는지를 숫자로 나타내는 방법
값들을 해당 값들의 전체 데이터에서의 순위 혹은 percentile로 변환
경우 정상 범위애서
비정상적으로 값이 
튀는 이상치가 있을 때
다수의 값들이 굉장히 제한된 범위 내에서만 존재하고 특정 값들이 굉장히 큰 형태의 분포의 경우 특정 특성이 굉장히 중요하나 타겟과 비선형 관계로 예측될 때, 또는
특정 특성에 대한
사전지식이 있을 경우

모든 데이터를 가진 경우
pandas/rank,
새로운 데이터가 들어올
가능성이 있는 경우 
sklearn/QuantileTransformer
비고 분포 전체의 모양을
변환시키지는 않으며
이상치에만 영향을 줌
모든 값들이 음수가 아닐 때만 적용 가능하여
음수는 적절한 값을 더해
양수로 우선 변환해야 
적용 가능함 
범위 지정 방법 :
(quantile) 각 범위 내 동일한 수의 데이터가 들어가도록,
(uniform) 각 범위를 동일한 간격을 갖도록,
(그 외) 기존 사전 지식에
따라서
범위를 쪼갤 수 있음
값들 간의 거리 정보들이
복구할 수 없는 형태로,
대소 관계만 남김 /
이상치에 민감하지 않고
어떠한 분포를 갖는
특성이든 균등 분포
(uniform distribution)로
변환시켜 줌

 

3. 범주형 변수 전처리

  OneHotEncoding OrdinalEncoding CountEncoding TargetEncoding
함수 선언 from category_encoders
import OneHotEncoder
from category_encoders
import OrdinalEncoder
from category_encoders
import CountEncoder
from category_encoders
import TargetEncoder
방법 각 범주형 특성 값들을 각 값들에 대해 (해당 여부)의 1과 0으로 인코딩 각 범주형 특성 값들을 단순히 서로 다른 정수값으로 인코딩 각 카테고리의 등장 빈도가 중요한 데이터셋의 경우 각 카테고리 값들의 등장 빈도로 범주형 값 대체 각 범주형 특성 값들을
해당 특성을 갖는 데이터의 타겟값의 평균으로 인코딩
변환 명목형 변수 순서형 변수 - -
사용 모델 선형 / 로지스틱 회귀 트리 기반 모델 - -
비고 카디널리티가 너무 클 경우에는 차원이 커지기 때문에 잘 사용하지 않음 각 범주형 데이터가 양적 대소 관계를 갖는 것처럼 간주되기 때문에 분기를 통해 대소관계가 점차 사라지는 트리 기반 모델에 적합 (장점) 구현/해석 쉬움,
특성 차원 늘리지 않음, 특성 빈도에 대한 정보를 모델에게 명시적으로
제공
(단점) 동일한 빈도를
가지는 서로 다른 특성값 구분안됨, 학습 완료 후 입력된 새로운 특성값에 대응하기 어려움
(장점) 해석 쉬우며, 특성 차원을 늘리지 않음,
특성과 타겟 값 간의 직접적인 관계를 모델링하여
모델에게 중요한 정보 제공
(단점) 동일한 평균 타겟값을 갖는 서로 다른 특성 값이 구분되지 않음, 과적합 문제 발생 가능 - 해결하기 위해 해당 특성의 출현
빈도까지 함께 고려하여
인코딩


  • Hyper-parameter Optimization (하이퍼파라미터 튜닝)
    • 모델의 성능을 향상시키기 위한 옵션
    • 기본 요소
      1. 튜닝 대상 모델 
      2. 탐색할 하이퍼파라미터의 범위
      3. 설정한 범위 내에서 하이퍼파라미터 조합을 선택하는 방법
      4. 검증 방법
      5. 스코어링 메트릭(scoring metric)
    • 직접 튜닝
      • 데이터를 이해하고 있는 개발자가 각 하이퍼파라미터의 임팩트에 대한 본인의 경험을 바탕으로 직접 튜닝
      • 데이터 및 모델의 특성에 대한 개발자의 직관과 통찰을 얻기 위한 필수 과정
      • 현 데이터에 대한 과적합 여부 판단, 각 특성 간의 상호작용 등의 충분한 반영도 확인하여 하이퍼파라미터 조정
        1. 대부분을 디폴트값으로 두고, 3개 이내의 중요 하이퍼파라미터부터 값을 바꿔가며 모델 성능 변화 관찰
        2. 모델의 복잡성과 관련되어 있으므로 과적합/과소적합 여부 확인하여 복잡성을 조절한다는 생각으로 튜닝 
    • 컴퓨터 튜닝
      • Exhaustive Grid Search
        • 범위 내에서 모든 조합에 대해 모델 학습, 그 중 가장 metric이 좋은 조합 선택
        • 성능에 대한 각 하이퍼파라미터의 영향 직관적 이해
        • 모든 조합 고려하므로 조합의 수가 크다. 이때 튜닝할 하이퍼파라미터의 수가 많을 경우 비효율적
      • Randomized Search
        • 범위 내에서 랜덤으로 몇 개의 조합 선택, 그 중 가장 metric이 좋은 조합 선택
        • 탐색의 횟수 지정 필요, 하이퍼파라미터의 수가 많고 범위가 넓더라도 탐색 가능
        • 모든 조합에 대한 검증이 아니므로 가장 이상적인 조합의 발견이 어려울 수 있음
      • Bayesian Search
        • 범위 내에서, 이전 탐색한 조합들의 성능 기반으로 성능이 잘 나오는 조합 중심으로 확률적 탐색
        • 랜덤 서치보다 상대적으로 효율적이며, 한정된 자원 내에서 좋은 하이퍼파라미터 조합 발견 가능성 ↑
        • sklearn에서 제공X, hyperpot 등의 라이브러리 추가 사용
from sklearn.model_selection import GridSearchCV
grid_search.best_params_	# 최적 하이퍼파라미터
grid_search.best_score_		# 최적 scoring metric
grid_search.cv_results_		# 각 하이퍼파라미터 조합에 따른 모델 나열

from sklearn.model_selection import RandomizedSearchCV
randomized_search.

!pip3 install hyperopt
from hyperopt import hp
from hyperopt import fmin, tpe, Trials, STATUS_OK
from skelarn.model_selection import cross_val_score
import numpy as np

 

  • 특성 선택
    • 충분하지 않은 데이터로 모델을 생성하여 예측 → 불필요한 특성이 과적합 유발 
    • 불필요한 특성을 제거 → 모델 학습 및 추론 과정에서의 효율 향상 
    • 직관 기반 특성 선택
      • 각 특성에 대한 이해도가 있는 개발자가 불필요 특성을 선제적으로 배제하는 방법
      • 선제적 제거로 모델 학습 시간 단축 및 효율성 향상 기대
    • 특성 중요도 기반 특성 선택
      • 모델 학습 이후, 각 특성의 모델 예측에 대한 중요도 기반 특성 선택 방법
      • 특성 중요도에 대한 수치값을 얻어 특정 값(threshold) 아래의 중요도를 갖는 특성 제거
      • 선형 회귀 기반 모델 - coefficient / 트리 기반 모델 - feature_importance 

 

< 표 요약 >

 

1. 하이퍼파라미터 튜닝 - 컴퓨터 튜닝

  GridSearch RandomizedSearch BayesianSearch
함수 선언 from sklearn.model_selection
import GridSearchCV
from sklearn.model_selection
import RandomizedSearchCV
from hyperopt import fmin, tpe, Trials, STATUS_OK /
from sklearn.model_selection
import cross_val_score /
import numpy as np

방법 범위 내에서 모든 조합에 대해
모델을 학습하고,
그 중 가장 metric이 좋은 조합 선택
범위 내에서 랜덤으로 몇 개의
조합을 선택하고,
그 중 가장 metric이 좋은 조합 선택
범위 내에서 이전 탐색한
조합들의 성능을 기반으로
성능이 잘 나오는 조합들을
중심으로 확률적 탐색
장점 성능에 미치는 각 하이퍼파라미터의 영향을 직관적으로 이해하기 쉬움 탐색의 횟수를 지정하여 검증하고자 하는 하이퍼파라미터의 수가 많고 범위가 넓더라도 탐색 가능 상대적으로 효율적으로 탐색하여 한정된 자원 내에서 좋은 조합을 발견할 가능성이 더 높음
단점 검증해야 할 조합의 수가 굉장히 크므로, 튜닝할 하이퍼파라미터의 수가 많을 때는 비효율적임 모든 조합에 대해 검증하지 않아 가장 이상적인 조합 발견이 어려울 수 있음 sklearn에서는 해당 기능을 제공하지 않아 hyperopt 등의 라이브러리 추가 설치 필요

 

2023.04.15(토)