[ML] 머신러닝에서 로그변환(Log Transformation)이 필요한 이유
로그(Logarithm)
- 로그는 지수함수의 역함수입니다.
- 어떤 수를 나타내기위해 고정된 밑을 몇 번 곱하여야 하는지를 나타냅니다.
- 이 성질을 이용하면 이상치가 있는 데이터를 정규분포와 비슷한 형태로 만들 수 있습니다.
로그 함수 특징
로그 함수의 특징은 다음과 같습니다.
- 밑이 더 작은 값에 기울기가 가파르고 값이 커질수록 기울기가 완만해 집니다.
- 밑이 작은 로그 함수는 밑이 큰 로그 함수보다
x
값들에 대해서y
값의 차이가 큽니다.
- 밑이 작은 로그 함수는 밑이 큰 로그 함수보다
0 < x < 1
범위에서는 기울기가 매우 가파릅니다.x
가(0, 1)
사이의 값을 가지면y
는(0, -∞)
사이의 값을 가집니다.
x
값이 점점 커짐에 따라 로그함수의 기울기는 급격히 작아집니다.x
에 큰 값이 들어가도y
값이 크게 차이나지 않습니다.- 즉, 넓은 범위를 가지는
x
를 비교적 작은y
값 구간 내에 모이게 합니다.
로그 함수 이해하기
- 로그(Logarithm)를 사용하면, 매우 작은 값과 매우 큰값 등을 포함하는 광범위한 범위를 작은 범위로 줄일 수 있습니다.
- 아래 예시로 이해해 봅시다.
import pandas as pd
import numpy as np
# pH 농도는 -log([H+])로 계산됩니다.
# 수소 이온 농도를 데이터프레임으로 생성합니다.
data = {"[H+]": [5.8e-3, 6.0e-12, 3.0e-2, 1.2e-10, 3.2e-4, 4.1e-6, 9.3e-8]}
# 데이터 프레임으로 변환
df = pd.DataFrame(data)
# pH 파생변수 생성
df["pH"] = round(-np.log(df["[H+]"])/np.log(10), 2)
df
[H+] | pH | |
---|---|---|
0 | 5.800000e-03 | 2.24 |
1 | 6.000000e-12 | 11.22 |
2 | 3.000000e-02 | 1.52 |
3 | 1.200000e-10 | 9.92 |
4 | 3.200000e-04 | 3.49 |
5 | 4.100000e-06 | 5.39 |
6 | 9.300000e-08 | 7.03 |
# 서브 플롯을 그려 로그변환 전, 후 비교하기
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 3))
sns.barplot(x=df.index, y=df["[H+]"], ax=axes[0]).set_title("용액별 수소이온 농도")
sns.barplot(x=df.index, y=df.pH, ax=axes[1]).set_title("용액별 pH");
로그 변환(Log Transformation)
데이터 분석에서 로그를 취하는 이유는 정규성을 높이고 분석에서 정확한 값을 얻기 위함이다.
데이터 간 편차를 줄여 왜도(skewness)와 첨도(Kurtosis)를 줄일 수 있기 때문에 정규성을 높일 수 있다.
실습으로 이해하기
사용한 데이터 : 데이콘, 와인 품질(Quality) 분류 경진대회
👉 데이터 보러가기
(1) 로그 변환 전, 필요성 파악
- 여러 컬럼 중,
total sulfur dioxide
컬럼에서 이상치가 많이 발견됨 - 이상치는 머신러닝 모델을 학습하는데 문제가 될 수 있음
- scale 범위가 너무 크면 노이즈 데이터가 생성되거나 overfitting이 될 가능성이 있음
(2) 로그 변환 전, 후 시각화
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 8))
# 로그변환 전
sns.boxplot(x=train["total sulfur dioxide"], ax=axes[0][0]
, color="#F8C4B4").set_title("로그변환 전, 총 이산화황")
sns.kdeplot(x=train["total sulfur dioxide"], ax=axes[1][0]
, color="#F8C4B4")
# 로그변환 후
sns.boxplot(x=np.log1p(train["total sulfur dioxide"]), ax=axes[0][1]
, color="#BCE29E").set_title("로그변환 후, 총 이산화황")
sns.kdeplot(x=np.log1p(train["total sulfur dioxide"]), ax=axes[1][1]
, color="#BCE29E");
Reference
- 위키백과, 우리 모두의 백과사전 - Logarithm
- 위키백과, 우리 모두의 백과사전 - 정규분포
- 티스토리 by 프로도의 블로그 - 데이터 분석 시 식에 로그를 취하는 이유
- suppppppp - 로그변환과 np.log()가 아닌 np.log1p()를 하는 이유
- 티스토리 by 퐁스 - 왜 machine learning에서는 Normal Distributions를 사용할까?
개인 공부 기록용 블로그입니다
오류나 틀린 부분이 있을 경우 댓글 혹은 메일로 따끔하게 지적해주시면 감사하겠습니다 :)
댓글남기기