目的変数の対数変換を効率化するsklearn.compose.TransformedTargetRegressor

地味に面倒な目的変数の対数変換がTransformedTargetRegressorで楽になります

目的変数を変換して、予測値を逆変換して、のような面倒な処理を効率化する方法を実際に試して紹介します

🕒 Last mod: 2021-07-04


1. 目的変数の対数変換

目的変数がカウントデータやロングテイルのように偏った分布をしている場合に対数変換でモデルの精度が上昇することがあります。

この対数変換の実装はそこまで難しいものではないですが使用頻度もそこそこ多いので個人的な実装に依存しない効率的で統一的な実装が欲しい。

このニーズに答えてくれるのが

です。

2. 対数変換の実装方法

実際の実装では目的変数の対数変換と予測時の逆変換が必要です。

今回使用する変換関数は下記です。

  1. numpy.log1p

  2. numpy.expm1

2.1. numpy.log1p

yに1を足してから対数変換します。

log(1 + y)

1を足す理由は0の場合に対数変換できないからです。

カウントデータは0以上の値を取るのでこの場合にlog1pが便利です。

もし目的変数が負の値を取る場合には異なる変換方法を考えなければなりません。

でも目的変数が0以上の値を取ることが結構多いのでlog1pを使用することも多くなります。

2.2. numpy.expm1

目的変数をlog1pで対数変換してモデルを学習したあとで予測値が欲しい場合に逆変換が必要です。

ここで使用するのがexpm1です。

exp(predicted) - 1

log1pの逆変換なので予測値を指数変換後に1を引いています。

3. TransformedTargetRegressor

このような目的変数の変換と逆変換を助けてくれるのがTransformedTargetRegressorです。

使い方は簡単です。regressorと変換関数と逆変換関数を指定するだけです。

あとは通常のRegressorと同様にfitとpredictを実施すれば対数変換後の目的変数で学習し、逆変換された予測値を得ることができます。

4. 実装

さて、実装です。

使用するデータはboston。

regressorはLGBMRegressorを使用してみます。

対数変換しない場合と実施した場合の精度の変換を比較します。

精度はneg_root_mean_squared_errorを使用します。

精度の確認のためにクロスバリデーションを実施します。

クロスバリデーションを実施するためにcross_val_scoreを使用します。

  1. データ作成

  2. 対数変換なしの精度確認

  3. TransformedTargetRegressorの適用

  4. 対数変換時の精度確認

今回の肝の部分はTransformedTargetRegressorの適用です。

そこだけプログラムを抜き出すとこうなります。

example.py
### TransformedTargetRegressorの適用
regr_trans = TransformedTargetRegressor(
    LGBMRegressor(),
    func=np.log1p,
    inverse_func=np.expm1,
)

regressorとfuncとinverse_funcを指定するだけです。

4.1. 実際のプログラム

example.py
import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import cross_val_score
from sklearn.compose import TransformedTargetRegressor
from lightgbm import LGBMRegressor

### データ作成
boston = datasets.load_boston()
boston_df = pd.DataFrame(
        boston.data,
        columns=boston.feature_names,
)
boston_df['target'] = boston.target

X = (
    boston_df
    .drop(
        'target',
        axis=1,
    )
)
y = boston_df.target


### 対数変換なしの精度確認
score = np.mean(
    cross_val_score(
        LGBMRegressor(),
        X,
        y,
        scoring='neg_root_mean_squared_error'
    )
)
print(f'対数変換なしの精度 = {score}')


### TransformedTargetRegressorの適用
regr_trans = TransformedTargetRegressor(
    LGBMRegressor(),
    func=np.log1p,
    inverse_func=np.expm1,
)

### 対数変換時の精度確認
score = np.mean(
    cross_val_score(
        regr_trans,
        X,
        y,
        scoring='neg_root_mean_squared_error'
    )
)
print(f'対数変換後の精度 = {score}')

4.2. アウトプット

Output
対数変換なしの精度 = -4.571009019613884
対数変換後の精度 = -4.2419803563797

今回は対数変換後のほうが精度が良くなりました。

必ずしも精度が良くなるわけではないですがカウントデータのように目的変数が0以上の値を取る場合には対数変換で精度が向上することが多いです。

5. まとめ

対数変換を楽に実装できるTransformedTargetRegressorを紹介しました。

目的変数の変換と逆変換は難しくはないですが地味に面倒です。

TransformedTargetRegressorを利用して楽をしましょう。