読者です 読者をやめる 読者になる 読者になる

CourseraのMachine Learningから線形回帰を学んだのでまとめてみた

CourseraのMachine Learningを受講しています。時間を見つけてはコツコツ進めて今のところWeek4に差し掛かったところです。Week4ではNeural Networksの話に入り一段とレベルが高くなった印象を受けています。Week1からWeek3までに学んだことを復習する必要があるなと焦りが生まれました。

講中は配布される資料や動画を見たり他の日本人の方のブログを拝見したりと課題に取り組んできました。このタイミングで復習して整理することでWeek4以降の学習が快適になるのではないかと淡い期待を込めてWeek1からまとめてみます。

Machine Learning - Stanford University | Coursera

こちらが受講しているMachine Learningのコースです。MOOCは好きな時間に進められるし前編英語(動画は日本語字幕あり)なので英語の学習になってオススメです。

www.coursera.org

どこまでの内容をまとめるか

このエントリではWeek1の内容に触れています。

線形回帰とは?

ある土地の家の価格とその家の部屋数の相関をグラフで表すと以下のようになったとします。

f:id:n_soushi:20170310101210p:plain

Xが部屋数(RM)でYが価格(MEDV)です。

(出典:Housing Data Set

※ このデータは部屋数以外に、その土地の犯罪率だったり児童と教師の比率など複数の要素から構成されています。

部屋数が4つの場合や部屋数が7つの場合はグラフから予想できそうです。 このとき頭の中ではグラフに右肩上がりな直線をイメージして予想できますが、この直線を数式から導き出すことを学びました。 この導き方は統計学では回帰分析の一種として線形回帰と呼ばれています。

仮定関数と目的関数

部屋数をX、部屋の価格をYとすると相関を表すグラフを引くための1次関数の式は次のようになります。(懐かしい数式)

 \displaystyle
Y = aX + b

Machine Learningのコースではθをつかって次のような式で定義しています。

 \displaystyle
h_\theta (X) = \theta_0 + \theta_1(X)

 h_\theta (X)仮定関数と呼ばれます。家の価格予想に最適な直線を引くために \theta_0 \theta_1の数値を変えながらグラフにフィットした仮定関数を導き出します。 つまり右肩上がりの直線のグラフを引くために最適な  aX + babを決めるということですね。

仮定関数がフィットしているか計算するための関数である目的関数があります。

{ \displaystyle
J(\theta_0, \theta_1) = \frac{1}{2m}\sum_{i=1}^{m} (h_\theta (X_i) - Y_i)^2
}

この目的関数をつかって J(\theta_0, \theta_1)を最小にする \theta_0 \theta_1を導き出します。

最急降下法

目的関数を最小にする方法に最急降下法があります。

{ \displaystyle
\theta_j = \theta_j - \alpha \sum_{i=1}^{m} (h_\theta (x^{(i)}) - y^{(i)}) x_j\ ^{(i)}
}

ここで微分が出てきます。微分は傾きを求めますがこのアルゴリズムを使い傾きが最小になるまで学習を繰り返していきます。傾きの値が最小になるほどグラフにフィットした \theta_jが求められます。   \alphaは学習率と呼ばれ数値が大きいほど傾きの変動幅が大きくなりフィットしたデータが得られず、小さいほど学習はゆっくりと進み確実にデータにフィットした値が求められます。

Octaveでプログラム化する

コースの課題ではOctaveを使いプログラミング課題を提出します。 最初に示した家の価格と部屋数のグラフのデータを使い、更にこれまでのアルゴリズムからデータにフィットした直線をグラフにプロットしてみます。

目的関数

function J = computeCost(X, y, theta)
    m = length(y);
    J = sum((X*theta -y).^2) / (2* m);
end

最急降下法

function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
    m = length(y);
    J_history = zeros(num_iters, 1);

    for iter = 1:num_iters
        theta = theta - alpha / m * X' * (X * theta -y);
        J_history(iter) = computeCost(X, y, theta);
    end
end

目的関数を求めグラフにプロットする。そして部屋数が5つのときの価格を予想する。

%% Initialization
clear ; close all; clc
data = load("housing.txt");
x = data(:, 6);
y = data(:, 14);
m = length(y);

theta = zeros(2, 1);
X = [ones(m, 1), x]

%% Compute Cost
J = computeCost(X, y, theta)

%% Gradient Descent
iterations = 1500;
alpha = 0.01;
[theta J_history] = gradientDescent(X, y, theta, alpha, iterations);

%% Output
fprintf('Initial cost = %f\n', J);
fprintf('Final cost = %f\n', J_history(iterations));
fprintf('Theta found by gradient descent: ');
fprintf('%f %f \n', theta(1), theta(2));

%% Plot data
figure; hold on;
plot(x, y, 'r+', 'LineWidth', 2);
plot(X(:,2), X*theta, '-')
xlabel('RM');
ylabel('MEDV');

%% Predict
fprintf('for RM = 5, MEDV = %f\n', [1, 5] *theta);

出力したグラフ

f:id:n_soushi:20170310115327p:plain

データにフィットした直線がプロットできたようです。

出力した数値

J =  296.07
initial cost 296.073458
final cost 27.131052
Theta found by gradient descent: -5.254087 4.477681
for RM = 5, MEDV = 17.134317

部屋数が5つのときに 17.134317と予想できました。グラフにプロットされたデータとフィットされているようです。

まとめ

  • 最後に出したグラフですが、もう少し角度が急な直線のほうがグラフにフィットしているようです。プロットして上手く行かなければ調整して再度プロットして、の繰り返しが機械学習の大事な工程なのでしょう。
  • 線形回帰はこの先で学ぶ機械学習の知識のベースになっています。データを分類する場合などに流用できます。
  • 今回の学習データは部屋数の1つでしたが部屋数に加え犯罪率児童と教師の比率などの複数の要素からも線形回帰をベースに家の価格を予想できる。(重回帰分析)この内容はWeek2で学びました。
  • MOOCで学び、コースを修了した先輩たちのブログで学び、自分のブログでアウトプットする、など多角的に学ぶことが大事。(ここに書籍を読んで学ぶも入れたい:money_with_wings: )
  • 数式書くの大変。