본문 바로가기

Machine Learning_모델설계_Python

데이터 전처리_3

안녕하십니까 배도리 입니다. 오늘은 데이터 전처리 마지막 부분입니다.

 

 데이터 실수화(Data Vectorization) ▪ 범주형 자료, 텍스트 자료, 이미지 자료 등을 실수로 구성된 형태로 전환하는 것

 

② 데이터 정제(Data Cleaning) ▪ 없는 데이터는 채우고, 잡음 데이터 제거하고, 모순 데이터를 올바른 데이터로 교정하는 것

 

 데이터 통합(Data Integration) ▪ 여러 개의 데이터 파일을 하나로 합치는 과정

--------------------------------- 여기까지 설명드렸습니다!

 

 데이터 변환 (Data Transformation) ▪ 데이터를 정규화 하거나, 로그를 씌우거나, 평균값을 계산하여 사용하거나, 사람 나이 등을 10대, 20대, 30대 등으로 구간화 하는 작업

 

 데이터 균형 (Data Balancing) ▪ 특정 클래스의 관측치가 다른 클래스에 비해 매우 낮을 경우 샘플링을 통해 클래스 비율을 맞추는 작업

 

 

 

 데이터 변환 .

▪ 머신러닝이 데이터의 특성(Feature)들을 비교하여 데이터 패턴을 찾습니다.

▪ 그런데 데이터가 가진 특성 간 스케일 차이가 심하면 패턴을 찾는데 문제가 발생하기 때문에 데이터변환은 필요합니다.

▪ 따라서 데이터 변환해야하는데 그 방법에는 대표적으로 2가지 방법이 있습니다.

▪ 표준화 (Standardization)

데이터를 원점 중심(zero mean)으로 이동시키고, 표준편차(standard deviation)로 스케일링하는 것을 의미합니다. 데이터의 분포가 정규분포에 가깝다면, 데이터를 표준화하여 이상치(outliers)를 제거하고 분석을 수행하는 것이 좋습니다. 또한, 데이터의 단위(unit)가 서로 다르고, 크기(scale)가 다르면 표준화를 통해 비교를 용이하게 할 수 있습니다.

표준화

▪ 정규화 (Normalization) 

데이터 정규화(normalization)는 데이터의 값 범위를 0과 1 사이로 변환하는 것을 의미합니다. 이 방법은 다양한 머신러닝 알고리즘에서 데이터를 입력할 때 사용됩니다. 예를 들어, 이미지 데이터를 처리할 때 픽셀 값 범위를 0과 1 사이로 정규화하여 처리하는 것이 일반적입니다. 또한, 신경망 모델에서 입력 데이터를 처리할 때 데이터를 정규화하여 학습 효과를 높일 수 있습니다.  이상치가 있을 때의 정규화는 정상적 관측치를 너무 작은 값으로 변환하게 되어 모형의 성능을 저하시키는 원인이 될 수 있습니다.

정규화

따라서, 데이터를 표준화할지 정규화할지 선택하는 것은 데이터의 특성과 분석 목적에 따라 달라집니다. 

 

 

 데이터 균형

▪ 데이터가 불균형(Data Imbalance)일 때 데이터를 균형있게 만드는 작업입니다.

데이터 불균형이란 머신러닝의 목적이 분류일 때, 특정 클래스의 관측치가 다른 클래스에 비해 매우 낮게 나타나면 이러한 자료를 불균형 자료라고 합니다. 

불균형 데이터셋은 한 클래스의 샘플 수가 다른 클래스보다 훨씬 적을 때 발생합니다.

불균형은 분류기의 성능을 저하시키므로, 데이터를 재샘플링하여 균형을 맞추는 것이 좋습니다.

▪ 데이터 불균형 해소 기법에는 크게 과소표집(undersampling), 과대표집(oversampling)이 있습니다.

 

 과대표집(over-sampling)은 데이터셋에서 특정 클래스의 비율을 높이기 위해 해당 클래스의 데이터를 복제하거나, 합성하여 데이터의 개수를 증가시키는 방법입니다. 이 방법은 데이터셋에서 소수 클래스 데이터가 부족한 경우 사용됩니다. 단점으로는 데이터를 복제하여 데이터셋을 증가시키기 때문에 과적합(overfitting) 문제가 발생할 수 있습니다. 대표적인 방법론으로 SMOTE(Synthetic Minority Oversampling Technique)와 ADASYN(Adaptive Synthetic Sampling Method)가 있습니다.


▪  과소표집(under-sampling)은 데이터셋에서 특정 클래스의 비율을 낮추기 위해 해당 클래스의 데이터를 삭제하거나, 일부만 사용하여 데이터의 개수를 감소시키는 방법입니다. 이 방법은 데이터셋에서 다수 클래스 데이터가 과도하게 많은 경우 사용됩니다. 단점으로는 데이터를 삭제하여 데이터셋을 감소시키기 때문에 소수 클래스 데이터의 정보를 잃을 수 있습니다. 대표적인 방법으로 NearMiss가 있습니다.

 

▪ 일반적으로 과소표집보다 과대표집이 통계적으로 유용합니다. 

▪ 의사결정나무(decision tree)와 앙상블(ensemble)은 상대적으로 불균형자료에 강인한 특성을 보입니다.

 

백문불여일견! 코드를 통해서 살펴보겠습니다! 이 코드는 불균형한 클래스 분포를 가진 분류용 데이터셋을 생성하고, 생성된 데이터셋의 클래스 개수를 출력합니다. 


from collections import Counter
#Python의 표준 라이브러리인 collections에서 Counter를 임포트합니다. Counter는 데이터의 개수를 세고, 개수를 기반으로 한 딕셔너리를 생성하는데 사용됩니다.

from sklearn.datasets import make_classification
#sikit-learn 라이브러리에서 분류용 데이터셋을 생성하는 함수인 make_classification을 임포트합니다.

from imblearn.over_sampling import SMOTE, ADASYN
#imbalanced-learn 라이브러리에서 오버샘플링 기법 중 SMOTE와 ADASYN을 임포트합니다. 이 예제에서는 사용되지 않았습니다.

X, y = make_classification(n_classes=3, weights=[0.03, 0.07,0.9], #함수를 사용하여 불균형한 분류용 데이터셋을 생성합니다
                           n_features=2, n_informative=2, n_redundant=0,
                           n_clusters_per_class=1, n_samples=200, random_state=10)
 
#이 데이터셋은 3개의 클래스, 2개의 특성을 가지며, 각 클래스의 가중치는 [0.03, 0.07, 0.9]로 설정됩니다.
#이렇게 설정하면 대부분의 데이터가 세 번째 클래스에 속하도록 데이터셋이 생성됩니다. 생성된 데이터셋의 독립 변수들은 X에, 종속 변수(레이블)은 y에 저장됩니다.
 
#n_informative=2: 이 인자는 데이터셋의 특성 중 실제로 클래스 구분에 도움이 되는 특성의 수를 의미합니다.
 
#n_redundant=0: 불필요한(다른 특성과 상관관계가 있는) 특성의 수를 0으로 설정합니다. 이 경우 불필요한 특성은 생성되지 않습니다.
 
#n_clusters_per_class=1: 각 클래스당 클러스터(cluster)(데이터 공간에서 유사한 특성을 가진 데이터 포인트들의 그룹)의 개수를 설정합니다. 여기서는 1로 설정하여 각 클래스당 하나의 클러스터를 생성합니다.
#만약 이 값을 2로 설정하면, 각 클래스당 두 개의 클러스터가 생성되고 데이터 분포가 더 복잡해집니다.
 
#n_smaples=200으로 설정하여 200개 샘플을 만듭니다. 각 클래스의 가중치에 따라서 분류도됩니다.
 
#random_state는 무작위로 데이터를 생성할 때 사용되는 난수 생성기(seed)의 초기값을 설정하는 매개변수입니다.
 
#이 예제에서 생성된 데이터셋의 종속 변수는 하나입니다. 종속 변수는 클래스 레이블을 나타내며,  3개의 클래스(0, 1, 2) 중 하나의 값을 가집니다. 여기서 y 변수에 저장된 값들이 해당 종속 변수입니다.
#make_classification() 함수에서 그룹을 나누는 기준은 주로 데이터 포인트들 간의 거리입니다.
#이 함수는 각 클래스에 대해 클러스터 중심(centroid)을 무작위로 생성한 후, 해당 클래스의 데이터 포인트들을 이 중심 주변에 배치합니다. 이 과정에서 각 클러스터의 데이터 포인트들은 서로 비슷한 특성을 가지게 됩니다.
 
print('Original dataset shape %s' % Counter(y))  
# %s는 문자열(string) 타입의 값을 받아서 문자열 안에 삽입하는 역할을 합니다.
#Counter(y)를 사용하여 각 클래스별 개수를 계산하고 출력합니다. 이를 통해 생성된 데이터셋이 불균형한 분포를 가지고 있는 것을 확인할 수 있습니다.
 
Original dataset shape Counter({2: 180, 1: 14, 0: 6}) 

 

이제  데이터셋의 2차원 특성을 이용해 산점도를 생성하고 그래프로 시각화합니다. 기본적으로 표준 정규 분포를 따르는 데이터를 생성합니다. 따라서 대부분의 데이터 포인트는 각 특성에 대해 평균 주변에 뭉쳐 있으며, 표준 편차 범위 내에 분포됩니다.

 
import matplotlib.pyplot as plt

plt.scatter(X[:, 0], X[:, 1], marker='o', c=y,
            s=100, edgecolor="k", linewidth=1)
#plt.scatter() 함수는 입력 데이터의 각 점에 대한 산점도를 그립니다. 여기서 X[:, 0]은 데이터셋의 첫 번째 특성(가로축, $X_1$) 값을 나타냅니다.
 
#X[:, 1]은 데이터셋의 두 번째 특성(세로축, $X_2$) 값을 나타냅니다. marker='o'는 점의 모양을 원형으로 지정합니다.
 
#c=y는 색상을 클래스 레이블에 따라 다르게 표시하도록 지정합니다. 이를 통해 산점도에서 각 클래스의 점들을 다른 색상으로 구분할 수 있습니다.
 
#s=100은 점의 크기를 설정합니다. edgecolor="k"는 점의 외곽선 색상을 검정색(black)으로 설정합니다. linewidth=1은 점의 외곽선 두께를 설정합니다.
 
plt.xlabel("$X_1$")
plt.ylabel("$X_2$")
plt.show()

산점도

 

이제 과대표집 방법중 하나인 SMOTE (Synthetic Minority Over-sampling Technique)를 사용하여 불균형한 클래스 분포를 가진 데이터셋을 재샘플링하겠습니다.

 
sm = SMOTE(random_state=42)
# SMOTE 인스턴스를 생성하고, 랜덤 시드를 42로 설정합니다. 이렇게 하면 코드를 실행할 때마다 동일한 결과를 얻을 수 있습니다.

X_res, y_res = sm.fit_resample(X, y)
# 입력 데이터 X와 레이블 y를 사용하여 데이터를 재샘플링합니다.
# 이 과정에서 소수 클래스의 샘플을 생성하여 클래스 간의 불균형을 줄입니다. 결과적으로 더 균형잡힌 데이터셋인 X_res와 y_res가 생성됩니다.

print('Resampled dataset shape %s' % Counter(y_res))
#각 클래스별 샘플 수를 출력하여 재샘플링된 데이터셋의 분포를 보여줍니다. 이를 통해 원래 데이터셋과 비교하여 더 균형잡힌 데이터셋이 생성되었음을 확인할 수 있습니다.
 
Resampled dataset shape Counter({2: 180, 1: 180, 0: 180}) # 3클래스 모두 180이 됐습니다.호

 

마찬가지로 산점도를 그려 시각화를 해보겠습니다.

import matplotlib.pyplot as plt

plt.scatter(X_res[:, 0], X_res[:, 1], marker='o', c=y_res,
            s=100, edgecolor="k", linewidth=1)
plt.xlabel("$X_1$")
plt.ylabel("$X_2$")
plt.show()

SMOTE 적용

 

 

과대표집의 또 다른 방법으로 ADASYN(Adaptive Synthetic Sampling) 방법을 사용하여 불균형한 클래스 분포를 가진 데이터셋을 재샘플링을 해보겠습니다.

ada=ADASYN(random_state=0)
X_syn,y_syn=ada.fit_resample(X,y)
print('Resampled dataset shape from ADASYN %s' % Counter(y_syn))
 
Resampled dataset shape from ADASYN Counter({2: 180, 1: 179, 0: 178})

 

이거 또한 산점도를 그려보겠습니다.

import matplotlib.pyplot as plt

plt.scatter(X_syn[:, 0], X_syn[:, 1], marker='o', c=y_syn,
            s=100, edgecolor="k", linewidth=1)
plt.xlabel("$X_1$")
plt.ylabel("$X_2$")
plt.show()

ADASYN 적용

 

ADASYN과 SMOTE 모두 불균형 데이터셋을 처리하는 데 유용한 과대표집(오버샘플링) 기법입니다.  각각의 특징은 다음과 같습니다.


 SMOTE (Synthetic Minority Over-sampling Technique):
소수 클래스의 샘플을 선택하고, 이웃 샘플들 사이에서 합성 샘플을 생성하여 데이터를 오버샘플링합니다. 정한 비율로 오버샘플링을 수행하며, 모든 소수 클래스 샘플에 대해 동일한 가중치를 부여합니다. 이 기법은 효과적이지만, 데이터 분포의 특성을 고려하지 않기 때문에, 특정 소수 클래스 영역에 과도하게 오버샘플링이 이루어질 수 있습니다. 데이터셋의 소수 클래스에 대한 정보가 어느 정도 균일하게 분포되어 있다고 가정할 때 사용합니다. SMOTE는 소수 클래스의 k-최근접 이웃을 이용하여 합성 샘플을 생성합니다.  이는 클래스 간의 경계에 새로운 샘플을 추가하여 분류기가 더 정확한 결정 경계를 학습하는 데 도움이 됩니다.

 ADASYN (Adaptive Synthetic Sampling):
소수 클래스 샘플 주변의 공간 밀도에 따라 적응적으로 합성 샘플을 생성합니다. 밀도가 낮은 영역에 더 많은 합성 샘플을 생성하여, 소수 클래스의 결정 경계를 더 세밀하게 모델링합니다. 이 기법은 데이터의 특성을 고려하여 샘플링을 수행하기 때문에, 데이터 분포에 따라 더 나은 결과를 얻을 수 있습니다. 소수 클래스의 데이터 분포가 불균형하거나, 데이터셋이 복잡하고 노이즈가 많은 경우 사용합니다. ADASYN은 소수 클래스의 각 샘플에 가중치를 부여하여, 합성 샘플 생성 시 더 어려운 샘플에 초점을 맞춥니다. 이로 인해 분류기가 소수 클래스의 더 복잡한 영역을 더 잘 학습할 수 있습니다..

 

 

이제 반대의 개념인 과소표집(언더샘플링)에 대해서도 알아보겠습니다. 과소표집 기법에는 소수 클래스(데이터셋에서 상대적으로 더 적은 비율을 차지하는 클래스)를 균형있게 만들어 주는 NearMiss가 있습니다. NearMiss는 k-최근접 이웃을 기반으로 소수 클래스 샘플 주변의 다수 클래스 샘플을 제거하는 방식으로 작동합니다.아래는 NearMiss를 적용한 코드입니다.

from imblearn.under_sampling import NearMiss
undersample = NearMiss(version=3, n_neighbors_ver3=3)
#버전 3에서는 n_neighbors_ver3 매개변수를 사용하여 각 소수 클래스 샘플에 대해 고려할 최근접 이웃의 수를 지정합니다 (여기서는 3).

X_Under, y_Under = undersample.fit_resample(X, y)
#NearMiss 객체를 사용하여 원래의 데이터셋 X와 y를 언더샘플링하여 새로운 데이터셋 X_Under와 y_Under를 생성합니다.
print('Resampled dataset shape from NearMiss %s' % Counter(y_Under))
 
Resampled dataset shape from NearMiss Counter({0: 6, 1: 6, 2: 6}) #3개클래스 모두 6개

 

소수 클래스에 맞춰 다른 2개의 클래스가 6개로 변화됐습니다. 시각화자료로도 확인해보겠습니다.

import matplotlib.pyplot as plt

plt.scatter(X_Under[:, 0], X_Under[:, 1], marker='o', c=y_Under,
            s=100, edgecolor="k", linewidth=1)
plt.xlabel("$X_1$")
plt.ylabel("$X_2$")
plt.show()

NearMiss 적용

 

 

드디어 데이터 전처리 설명이 완료됐습니다. 다음 게시글 부터는 이제 모델 설계 방법들에 대해서 본격적으로 시작해보겠습니다!

'Machine Learning_모델설계_Python' 카테고리의 다른 글

kNN_1 분류  (2) 2023.05.09
기계학습(Machine Learning) 방법론  (2) 2023.05.08
데이터 전처리_2  (1) 2023.05.05
데이터 전처리_1  (3) 2023.05.04
Pandas_3 그룹별 집계  (2) 2023.05.03