Osaka の住宅価格の推定
Copyright (c) 2016, The MathWorks, Inc.
このデモでは、大阪の住宅価格を推定する回帰モデルを作成します。
データの読み込み
大阪市オープンデータポータルサイトから、大阪市の地価データをダウンロード
位置情報、部屋のサイズ、最寄り駅からの距離などの情報が住宅価格と一緒に入った Excel ファイルを Table 型として読み込みます。なお、住宅価格は一番最後の列の MedianValue という値です。
Housing = importfile_Osaka('data\Housing_Osaka_preprocessed.csv');
文字列の値が入っている ward (区)、 neighborhood (地域)、building (建物の建築材料) をカテゴリカル型に変更します。
カテゴリカル型にすることで、メモリの節約をすることができ、より大規模データを扱うことができます。
Housing.ward = categorical(Housing.ward);
Housing.neighborhood = categorical(Housing.neighborhood);
Housing.building = categorical(Housing.building);
Housing.shape_flag = categorical(Housing.shape_flag);
1. 線形回帰
fitlm 関数には一つの引数しか入れていません。デフォルトでは、テーブル型の変数 Housing の最後の変数が自動的に目的変数と認識されます。
カテゴリカル型の変数 (今回の場合は ward, neighborhood など) が含まれる際にはダミー変数を作る必要がありますが、fitlm などの回帰の関数は、自動的にカテゴリカル型の変数を認識してダミー変数を作成します。ダミー変数は数値を量的変数として扱うのではなく、Yes/No 2つの値のうちのどちらかしか取らないような質的変数です。今回の場合は、例えば ward_* というダミー変数が作成されています。
myFit = fitlm(Housing)
myFit.NumPredictors
予測に使用した変数の数は17で、自由度調整済み決定係数は 0.517と、あまり良くない結果になっています。
2. ステップワイズ回帰
ステップワイズ回帰はどの変数がモデルを改善するのに重要であるかを 見つける特徴選択の回帰方法です。
(独立)変数を追加したときに 精度が良くなれば、その変数を追加します。
また、変数を抜いたときに、 抜かない場合と結果がほぼ変わらないのであれば その変数を削除します。
変数が重要だとわかった場合、重要な変数同士の交差項も追加されます。例えば2項目の ChangeRate:road は2つの変数の交差項も見ています。
myFit2 = stepwiselm(Housing)
myFit2.NumPredictors
学習データに対する予測の描画
figure;
plot(Housing.value, 'r.');
hold on
[ypred_sw,yci_sw] = predict(myFit2, Housing);
plot(ypred_sw, 'LineWidth', 2);
plot(yci_sw(:,1), '-', 'color', [0.7 0.7 0.7])
plot(yci_sw(:,2), '-', 'color', [0.7 0.7 0.7])
xlabel('x');
ylabel('y');
legend({'data','predictions', 'confidence interval (95%)'},'Location','Best');
hold off;
title('学習データに対する予測 (ステップワイズ回帰)')
価格がとても高い場所については学習サンプル数も少ないので推定があまりうまくいっていないことが分かります。この推定を改善する方法はないでしょうか。
予測結果を地図上に描画
addpath(fullfile(pwd, 'readhgt'))
取得したい画像の緯度経度の範囲を指定します。
latlim = [34.55 34.8];
lonlim = [135.4 135.6];
画像を取得して描画します。
readhgt(latlim(1):latlim(2), lonlim(1):lonlim(2))
xlim(lonlim)
ylim(latlim)
h = gca;
delete( h.Children(1:end-1) )
h.Visible = 'on';
hold on
idx = ~isnan(myFit2.predict);
predict_res = myFit2.predict;
s = scatter(Housing(idx,:).longitude, Housing(idx,:).latitude, 70, predict_res(idx), 'filled');
図の設定の変更
hold off
alpha(s, 0.7)
colorbar('eastoutside')
title('Osaka の住宅価格 (円/㎡)')
h.Title.FontName = 'Meiryo UI'; % フォントの設定
colormap('jet'); % カラーマップの設定
3. ガウス過程回帰による住宅価格予測
gprMdl = fitrgp(Housing, 'value');
[ypred_gp,~,yci_gp] = predict(gprMdl, Housing);
学習データに対する予測の描画
figure;
plot(Housing.value, 'r.');
hold on
plot(ypred_gp, 'LineWidth', 2);
plot(yci_gp(:,1), '-', 'color', [0.7 0.7 0.7])
plot(yci_gp(:,2), '-', 'color', [0.7 0.7 0.7])
xlabel('x');
ylabel('y');
legend({'data','predictions', 'confidence interval (95%)'},'Location','Best');
hold off;
title('学習データに対する予測 (ガウス過程回帰)')
新規データに対する住宅価格予測
住宅情報の入ったテーブル型変数 Housing1を読み込みます。
load Housing1
1行目は大阪駅周辺、2行目は放出駅の緯度経度情報です。その他の項目は ward (区) 情報以外同じです。
市の中心部の駅(大阪駅)と、中心街から少し離れた駅(放出駅)で値段の違いがあるか見てみましょう。
OsakaStation = predict(gprMdl, Housing1(1,:));
round(OsakaStation)
HanatenStation_close = predict(gprMdl, Housing1(2,:));
round(HanatenStation_close)
1平方メータあたりの価格は、大阪駅周辺でおよそ73.9万円、放出駅周辺でおよそ71.0万円で、大阪駅周辺の方が高いことがわかります。
2行目と3行目は同じ放出駅ですが、駅からの距離が違います。駅からの距離が、2行目は50m、3行目は1000mになります。
HanatenStation_far = predict(gprMdl, Housing1(3,:));
round(HanatenStation_far)
放出駅から50mの場合は71.0万円、1km の場合は 66.4万円となっており、駅からの距離が近いほうが価格が高くなっていることが分かります。