[ML] RMSLE(Root Mean Square Logarithmic Error)

윰진·2023년 12월 11일
0

Competetion

목록 보기
2/8

01. Metrics - RMLSE

RMSLE(Root Mean Square Logarithmic Error)

  • p = predict
  • a = actual
RMSLE=1Ni=1N(log(pi+1)log(ai+1))2RMSLE = \sqrt{\frac{1}{N} \sum_{i=1}^{N}(log(p_i + 1) - log(a_i + 1))^2 }
  • Regression 문제에서 사용되는 지표
    • MSE(Mean Square Error)의 확장으로 예측값이 큰 편차를 가지는 경우에 주로 사용
    • 예측값과 실제값 사이의 비율적인 차이를 중요시하므로, 값의 절대적인 크기보다는 상대적인 비율에 민감하게 반응하는 특징이 있음
      • best_const = np.expm1(np.mean(np.log1p(df['predict_target_column'])))
        • RMSLE를 최소화하는 최적의 상수 값
        • 로그 변환된 예측 대상 열의 평균을 원래 스케일로 역변환한 값
          {\rightarrow}예측 대상 열의 평균을 나타내는 가장 좋은 상수 값으로 사용할 수 있음

1 ) RMSLE 구현

scikit-learn

def RMSLE(y_true: np.array, y_pred: np.array) -> np.float64:
    """
    The Root Mean Squared Log Error (RMSLE) metric 
        
    :param y_true: The ground truth labels given in the dataset
    :param y_pred: Our predictions
    :return: The RMSLE score
    """
    return mean_squared_log_error(y_true, y_pred, squared=False)

Numpy 방식을 사용하면 벡터 계산이 가능하므로 scikit-learn을 사용하는 것 보다 빠름

def NumPyRMSLE(y_true: list, y_pred: list) -> float:
    """
    The Root Mean Squared Log Error (RMSLE) metric using only NumPy
    
    :param y_true: The ground truth labels given in the dataset
    :param y_pred: Our predictions
    :return: The RMSLE score
    """
    n = len(y_true)
    msle = np.sqrt(np.mean(np.square(np.log1p(y_pred) - np.log1p(y_true))))
    return msle
import torch

def rmsle_torch(y_pred:torch.Tensor, y_true:torch.Tensor) -> torch.float64:
    """
    The Root Mean Squared Log Error (RMSLE) metric for PyTorch

    :param y_true: The ground truth labels given in the dataset
    :param y_pred: Predicted values
    :return: The RMSLE score
    """
    y_pred = y_pred.double()
    y_true = y_true.double()
    y_pred = torch.relu(y_pred) # 음수 값은 0으로 만들고, 양수 값은 그대로 사용
    return torch.sqrt(torch.mean((torch.log1p(y_pred) - torch.log1p(y_true)) ** 2))

02. RMSLE의 특징

1 ) Outlier에 강건함

predicted_values = [10, 20, 30, 45]
actual_values = [8, 19, 28, 42]

rmsle = np.sqrt(mean_squared_log_error(actual_values,predicted_values))
rmse = np.sqrt(mean_squared_error(actual_values, predicted_values))

print(f"RMLSE: {rmsle} RMSE: {rmse}")

RMLSE: 0.11362798282642304 RMSE: 2.1213203435596424

예측 값과 실제 값 간의 로그 스케일 차이를 줄여, Outlier의 영향력을 상대적으로 줄임

predicted_values = [10, 20, 30, 450]
actual_values = [8, 19, 28, 102]

rmsle = np.sqrt(mean_squared_log_error(actual_values,predicted_values))
rmse = np.sqrt(mean_squared_error(actual_values, predicted_values))

print(f"RMLSE: {rmsle} RMSE: {rmse}")

RMLSE: 0.7462997229146763 RMSE: 174.00646539712253

2 ) 상대적 오차를 측정

예측 값과 실제 값의 비율에 초점을 맞춤

→ 예측 값이 상대적으로 크거나 작을 때도 일관된 측정을 제공
⇒ 예측 값의 절대적인 크기가 결과에 영향을 미치지 않음

predicted_values = [1]
actual_values = [2]

rmsle = np.sqrt(mean_squared_log_error(actual_values,predicted_values))
rmse = np.sqrt(mean_squared_error(actual_values, predicted_values))

print(f"RMLSE: {rmsle} RMSE: {rmse}")

RMLSE: 0.4054651081081645 RMSE: 1.0
predicted_values = [1000]
actual_values = [999]

rmsle = np.sqrt(mean_squared_log_error(actual_values,predicted_values))
rmse = np.sqrt(mean_squared_error(actual_values, predicted_values))

print(f"RMLSE: {rmsle} RMSE: {rmse}")
RMLSE: 0.0009995003330836028 RMSE: 1.0

3 ) Under Estimation에 큰 패널티

RMSLE는 로그 스케일에서 오차를 계산하기 때문에, 예측 값이 실제 값보다 작을 경우에 큰 패널티를 부여함
{\rightarrow} 예측 값이 실제 값보다 과소평가되는 경우에 더 큰 오차를 나타내게 됨

  • 예측 값이 실제 값보다 작을 경우, 큰 패널티가 부여됨
    • 예측 값이 실제 값보다 과소 평가되는 경우 더 큰 오차
      • 로그 스케일에서 오차를 계산하기 때문임
predicted_values = [100]
actual_values = [95]

# custom_rmsle = rmsle(actual_values, predicted_values)
rmsle = np.sqrt(mean_squared_log_error(actual_values,predicted_values))
rmse = np.sqrt(mean_squared_error(actual_values, predicted_values))

print(f"RMLSE: {rmsle} RMSE: {rmse}")

RMLSE: 0.04831857727080724 RMSE: 5.0
predicted_values = [100]
actual_values = [105]

# custom_rmsle = rmsle(actual_values, predicted_values)
rmsle = np.sqrt(mean_squared_log_error(actual_values,predicted_values))
rmse = np.sqrt(mean_squared_error(actual_values, predicted_values))

print(f"RMLSE: {rmsle} RMSE: {rmse}")

RMLSE: 0.05077232537342358 RMSE: 5.0

99. Reference

0개의 댓글