AI_STUDY/머신러닝

머신러닝 _ 04_데이터 전처리

SO__OS 2022. 7. 1. 01:18
플레이데이터 빅데이터캠프 공부 내용 _ 6/29 30

머신러닝 _ 04_데이터 전처리

1. 데이터 전처리 

 : 모델을 학습시키기 전에 처리시키는 것
    = > 학습이 가능한 혹은 학습이 더 잘되도록 dataset 으로 만들어주기 
    
- 공학적 전처리

: 사람들이 연구한 전처리. 항상 일정한 퍼포먼스를 보여줌.

  어떤 feature 인지, 어떤 타입인지 등에 따라 전처리 방식이 정해져 있다.

 

- 도메인 지식에 의한 전처리 

우리가 해결해야 할 업무 즉, 특정 분야에 대한 도메인 지식에 맞는 전처리가 필요하다.

  이를 위해 그 분야에 대한 지식을 알아야 전처리를 할 수 있다.



1) 학습이 가능한(무조건해줘야함) : 학습을 못 시키게 하는 값들이 있다. 
    - 머신러닝은 수학 함수 처리이다. 모든 모델은 숫자만을 처리할 수 있기에 이에 대하 전처리가 필요할 것이다.
            
2) 학습이 잘 되도록 하는 처리 : 패턴을 잘 찾을 수 있게

 

 

2. 결측치 처리

2.1 결측치 ( Not Available  -  NA, NaN, None, Null )

    : 수집하지 못한 값. 모르는 값.


- 머신러닝 알고리즘은 데이터셋에 결측치가 있으면  (러신러닝 모델 학습은 수식 처리 함수이기 때문에)

  학습이나 추론을 하지 못하기 때문에(에러) 적절한 처리가 필요하다.
        - ex) NaN + 30 = NaN  - - > 학습 불가

 

 - 결측치 처리는 데이터 전처리 단계에서 진행한다.

 

2.2 결측치 처리방법

 

    1) 제거 (열단위 or 행단위 => 축단위로 같은 열, 행인 데이터 모두 제거) 
        - 행단위를 기본으로 제거하는데, 특정 열에 결측치가 너무 많을 경우 열을 제거한다.
        - 결측치 처리 방법 중 가장 좋은 방법은 제거이다. 

          데이터 포인트가 많다면 제거한다고 패턴 찾는데 문제되지 않는다.

          하지만, 데이터가 적다면 문제가 되기에 다른 값으로 대체해야 한다. 

 

    2) 다른 값으로 대체
        - 차선이다. 이 처리는 정확도를 떨어뜨릴 것이다.


        - 가장 가능성이 높은 값으로 대체
              - 수치형: 평균, 중앙값, 
              - 범주형: 최빈값(출연 빈도가 가장 많은 값)
              - Feature의 결측치를 예측하는 머신러닝 알고리즘을 모델링해서 추론한 값

                 (이렇게 까지 하면 돈 많이 들어서 보통 평균, 중앙값, 최빈값로 대체한다.)


        - 결측치 자체를 표현하는 값을 만들어서 대체 
              - 나이에  - 1 , 혈액형에 ? 와 같이

                그 Feature가 가질 수 없는 값으로 결측치를 표현하는 값을 정한 뒤 대체한다.

 

 

3. 이상치 처리

- 의미 그대로 이상한 값, 튀는 값, 패턴을 벋어난 값으로 그 Feature를 가지는 대부분의 값들과는 동떨어진 값을 말한다.

 

(1) 오류값 
    - 잘못 수집 된 값.


    - 처리    
        - 무조건 결측치 처리 제거한다.

 

(2) 극단치(분포에서 벋어난 값)
    - 정상적이 값이지만 다른 값들과 다른 패턴을 가지는 값.
    - 일반적으로 극단적으로 크거나 작은 값


    - 처리
        1. 그 값을 그대로 유지한다.
        2. 결측치 처리 제거한다.
        3. 다른 값으로 대체한다.
            - 보통 그 값이 가질 수 있는 Min/Max값을 설정한 뒤 그 값으로 변경한다.

 

 

4. Feature 타입 별 전처리

어떤 feature 타입이냐 따라 어떤 전처리를 할 지 정해져 있다. = > 공학적전처리

 

4.1  Feature(변수)의 타입

 

(1) 범주형(Categorical) 변수/이산형(Discrete) 변수 = > 분류 문제


    : 대상값들이 서로 떨어진 값을 가지는 변수.

      대부분 몇 개의 범주 중 하나에 속하는 값들로 구성되어 어떤 분류에 대한 속성을 가진다.


    - 명목(Norminal) 변수/비서열(Unordered) 변수
        - 범주에 속한 값간에 서열(순위)가 없는 변수
        - 성별, 혈액형


    - 순위(Ordinal) 변수/서열(Ordered) 변수
        - 범주에 속한 값 간에 서열(순위)가 있는 변수
        - 성적, 직급

 

 

(2) 연속형(Continuous) 변수 = > 회귀 문제


    :  대상값들이 서로 연속된 값을 가지는 변수를 말한다.

       대상 값은 보통 정해진 범위 안의 모든 실수(범주형과 달리 가질 수 있는 값이 무한대) 이다. 


    - 등간(Interval) 변수
        - 측정 대상의 순서와 측정 대상 간의 간격을 알 수 있는 변수로, 그 사이의 간격이 같은 변수를 말한다.
        - 0의 값이 특정의미로 사용되는 값으로 '0이 절대적인 0의 값이 아닐' 수 있다. 
        - 예) 온도 : 온도에서 0은 절대적 0의 값이 아니라 얼음이 어는 빙결점의 온도를 의미한다. 

                           0 이 온도가 없다라는 의미가 아니다.


    - 비율(Ratio) 변수
        - 측정 대상의 순서와 측정 대상 간의 간격을 알 수 있는 변수로, 그 사이의 간격이 같은 변수를 말한다. 

           (등간변수와 동일)
        - '0이 절대적인 0의 값'으로 사용된다. 
        - 예) 나이, 무게, 거리, 소득

               무게 0kg에서 0은 무게가 없는것. 금액 0원은 돈이 없다는 것

.

5. Feature 타입 별 전처리 : 범주형 데이터 전처리

 

- Scikit-learn의 머신러닝 API들은 

  Feature나 Label의 값들이 숫자(정수/실수)인 것만 처리할 수 있다.  = > 전처리 필요.


    - 모든 머신러닝 알고리즘 모델은 수식으로 되어 있다. 데이터든 정답이든 모두 숫자로만 이뤄져 있다.

      근데 sci 말고 다른 라이브러리 중 문자열을 숫자로 바꿔주는 라이브러리가 있지만,

      Scikit-learn 는 숫자만을 다루는 라이브러리이기에 우리가 전처리 해줘야 한다.

 

  • 범주형 데이터     

- 범주형 변수라고 모두 문자라고 생각하면 안된다. 

     - 범주 자체가 등급 1 ~ 8 등급 ... 숫자로 이뤄져 있을 수 있다.

     - 범주형이 숫자로 표현, 표기 되어 있을 수 있다. 남여를 0 과 1 로 표현


- 실수는 다 연속형이다.

  정수는 연속형일 수도 또 범주형일 수 있다.  어떠한 데이터인지, 어떠한 고유값을 가지고 있는지 찾아봐야 한다.

 

 

  • 범주형 Feature의 처리

- 문자열(str)일 경우 숫자 형으로 변환해야 한다. 

    - 범주형 변수의 경우                          = > 전처리를 통해 정수값으로 변환한다.
    - 범주형이 아닌 단순 문자열인 경우  = > 일반적으로 제거한다.


    - ex) 범주형 변수인 직업, 나이대 등의 데이터는 결과를 예측하는데 영향을 준다.

            그러나, 단순 문자열인 id, 이름 등으로는 패턴이 구분되어 지지 않는다.

            이러한 단순 문자열은 데이터 분석하는데에 필요가 없기에 제거한다. 

 

범주형이라면? 두 가지 전처리 방식을 할 수 있다.

 

(1) Label Encoding

- 숫자의 차이가 모델에 영향을 주지 않는 트리 계열 모델(의사결정나무, 랜덤포레스트)에 적용한다.

(2) One-Hot Encoding 

- 숫자의 차이가 모델에 영향을 미치는 선형 계열 모델(로지스틱회귀, SVM, 신경망)에서 범주형 데이터 변환시 적용한다.

 

 

  • encoding 과 decoding

 - 범주형 Feature == encoding == > 정수값 으로
     원래 값이 뭔지 알아야 하기에 원래 값으로 복원하는 decoding 도 필요. 

- encoding : 원래 값을 다른 형식의 값으로 바꾸는 처리. 
- decoding : 다시 원래 값으로 복원하는 처리.  = > 늘 encoiing 하면 decoding이 필요하다.

 

 

5.1  레이블 인코딩(Label encoding)

: 문자열(범주형) 값을 오름차순 정렬 후 0 부터 1씩 증가하는 값으로 변환

 

- 숫자의 차이가 모델에 영향을 주지 않는

  트리 계열 모델(의사결정나무, 랜덤포레스트)에 적용한다.

 

- 숫자의 차이가 모델에 영향을 미치는 

 트리를 제외한 모든 모델들 선형 계열 모델(로지스틱회귀, SVM, 신경망)에는 사용하면 안된다.

 성능을 떨어뜨릴 수 있다.

    - 값의 차이가 모델이 학습하는 데에 큰 영향을 끼친다.

      우리가 레이블 인코딩 하는 것은 그저 tv 라는 것을 0 기호로 표시를 한 것이다.

      이때는 값의 차이가 의미가 없다. 0~3 이라는 것은 수의 의미가 아닌 그저 기호의 의미인 것이다.

      근데 선형 계열 모델의 경우 값의 차이를 이용해 모델을 학습하기에

      이 레이블의 숫자가 값의 차이로 영향을 줄 수 있다. 


- 원래 값으로 복원하기 위해 decoding이 필요하다. = = > 원래 값이 무엇인지 주황색표처럼 저장되어야 한다.

 

 

 

- estimator : 모델 추론용   transformer : 변환기 전처리용.
        
- 추론하는 방식은 달라도 estimator를 상속받기에 메소드는 동일하다.
    - 즉, 이 클래스를 상속해서 만든 클래스는 하는 일은 다르지만 메소드는 동일하다.

 

(1) 메소드

 

sklearn.preprocessing.LabelEncoder

 

- LabelEncoder() : 변환기(Transformer) 객체 생성

 

- transformer 변환기 전처리용 객체의 메소드들


    - .fit(): 어떻게 변환할 지 학습
    - .transform(): 문자열를 숫자로 변환
    - .fit_transform(): 학습과 변환을 한번에 처리
    - .inverse_transform():숫자를 문자열로 변환. 원래 상태로 변환.
    - .classes_ : 인코딩한 클래스 조회

 

 

(2) 기본 코드

 

- import

from sklearn.preprocessing import LabelEncoder

 

- 변환기(Transformer) 객체 생성 - > LabelEncoder()

encoder = LabelEncoder()

 

- 어떻게 변환할 지 학습

  fit(학습할 대상)   = > 주황색 표 만드는 작업 (고유값 찾아 정렬하여 0 -3 기호 부여 학습)

items=['TV','냉장고','컴퓨터','컴퓨터','냉장고','에어컨','TV','TV'] # 범주형 값들

encoder.fit(items)

 

- 변환 - transform(변환대상)

labels = encoder.transform(items)

 

- 확인

print('인코딩 전 값', items)
print('인코딩 변환값:',labels)
인코딩 전 값 ['TV', '냉장고', '컴퓨터', '컴퓨터', '냉장고', '에어컨', 'TV', 'TV']
인코딩 변환값: [0 1 3 3 1 2 0 0]

 

- 인코딩한 클래스 조회

 

   인코딩 변환값 labels 를 보았을 때, 해당 값이 어떤 class를 뜻하는 지 알 수 없다. 그렇다면 디코딩 또한 할 수 없다.

   이를  encoder.classes_ 로 조회 가능하다.

 

   # ['TV' '냉장고' '에어컨' '컴퓨터']  의  index가  encoding 된 정수

print('인코딩 클래스:',encoder.classes_)

 

- 디코딩

print('디코딩 :',encoder.inverse_transform([1, 0, 2, 0, 1, 1, 3, 3]))
print('디코딩 원본 :', encoder.inverse_transform(labels) ) # [0 1 3 3 1 2 0 0]
디코딩: ['냉장고' 'TV' '에어컨' 'TV' '냉장고' '냉장고' '컴퓨터' '컴퓨터']
디코딩 원본값: ['TV' '냉장고' '컴퓨터' '컴퓨터' '냉장고' '에어컨' 'TV' 'TV']

 

 

(3) 기본 코드 _ 학습할 대상과 변환할 대상이 같은 경우 : fit_transform()

le2 = LabelEncoder()
item_labels = le2.fit_transform(items) # 학습, 변환 같이
item_labels

 

 

(4) 기본 코드 _ 하나의 데이터 셋으로 학습 후 다른 데이터 셋을 변환

 

같은 범주값을 가진 변환할 대상 데이터 셋이 2개가 있다.

    = > 하나의 데이터셋으로 학습시킨 변환기 객체를 가지고 둘 다 변환한다.

items1 = ['TV','냉장고','컴퓨터','컴퓨터','냉장고','에어컨','TV','TV']
items2 = ['TV',"TV",'냉장고']

le3 = LabelEncoder()

# items1로 학습 - > 변환
item_labels1 = le3.fit_transform(items1)
print(le3.classes_)

# items1과 2가 같은 범주값을 가진다. 굳이 다시 학습할 필요 없다. 
# items1 로 학습한 LabelEncoder를 이용해 변환만 한다.
item_labels2 = le3.transform(items2)

 

- 이때, 데이터 셋들은 같은 범주값을 가져야 한다.

 학습할 때 없었던 class 값이 있을 경우에는 Exception (keyError) 발생

 # 핸드폰은 어떻게 바꿔져야 하는지 정의가 되어 있지 않다.
items3 = ['TV','핸드폰']
le3.transform(items3)

 

5.2 원핫 인코딩 (One-Hot encoding)

: N개의 클래스를 N 차원의 One-Hot 벡터로 표현되도록 변환
: 고유값들을 피처(컬럼)로 만들고 정답에 해당하는 열은 1로 나머진 0으로 표시한다..

 

- 숫자의 차이가 모델에 영향을 미치는 선형 계열 모델(로지스틱회귀, SVM, 신경망)에서

 범주형 데이터 변환시 Label Encoding보다 One Hot Encoding을 사용한다.


- DecisionTree 계열의 알고리즘Feature에 0이 많은 경우  (Sparse Matrix라고 한다.)

  성능이 떨어지기 때문에 Label Encoding을 한다.

 

- One-Hot Encoding 변환처리

   1) Scikit-learn

   2) Pandas

 

 

 

5.2.1 scikit-learn

 

- sklearn.preprocessing.OneHotEncoder 이용


        - fit(데이터셋) : 데이터셋을 기준으로 어떻게 변환할 지 학습
        - transform(데이터셋) : Argument로 받은 데이터셋을 원핫인코딩 처리
        - fit_transform(데이터셋) : 학습과 변환을 한번에 처리
        - get_feature_names_out()  : 원핫인코딩으로 변환된 컬럼 Feature의 이름을 반환


- 데이터셋은 테이블 형태 2차원 배열을 전달 하여야 하며,  Feature별로 원핫인코딩 처리한다.

            - labelencoding의 경우, 한 feature 1차원 배열 에 대해 적용되는 함수로 

              여러 feature을 한 번에 못 바꾼다.

            - 근데, 원핫인코더는 여러 feature 가 가능하다.

              한번에 feature 별로 encoding 할 수 있다.

 

            - feature 단위로 encoding 하기 때문에

               테이블 형태 2차원 배열을 넣어줘야 하며, DataFrame 도 처리 가능하다.

 

            - 원핫인코딩 처리시, 넣은 데이터 셋의 모든 타입의 값들을 다 변환한다. (연속형 값들도 변환) 

                 = > 그래서 변환려는 변수들만 모아서 처리해야 한다.

 

 

 

(1) 기본 코드 _ sparse =True,  csr_matrix 반환

 

- import

from sklearn.preprocessing import OneHotEncoder
import numpy as np
import pandas as pd

# 배열
items=np.array(['TV','냉장고','전자렌지','컴퓨터','선풍기','선풍기','믹서','믹서'])

 

- feature 단위로 enconding 하기에, 테이블 이차원 형태로 넣어줘야 함.

    현재, items 배열은 1차원 넘파이 배열 형태이다. 이를 이차원 배열로 바꿔줘야 한다.

     np.newaxis 더미축을 이용하여 차원을 확장해준다.

a = items[..., np.newaxis]
a
array([['TV'],
       ['냉장고'],
       ['전자렌지'],
       ['컴퓨터'],
       ['선풍기'],
       ['선풍기'],
       ['믹서'],
       ['믹서']], dtype='<U4')

 

 

- OneHotEncoder() 변환 객체 생성

   def : sparse = True   - > csr 방식으로 실제 값이 아닌 0 이 아닌 값 위치와 해당 값 정보만 저장한다.

oh_encoder = OneHotEncoder()

 

- 어떻게 변환할 지 학습 fit

oh_encoder.fit(a) # a = items[..., np.newaxis]

 

- 변환 - transform(변환대상)

r = oh_encoder.transform(a) # a = items[..., np.newaxis]

 

- type 확인 : csr_matrix 

print(type(r))
<class 'scipy.sparse.csr.csr_matrix'>

 

 

- sparse Matrix 희소행렬

       : 대부분의 값이 0으로 구성되어 있는 것. 

         원핫 인코딩 한 데이터는 희소행렬 대부분 0의 값을 가지고 있을 것이다.

          이를 그대로 메모리에 저장하는 것은 비효율적이다.

        = > sparse를 False로 주지 않으면,  scipy의 csr_matrix(희소행렬 객체)로 반환.     


- csr 방식

       : 실제 값이 아닌 정보만 저장하는 것. 값이 아닌, 0이 아닌 값 위치(index)와 해당 값만 저장한다. 그게 csr_matrix  

        = > csr_matrix.toarray()로 ndarray로 바꿀수 있다

 

 

- csr_matrix 을 반환

print(r)
  (0, 0)	1.0
  (1, 1)	1.0
  (2, 4)	1.0
  (3, 5)	1.0
  (4, 3)	1.0
  (5, 3)	1.0
  (6, 2)	1.0
  (7, 2)	1.0

 

-  csr_matrix(배열정보)를 ndarray(실제값으로 구성)로 변환

[[1. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0.]]

 


(2) 기본 코드 _ sparse = False,  실제값 ndarray 반환

oh_encoder = OneHotEncoder(sparse = False)
oh_encoder.fit(items[...,np.newaxis])
r = oh_encoder.transform(items[...,np.newaxis])

print(type(r))
print(r)

 

<class 'numpy.ndarray'>
[[1. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0.]]

 

 

- get_feature_names_out()  :  각 열 feature 의 이름을 알 수 있다.

 

oh_encoder.get_feature_names_out()
array(['x0_TV', 'x0_냉장고', 'x0_믹서', 'x0_선풍기', 'x0_전자렌지', 'x0_컴퓨터'],
      dtype=object)

 

- 변환한 데이터 배열을 데이터 프레임으로

pd.DataFrame(r, columns=oh_encoder.get_feature_names_out())

 

 

(3) 기본 코드 : pandas 데이터프레임의 특정 컬럼을 encoding

 

- 데이터 프레임

     범주형 : Item , Level    연속형 : Count 

     onehot encoding 대상 : Item, Level

 

      = > DataFrame, 2차원 배열을 넣어서 변환하면 그 안의 Feature들을 모두 변환한다.
      = > 변환할 컬럼만
을 조회하여 넣어야 한다.

 

- One Hot encoding

from sklearn.preprocessing import OneHotEncoder

ohe = OneHotEncoder(sparse=False) # 실제값 넘파이 배열을 반환
ohe.fit(df[['Item', 'Level']])
rv = ohe.transform(df[['Item','Level']])
rv

 

- feature 이름 조회

ohe.get_feature_names_out()
array(['Item_TV', 'Item_냉장고', 'Item_믹서', 'Item_선풍기', 'Item_전자렌지',
       'Item_컴퓨터', 'Level_1', 'Level_2', 'Level_3'], dtype=object)

 

 

- item, level one hot encoding 한 결과에 나머지 데이터 count 를 합침.

  = >  2차원 넘파이 배열에 맞춰서 넣어줘야 한다.

df['Count'].values # ndarray로 바꿔서
df['Count'].values[..., np.newaxis] # 더미축 추가해서 넣어줌.

result = np.concatenate([rv, df['Count'].values[..., np.newaxis]], axis=1)
result
array([[ 1.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0., 10.],
       [ 0.,  1.,  0.,  0.,  0.,  0.,  1.,  0.,  0., 10.],
       [ 0.,  0.,  0.,  0.,  1.,  0.,  1.,  0.,  0., 20.],
       [ 0.,  0.,  0.,  0.,  0.,  1.,  0.,  1.,  0., 15.],
       [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  1., 13.],
       [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  1.,  3.],
       [ 0.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0., 12.],
       [ 0.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0., 33.]])

 

5.2.2 pandas의 get_dummies() 이용

 

- 기본적으로, 데이터프레임에서 숫자가 아닌 object, categroy 타입의 Feature(컬럼) 들만 변환

 

- 특정 열만 인코딩 가능하다.

      - 숫자로 된 데이터도 인코딩 하도록 지정하면 처리해준다.

 

- 알아서 열 이름을 지정해준다.

 

 

(1) 데이터프레임 그대로 넣어줌. object 형 데이터만 인코딩

pd.get_dummies(df)

 

(2) 변환할 컬럼들을 지정하면 지정된 컬럼들은 one hot encoding 되고 

     나머지 컬럼들은 값을 유지하는 dataframe을 반환한다.

 

pd.get_dummies(df, columns=['Item', 'Level'])

 

6. Feature 타입 별 전처리 : 연속형(수치형) 데이터 전처리

 

- 연속형 데이터는 

  변수가 가지는 값들이 연속된 값으로 보통 정해진 범위 안의 모든 실수가 값이 될 수 있다.

 

 

연속형 데이터 전처리  Feature Scaling 정규화 이란? 언제? 어떻게? 왜 하는가?

 

각 피처들간의 값의 범위(척도-Scale)가 다를 경우   --- > Feater Scaling 의 목적

  이 값의 범위를 일정한 범위로 맞추는 작업


트리계열을 제외한 대부분의 머신러닝 알고리즘들이 Feature간의 서로 다른 척도(Scale)에 영향을 받는다.
    - 선형모델, SVM 모델, 신경망 모델

         = > 값의 단위 scale 이 모델 값 예측에 영향을 주게 된다.!!


- Scaling(정규화)은 train set으로 fitting 한다.

   test set이나 예측할 새로운 데이터는 train set으로 fitting 학습한 것으로 변환한다.

 

 

1) 어떤 scaling 방식을 사용하냐?

 

    - 표준화(Standardization)
    - Min Max Scaling


    - 이론적으로 정해진 것은 없다.
    - 둘 다 해보고 더 좋은 성능을 내는 방식을 한다.(Data set에 따라 다르다.) 
    - 경험에 따라 하나 선택해서 쓴다.
    


2) 언제 할 것이냐?


    - Dataset을 train/val/test 으로 나눈 뒤에 한다.


    - train 셋으로 학습시킨 scaler로   = >  Train/Validation/Test set 모두 변환한다.
        - 평가를 조금 더 정밀하게 하기 위해서 
        - 새로운 데이터들이 들어왓을 때 조금 더 평가를 더 잘 하기 위해서
       

        - 우리가 가지고 있는 sample 표본로 모델 학습을 한다.

          추론은 새로운 데이터로 할텐데 앞으로 들어올 새로운 데이터들의 값의 scale 은 어떨지 알 수 없다.

             - 그래서 scaling 할 때도 검증 평가로 쓰이는 val, test 데이터들은

                자신을 기준으로 scaling 하지 않고 test 기준에서 scaling 한다.

 

 

3) 함수

 

- fit(): 어떻게 변환할 지 학습
- transform(): 변환
- fit_transform(): 학습과 변환을 한번에 처리 
- inverse_transform(): 변환된 값을 원래값으로 복원

 

6.1 표준화(StandardScaler)

: 피쳐의 값들이 평균이 0이고 표준편차가 1인 범위에 있도록 변환한다.
    - 0을 기준으로 모든 데이터들이 모여있게 된다.

 

- Feature 별로 표준화 처리한다.

  각 Feature 별 데이터들의 평균과 표준편차가 변환 기준이다.

 

- 함수 : sklearn.preprocessing.StandardScaler

 

-  각 Feature 별로 처리되기 때문에   = > 데이터 셋은 2차원 배열이여야 한다.  

        - 데이터프레임도 가능하다.

 

 

(1) 기본예제 _ 변환할 데이터 : 넘파이 2차원 데이터

 

- 표준화 

import numpy as np
from sklearn.preprocessing import StandardScaler

# 변환할 데이터 (2차원)
data = np.array([10,2,30]).reshape(3,1)

# standardScaler 객체 생성
stn_scaler = StandardScaler()

# 학습시키기 - > data의 평균과 표준편차 계산
stn_scaler.fit(data)

# 변환
result = stn_scaler.transform(data)

 

- 확인

print(f'평균: {np.mean(result)}, 표준편차: {np.std(result)}')
print(result)
array([[-0.33968311],
       [-1.01904933],
       [ 1.35873244]])
평균: 0.0, 표준편차: 1.0

 

 

(2) 기본예제 _ 변환할 데이터 :  iris  데이터프레임 

 

- 표준화 

  한 컬럼 씩 스케일링

    = > feature 가 해당 각 컬럼의 평균과 표준편차을 기준으로 통일된다.

from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

scaler = StandardScaler()
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)

 

 

- 반환값은 넘파이 배열 numpy.ndarray 

  시각적으로 확인하고 싶다면 판다스 데이터 프레임으로

iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
iris_df_scaled.head()

 

 

- 각 feature 들의 평균(0)과 표준편차(1)을 확인  

print('feature 들의 평균 값')
print(iris_df_scaled.mean())
print('\nfeature 들의 표준편차 값')
print(iris_df_scaled.std())
feature 들의 평균 값
sepal length (cm)   -1.690315e-15
sepal width (cm)    -1.842970e-15
petal length (cm)   -1.698641e-15
petal width (cm)    -1.409243e-15
dtype: float64

feature 들의 표준편차 값
sepal length (cm)    1.00335
sepal width (cm)     1.00335
petal length (cm)    1.00335
petal width (cm)     1.00335
dtype: float64

 

6.2 MinMaxScaler

데이터셋의 모든 값을 0(=Min value)과 1(=Max value) 사이의 값으로 변환한다. 

  어떤 값이든 0 과 1 사이로 만들기.이거 해주는 함수가 MinMaxScaler

 

- 반환 데이터 : ndarray

 

- 수식을 보면 max(X)가 1되고, min(X) 가 0 되고, 그 사이 값을 0~1 사이

 

(1) 기본 예제

from sklearn.preprocessing import MinMaxScaler

# 객체생성
mm_scaler = MinMaxScaler()
# 학습 - 최소/최대값을 계산
mm_scaler.fit(data)
# 변환
result = mm_scaler.transform(data)

 

- 바뀐 데이터 : ndarray을 반환

print(data) # 원래 이건데
print(result) # 이렇게 스케일링
[[10]
 [ 2]
 [30]]
[[0.28571429]
 [0.        ]
 [1.        ]]

 

- 확인

print(f'최소값: {np.min(result)}, 최대값: {np.max(result)}')
최소값: 0.0, 최대값: 1.0
 
 

 

 

(2) 기본예제  _ 학습과 변환 동시에 가능하다.

  학습에 쓰이는 데이터와 변환할 데이터가 같다면 이렇게.

from sklearn.preprocessing import MinMaxScaler

mm_scaler = MinMaxScaler()
result = mm_scaler.fit_transform(data)

 

 

(3) iris 데이터 프레임 예제

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()

scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df) # ndarray 반환

iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print('feature들의 최소 값')
print(iris_df_scaled.min())
print('\nfeature들의 최대 값')
print(iris_df_scaled.max())
feature들의 최소 값
sepal length (cm)    0.0
sepal width (cm)     0.0
petal length (cm)    0.0
petal width (cm)     0.0
dtype: float64

feature들의 최대 값
sepal length (cm)    1.0
sepal width (cm)     1.0
petal length (cm)    1.0
petal width (cm)     1.0
dtype: float64