로그(Logarithm)

  • 로그는 지수함수의 역함수입니다.
  • 어떤 수를 나타내기위해 고정된 밑을 몇 번 곱하여야 하는지를 나타냅니다.
    • 이 성질을 이용하면 이상치가 있는 데이터를 정규분포와 비슷한 형태로 만들 수 있습니다.


Fig 1. 일반적으로 사용되는 세 가지 밑이 있는 로그 함수 플롯


로그 함수 특징

로그 함수의 특징은 다음과 같습니다.

  • 밑이 더 작은 값에 기울기가 가파르고 값이 커질수록 기울기가 완만해 집니다.
    • 밑이 작은 로그 함수는 밑이 큰 로그 함수보다 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");
Fig 2. 로그변환 전(왼쪽), 후(오른쪽) 그래프


로그 변환(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");
Fig 3. 로그변환 전(왼쪽), 후(오른쪽) 그래프


Reference


개인 공부 기록용 블로그입니다
오류나 틀린 부분이 있을 경우 댓글 혹은 메일로 따끔하게 지적해주시면 감사하겠습니다 :)

댓글남기기