프로그래밍/PySpark

[PySpark] 오버샘플링(oversampling), 언더샘플링(undersampling)

히또아빠 2023. 9. 18. 16:41

기계 학습에서 불균형 훈련 데이터 세트로 분류 문제를 다룰 때 오버 샘플링과 언더 샘플링은 결과를 개선하는 두 가지 쉽고 종종 효과적인 방법이다.

1.불균형(imbalanced) 데이터란?

데이터셋의 한 클래스(레이블) 수가 다른 클래스보다 상당히 많거나 적을때 데이터의 클래스가 불균형 상태라고 말한다. '불균형'이라는것이 상당히 분석가나 과학자의 입장에서 주관적인 판단이 개입된다. 그리고 실제 문제를 ML(머신러닝, 기계학습)으로 해결할 때 깔끔하게 균형잡힌 데이터를 만나기는 힘들다. (예를들어, 이상치 탐지, 사기탐지 데이터, 질병 데이터 등)


머신러닝 모델은 맹목적으로 다수의 클래스를 대부분 학습하기 때문에 대다수 예측 데이터를 학습된 다수의 클래스로 예측하려는 경향이 있다. 그렇기 때문에, 소수 클래스를 과대 샘플링(oversampling)하거나, 다수 클래스를 과소 샘플링(under sampling)하거나, 클래스 가중치를 추가하거나, 알고리즘을 변경하거나, 합성 샘플을 생성하는 등 클래스 불균형 문제를 보정하여 머신러닝 알고리즘이 해당 문제에서 합리적으로 학습하고 예측하도록 하는 다양한 방법론들이 존재한다.

이 자료에서는 PySpark Dataframe에서 오버샘플링하거나 언더샘플링하는 방법을 보여준다.

 

2.pyspark 예제

클래스(label) 1은 6개의 데이터를 가지고 있는 반면 클래스 0은 2개의 데이터만 가지고 있다. 클래스 1을 언더샘플링하거나 클래스 0을 오버샘플링할 수 있는데 불균형 비율은 3이다. 학습 데이터 비율을 1:1로 맞추든 1:5, 1:10 으로 맞추든 불균형을 해소하는 객관적인 지침이나 메뉴얼이 있는 것은 아니다. 데이터 과학자의 재량이 필요하다. 그렇기에 실험적인 결과로 잘(?) 학습된 모델을 선정하고 예측하고 데이터상황이나 특성에 맞는 적절한 알고리즘을 선택하는 역량이 필요하다.

from pyspark.sql.functions import col, explode, array, lit

df = spark.createDataFrame([['a',1],['b',1],['c',1],['d',1], ['e',1], ['f',1], ['x', 0], ['y', 0]], ['feature', 'label'])
df.show()

major_df = df.filter(col("label") == 1)
minor_df = df.filter(col("label") == 0)

ratio = int(major_df.count()/minor_df.count())

print("ratio: {}".format(ratio))


+-------+-----+
|feature|label|
+-------+-----+
|      a|    1|
|      b|    1|
|      c|    1|
|      d|    1|
|      e|    1|
|      f|    1|
|      x|    0|
|      y|    0|
+-------+-----+
ratio: 3

 

3.오버샘플링(oversampling)

오버샘플링의 개념은 적은 클래스의 샘플을 복제하여 다수의 클래스와 동일한 수준에 도달할 때까지 숫자를 부풀리는 것이다. 다음은 PySpark Dataframe에서 수행하는 방법이다.

아래의 코드에서 pyspark의 'explode' 함수를 사용한다.

a = range(ratio)

# duplicate the minority rows
oversampled_df = minor_df.withColumn("dummy", explode(array([lit(x) for x in a]))).drop('dummy')

# combine both oversampled minority rows and previous majority rows combined_df = major_df.unionAll(oversampled_df)
combined_df.show()

+-------+-----+
|feature|label|
+-------+-----+
|      a|    1|
|      b|    1|
|      c|    1|
|      d|    1|
|      e|    1|
|      f|    1|
|      x|    0|
|      x|    0|
|      x|    0|
|      y|    0|
|      y|    0|
|      y|    0|
+-------+-----+

4.언더샘플링(undersampling)

언더샘플링은 오버샘플링과 반대되는 것으로, 소수 클래스의 중복을 만드는 대신 다수 클래스의 크기를 줄인다. PySpark에는 이를 위한 샘플 기능이 내장되어 있다. 언더샘플링은 전체 학습용 데이터셋 크기를 줄여주기 때문에 원래 데이터셋 크기가 상당히 큰 경우에는 이 방법을 사용하는게 좋다.

sampled_majority_df = major_df.sample(False, 1/ratio)
combined_df_2 = sampled_majority_df.unionAll(minor_df)
combined_df_2.show()

+-------+-----+
|feature|label|
+-------+-----+
|      a|    1|
|      b|    1|
|      x|    0|
|      y|    0|
+-------+-----+

 

5.reference

https://medium.com/@junwan01/oversampling-and-undersampling-with-pyspark-5dbc25cdf253

 

Oversampling and Undersampling with PySpark

In Machine Learning, when dealing with Classification problem with imbalanced training dataset, oversampling and undersampling are two…

medium.com

 

300x250
반응형