AIに欠かせない数学を、プログラミング言語Pythonを使って高校生の学習範囲から学び直す連載。今回は「回帰分析」には対数変換を用いるとよい理由について解説します。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
AIに欠かせない数学を、プログラミング言語Pythonを使って高校生の学習範囲から学び直す本連載『「AI」エンジニアになるための「基礎数学」再入門』。前回は最小二乗法および回帰分析について解説しました。
今回のテーマは、有用なケースが多いのでぜひ覚えてほしいテクニック「対数変換」です。前回の回帰分析に使えるものですが、「なぜ有用なのか?」についても解説します。
前回学んだ単回帰分析について簡単に復習します。単回帰分析は、「y = ax + b」という数式である値を予測するものでした。例として、以下のような課題を与えられたとします。
Name | y:資産額(万円) | x:年収(万円) |
---|---|---|
A | 300 | 1000 |
B | 240 | 800 |
…… | …… | …… |
単回帰分析なら次のような数式を仮定します。
この仮定の下で、データからa,bを求めることで数式を完成させるのが単回帰分析でした。この仮定をもう少し深く考察します。
数式(1)の両辺を“年収”で微分してみます。
数式(2)から何を読み取れるかというと、aは固定値なので「変化量の比は一定」ということです。すなわち、本仮定は次のようなことを言っているも同然だということになります(aを適当に0.3として、低所得/高所得者で考えてみましょう)。
つまり「ベースとなる年収に限らず、同じだけ年収が上がれば、同じだけ資産額は増える」という仮定です。この仮定は本当に正しいのでしょうか。これには少し違和感があります。一方、例えば次のような仮定の方が美しい、つまりシンプルかつ正しそうではないでしょうか。
このような仮定の方が現実世界に当てはまることが多いのです。しかし、この仮定を置くにはどうしたらよいでしょうか?
答えは連載第5回で学んだ「対数変換」です。対数を用いて次のような数式を考えます。
こうするだけで前述の“美しい仮定”が出来上がります。理由は後述するので、まずは「本当に精度が上がるのか?」を確認します。
ボストンの住宅価格データは統計学や機械学習の初学者用チュートリアルによく使用されるオープンデータです。
配布元はカーネギーメロン大学で、ライセンス指定はありません。
今回はDISを使ってMEDVを予測する単回帰分析をします。準備として以下のようにデータを読み込んでおきましょう(※機械学習用ライブラリ「sklearn」にはボストン住宅価格を簡単に読み込めるメソッドが用意されています)。
import pandas as pd from sklearn.datasets import load_boston boston = load_boston() df = pd.DataFrame(boston.data, columns=boston.feature_names) df["MEDV"] = boston.target
単回帰分析を始める前に、DISとMEDVの相関を確認します。
とても1本の直線を引いたところでうまく予測できそうにありません。特にグラフ右上の方に点在するデータにいえることです。ひとまず、単回帰分析をしてみましょう。
Pythonにおける単回帰分析は、次のように簡単です。
from sklearn.linear_model import LinearRegression # 線形回帰(単回帰/重回帰)用クラス X = df[["DIS"]] y = df["MEDV"] model = LinearRegression() model.fit(X, y) # 学習 print("MODEL: MEDV = {0:.1f} DIS {1:+.1f}".format(model.coef_[0], model.intercept_)) # MODEL: MEDV = 1.1 DIS +18.4
ここで出来上がったモデル(数式)の精度を確認します。精度には、現場でよく使われる指標「MAPE」(Mean Absolute Percentage Error:平均絶対パーセント誤差)を使用してみます。
MAPEは端的にいうと、「1予測当たり平均で何%の誤差(正解の大きさ基準)があるか」が読み取れるものです。計算します。
# modelは学習済みの状態で実行 pred = model.predict(X) # 予測 # MAPEの計算 pe = (pred - y)/y mape = abs(pe).mean() print("MAPE = %.3f" % mape) # 0.333
どうやら通常の単回帰分析では、1予測当たり平均で33.3%の誤差が発生しているようです。
対数変換を用いた単回帰分析を確認します。
X = df[["DIS"]] X_log = np.log(X + 1) # log(0)は計算できないので+1をしている y = df["MEDV"] y_log = np.log(y + 1) model = LinearRegression() model.fit(X_log, y_log) model_desc = "MODEL: log(MEDV+1) = {0:.1f} log(DIS+1) {1:+.1f}".format(model.coef_[0], model.intercept_) print(model_desc) # MODEL: log(MEDV+1) = 0.4 log(DIS+1) +2.5
「精度を確認します」といきたいところですが、現状では対数変換されているので計算されたMAPEは単純比較できません。そこでlogを外します。
「log(y+1)=y'」のとき、「y+1=ey'」となるので、Pythonで次のように記述するとlogを外すことができます。
y = df["MEDV"] # 元のy y_log = np.log(y + 1) # 対数変換後のy np.exp(y_log) - 1 # y_logを元のyに戻す処理
対数の外し方が分かったところで、MAPEを確認してみましょう。
pred_log = model.predict(X_log) pred = np.exp(pred_log)-1 pe = (pred - y)/y mape = abs(pe).mean() print("MAPE = %.3f" % mape) # MAPE = 0.286
なんとMAPEが33.3%から28.6%まで下がりました。この現象の要因について考察します。
「単回帰分析の深掘り」の部分と同様に対数変換版の単回帰分析の数式を確認していきます。数式(3)は次のようなものでした。
両辺を“年収”で微分してみましょう。
このままではよく分からないので、ひとまず今度は両辺を“資産額”で微分してみます。
数式(5''')から読み取れるのは、仮定「変化割合の比が一定」が置かれているということです。
つまり前述の、下記のように美しい仮定が対数変換をするだけで設定できていることが分かります。
今回はボストンの住宅価格データを例に対数変換版の単回帰分析を試しました。
これ以外にも対数変換が適しているデータは世の中にたくさんあります。むしろ「通常の単回帰分析が当てはまることの方が少ない」ということは大切なのでぜひ覚えておいてください。
最後におまけで対数変換が適しているケースを1つ紹介します。
ちまたで有名な「アッシェンフェルターのワイン方程式」の原論文からの引用です。生産年とlog(価格)は比例関係があるように見えます。言い換えれば、「年数が深まるごとにボルドーワインの価格は“指数的”に上昇する」ことになります。
これを「ヴィンテージワインはコスパが悪いな」と思うか、「ヴィンテージワインの価値は指数的に高まるのか! あらためて素晴らしい!」と思うかは皆さんにお任せします。
Copyright © ITmedia, Inc. All Rights Reserved.