Pythonによる線形重回帰

線形回帰は、機械学習で最もよく使われるアルゴリズムの1つです。2つ以上の連続値の間の関係を測定しようとする場合、線形回帰を使用する必要があるため、線形回帰に精通しておくとよいでしょう。

線形回帰の理論と実装を深く掘り下げることで、この貴重な機械学習アルゴリズムを理解することができます。

用語の定義

線形回帰を掘り下げる前に、回帰とは何かを明確にするための時間を取りましょう。

機械学習では、教師あり学習の手法として分類と回帰の2種類がある。

一般に、回帰は変数間の関係を推定する統計的手法である。分類も変数間の関係を見出そうとするもので、分類と回帰の主な違いはモデルの出力にあります。

回帰タスクでは、出力変数は数値または連続的な性質を持っていますが、分類タスクでは、出力変数はカテゴリー的または離散的な性質を持っています。変数がカテゴリカルである場合、その変数が適合できるグループまたはカテゴリの数が有限/離散であることを意味します。

例えば、ある動物がどのような種類の哺乳類であるかを、様々な特徴に基づいて予測しようとする分類器を考えてみましょう。哺乳類はたくさんいますが、無限にあるわけではなく、出力が分類できるカテゴリの数は限られています。

一方、連続変数では、どの2つの変数の間にも無限の値が存在する。与えられた2つの数値の差は、どんどん長い小数を書き出し、無限に表現することができる。つまり、日時の計測のようなものでも、その計測値を離散的なカテゴリーに入れなければ連続変数とみなすことができる。

回帰タスクは、ある入力変数と連続出力変数の関係を推定することに関係するが、回帰アルゴリズムには様々な種類がある。

  • 線形回帰
  • 多項式回帰
  • ステップワイズ回帰
  • リッジ回帰
  • ラッソ回帰
  • ElasticNet回帰

これらの異なるタイプの回帰は、異なるタスクに適しています。Ridge回帰は、特徴のセットに高い共線性またはほぼ直線的な関係がある場合に最適に使用されます。一方、多項式回帰は、曲線的な予測線を描くことができるため、特徴量の間に非線形関係がある場合に最もよく使用されます。

線形回帰は、最も一般的に使用される回帰の種類の1つで、変数間の線形関係を示すグラフに直線を引くのに適しています。

重回帰の理論

線形回帰とは、簡単に言えば、従属変数と独立変数の関係を示すものです。

線形回帰が独立変数(X)と従属変数(Y)の関係をプロットするだけなら、多変量・重回帰は複数の独立変数で線形回帰を実施するだけと推測できます。

線形回帰の式を理解することで、どのような場合に適用するかを知ることができますので、見ていきましょう。

linear_regression

出典:commons.wikimedia.org

線形回帰の方程式は、Y = a+b*X です。線形回帰の課題では、モデルによってパラメータ(ab)が推定されることになる。そして定数、つまり切片aを取り、線の傾きbに独立変数X(入力特徴)を掛けて、従属変数(Y)の値を計算します。

上の図は、変数 XY の間の線形関係がどのようなものかを示す例である。

最適な直線のためのabの値を計算するために使われる方程式は最小二乗法で、各データ点から描かれる直線までの二乗距離を最小にすることで機能します。線形回帰を実行するために、この式がどのように機能するかを正確に知る必要はありませんが、もし興味があれば、上のリンクでもっと詳しく読むことができます。

Y = a+b*X` が単回帰の方程式だとすると、重回帰の場合は独立変数の数と傾きを方程式に突っ込むということになります。

例えば、独立変数が2つの重回帰の方程式は以下の通りです。

Y=a+b1∗X1+b2∗x2Y=a+b1∗X1+b2∗x2

Y=a+b1X1+b2x2

これは、任意の数の変数に対して成り立つ。

多変量線形回帰は、与えられた特徴数の特徴間の相関を比較しているだけなので、複数の通常の線形回帰モデルと考えることができる。

上記の式では、従属変数と独立変数の間に線形関係があることが仮定されています。また、変数/素性は離散値ではなく、すべて連続値であることを仮定しています。

MLRの実装

カテゴリー変数の変換

出典:commons.wikimedia.org

機械学習システムで線形回帰を実装する場合、変数はカテゴリー変数ではなく、連続変数でなければなりません。しかし、連続変数ではなく、カテゴリカル変数を含むデータが頻繁にあります。

例えば、あるデータセットが、特定の国でのあるイベントの発生を含むとする。国はカテゴリカル変数である.線形回帰を適切に使用するためには、これらのカテゴリカル変数を連続変数に変換する必要があります。

これを達成する方法は、問題の変数のタイプによって、いくつかあります。変数は、2分法、名義法、順序法のいずれかである。

二項対立型変数

二項変数は,2つのカテゴリのうちの1つだけに存在する変数である.二項変数は、「はい」か「いいえ」、「白」か「黒」のどちらかである。2値変数は連続変数に変換するのが簡単で,単に 0 または 1 というラベルをつけるだけでよい.

名目/序数変数

名義変数と順序変数は,カテゴリ変数の一種であり,値が属することができるカテゴリの数はいくつでも可能である.順序変数に関しては,変数に何らかの順序があること,または変数が異なる重みを持つことが仮定される.したがって,カテゴリ変数は,0から始まってカテゴリの長さまで続く番号を割り当てることによって,連続値に変換することができる.

名目変数の連続変数への変換は,3種類の変換の中で最も困難なタスクである.なぜなら、名義変数は、それらに異なる重みまたは順序を付けてはならず、すべてのカテゴリ変数が同等の「値」を持っていると推定されるからです。これは、初期のカテゴリが後のカテゴリよりも少ない「価値」を持つことを意味するので、単純にゼロからカテゴリの数まで並べることはできないことを意味します。

このため、名義変数を連続変数に変換するためのデフォルトの戦術は、ワンホットエンコーディングと呼ばれるもので、「ダミー変数の作成」と呼ばれることもある。基本的には、データ中の実際のカテゴリの代わりになる特徴量や変数をより多く作成します。ワンホットエンコーディングのプロセスは、カテゴリの数と同じサイズの配列を作成し、関連するカテゴリに対応する位置に「1」、それ以外はすべて「0」で埋めることを意味します。

例として、カテゴリデータを持つテーブルを示します。

このテーブルをワンホットエンコーディングにかけると、次のようになります。

| 赤|緑|青
| — | — | — |
| 1 | 0 | 0 |

| 0 | 0 | 1 |

あなたがカテゴリ変数のための連続的なラベルを作成しているとき、値が純粋に問題のカテゴリの重要性に対応することを確認してください。順序変数があり、与えられた値の範囲が、ランクを念頭に置いていない場合、カテゴリ間の関係は失われ、分類器は悪影響を受けるでしょう。

機械学習パイプライン

実際のデータセットに重回帰を実装する例を見る前に、機械学習のワークフローまたはパイプラインを理解するために少し時間を取りましょう。

機械学習アルゴリズムの実装は、どれも同じ基本的な構成要素を持っています。必要なのは

  • データの準備
  • モデルの作成
  • モデルの学習
  • モデルを評価する

データを準備することは、機械学習において最も困難な部分の一つである。なぜなら、データを収集するだけでなく、そのデータを選択したアルゴリズムが利用できる形式に変換する必要があるからである。この作業には、欠損値や破損/変形したデータの処理など、多くのタスクが含まれる。このため、今回は前処理をほとんど必要としない、あらかじめ用意されたデータセットを使用する。

Scikit-Learnのようなライブラリを使用すれば、機械学習モデルの作成はかなり簡単です。与えられた機械学習アルゴリズムをインスタンス化するのに必要なコードは、通常数行だけです。しかし、これらのアルゴリズムが取る引数やパラメータは様々で、モデルの精度に影響します。モデルの正しいパラメータ値を選択する術は、時間が経つにつれてわかってきますが、選んだライブラリのアルゴリズムのドキュメントを参照すれば、いつでもどのパラメータを実験できるかを確認できます。

Scikit-Learnのようなライブラリを使用する場合、モデルの学習もかなり簡単です。選択したデータセットでアルゴリズムを学習するために必要なコードは、通常数行だけです。

しかし、データをトレーニングセットとテストセットに分割する必要があります。学習させたデータと同じデータセットで分類器の性能を評価することはできません.なぜなら,モデルはすでにこのデータセットのパラメータを学習してしまっているからです.訓練セットのデータを評価しても,別のデータセットでのモデルの性能に関する知見は得られません.

MLRの実施例

早速ですが、PythonのScikit-Learnモジュールを使って重回帰を行う方法について見ていきましょう。

出典:commons.wikimedia.org
まず、データセットをロードする必要があります。Scikit-Learnライブラリには、いくつかのサンプルデータセットがあらかじめパッケージされています。今回使用するデータセットは、Boston Housing Datasetです。このデータセットには、家の大きさ、犯罪率、築年数など、ボストン地域の家に関する多くの異なる特徴があります。目標は、これらの特徴に基づいて、家の価格を予測することです。

ここに必要なインポートがすべてあります。

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error, r2_Score


次に、 load_boston() 関数を呼び出して、データセットのインスタンスを作成します。

bh_data = load_boston()


data 変数の値を出力して、どんなデータが入っているのか見てみましょう。

print(bh_data.keys())


返ってきたのは次のようなものです。

dict_keys(['data', 'target', 'feature_names', 'DESCR'])


dataは住宅に関する実際の情報、targetは住宅の価格、feature namesはデータが分類されるカテゴリ名、DESCR` はデータセットの特徴を記述するためのコマンドである。

データと特徴名をモデルが利用できるデータフレームにするために、Pandasを使ってデータからdataframeオブジェクトを作成しましょう。

また、カラムヘッダとして特徴名を渡します。

boston = pd.Dataframe(bh_data.data, columns=bh_data.feature_names)


データセットに含まれる素性の種類を知りたい場合は、いくつかの行を出力して、その素性の説明を表示します。

print(data.DESCR)


返された説明文の一部を以下に示す。

CRIM: Per capita crime rate by town
ZN: Proportion of residential land zoned for lots over 25,000 sq. ft
INDUS: Proportion of non-retail business acres per town
...
LSTAT: Percentage of lower status of the population
MEDV: Median value of owner-occupied homes in $1000s


住宅の中央値を予測したいのですが、現在のデータセットには学習・テスト用の情報がないので、データフレームに新しい列を作り、データセットから目標値をロードしてみます。

これは、変数にデータフレームと作りたい列の名前を指定し、targetの値を選択するだけで完了します。

boston['MEDV'] = bh_data.target


通常、最も重要な特徴が何かを把握するためにデータ分析を行い、それらの変数を回帰に使用することになります。しかし、それだけで1つの記事になるので、今回は、最も強い相関を持つ特徴が、人口における「低い地位」の割合 (‘LSTAT’) と家の中の部屋数 (‘RM’) であるとだけお伝えします。

そこで、’RM’ と ‘LSTAT’ を線形回帰のための変数として使いましょう。これらの値はデータセット内ですでに連続なので、エンコードする必要はまったくありません。

しかし、Numpyライブラリのnp.c_コマンドで2つの変数の列を1つの列に連結してみましょう。また、boston データフレームと必要なカラムを指定して、対象の値を格納するための新しい変数を作成することにします。

X = pd.DataFrame(np.c_[boston['LSTAT'], boston['RM']], columns=['LSTAT','RM']
Y = boston['MEDV']


次に、データフレームをトレーニングセットとテストセットに分割します。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state=9)


次に、モデルのインスタンスを作成します。Scikit-Learn の LinearRegression 関数を呼び出すだけでよいのです。

lin_reg_mod = LinearRegression()


学習データに対してモデルのフィットを行います。

lin_reg_mod.fit(X_train, y_train)


モデルのフィットが完了したので、predictコマンドを呼び出して予測を行います。ここではテストセットに対して予測を行います。

pred = lin_reg_mod.predict(X_test)


ここで、RMSEとR-2という回帰タスクの評価によく使われる2つのメトリクスを使って、実際の値に対する予測値をチェックしましょう。

test_set_rmse = (np.sqrt(mean_squared_error(y_test, pred)))


test_set_r2 = r2_score(y_test, pred)


素晴らしい。モデルの評価を格納する変数があり、サンプルデータセットでの重回帰の完全な実装があります。

精度メトリクスを出力して、どのような結果が得られるか見てみましょう。

print(test_set_rmse)
print(test_set_r2)


以下はその結果です。

# Note that for rmse, the lower that value is, the better the fit
6.035041736063677
# The closer towards 1, the better the fit
0.6400551238836978


モデルの精度を向上させるために、より多くの機能を使用してみることができます。

結論

多変量/重回帰は、連続変数の関係を追跡するための非常に有用なアルゴリズムの1つです。また、機械学習で最もよく使われるアルゴリズムの1つでもあるので、よく理解しておくとよいでしょう。

線形回帰の背後にある理論を理解し、実際のデータセットでの使用例を見たので、感触を得るために異なるデータセットで実装してみるべきです。また、他の回帰アルゴリズムについても調べてみるとよいでしょう。

ソースコードを見たい場合は、GitHubにあります!

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