ディープラーニングと重回帰分析を比較した結果【Python】

ディープラーニングと重回帰分析を比較した結果【Python】 プログラミング

「ディープラーニングは全知全能」みたいなイメージではありませんか?
機械学習の初心者には、そのようなイメージがあると思います。

実際、私はそのようなイメージでした。
ディープラーニングから、機械学習に興味を持った人間です。
だから、ディープラーニングこそすべてというイメージなのかもしれません。

そのような中で、重回帰分析を何度か触りました。
scikit-learnとstatsmodelsの両方で重回帰分析を行っています。
それらは次の記事にまとめています。

そこで一つの疑問を感じました。
「ディープラーニングと重回帰分析でどちらが良い分析を行えるのだろうか?」

この記事では、この疑問を解決していきます。

本記事の内容

  • ディープラーニングと重回帰分析で比較する内容
  • 重回帰分析による分析結果
  • ディープラーニングによる分析結果
  • ディープラーニングと重回帰分析による比較の結果

ディープラーニングと重回帰分析で比較する内容

扱うデータは、以下。
各市区に関する情報と議員の報酬をまとめています。

議員報酬に関するデータ

目的変数は、議員報酬です。
それ以外が説明変数です。
ただし、重回帰分析では説明変数を試行錯誤して絞っています。

議員報酬を予測するモデルを構築することが、各分析での目的と言えます。
そして、その予測精度をディープラーニングと重回帰分析で比較します。

予測するのは、議員報酬です。
そのため、数値回帰の問題となります。

数値回帰でよく使われる評価指標は以下の2つ。

  • 平均絶対誤差(MAE:Mean Absolute Error)
  • 二乗平均平方根誤差(RMSE:Root Mean Squared Error)

これらの値でディープラーニングと重回帰分析を比較します。

重回帰分析による分析結果

以前に重回帰分析したときより、コードは変更しています。
説明変数も対象を変更しています。
元データのcsv自体にも「capacity」議員定数を追加しています。

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_absolute_error, mean_squared_error


# csv読み込み
df = pd.read_csv('./data/city_info.csv')
# 標準化
scaler = StandardScaler()
scaler.fit(np.array(df))
df_std = scaler.transform(np.array(df))
df_std = pd.DataFrame(df_std,columns=df.columns)
# 目的変数(Y)
Y = np.array(df['annual_income'])
# 説明変数(X)
col_name = [ 'population','fiscal_index', 'revenue', 'capacity']
X = np.array(df_std[col_name])
# データの分割(訓練データとテストデータ)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)
# モデル構築 
model = LinearRegression()
# 学習
model.fit(X_train, Y_train)
# 回帰係数
coef = pd.DataFrame({"col_name":np.array(col_name),"coefficient":model.coef_}).sort_values(by='coefficient')


# 予測
Y_pred = model.predict(X_test)
# 結果
print("MAE(Mean-Absolute-Error) : {:5.2f} ".format(mean_absolute_error(Y_test, Y_pred)))
print("MSE(Mean-Squared-Error)  : {:5.2f} ".format(mean_squared_error(Y_test, Y_pred)))
print("RMSE(Rooted-MSE)         : {:5.2f} ".format(np.sqrt(mean_squared_error(Y_test, Y_pred))))

この重回帰分析の結果は以下。

MAE(Mean-Absolute-Error) : 744765.86
MSE(Mean-Squared-Error)  : 995491236142.60
RMSE(Rooted-MSE)         : 997743.07

ディープラーニングによる分析結果

GoogleによるTensorFlow公式マニュアルを参考にしています。
https://www.tensorflow.org/tutorials/keras/regression?hl=ja

import numpy as np
import tensorflow as tf
from tensorflow import keras
import pandas as pd
import tensorflow.keras.layers as layers

def norm(x):
  return (x - train_stats['mean']) / train_stats['std']

def build_model():
  model = keras.Sequential([
    layers.Dense(64, activation='relu', input_shape=[len(train_dataset.keys())]),
    layers.Dense(64, activation='relu'),
    layers.Dense(1)
  ])

  optimizer = tf.keras.optimizers.RMSprop(0.001)

  model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])
  return model

# csv読み込み
dataset = pd.read_csv('./data/city_info.csv')

train_dataset = dataset.sample(frac=0.8,random_state=0)
test_dataset = dataset.drop(train_dataset.index)

train_stats = train_dataset.describe()
train_stats.pop("annual_income")
train_stats = train_stats.transpose()

train_labels = train_dataset.pop('annual_income')
test_labels = test_dataset.pop('annual_income')

normed_train_data = norm(train_dataset)
normed_test_data = norm(test_dataset)

model = build_model()

# patience は改善が見られるかを監視するエポック数を表すパラメーター
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)

# エポックが終わるごとにドットを一つ出力することで進捗を表示
class PrintDot(keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs):
    if epoch % 100 == 0: print('')
    print('.', end='')

EPOCHS = 1000

model.fit(normed_train_data, train_labels, epochs=EPOCHS,
                    validation_split = 0.2, verbose=0, callbacks=[early_stop, PrintDot()])

loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=2)

print("MAE(Mean-Absolute-Error) : {:5.2f} ".format(mae))
print("MSE(Mean-Squared-Error)  : {:5.2f} ".format(mse))
print("RMSE(Rooted-MSE)         : {:5.2f} ".format(np.sqrt(mse)))

このディープラーニングの結果は以下。

MAE(Mean-Absolute-Error) : 1188822.75
MSE(Mean-Squared-Error)  : 2192420503552.00
RMSE(Rooted-MSE)         : 1480682.45

ディープラーニングと重回帰分析による比較の結果

分析結果を表にまとめました。
目的変数は、議員報酬です。

平均絶対誤差よりも二乗平均平方根誤差の方が厳しい評価となります。
つまり、より正確に評価したい場合は、二乗平均平方根誤差を用います。


平均絶対誤差(MAE)二乗平均平方根誤差(RMSE)
重回帰分析744765.86997743.07
ディープラーニング1188822.751480682.45

平均絶対誤差(MAE)

重回帰分析の場合、誤差が約74万円ということです。
ディープラーニングの場合は、約119万円です。

二乗平均平方根誤差(RMSE)

重回帰分析の場合、誤差が約100万円ということです。
ディープラーニングの場合は、約148万円です。

まとめ

まず、重回帰分析の方が、優れた分析となりました。
ディープラーニングは、チューニングしていけばさらに精度は上がるかもしれません。

ただ、簡単に分析する上では、重回帰分析の方が優れていると言えます。
よって、一概に何でもかんでもディープラーニングで分析すればよいという訳ではありません。

これは頭ではわかっていましたが、実際に体感できたのは大きいです。
データ分析を仕事にしている人は、当たり前かもしれません。
しかし、素人にはその当たり前がわかりにくいことが多々あります。

比較論はとりあえずここまでとします。
それはそうとして、誤差が74万という分析結果はどうなのでしょうか?

地方議員の平均報酬は、698万です。
中央値は、638万円となります。

これをベースに考えれば、74万円の誤差は許容範囲と言えます。
また、決定係数が0.7以上であることから、そこそこ使えるモデルのはずです。

この重回帰分析のモデルをもとに市区毎の標準年収を算出できそうですね。
その標準年収から、どれくらい乖離しているのか?

これで該当市区の議員報酬が安いのか?高いのか?を決定できます。
ただし、これはあくまで相対評価です。
絶対評価でいけば、地方議員の報酬は高いかもしれませんけどね。。。

タイトルとURLをコピーしました