#1.機械学習
学習種類 | タスク | 機械学習モデル | パラメータの推定問題 | モデル選択・評価 |
---|---|---|---|---|
教師あり学習 | 予測 | 線形回帰・非線形回帰 | 最小二乗法・尤度最大化(最尤法) | ホールドアウト法・交差検証 |
分類 | ロジスティック回帰 | 尤度最大化(最尤法) | ||
最近傍・k-近傍アルゴリズム | ||||
サポートベクターマシン | マージン最大化 | |||
教師なし学習 | クラスタリング | k-meansアルゴリズム | なし | |
次元削減 | 主成分分析 | 分散最大化 |
#2.線形回帰モデル
パラメータ $$ w = (w_1,w_2,・・・,w_m)^T \in \mathbb{R}^m $$
予測値 $$ \hat{y} = w^T x + w_0 = \sum_{j=1}^{m} w_j x_j + w_0 $$
●線形結合(入力とパラメータの内積)
○入力ベクトルと未知のパラメータの各要素を掛け算し足し合わせたもの
○入力ベクトルとの線形結合に加え、切片も足し合わせる
○(入力ベクトルが多次元でも)出力は1次元(スカラ)となる
線形結合
\hat{y} = \underline{w^T} x + \underline{w_0} =
\sum_{j=1}^{m} \underline{w_j} x_j + \underline{w_0}
下線を引いているパタメータは未知
●モデルのパラメータ
○モデルに含まれる推定すべき未知のパラメータ
○特徴量が予測値に対してどのように影響を与えるかを決定する重みの集合
■正の(負の)重みをつける場合、その特徴量の値を増加させると、予測の値が増加(減少)
■重みが大きければ(0であれば)、その特徴量は予測に大きな影響力を持つ(全く影響しない)
○切片
■y軸との交点を表す
最小二乗法により推定
●説明変数が1次元(m=1)
○単回帰モデルと呼ぶ
●データへの仮定
○データは回帰直線に誤差が加わり観測されていると仮定
モデル数式 $$ y = w_0 + w_1 x_1 + \varepsilon $$
y:目的変数
$w_0$:切片
$w_1$:回帰係数
$x_1$:説明変数
$\varepsilon$:誤差
連立方程式
\begin{eqnarray}
y_1 &= \boxed{w_0} + \boxed{w_1} x_1 + \varepsilon_1 \\
y_2 &= \boxed{w_0} + \boxed{w_1} x_2 + \varepsilon_2 \\
\vdots \\
y_n &= \boxed{w_0} + \boxed{w_1} x_n + \varepsilon_n
\end{eqnarray}
行列表現
\boldsymbol{y} = \boldsymbol{X} \boldsymbol{w} + \boldsymbol{\varepsilon}
$\boldsymbol{X} =
(\boldsymbol{x_1},\boldsymbol{x_2},・・・,\boldsymbol{x_n})^T$
$\boldsymbol{y} = (y_1,y_2,・・・,y_n)^T$
$\boldsymbol{x_i} = (1,\boldsymbol{x_1})^T$
$\boldsymbol{\varepsilon} =
(\varepsilon_1,\varepsilon_2,・・・,\varepsilon_n)^T $
$ \boxed{\boldsymbol{w} = (w_0,w_1)^T}$
連立方程式・行列表現ともに四角で囲った物が未知のパラメータとなる。
※実装時は行列表現や行列の計算をまちがえやすいので、こまめに型を確認する。
●説明変数が多次元の場合(m>1)
○線形重回帰モデル
○単回帰は直線⇨重回帰は曲面(超平面)
●データへの仮定
○データは回帰曲面に誤差が加わり観測されていると仮定
モデル数式 $$y = w0 + w1x1 + w2x2 + ε$$
y:目的変数
$w_0$:切片
$w_1,w_2$:回帰係数
$x_1,x_2$:説明変数
$\varepsilon$:誤差
連立方程式
\begin{eqnarray}
y_1 &= \boxed{w_0} + \boxed{w_1} x_{11} + \boxed{w_2} x_{21} + \cdots +
\boxed{w_m} x_{1m} + \varepsilon_1 \\
y_2 &= \boxed{w_0} + \boxed{w_1} x_{21} + \boxed{w_2} x_{22} + \cdots +
\boxed{w_m} x_{1m} +\varepsilon_1 \\
\vdots \\
y_n &= \boxed{w_0} + \boxed{w_1} x_{n1} + \boxed{w_2} x_{n2} + \cdots +
\boxed{w_m} x_{nm} +\varepsilon_1 \varepsilon_n
\end{eqnarray}
行列表現
$$ y = Xw + \varepsilon $$
$\boldsymbol{X} =
(\boldsymbol{x_1},\boldsymbol{x_2},・・・,\boldsymbol{x_n})^T$
$\boldsymbol{y} = (y_1, y_2, ・・・ , y_n)^T$
$\boldsymbol{x_i} = (1, x_{i1}, x_{i2} , ・・・ , x_{im})^T$
$\boldsymbol{\varepsilon} =
(\varepsilon_1, \varepsilon_2, ・・・, \varepsilon_n)^T $
$ \boxed{\boldsymbol{w} = (w_0, w_1 , w_2 , ・・・ , w_n)^T}$
●データの分割
○学習用データ:機械学習モデルの学習に用いるデータ
○検証用データ:学習済みモデルの精度を検証するためのデータ
●なぜ分割するか
○モデルの汎化性能(Generalization)を測定するため
○データへの当てはまりの良さではなく、未知のデータに対してどれくらい精度が高いかを測る
※最終的には手元にないデータが入ってきた時に正しい識別ができるようにする。
学習データ
$$ { (x_i^{(train)} , y_i^{(train)});i = 1,・・・, n_{train} } $$
検証データ
$$ { (x_i^{(test)} , y_i^{(test)});i = 1,・・・, n_{test} } $$
MSE_{train} = \frac{1}{n_{train}} \sum_{i=1}^{n_{train}}
(\hat{y}_i^{train} - y_i^{train})^2
※二乗損失は一般に外れ値に弱い、ゆえに使用する際は外れ値がないか確認する。
外れ値に強い損失関数として、Huber損失、Tukey損失などがある。
最終的には、MSEの誤差が小さくなるようなwを探していく。
\hat{w} = arg\ min\ MSE_{train} \\
w \in \mathbb{R}^{m+1}
最小化するにあたって、MSEをwに関して、微分したものが0になるようなwを求める
\begin{eqnarray}
\frac{\partial}{\partial w} MSE_{train} = 0
\end{eqnarray}
MSEの微分
\frac{\partial}{\partial w} \bigl\{ \frac{1}{n_{train}}
\sum_{i=1}^{n_{train}}
(\hat{y}_i^{train} - y_i^{train})^2 \bigr\} = 0 \\
⇨ \frac{1}{n_{train}}\frac{\partial}{\partial w} \bigl\{ (X^{(train)} w \
- y^{(train)} )^T (X^{(train)} w \ - y^{(train)}) \bigr\} = 0 \\
⇨\frac{1}{n_{train}}\frac{\partial}{\partial w} \bigl\{ w^T X^{(train)T}
X^{(train)} w - 2w^T X^{(train)T} y^{(train)} + y^{(train)T} y^{(train)}
\bigr\} \\
⇨2 X^{(train)T} X^{(tarin)} w - 2 X^{(train)T} y^{(train)} = 0 \\
⇨\hat{w} = \bigl( X^{(train)T} X^{(train)} \bigr)^{-1} X^{(train)}
y^{(train)}
1行目:平均二乗和誤差(MSE)に関してwで微分
2行目:行列を変形
具体的には、$ \frac{1}{n_{train}} $ を括弧の外に出し、
$\hat{y}^{(train)}$ を元の式である、Xwの形に分解
3行目:{ }の中を展開
4行目:行列微分計算
5行目:回帰係数
回帰係数
$$ \hat{w} = \bigl( X^{(train)T} X^{(train)} \bigr)^{-1} X^{(train)}
y^{(train)} $$
予測値
$$ \hat{y} = X ( X^{(train)T} X^{(trainT})^{-1} X^{(train)T} y^{(train)}
$$
●[topic] 最尤法による回帰係数の推定
○誤差を正規分布に従う確率変数を仮定し尤度関数の最大化を利用した推定も可能
○線形回帰の場合には、最尤法による解は最小二乗法の解と一致回帰係数予測値
#3.ハンズオン
●使用するデータセット
データセット名 | ボストンの住宅データセット(ボストン市の住宅価格) |
レコード数 | 506 |
カラム数 | 14 |
詳細 | UCI Machine Learning Repository: Housing Data Set |
備考 | よく線形回帰モデルのテストセットとして使用される |
○numpy
■特徴:値計算を効率的に行うための拡張モジュール。
効率的な計算を行うための型付きの多次元配列のサポートをPythonに加えるとともに、
それらを操作するための大規模な高水準の数学関数ライブラリを提供する。
○pandas
■特徴:Excelのような2次元のテーブルを対象にした、
データ解析を支援する機能を提供するライブラリです。
DataFrame がpandasのメインとなるデータ構造で二次元のテーブルを表します。
#from モジュール名 import クラス名(もしくは関数名や変数名)
from sklearn.datasets import load_boston
from pandas import DataFrame
import numpy as np
#ボストンデータを"boston"というインスタンスにインポート
boston = load_boston()
2.データの確認
#インポートしたデータを確認(型の確認)
print(type(boston))
#実行結果
# <class 'sklearn.utils.Bunch'>
実行結果からbostonのデータセットは「sklearn.utils.Bunch」型と判明
Bunch クラスは辞書類似型のクラスで、データセットのパッケージに用いられる。
#インポートしたデータを確認(プロパティの確認)
print(dir(boston))
#実行結果
#['DESCR', 'data', 'feature_names', 'filename', 'target']
dir()でプロパティの確認
各項目は以下が、格納されている。
DESCR:データセットの詳細情報
data:説明変数
feature_names:カラム名
filename:ファイルの格納場所
target:目的変数
#DESCR変数の中身を確認
print(boston['DESCR'])
#実行結果
#.. _boston_dataset:
#Boston house prices dataset
#---------------------------
#**Data Set Characteristics:**
#:Number of Instances: 506
#:Number of Attributes: 13 numeric/categorical predictive. Median Value (attribute 14) is usually the target.
#:Attribute Information (in order):
#- 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
#- CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
#- NOX nitric oxides concentration (parts per 10 million)
#- RM average number of rooms per dwelling
#- AGE proportion of owner-occupied units built prior to 1940
#- DIS weighted distances to five Boston employment centres
#- RAD index of accessibility to radial highways
#- TAX full-value property-tax rate per $10,000
#- PTRATIO pupil-teacher ratio by town
#- B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
#- LSTAT % lower status of the population
#- MEDV Median value of owner-occupied homes in $1000's
#:Missing Attribute Values: None
#:Creator: Harrison, D. and Rubinfeld, D.L.
#This is a copy of UCI ML housing dataset.
#https://archive.ics.uci.edu/ml/machine-learning-databases/housing/
#This dataset was taken from the StatLib library which is maintained at
#Carnegie Mellon University.
#The Boston house-price data of Harrison, D. and Rubinfeld, D.L. 'Hedonic
#prices and the demand for clean air', J. Environ. Economics & Management,
#vol.5, 81-102, 1978. Used in Belsley, Kuh & Welsch, 'Regression diagnostics
#...', Wiley, 1980. N.B. Various transformations are used in the table on
#pages 244-261 of the latter.
#The Boston house-price data has been used in many machine learning papers that address regression
#problems.
#.. topic:: References
#- Belsley, Kuh & Welsch, 'Regression diagnostics: Identifying Influential Data and Sources of Collinearity', Wiley, 1980. 244-261.
DESCRにはデータセットについての詳細な情報が載っている
例えば「#:Number of Instances: 506 」はレコード数
「#- CRIM per capita crime rate by town」は説明変数の犯罪発生率など
#feature_names変数の中身を確認
print(boston['feature_names'])
#実行結果
#['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
#'B' 'LSTAT']
#data変数(説明変数)の中身を確認
print(boston['data'])
#実行結果
#[[6.3200e-03 1.8000e+01 2.3100e+00 ... 1.5300e+01 3.9690e+02 4.9800e+00]
#[2.7310e-02 0.0000e+00 7.0700e+00 ... 1.7800e+01 3.9690e+02 9.1400e+00]
#[2.7290e-02 0.0000e+00 7.0700e+00 ... 1.7800e+01 3.9283e+02 4.0300e+00]
#...
#[6.0760e-02 0.0000e+00 1.1930e+01 ... 2.1000e+01 3.9690e+02 5.6400e+00]
#[1.0959e-01 0.0000e+00 1.1930e+01 ... 2.1000e+01 3.9345e+02 6.4800e+00]
#[4.7410e-02 0.0000e+00 1.1930e+01 ... 2.1000e+01 3.9690e+02 7.8800e+00]]
接名変数の中身には実際のデータが入っている。
「・・・」で省略されているが、実際には506レコード・13カラム分ある
実際の値を見たり、最初の○行を表示したりなどは後述
#target変数(目的変数)の中身を確認
print(boston['target'])
#実行結果
#[24. 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 15. 18.9 21.7 20.4
#18.2 19.9 23.1 17.5 20.2 18.2 13.6 19.6 15.2 14.5 15.6 13.9 16.6 14.8
#18.4 21. 12.7 14.5 13.2 13.1 13.5 18.9 20. 21. 24.7 30.8 34.9 26.6
#25.3 24.7 21.2 19.3 20. 16.6 14.4 19.4 19.7 20.5 25. 23.4 18.9 35.4
#24.7 31.6 23.3 19.6 18.7 16. 22.2 25. 33. 23.5 19.4 22. 17.4 20.9
#24.2 21.7 22.8 23.4 24.1 21.4 20. 20.8 21.2 20.3 28. 23.9 24.8 22.9
#23.9 26.6 22.5 22.2 23.6 28.7 22.6 22. 22.9 25. 20.6 28.4 21.4 38.7
#43.8 33.2 27.5 26.5 18.6 19.3 20.1 19.5 19.5 20.4 19.8 19.4 21.7 22.8
#18.8 18.7 18.5 18.3 21.2 19.2 20.4 19.3 22. 20.3 20.5 17.3 18.8 21.4
#15.7 16.2 18. 14.3 19.2 19.6 23. 18.4 15.6 18.1 17.4 17.1 13.3 17.8
#14. 14.4 13.4 15.6 11.8 13.8 15.6 14.6 17.8 15.4 21.5 19.6 15.3 19.4
#17. 15.6 13.1 41.3 24.3 23.3 27. 50. 50. 50. 22.7 25. 50. 23.8
#23.8 22.3 17.4 19.1 23.1 23.6 22.6 29.4 23.2 24.6 29.9 37.2 39.8 36.2
#37.9 32.5 26.4 29.6 50. 32. 29.8 34.9 37. 30.5 36.4 31.1 29.1 50.
#33.3 30.3 34.6 34.9 32.9 24.1 42.3 48.5 50. 22.6 24.4 22.5 24.4 20.
#21.7 19.3 22.4 28.1 23.7 25. 23.3 28.7 21.5 23. 26.7 21.7 27.5 30.1
#44.8 50. 37.6 31.6 46.7 31.5 24.3 31.7 41.7 48.3 29. 24. 25.1 31.5
#23.7 23.3 22. 20.1 22.2 23.7 17.6 18.5 24.3 20.5 24.5 26.2 24.4 24.8
#29.6 42.8 21.9 20.9 44. 50. 36. 30.1 33.8 43.1 48.8 31. 36.5 22.8
#30.7 50. 43.5 20.7 21.1 25.2 24.4 35.2 32.4 32. 33.2 33.1 29.1 35.1
#45.4 35.4 46. 50. 32.2 22. 20.1 23.2 22.3 24.8 28.5 37.3 27.9 23.9
#21.7 28.6 27.1 20.3 22.5 29. 24.8 22. 26.4 33.1 36.1 28.4 33.4 28.2
#22.8 20.3 16.1 22.1 19.4 21.6 23.8 16.2 17.8 19.8 23.1 21. 23.8 23.1
#20.4 18.5 25. 24.6 23. 22.2 19.3 22.6 19.8 17.1 19.4 22.2 20.7 21.1
#19.5 18.5 20.6 19. 18.7 32.7 16.5 23.9 31.2 17.5 17.2 23.1 24.5 26.6
#22.9 24.1 18.6 30.1 18.2 20.6 17.8 21.7 22.7 22.6 25. 19.9 20.8 16.8
#21.9 27.5 21.9 23.1 50. 50. 50. 50. 50. 13.8 13.8 15. 13.9 13.3
#13.1 10.2 10.4 10.9 11.3 12.3 8.8 7.2 10.5 7.4 10.2 11.5 15.1 23.2
#9.7 13.8 12.7 13.1 12.5 8.5 5. 6.3 5.6 7.2 12.1 8.3 8.5 5.
#11.9 27.9 17.2 27.5 15. 17.2 17.9 16.3 7. 7.2 7.5 10.4 8.8 8.4
#16.7 14.2 20.8 13.4 11.7 8.3 10.2 10.9 11. 9.5 14.5 14.1 16.1 14.3
#11.7 13.4 9.6 8.7 8.4 12.8 10.5 17.1 18.4 15.4 10.8 11.8 14.9 12.6
#14.1 13. 13.4 15.2 16.1 17.8 14.9 14.1 12.7 13.5 14.9 20. 16.4 17.7
#19.5 20.2 21.4 19.9 19. 19.1 19.1 20.1 19.9 19.6 23.2 29.8 13.8 13.3
#16.7 12. 14.6 21.4 23. 23.7 25. 21.8 20.6 21.2 19.1 20.6 15.2 7.
#8.1 13.6 20.1 21.8 24.5 23.1 19.7 18.3 21.2 17.5 16.8 22.4 20.6 23.9
#22. 11.9]
目的変数には、住宅価格($1000単位)が格納されている。
作成していく線形回帰モデルはこの目的変数に近い値になるように調整していく。
3.データフレームワークの作成
# 説明変数らをDataFrameへ変換
df = DataFrame(data=boston.data,columns=boston.feature_names)
# 目的変数をDataFrameへ追加
df['price'] = np.array(boston.target)
pandasのデータフレームを使用して、説明変数・目的変数を変換する。
# 最初の6行を表示
df.head(6)
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 |
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 | 28.7 |
4.線形単回帰分析
今回は「RM(1戸あたりの平均部屋数)で分析を行う。
#説明変数の要素を抽出
data = df.loc[:, ['RM']].values
df.locにて、今回対象のRMを抽出する、
[]の中身は[どこからどこまで,どのカラムを]を選択できる。
今回は、全てが対象のなので、「:」のみで、カラムは「RM」を指定する。
loc以外にも、iloc, at, iat 属性(attribute)が存在する。
#確認のためのdataリストの表示(1-5)
data[0:5]
#実行結果
#array([[6.575],
# [6.421],
# [7.185],
# [6.998],
# [7.147]])
次に、目的変数である、「price」を抽出する。
#目的変数の要素を抽出
target = df.loc[:, ['price']].values
#targetリストの表示(1-5)
target[0:5]
#実行結果
#array([24. , 21.6, 34.7, 33.4, 36.2])
線形回帰モデル用のモジュールをインポート
#skleanモジュールからLinearRegressionをインポート
from sklearn.linear_model import LinearRegression
#オブジェクトの作成
model = LinearRegression()
model.get_params()
#実行結果
#{'copy_X': True, 'fit_intercept': True, 'n_jobs': None, 'normalize': False}
LinerRegression()でオブジェクトを作成し、各パラメータの確認
各パラメータの設定値の説明は以下である。
copy_X:メモリ内でデータを複製してから実行するかどうか。 (デフォルト値: True)
fit_insercept:False に設定すると切片を求める計算を含めない。
目的変数が原点を必ず通る性質のデータを扱うときに利用。 (デフォルト値: True)
n_jobs:計算に使うジョブの数。
-1 に設定すると、すべての CPU を使って計算します。 (デフォルト値: 1)
normalize:True に設定すると、説明変数を事前に正規化します。 (デフォルト値: False)
#fit関数でパラメータ推定
model.fit(data, target)
fit関数を使用して、実際に、パラメータ推定が行えるようにする。
#予測
model.predict([[1]])
#実行結果
#array([-25.5685118])
実際に実行してみる。
今回は、部屋数を1で計算。
すると、実行結果は約-25となった。
目的変数である、住宅価格でマイナスの値が出てしまった。
もう一度、RMの詳細なデータについて確認してみると
#RMカラムの最大値や最小値を抽出
df['RM'].describe()
#実行結果
#count 506.000000
#mean 6.284634
#std 0.702617
#min 3.561000
#25% 5.885500
#50% 6.208500
#75% 6.623500
#max 8.780000
#Name: RM, dtype: float64
部屋数の最小値(min)が「3.56・・・」となっている。
そのため、1部屋で分析しようとしたら、マイナスの値が出てしまった。
試しに、それらしい、6部屋で分析してみると、
#予測
model.predict([[6]])
#実行結果
#array([19.94203311])
分析予測も約19とそれらしい値となった。
しかし、「RM」だけだと1部屋などの予測ができないため、
モデル学習に、他のカラムを使ってみる。
線形重回帰分析
#説明変数
data2 = df.loc[:, ['CRIM','RM']].values
#目的変数
target2 = df.loc[:, 'price'].values
今回は説明変数に「RM」(1戸あたりの部屋数)に加え、「CRIM」(犯罪発生率)を使用する。
#オブジェクト生成
model2 = LinearRegression()
#fit関数でパラメータ推定
model2.fit(data2, target2)
単回帰分析と同じようにオブジェクトを生成し、fit関数でパラメータ推定を行う。
最後に、課題である、「部屋数が4で犯罪率が0.3の物件はいくらになるか」を出してみる。
model2.predict([[0.3, 4]])
#実行結果
#array([4.24007956])
結果としては、約4となった。
回帰係数と切片の値を確認
最後に先ほど、作成した、単回帰モデルと重回帰モデルの回帰係数と切片を確認する。
#単回帰の回帰係数と切片を出力
print('推定された回帰係数: %.3f,推定された切片: %.3f'%(model.coef_, model.intercept_))
#実行結果
#推定された回帰係数: 9.102,推定された切片: -34.671
```python
#重回帰の回帰係数と切片を出力
print(model2.coef_)
print(model2.intercept_)
#実行結果
#[-0.26491325 8.39106825]
#-29.24471945192992