単回帰分析とは、1つの説明変数から目的変数を予測する分析手法です。重回帰分析は複数の説明変数を使う所が単回帰分析との違いとなります。 Pythonで使えるscikit-learnライブラリを用いた単回帰分析は、sklearn.linear_model.LinearRegression()を呼び出すことで実装できます。
Scikit-learnを使った単回帰分析のポイント
- データの準備: 単回帰分析では、説明変数と目的変数の2つの変数が必要です。これらの変数を準備します。また、データセットをトレーニングデータとテストデータに分割する必要があります。
- モデルの作成: Scikit-learnでは、線形回帰モデルを使って単回帰分析を行います。線形回帰モデルを作成するには、LinearRegressionクラスをインポートし、インスタンスを作成します。
- モデルのトレーニング: トレーニングデータを使って、モデルをトレーニングします。LinearRegressionクラスのfit()メソッドを使ってトレーニングを行います。
- モデルの評価: テストデータを使って、モデルの予測精度を評価します。LinearRegressionクラスのscore()メソッドを使って、R2スコアを計算します。
- モデルの利用: トレーニングが完了したモデルを使って、新しいデータに対する予測を行います。LinearRegressionクラスのpredict()メソッドを使って予測を行います。
ボストン住宅価格のデータセット(学習用サンプル)で行う単回帰分析
ボストン住宅価格データのロード
Boston Housingデータセットは、1970年代にアメリカ合衆国のボストン市で収集された住宅価格データを含む、scikit-learnのサンプルデータセットの一つです。以下のようにして、scikit-learnでBoston Housingデータセットを読み込むことができます。
from sklearn.datasets import load_boston boston = load_boston()
読み込んだデータセットは、boston.data
に説明変数(13種類)が、boston.target
に目的変数(住宅価格)が格納されています。また、boston.feature_names
には説明変数の名前が、boston.DESCR
にはデータセットの説明が含まれています。
bostonデータセットはBunch型(辞書型に似ている)になっていますので辞書のようにキーを指定することでデータを取り出すことが可能です。
または、ドット(.)でつなぐ属性の取り出し方でも取り出すことができます。
*Bunch型は辞書類似型のクラスで、データセットのパッケージに用いられます。
説明変数と目的変数
説明変数とは、分析対象のデータにおいて、その結果を説明するために使用される変数のことです。また、独立変数、予測変数、入力変数などとも呼ばれます。一般的には、説明変数は縦軸に表示される変数で、その値に基づいて横軸に表示される目的変数の値を説明する役割を持ちます。
一方、目的変数とは、説明変数によって予測される対象の変数のことです。また、従属変数、応答変数、出力変数などとも呼ばれます。例えば、ある商品の売上を予測する場合、売上が目的変数であり、その売上に影響を与える要因(価格、広告費、天気など)が説明変数となります。
説明変数と目的変数は、データ分析や機械学習において非常に重要な役割を持ちます。目的変数を説明するために最も効果的な説明変数を見つけることで、予測精度を高めたり、効果的な意思決定を行うことができます。
説明変数の構成
項目 | 内容 |
---|---|
CRIM | 人口 1 人当たりの犯罪発生数 |
ZN | 25,000 平方フィート以上の住居区画の占める割合 |
INDUS | 小売業以外の商業が占める面積の割合 |
CHAS | チャールズ川によるダミー変数 (1: 川の周辺, 0: それ以外) |
NOX | NOx の濃度 |
RM | 住居の平均部屋数 |
AGE | 1940 年より前に建てられた物件の割合 |
DIS | 5 つのボストン市の雇用施設からの距離 (重み付け済) |
RAD | 環状高速道路へのアクセスしやすさ |
TAX | $10,000 ドルあたりの不動産税率の総計 |
PTRATIO | 町毎の児童と教師の比率 |
B | 町毎の黒人 (Bk) の比率を次の式で表したもの。 1000(Bk – 0.63)^2 |
LSTAT | 給与の低い職業に従事する人口の割合 (% |
目的変数
MEDV 住宅価格の中央値(単位 1000ドル)
データ観察
分析をする時はまずデータの特徴をしっかりと観察しておくことが大事です。
PandasのDataFrame型に変換してデータを観察すると非常にわかりやすくなります。
boston_pd = pd.DataFrame(boston.data, columns=boston.feature_names) boston_pd.head(10)
表示結果 (最左列にある太字の0〜9は行番号)
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18.0 | 2.31 | 0.0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1.0 | 296.0 | 15.3 | 396.90 | 4.98 |
1 | 0.02731 | 0.0 | 7.07 | 0.0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2.0 | 242.0 | 17.8 | 396.90 | 9.14 |
2 | 0.02729 | 0.0 | 7.07 | 0.0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2.0 | 242.0 | 17.8 | 392.83 | 4.03 |
3 | 0.03237 | 0.0 | 2.18 | 0.0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3.0 | 222.0 | 18.7 | 394.63 | 2.94 |
4 | 0.06905 | 0.0 | 2.18 | 0.0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3.0 | 222.0 | 18.7 | 396.90 | 5.33 |
5 | 0.02985 | 0.0 | 2.18 | 0.0 | 0.458 | 6.430 | 58.7 | 6.0622 | 3.0 | 222.0 | 18.7 | 394.12 | 5.21 |
6 | 0.08829 | 12.5 | 7.87 | 0.0 | 0.524 | 6.012 | 66.6 | 5.5605 | 5.0 | 311.0 | 15.2 | 395.60 | 12.43 |
7 | 0.14455 | 12.5 | 7.87 | 0.0 | 0.524 | 6.172 | 96.1 | 5.9505 | 5.0 | 311.0 | 15.2 | 396.90 | 19.15 |
8 | 0.21124 | 12.5 | 7.87 | 0.0 | 0.524 | 5.631 | 100.0 | 6.0821 | 5.0 | 311.0 | 15.2 | 386.63 | 29.93 |
9 | 0.17004 | 12.5 | 7.87 | 0.0 | 0.524 | 6.004 | 85.9 | 6.5921 | 5.0 | 311.0 | 15.2 | 386.71 | 17.10 |
目的変数を追加
ボストンデータセットは説明変数(boston.data)と目的変数(boston.target)が別々になっています。そのため、boston_pd に目的変数を追加して一覧表示させます。
boston_pd['PRICE'] = boston.target boston_pd
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | PRICE | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18.0 | 2.31 | 0.0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1.0 | 296.0 | 15.3 | 396.90 | 4.98 | 24.0 |
1 | 0.02731 | 0.0 | 7.07 | 0.0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2.0 | 242.0 | 17.8 | 396.90 | 9.14 | 21.6 |
2 | 0.02729 | 0.0 | 7.07 | 0.0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2.0 | 242.0 | 17.8 | 392.83 | 4.03 | 34.7 |
3 | 0.03237 | 0.0 | 2.18 | 0.0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3.0 | 222.0 | 18.7 | 394.63 | 2.94 | 33.4 |
4 | 0.06905 | 0.0 | 2.18 | 0.0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3.0 | 222.0 | 18.7 | 396.90 | 5.33 | 36.2 |
… | … | … | … | … | … | … | … | … | … | … | … | … | … | … |
501 | 0.06263 | 0.0 | 11.93 | 0.0 | 0.573 | 6.593 | 69.1 | 2.4786 | 1.0 | 273.0 | 21.0 | 391.99 | 9.67 | 22.4 |
502 | 0.04527 | 0.0 | 11.93 | 0.0 | 0.573 | 6.120 | 76.7 | 2.2875 | 1.0 | 273.0 | 21.0 | 396.90 | 9.08 | 20.6 |
503 | 0.06076 | 0.0 | 11.93 | 0.0 | 0.573 | 6.976 | 91.0 | 2.1675 | 1.0 | 273.0 | 21.0 | 396.90 | 5.64 | 23.9 |
504 | 0.10959 | 0.0 | 11.93 | 0.0 | 0.573 | 6.794 | 89.3 | 2.3889 | 1.0 | 273.0 | 21.0 | 393.45 | 6.48 | 22.0 |
505 | 0.04741 | 0.0 | 11.93 | 0.0 | 0.573 | 6.030 | 80.8 | 2.5050 | 1.0 | 273.0 | 21.0 | 396.90 | 7.88 | 11.9 |
要約統計量
Pandasの要約統計量(summary statistics)とは、データフレームやシリーズの各列に対して、平均値、中央値、標準偏差、四分位数などの基本的な統計量を計算して表示する機能のことです。Pandasは、describe()
メソッドを使って要約統計量を簡単に出力できます。
項目名 | 意味 |
---|---|
count | そのカラムの件数 |
mean | 平均 |
std | 標準偏差 |
min | 最小値 |
25% | 第一四分位数 |
50% | 第二四分位数 |
75% | 第三四分位数 |
max | 最大値 |
boston_pd.describe()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | PRICE | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 |
mean | 3.613524 | 11.363636 | 11.136779 | 0.069170 | 0.554695 | 6.284634 | 68.574901 | 3.795043 | 9.549407 | 408.237154 | 18.455534 | 356.674032 | 12.653063 | 22.532806 |
std | 8.601545 | 23.322453 | 6.860353 | 0.253994 | 0.115878 | 0.702617 | 28.148861 | 2.105710 | 8.707259 | 168.537116 | 2.164946 | 91.294864 | 7.141062 | 9.197104 |
min | 0.006320 | 0.000000 | 0.460000 | 0.000000 | 0.385000 | 3.561000 | 2.900000 | 1.129600 | 1.000000 | 187.000000 | 12.600000 | 0.320000 | 1.730000 | 5.000000 |
25% | 0.082045 | 0.000000 | 5.190000 | 0.000000 | 0.449000 | 5.885500 | 45.025000 | 2.100175 | 4.000000 | 279.000000 | 17.400000 | 375.377500 | 6.950000 | 17.025000 |
50% | 0.256510 | 0.000000 | 9.690000 | 0.000000 | 0.538000 | 6.208500 | 77.500000 | 3.207450 | 5.000000 | 330.000000 | 19.050000 | 391.440000 | 11.360000 | 21.200000 |
75% | 3.677083 | 12.500000 | 18.100000 | 0.000000 | 0.624000 | 6.623500 | 94.075000 | 5.188425 | 24.000000 | 666.000000 | 20.200000 | 396.225000 | 16.955000 | 25.000000 |
max | 88.976200 | 100.000000 | 27.740000 | 1.000000 | 0.871000 | 8.780000 | 100.000000 | 12.126500 | 24.000000 | 711.000000 | 22.000000 | 396.900000 | 37.970000 | 50.000000 |
相関関係の確認
pandas.DataFrameオブジェクトからcorr()メソッドを呼ぶと、相関係数が算出されます。
単回帰分析では、説明変数と目的変数で相関が高い説明変数を見つけることが重要です。
相関係数(Correlation coefficient)は、2つの変数の間の関係を示す統計指標の一つです。具体的には、2つの変数がどの程度一緒に変動するかを表現します。相関係数は、-1から1までの値をとり、以下のように解釈されます。
- 相関係数が1に近い場合、2つの変数は強い正の相関があると言えます。つまり、一方が増加するともう一方も増加する傾向があるということです。
- 相関係数が0に近い場合、2つの変数は相関がないと言えます。つまり、一方が増加してももう一方に影響を与えないということです。
- 相関係数が-1に近い場合、2つの変数は強い負の相関があると言えます。つまり、一方が増加するともう一方が減少する傾向があるということです。
相関係数は、データの分布や外れ値の影響を受けやすいため、単に相関があるとして因果関係があるとは言えません。
boston_pd.corr()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | PRICE | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
CRIM | 1.000000 | -0.200469 | 0.406583 | -0.055892 | 0.420972 | -0.219247 | 0.352734 | -0.379670 | 0.625505 | 0.582764 | 0.289946 | -0.385064 | 0.455621 | -0.388305 |
ZN | -0.200469 | 1.000000 | -0.533828 | -0.042697 | -0.516604 | 0.311991 | -0.569537 | 0.664408 | -0.311948 | -0.314563 | -0.391679 | 0.175520 | -0.412995 | 0.360445 |
INDUS | 0.406583 | -0.533828 | 1.000000 | 0.062938 | 0.763651 | -0.391676 | 0.644779 | -0.708027 | 0.595129 | 0.720760 | 0.383248 | -0.356977 | 0.603800 | -0.483725 |
CHAS | -0.055892 | -0.042697 | 0.062938 | 1.000000 | 0.091203 | 0.091251 | 0.086518 | -0.099176 | -0.007368 | -0.035587 | -0.121515 | 0.048788 | -0.053929 | 0.175260 |
NOX | 0.420972 | -0.516604 | 0.763651 | 0.091203 | 1.000000 | -0.302188 | 0.731470 | -0.769230 | 0.611441 | 0.668023 | 0.188933 | -0.380051 | 0.590879 | -0.427321 |
RM | -0.219247 | 0.311991 | -0.391676 | 0.091251 | -0.302188 | 1.000000 | -0.240265 | 0.205246 | -0.209847 | -0.292048 | -0.355501 | 0.128069 | -0.613808 | 0.695360 |
AGE | 0.352734 | -0.569537 | 0.644779 | 0.086518 | 0.731470 | -0.240265 | 1.000000 | -0.747881 | 0.456022 | 0.506456 | 0.261515 | -0.273534 | 0.602339 | -0.376955 |
DIS | -0.379670 | 0.664408 | -0.708027 | -0.099176 | -0.769230 | 0.205246 | -0.747881 | 1.000000 | -0.494588 | -0.534432 | -0.232471 | 0.291512 | -0.496996 | 0.249929 |
RAD | 0.625505 | -0.311948 | 0.595129 | -0.007368 | 0.611441 | -0.209847 | 0.456022 | -0.494588 | 1.000000 | 0.910228 | 0.464741 | -0.444413 | 0.488676 | -0.381626 |
TAX | 0.582764 | -0.314563 | 0.720760 | -0.035587 | 0.668023 | -0.292048 | 0.506456 | -0.534432 | 0.910228 | 1.000000 | 0.460853 | -0.441808 | 0.543993 | -0.468536 |
PTRATIO | 0.289946 | -0.391679 | 0.383248 | -0.121515 | 0.188933 | -0.355501 | 0.261515 | -0.232471 | 0.464741 | 0.460853 | 1.000000 | -0.177383 | 0.374044 | -0.507787 |
B | -0.385064 | 0.175520 | -0.356977 | 0.048788 | -0.380051 | 0.128069 | -0.273534 | 0.291512 | -0.444413 | -0.441808 | -0.177383 | 1.000000 | -0.366087 | 0.333461 |
LSTAT | 0.455621 | -0.412995 | 0.603800 | -0.053929 | 0.590879 | -0.613808 | 0.602339 | -0.496996 | 0.488676 | 0.543993 | 0.374044 | -0.366087 | 1.000000 | -0.737663 |
PRICE | -0.388305 | 0.360445 | -0.483725 | 0.175260 | -0.427321 | 0.695360 | -0.376955 | 0.249929 | -0.381626 | -0.468536 | -0.507787 | 0.333461 | -0.737663 | 1.000000 |
最後のPRICEの行を注目すると価格と相関関係の高い説明変数がわかります。
この場合、LSTATが -0.737663で負の相関にありますが、相関関係が高いことがわかります。
そのため、単回帰分析にはLSTATを使うことにします。
分かりやすいように説明変数LSTATと目的変数PRICEをそれぞれ変数に代入しておきます。
# 説明変数をfeatures features = boston_pd['LSTAT'] # 目的変数をtarget target = boston['target']
相関関係を図示
seabornを使うと簡単にグラフ化できます。
下図は LSTAT と PRICE の散布図です。負の相関が見て取れます。
sns.pairplot(boston_pd[['LSTAT', 'PRICE']])
説明変数の次元を2次元に変更
この処理はScikit-learnで単回帰分析を行う際必須です 。
Scikit-learnで学習させるデータは2次元以上の配列のデータにする必要があります。
単回帰分析の場合は説明変数が1つだけということもあり、データはフラットな配列(1次元の配列)になってしまいます。従ってフラットな配列をreshapeする必要があります。
現在の features の型はnumpy配列のndarray型のため、numpyのreshape()メソッドを使って次元を変更します。
reshape()の引数指定は reshape(行数, 列数) ですが、このメソッドの面白い使い方として列数だけ決めて行数を-1にすることで行数はその列数に応じて自動で行数を決めることができます。
reshape(-1, 1)の場合は、フラットな配列を1列にした状態で必要な行数はNumpyが自動で決めます。
例えば、次のような配列を [1, 2, 3, 4, 5] を [[1], [2], [3], [4], [5]]のように配列の形態を変えることができます。
features = features.values.reshape(-1, 1)
トレーニングデータとテストデータの分割
データ分析を行うには全てのデータを学習させてモデルを作成するのではなく、学習用のデータとトレーニング用のデータにデータを分割して学習用のデータでモデルを作成します。そうすることで学習用のデータで作成したモデルが過学習に陥ってもテストデータの予測と比較することでモデルの過学習が発見できるようになります。
Scikit-learnにはテストデータは盗み見ができない(意図的なデータの分類をしない)ように機械的に抽出する train_test_split() があります。
このメソッドはランダムな関数を活用してテストデータを抜き出すことができます。
けれども、これを何度か繰り返すと毎回テスト用とトレーニング用のデータが変わります。 それはつまりテストデータの特徴を知ってしまうことになります。
このようなことを避けるために、シードを作ることで解決することができます。
乱数シードを設定すると毎回同じ疑似乱数が得られため、いつも同じ結果を得ることができます。そうすることで再現性のあるプログラムにすることができます。
# トレーニングデータとテストデータの分割 X_train, X_test, y_train, y_test = train_test_split( features, target, random_state=1 )
線形回帰器を作成
LinearRegressionをインスタンス化して線形回帰器を作成します。
# 線形回帰器を作成 regression = LinearRegression()
モデルの学習
モデルの学習は regression.fit()を使います。
これでmodelには学習ずみのモデルが出来上がります。modelは変数なので自分の好きな名前にすることができます。
# 線形回帰器を訓練 model = regression.fit(X_train, y_train)
切片を求める
intercept_ 属性を使っうと切片を取得できます。アンダースコアが必要なので忘れないようにしましょう。
# 切片(intercept)を表示 model.intercept_
表示結果 34.12464993748093
回帰係数を求める
coef_ 属性で回帰係数が取得できます。アンダースコアが必要なので忘れないようにしましょう。
# 特徴量の係数(coefficient)を表示 model.coef_
# 表示結果
array([-0.91062928])
決定係数 (R^2)
決定係数 (R2, R-squared, coefficient of determination) は、モデルの当てはまりの良さを示す指標で、最も当てはまりの良い場合、1.0 となります (当てはまりの悪い場合、マイナスとなることもあります)。寄与率 (きよりつ) とも呼ばれます。
model.score(features, target)
# 表示結果
0.543152101306229
ボストン住宅価格を重回帰分析するための考え方
ボストン住宅価格を重回帰分析するには単回帰分析の手法とほとんど変わりません。変える必要があるのは、説明変数を一つに絞るのではなく複数の説明変数を使用することが特徴です。
複数の説明変数を使用することから、単回帰分析のように散布図と回帰直線を描くことができず可視化できないところに直感的な分かりにくさがありますが、精度としては単回帰分析より上がる場合が多いです。
Scikit-learnを使う上での注意点は、単回帰分析では説明変数の次元を2次元にreshapeする工程がありましたが、重回帰分析ではその必要がありません。
多重共線性
多重共線性(multicollinearity)とは、回帰分析において、説明変数同士の相関が高い場合に発生する問題です。つまり、2つ以上の説明変数が強い相関を持つと、それらの説明変数が互いに影響し合い、回帰係数の信頼性が低下する可能性があります。
多重共線性が発生すると、以下のような問題が発生する可能性があります。
-
回帰係数の解釈が困難になる:複数の説明変数が互いに強く相関している場合、そのうちの1つの説明変数の回帰係数が正であっても、別の説明変数の回帰係数が負になることがあり、その解釈が難しくなります。
-
予測精度が低下する:多重共線性があると、説明変数の変動に対する目的変数の変動の説明が曖昧になり、モデルの予測精度が低下する可能性があります。
-
信頼区間が広がる:多重共線性があると、回帰係数の推定値の分散が大きくなり、信頼区間が広がる傾向があります。
多重共線性を解決するためには、以下のような手法があります。
-
相関係数の確認:説明変数同士の相関係数を確認し、相関が強い場合は1つの説明変数を削除するなどして、相関を低減することが考えられます。
-
主成分分析(PCA):PCAを用いて、説明変数を少数の独立な成分に変換することで、多重共線性を解消することができます。
-
リッジ回帰:リッジ回帰では、回帰係数の推定値を大きくしないようにするために、正則化項を加えることができます。これにより、多重共線性がある場合でも、回帰係数の推定値を安定させることができます。