盆暗の学習記録

データサイエンス ,エンジニアリング,ビジネスについて日々学んだことの備忘録としていく予定です。初心者であり独学なので内容には誤りが含まれる可能性が大いにあります。

Windows Subsystem for Linuxやコマンドプロンプトのフォントを変える

WindowsUbuntu Bashのフォントを変える

f:id:nigimitama:20181026203154p:plain

このWSL Ubuntuのフォントが大変ギザギザしていて汚いなと思っていて,変える方法は無いんだろうかと調べたところ

ウィンドウ上部を右クリックして[プロパティ]から変えられることに気づきました。

f:id:nigimitama:20181026202228p:plain

Rictyhttps://github.com/mzyy94/RictyDiminished-for-Powerline)とかもいいですし

f:id:nigimitama:20181026202638p:plain

f:id:nigimitama:20181026203100p:plain

Ubuntu公式(https://design.ubuntu.com/font/)からフォントをダウンロードしてきてUbuntu Monoにするのもいいですね

f:id:nigimitama:20181026202852p:plain

f:id:nigimitama:20181026203032p:plain

コマンドプロンプトのフォントを変える

コマンドプロンプトも同じように変えられるんじゃないかと思って試したら,変えられました。

f:id:nigimitama:20181026203400p:plain

f:id:nigimitama:20181026203911p:plain

colorschemeを変える

「文字色や背景色も,もっと目に優しいものに変えたい」という場合はこの記事が参考になりそうです。

qiita.com

宅建

宅建受けました。

試験前日に解いた模試も33点しかとれなくて合格圏に一度も乗らなかったのであきらめモードで本番を受けましたが,すごく易化してたみたいで,自己採点だと39点。ボーダーがかなり上がりそうだけど合格できるかも…。せっかく勉強したので受かるといいなあ。

以下では勉強にあたって使ったツールや,使用した教材とかアプリとかメモしていきます。

勉強時間とその記録づけ

Studyplusという,中高生が受験で使うような勉強時間の記録アプリを使いました。

中高生向けとかバカにせずに使って本当に良かったと思っています。

www.studyplus.jp

一応WebアプリになっているのでPCやスマホなど複数の端末からアクセスできます。機能はスマホのほうが多めです。

主に使っていた機能が,ストップウォッチで勉強時間を測る機能です。測った時間はそのまま「教材名」などのタグ付けをしてデータを記録することができます。

10分,20分の短い時間でも勉強して,それを記録していけば積もり積もって長い勉強時間になったりします。

f:id:nigimitama:20181022020211p:plain

また,週ごとに「目標勉強時間」を設定するようになっていて,週ごとに勉強のPDCAサイクルを回すことの助けになります。

f:id:nigimitama:20181022020431p:plain

このアプリはSNSでもあって,他のユーザーの勉強の記録をみることができます。

例えば自分が「宅地建物取引士」という目標設定をしていると,そのタグのついたユーザー(つまり,他の宅建受験生)の勉強記録などを見ることができ,「うわ,この人は日曜に10時間も勉強してる…すげぇ!俺もやらなきゃ!」みたいに良い刺激を受けることができます。

使用した教材

まんが

2018年版 マンガ宅建塾 (らくらく宅建塾シリーズ)

2018年版 マンガ宅建塾 (らくらく宅建塾シリーズ)

勉強を始めた最初期に使いました。ストーリーと絵で覚えるのって結構効果的ですよね。

テキスト:らくらく宅建

2018年版 らくらく宅建塾 (らくらく宅建塾シリーズ)

2018年版 らくらく宅建塾 (らくらく宅建塾シリーズ)

らくに合格できるらしいので買いました。

堅苦しい法律用語を柔らかく表現しようと努力されてるテキストで,良かったです。

ただ,ページ数が少ない分,最低限の基本的な情報だけが載っているテキストかもしれません。

過去問に出てくるようなマニアックな知識までは載っていないので,適宜書き込んで自分でテキストを完成させるつもりで使うのが良い気がします。

過去問:過去問宅建

第一巻(権利関係)と第二巻(宅建業法)を買いました。

2018年版 宅建士問題集 過去問宅建塾〔1〕 権利関係 (らくらく宅建塾シリーズ)

2018年版 宅建士問題集 過去問宅建塾〔1〕 権利関係 (らくらく宅建塾シリーズ)

2018年版 宅建士問題集 過去問宅建塾〔2〕 宅建業法 (らくらく宅建塾シリーズ)

2018年版 宅建士問題集 過去問宅建塾〔2〕 宅建業法 (らくらく宅建塾シリーズ)

第三巻(法令上の制限や税その他)はやってる時間がなかったので買いませんでしたが,友達から2017年版のLECの過去問の第三巻(法令上の制限や税その他)をもらったのでこれを使いました(時間なくて2割位しか読めませんでしたが)

一問一答:出る順

これはスマホのアプリがついていて,電車内やトイレ中などスキマ時間に解くことができるのが良かったです。

模試:出る順

使えばよかったかも?と思った教材

音声教材

私は音声教材が結構好きです。

普段から家にいるときは「パソコン+Bluetoothのヘッドホン」の環境で生活していて,家事とかなにかの作業中でも常に音楽を聞いている(=常にヘッドホンをつけている)人間なので,環境的に音声教材と相性が良いのです。大学受験期にも「世界史の実況中継」とか「DUO 3.0」とかを活用していました。

なので,試験の直前期にこの音声教材の存在を知って,「もっと早くに存在を知っていれば…」と悔しかったです。(まぁ,この音声教材の品質は高くないらしくて低評価が多いようですが)

過去問ドットコム

試験日の前日に知ったのでほとんど使わなかったのですが,過去問アプリみたいなサイトです。

kakomonn.com

宅建の勉強に関して

過去問題集は第二のテキスト。早めに始める

過去問(過去問題集)を解いていて思ったのが,「暗記すべき範囲が想像よりも広い」ということです。

私が使っていた『らくらく宅建塾』は,LECの「出る順テキスト」だと3冊に分かれているようなこの宅建の知識を1冊にまとめているのでマニアックな情報は省略していることが多く,過去問を解いてみるとテキストの範囲に無い知識が問われることも多いことに気づいてショックを受けました。

また,過去問(や試験本番)と『らくらく宅建塾』のテキストで用語(呼び方)が異なることもありました。

たとえば,試験(過去問)では「居住用財産を譲渡した場合の軽減税率」と呼ばれる制度が,『らくらく宅建塾』だと「居住用財産の長期譲渡所得(10年超)の軽減税率」と呼ばれていたり,『らくらく宅建塾』はフランクに書いてあってわかりやすいんですが,試験では堅苦しい正規の書き方をするのでそこの差を埋める必要もありました。

なので,テキストの内容を覚えるのはゴールではなくスタートと考えて,テキスト(+一問一答)で基本知識を身につけ,過去問で応用知識を身につけると考えるのが良いのかなと思います(「過去問をやる」なんて当たり前かもしれませんが…)

私が過去問題集を解き始めたのは試験まであと2週間になったときからなのですが,これはおそすぎました。

過去問題集から学ぶことは多く,過去問題集は第二のテキストだと思います。なので早めに始めて過去問題集の解説を読み込んでおくのが良いように思います。

一問一答は正解率9割~満点を目指す

私は当初「一問一答で正解率7~8割にすれば受かるだろう」と思っていたのですが,上に述べたように,実際の問題ではマニアックな知識(一問一答に出てこないような問題)も問われるので,一問一答にあるような基本問題は9割以上正解できるように,完璧を目指してきっちりやる必要があります。

[R]パッケージのインストールがうまくいかなくなった際の解決法(Windows)

環境

  • Windows 10
  • R 3.5.1
  • RStudio 1.1.456

問題

Rを3.5系にし,ついでにRStudioも更新したらパッケージのインストールができなくなった。

これまで(3.4系+昔のRStudio)は,パッケージのインストール時にはRStudioが自動的に

F:/マイドキュメント/R/win-library/3.4

というuser library directoryを作ってそこに入れてくれたのだが,今回この"マイドキュメント"という日本語が文字化けしてF:/????????/R/win-library/3.5になってしまうようになった。

今までは文字化けしながらもなんとかなる場合も多かったのだが,さすがに今回はパッケージをインストールできなくなった。

解決法:環境変数の指定

user libraryディレクトリは環境変数R_LIBS_USERで設定できるらしい。

Rの環境変数の設定方法は複数あって,だいたいこんなかんじ

  1. RからSys.setenv()で設定する
  2. Rの設定ファイルを書き換える
  3. Windows環境変数の設定から設定する

1や2の方法も試したが,結局3を使うことになった(多分3で設定するのが一番早いと思います)

Windows環境変数の設定から設定する

一応細かい手順もかいておくと,

1.user libraryディレクトリに使いたいディレクトリを作成しておく

2.環境変数の設定を開く

f:id:nigimitama:20181022012908p:plain

3.ユーザー環境変数を新規作成

名前にR_LIBS_USERなどRの環境変数の名前を入れ,ディレクトリのパスを指定する

f:id:nigimitama:20181022013210p:plain

これでおわり。

Sys.getenv()を使うと,環境変数の値が確認できる。

> Sys.getenv("R_LIBS_USER")
[1] "F:\\Programs\\R\\R_win_library"

[Python]予測モデル作成の一連の流れのメモ

Pythonで予測モデルを作るときの大まかな流れの雛形みたいなやつ(自己流なので正しいかはわかりませんが…)をメモしていきます。

1. データの読み込みと確認

Boston Housingデータを使います。サンプルサイズが500程度なのでかなり小さいですが,まぁ例なのでご了承ください。

import pandas as pd

# データの読み込み
from sklearn.datasets import load_boston
boston = load_boston()

boston_df = pd.concat([pd.DataFrame(boston['data'], columns = boston['feature_names']), pd.Series(boston['target']).rename('MEDV')],axis=1)
boston_df.head()
# print(boston.DESCR) # データの詳細

f:id:nigimitama:20180929031038p:plain

データの確認

変数の意味は以下のような感じらしいです。

  • CRIM:一人あたり犯罪率
  • ZN:25,000平方フィート以上の住宅区画の割合
    • 25,000平方フィート=2322.576平方メートル
  • INDUS:町ごとの非小売業の土地面積の割合
  • CHAS:チャールズ川ダミー(川沿いなら1,そうでないなら0)
  • NOX:一酸化窒素濃度(1000万分率)
  • RM:1戸あたりの平均部屋数
  • AGE:1940年よりも前に建てられた持家住宅の割合
  • DIS:ボストンの主な5つの雇用圏までの重み付き距離
  • RAD:幹線道路へのアクセス可能性の指標
  • TAX:1万ドルあたりの固定資産税の最大税率
  • PTRATIO:町ごとの生徒-教師の比率
  • B:[tex: 1000(Bk-0.63)2] , ここで Bkは町ごとの黒人の割合
  • LSTAT:低所得者の割合
  • MEDV:持ち家住宅の価格の中央値(単位:1000ドル)

一般的に予測の目的変数はMEDVらしいので,今回もそうします。

データ間の関係を確認

データの可視化(単変量)

pandas_profilingでヒストグラムなどを描いてざっくり可視化してもらいます。

# pandas_profilingによるお手軽なデータ可視化
import pandas_profiling as pdp
report = pdp.ProfileReport(boston_df)
report.to_file(outputfile="report.html")

f:id:nigimitama:20180929031922p:plain

データの可視化(多変量)

相関行列・ヒートマップ等

2変量の間の関係の強さを見ていきたいと思います。

ヒートマップはpandas_profilingが出してくれていたので,数字で見てみます。

# 相関係数の絶対値でソート
boston_df.corr()[['MEDV']].abs().sort_values('MEDV')

f:id:nigimitama:20180929032138p:plain

線形な相関関係の強さでいうとLSTAT(低所得者の割合)やRM(1戸あたりの平均部屋数)が高いみたいですね。

グラフ

相関係数(2変数間の直線的な関係を示す)が高くても,実際の分布が直線的(線形)かそうでない(非線形)かはプロットしてみないとわかりません。

実際にプロットしてみると非線形な関係でした

import matplotlib.pyplot as plt
% matplotlib inline # Jupyter Notebookで描くときのみ

plt.scatter(x = boston_df['LSTAT'], y = boston_df['MEDV'])
plt.xlabel('LSTAT')
plt.ylabel('MEDV')

他の変数とMEDVの関係も散布図で見てみます。やはり非線形な関係にある変数が多いです。

# MEDVとその他全変数との散布図
plt.figure(figsize=(12,12))
plt.subplots_adjust(wspace=0.4, hspace=0.4) # subplotの余白
i = 1
for var in boston_df.columns:     
    plt.subplot(4, 4, i) # 4×4のグリッドに順番にplotしていく
    sns.scatterplot(x = var, y = 'MEDV', data = boston_df)
    i = i + 1
    
plt.show()

f:id:nigimitama:20180929153658p:plain

2. 前処理

※実際の分析ではここからが重要なパートなのですが,今回のデータだとあんまりいじり甲斐がないのでこのあたりは省略します。

ドメイン知識の収集・整理

データを正しく扱うために,分析対象に関する知識を仕入れていきます。

特徴量エンジニアリング

データを集計した結果およびドメイン知識から,既存のデータから新たな特徴量を生み出したり,外部データを持ってきたりします。

データのクリーニング

欠損値がある場合,補完を行います。(今回のデータは欠損値なし)

# 欠損値の確認
boston_df.isnull().sum()
CRIM       0
ZN         0
INDUS      0
CHAS       0
NOX        0
RM         0
AGE        0
DIS        0
RAD        0
TAX        0
PTRATIO    0
B          0
LSTAT      0
MEDV       0
dtype: int64

もし欠損があった場合,以下の手法を使うのが手っ取り早いです

データの分割

# データの分割
X = boston_df.drop(['MEDV'],axis=1)
y = boston_df['MEDV']

# trainデータ, testデータへの分割
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

3. 予測

3つの予測モデルを使ってアンサンブルしてみます。

ElasticNetによる予測

パラメータチューニング

# GridSearchによるパラメータチューニング
from sklearn.linear_model import ElasticNet
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import mean_squared_error

# grid search
parameter_range = [{'alpha': [0.00001, 0.0001, 0.001, 0.01, 0.1, 1],
                    'l1_ratio' : [0.001, 0.01, 0.1, 1]}]

model = GridSearchCV(estimator = ElasticNet(normalize=True, max_iter=10000),
                     param_grid = parameter_range,
                     cv = 10,
                     scoring = 'neg_mean_squared_error')

model.fit(X_train, y_train)

# best estimator
best_model = model.best_estimator_

予測精度の評価

Cross Validationによる予測精度の評価

# Cross Validationによる予測精度の評価
from sklearn.model_selection import cross_validate
from sklearn.metrics import mean_squared_error, r2_score, make_scorer

# 誤差関数の定義
def root_mean_squared_error(y_true, y_pred):
    return np.sqrt(mean_squared_error(y_true, y_pred))

def median_absolute_error_rate(y_true, y_pred):
    return np.median(np.absolute(y_true - y_pred) / y_true)

# Cross Validationで使う誤差関数のセット
scoring = {"r2": "r2",
           "RMSE":make_scorer(root_mean_squared_error),
           "MER":make_scorer(median_absolute_error_rate)}

# cross_validate
scores = cross_validate(best_model, X_train, y_train, cv = 10, scoring = scoring, return_train_score=False)
for key,value in scores.items():
    print("{}:{:.3g}+/-{:.3g}".format(key, value.mean(), value.std()))

# モデルを格納
best_model_EN = best_model
# 結果を格納
cv_accuracy_EN = pd.DataFrame(scores)[['test_r2','test_RMSE','test_MER']].mean()
test_r2:0.732+/-0.106
test_RMSE:4.56+/-0.758
test_MER:0.115+/-0.0163

testデータに対する予測精度の確認

学習させずにとっておいたtestデータに対する予測精度を評価します。

# 予測値の算出
y_pred = pd.Series(best_model.predict(X_test))
y_pred.name = 'predicted'

# 誤差を算出
y_true = y_test.reset_index(drop=True)
print('R2:', '{:.3g}'.format(r2_score(y_true, y_pred)))
print('RMSE:', '{:.3g}'.format(root_mean_squared_error(y_true, y_pred)))
print('MER:', '{:.3g}'.format(median_absolute_error_rate(y_true, y_pred)))
R2: 0.586
RMSE: 5.81
MER: 0.133

regplot

# 予測-実測プロット
sns.regplot(y_true, y_pred)

f:id:nigimitama:20180930182353p:plain

RandomForestによる予測

パラメータチューニング

# GridSearchによるパラメータチューニング
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import mean_squared_error

# grid search
parameter_range = [{'n_estimators': [20, 50, 100, 200],
                    'max_depth' : [5, 10, 50, 100, 200]}]

model = GridSearchCV(estimator = RandomForestRegressor(),
                     param_grid = parameter_range,
                     cv = 10,
                     scoring = 'neg_mean_squared_error')

model.fit(X_train, y_train)

# best estimator
best_model = model.best_estimator_

Cross Validationによる予測精度の評価

ここのコードは上のと同じなので結果だけ。

test_r2:0.863+/-0.0899
test_RMSE:3.17+/-0.855
test_MER:0.069+/-0.0178

testデータに対する予測精度の確認

R2: 0.752
RMSE: 4.49
MER: 0.0779

特徴量重要度の確認

# feature importances
fi = best_model.feature_importances_  
fi_df = pd.DataFrame({'feature': list(X_train.columns),
                       'feature importance': fi[:]}).sort_values('feature importance', ascending = False)
fi_df

f:id:nigimitama:20180930205827p:plain

sns.barplot(fi_df['feature importance'],fi_df['feature'])

f:id:nigimitama:20180930205834p:plain

合計が100%になるように累積分布にして図を描いたらわかりやすいかも,と思ったので描いてみます。

# 累積 feature importance
sns.lineplot(x = fi_df['feature'], y = fi_df['feature importance'].cumsum(),
             marker="o", sort=False)
plt.ylim(0)
plt.hlines(y = 1, xmin = 0, xmax = 12) # y = 1 の水平線
plt.xticks(rotation=90)

f:id:nigimitama:20180930205844p:plain

ZNあたりからはほとんど予測に寄与していなさそうにも思えます。

いくつかの変数を除外したモデルを試しに作ってみます。

Feature Importanceに基づく特徴量選択

Feature Importanceの相対度数が0.001以上の特徴量だけを使って再度学習させてみます。

「Feature ImportanceがXX以上の特徴量だけを使う」という処理は

use_features = fi_df.loc[fi_df['feature importance'] >= XX,'feature']
X_train2 = X_train[use_features]

と書くこともできますし,

from sklearn.feature_selection import SelectFromModel
selector = SelectFromModel(best_model, threshold = XX, prefit = True)
X_selected = selector.transform(X_train)

と書くこともできます。

arrayで返ってくるSelectFromModelよりは自分でdf.loc[]で選んだほうが,選択した特徴量の把握がやりやすい気がします。

今回はFeature Importanceの”相対度数”を使うのでSelectFromModelは使えないためdf.loc[]で選びます。

# feature importanceの相対度数が0.01以上の特徴量を使う
use_features_RF = fi_df.loc[fi_df['FI_ratio'] >= 0.001,'feature']
X_train2 = X_train[use_features_RF]

特徴量を減らした以外は同様に予測させた結果がこちら。

予測精度の評価

Cross Validationによる予測精度の評価

test_r2:0.863+/-0.0881
test_RMSE:3.17+/-0.774
test_MER:0.0756+/-0.018

testデータに対する予測精度の確認

R2: 0.726
RMSE: 4.72
MER: 0.0822

特徴量を絞ったことで予測精度が少し悪化しました。

後のアンサンブル用に,特徴量を絞らなかった方のモデルとその予測精度の評価結果を格納しておきます。

best_model_RF = best_model
cv_accuracy_RF = pd.DataFrame(scores)[['test_r2','test_RMSE','test_MER']].mean()

LGBMによる予測

パラメータチューニング

import lightgbm as lgb

# grid search
parameter_range = {'num_leaves': [5, 10, 20],
                   'learning_rate': [0.01, 0.1, 1],
                   'n_estimators': [100, 200, 500],
                   'max_depth': [2, 4, 6, 8, 10, -1]}

model = GridSearchCV(estimator = lgb.LGBMRegressor(),
                     param_grid = parameter_range,
                     cv = 10,
                     scoring = 'neg_mean_squared_error')
model.fit(X_train, y_train)

# best estimator
best_model = model.best_estimator_

予測精度の評価

Cross Validationによる予測精度の評価

test_r2:0.889+/-0.0689
test_RMSE:2.83+/-0.5
test_MER:0.0755+/-0.0138

testデータに対する予測精度の確認

R2: 0.714
RMSE: 4.82
MER: 0.0965

特徴量重要度の確認

RandomForestと同様に.feature_importances_で特徴量重要度を見ることができます。

# feature importances
fi = best_model.feature_importances_  
fi_df = pd.DataFrame({'feature': list(X_train.columns),
                       'feature importance': fi[:]}).sort_values('feature importance', ascending = False)
fi_df

f:id:nigimitama:20180930184504p:plain f:id:nigimitama:20180930193240p:plain f:id:nigimitama:20180930193244p:plain

特徴量選択

feature importanceの相対度数が0.01に満たない特徴量(CHAS)を落として再度予測をさせてみます。

Cross Validationによる予測精度の評価

test_r2:0.89+/-0.0743
test_RMSE:2.81+/-0.485
test_MER:0.0653+/-0.00994

testデータに対する予測精度の確認

R2: 0.759
RMSE: 4.43
MER: 0.0893

LGBMは特徴量を絞ったほうが予測精度が良くなりました。

後のアンサンブル用にモデルと精度評価結果を格納しておきます。

best_model_LGBM = best_model
cv_accuracy_LGBM = pd.DataFrame(scores)[['test_r2','test_RMSE','test_MER']].mean()

4. 予測モデルのアンサンブル

3つの予測モデルから予測値を得ることができました。

# 予測値の算出
y_pred_EN = pd.Series(best_model_EN.predict(X_test))
y_pred_RF = pd.Series(best_model_RF.predict(X_test))
y_pred_LGBM = pd.Series(best_model_LGBM.predict(X_test[use_features_LGBM]))

これらの予測値を統合し,より良い予測値にしたいと思います。

もし予測モデルたちがどれも同程度に予測性能が良いのであれば単純に平均(一様な重み付け)をとってもいいのですが,今回は予測精度に差があるため,適切な重み付けを推定することを考えていきます。

今回は2つのアプローチを試してみます。 1. 誤差の指標に応じた重み付け 2. OLSで重みを推定する

誤差の指標に応じた重み付け

cross_validateで評価した各モデルの誤差の指標を加工して重みの値にします。

# cross validationの結果
cv_accuracy_df = pd.concat([cv_accuracy_EN, cv_accuracy_RF, cv_accuracy_LGBM],axis=1)
cv_accuracy_df.columns = ['EN','RF','LGBM']
cv_accuracy_df

f:id:nigimitama:20180930210758p:plain

決定係数を基準にする場合

決定係数のように「指標の値が高いほど予測精度が高いことを示す」ような指標なら,

重みの合計が1になるように決定係数の合計で除して,それを重みに使います。

# r2を基準にする場合
accuracy_scores = cv_accuracy_df.loc['test_r2',]
## 合計が1になるように変換
accuracy_scores = accuracy_scores / accuracy_scores.sum()
accuracy_scores
EN      0.294615
RF      0.347377
LGBM    0.358007
Name: test_r2, dtype: float64

これが重みになります。

これで予測値を統合した場合のtestデータとの誤差は

# アンサンブルした予測値の算出
y_pred_ens = accuracy_scores[0] * y_pred_EN + accuracy_scores[1] * y_pred_RF + accuracy_scores[2] * y_pred_LGBM

# 誤差を算出
y_true = y_test.reset_index(drop=True)
print('R2:', '{:.3g}'.format(r2_score(y_true, y_pred_ens)))
print('RMSE:', '{:.3g}'.format(root_mean_squared_error(y_true, y_pred_ens)))
print('MER:', '{:.3g}'.format(median_absolute_error_rate(y_true, y_pred_ens)))
R2: 0.741
RMSE: 4.6
MER: 0.0916

こうなります。

RMSEを基準にする場合

RMSEやMERなど「指標の値が低いほど予測精度が高いことを示す」ような指標は逆数にしてから同様の処理を行います。

# RMSEを基準にする場合
## 逆数を使う
accuracy_scores = 1 / cv_accuracy_df.loc['test_RMSE',]
## 合計が1になるように変換
accuracy_scores = accuracy_scores / accuracy_scores.sum()
accuracy_scores
EN      0.246879
RF      0.354779
LGBM    0.398342
Name: test_RMSE, dtype: float64

予測の誤差はこうなりました。

R2: 0.746
RMSE: 4.54
MER: 0.0888

また,MERを基準にしたものも同様に試しましたが,予測の誤差は

R2: 0.747
RMSE: 4.54
MER: 0.0906

というもので,このアプローチではいずれもLGBM単体の予測精度に劣る結果になりました

OLSで重みを推定

各予測モデルでtrainデータでの予測値を算出し,それらの線形和でtrainデータの実測値を近似するOLSを回してみます。

# アンサンブルで予測値の重み付け和を作る
## 各予測モデルのtrainデータの予測値の算出
y_train_pred_EN = pd.Series(best_model_EN.predict(X_train))
y_train_pred_RF = pd.Series(best_model_RF.predict(X_train))
y_train_pred_LGBM = pd.Series(best_model_LGBM.predict(X_train[use_features_LGBM]))
pred_df = pd.concat([y_train_pred_EN, y_train_pred_RF, y_train_pred_LGBM],axis=1)

## 最適な重みをOLSで推定する
from sklearn.linear_model import LinearRegression

lm = LinearRegression(fit_intercept=False)
lm.fit(pred_df, y_train)

lm.coef_
array([-0.07140172,  0.23783679,  0.83375187])

この係数も合計が1になるように調整して使います

# 係数の合計が1になるように調整
coef = lm.coef_ / lm.coef_.sum()

# アンサンブルした予測値の算出
y_pred_ens = coef[0] * y_pred_EN + coef[1] * y_pred_RF + coef[2] * y_pred_LGBM
R2: 0.766
RMSE: 4.37
MER: 0.0856

だいぶ予測精度が良くなりました。

LGBMの予測精度が

R2: 0.759
RMSE: 4.43
MER: 0.0893

だったので,それよりも良い予測精度になりました。

今回はデータセットのサンプル数が少なかったので,もっとしっかりした規模のデータを扱うときもOLSを使ったほうが良い結果になるのかはあとで試してみたいですね…

scikit-learnメモ:サンプルデータセットの読み込み方

機械学習を使うための処理の書き方を勉強する上でお世話になるのがサンプルデータセットですが,

scikit-learnはRとは読み込み方が異なって面倒くさかったため,メモしておきます。

iris データセット

定番のirisデータを例にしてみます。

Rだとdata(iris)あるいは単にirisで済みますが,sklearnでは以下のように書きます。

from sklearn import datasets
import pandas as pd

iris = datasets.load_iris()
iris_df = pd.DataFrame(iris.data, columns = iris.feature_names)
iris_df['Species'] = iris.target_names[iris.target]

あるいは,こう書きます。(読みやすさを捨てて少ない行数で書く場合の例)

from sklearn import datasets
import pandas as pd

iris = datasets.load_iris()
iris_df = pd.concat([pd.DataFrame(iris.data, columns = iris.feature_names), pd.Series(iris.target_names[iris.target]).rename('Species')], axis=1)

これらのコードによって,Rのdata(iris)と同様に,扱いやすいデータフレームの形でデータを取得できます。

In [16]: iris_df.head()
Out[16]: 
   sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)  \
0                5.1               3.5                1.4               0.2   
1                4.9               3.0                1.4               0.2   
2                4.7               3.2                1.3               0.2   
3                4.6               3.1                1.5               0.2   
4                5.0               3.6                1.4               0.2   

  Species  
0  setosa  
1  setosa  
2  setosa  
3  setosa  
4  setosa  

ざっくりまとめるとこんなかんじ。

  • sklearn.datasets.load_**():データの読み込み
  • data.data:説明変数
  • data.feature_names:説明変数の名称
  • data.target:目的変数
  • data.target_names:目的変数のラベル(カテゴリカル変数のラベル)
  • print(data.DESCR):データセットの説明

data['target']のような書き方も可能

参考

Rで小地域データの塗り分け地図を描く

小地域(町字レベルの細かい地域区分のデータ)のシェープファイル(.shp)を使用してコロプレス図(塗り分け地図)を描く方法のメモ。

f:id:nigimitama:20180925013333p:plain

1. データの取得

まず,シェープファイルを取得します。

e-statに行き,「統計GIS」から

f:id:nigimitama:20180924215229p:plain

「境界データダウンロード」をクリックしていった先からダウンロードできます。

f:id:nigimitama:20180924215324p:plain

今回は「小地域」の「国勢調査」のデータを使ってみます。

f:id:nigimitama:20180924220136p:plain

f:id:nigimitama:20180924220155p:plain

データの説明書である「定義書」のpdfをダウンロードし,「小地域(町丁・字等別)」をクリックします。

f:id:nigimitama:20180924220324p:plain

シェープファイルが欲しいので「Shape形式」のものを選ぶのですが,地図の作成方式の違いから「世界測地系緯度経度・Shape形式」と「世界測地系平面直角座標系・Shape形式」があります。

世界測地系緯度経度・Shape形式」を選びます。

f:id:nigimitama:20180924220505p:plain

港区のデータを選んでみます。

f:id:nigimitama:20180925002532p:plain

世界測地系緯度経度・Shape形式」をクリックすれば,シェープファイルが入ったzipファイルがダウンロードされます。

2. データの読み込みとデータの確認

{rgdal}パッケージを使用して読み込んでみます。

library(rgdal)
shape <- readOGR("h27ka13103.shp",
                 stringsAsFactors = FALSE, encoding = "UTF-8")

RStudioのEnvironment部で,読み込んだシェープファイルの中身を確認してみます。

f:id:nigimitama:20180924223947p:plain

f:id:nigimitama:20180925011036p:plain

このpolygonsには地図の図形が入っています。

そしてdataというデータフレームには,自治体コードや自治体名,町字,面積といった地域のデータと,人口,世帯数といった国勢調査のデータが入っています。

> head(shape@data)
     KEY_CODE PREF CITY S_AREA PREF_NAME CITY_NAME     S_NAME KIGO_E HCODE      AREA
0 13103001001   13  103 001001    東京都      港区   芝1丁目   <NA>  8101  68807.76
1 13103001002   13  103 001002    東京都      港区   芝2丁目   <NA>  8101 165462.02
2 13103001003   13  103 001003    東京都      港区   芝3丁目   <NA>  8101 153048.48
3 13103001004   13  103 001004    東京都      港区   芝4丁目   <NA>  8101  94327.10
4 13103001005   13  103 001005    東京都      港区   芝5丁目   <NA>  8101 215053.82
5 13103002001   13  103 002001    東京都      港区 海岸1丁目   <NA>  8101 391922.17
(以下省略)

塗分ける前の地図データを確認してみます。

{leaflet}で描画します。

# シェープファイルの単純表示
library(leaflet)
shape %>% 
leaflet() %>% 
  addTiles() %>% 
  setView(lat = 35.65, lng = 139.75, zoom = 12) %>% 
  addProviderTiles(providers$CartoDB.Positron) %>% 
  addPolygons(fillOpacity = 0.5,
              weight = 1,
              fillColor = "lightblue")

こんな感じです。

f:id:nigimitama:20180925005129p:plain

3. 塗り分け地図の作図

地図作成の準備

まず,塗り分け用に人口密度データを作ります。(人口で塗り分けると面積の差が出て自治体同士を正しく比較できないため)

定義書によれば,shape@data$JINKOが人口データで,shape@data$AREAが面積(㎡)のようなので,これを使います。

# 人口密度データの作成
PopDensity <- as.numeric(shape@data$JINKO) / shape@data$AREA * 1000000 # 1平方キロあたりにするために*1000000

つぎに,塗り分け地図の装飾用のセッティングを行います。

plot用のカラーパレットを定義して…

# 塗る色(連続値のカラーパレット)をセット
pal <- colorNumeric("Blues", domain = PopDensity, reverse=F)

マウスオーバー時のラベルを定義します。

# マウスオーバー時の表示内容を設定
labels <- sprintf("<strong>%s</strong><br/>%5.1f",
                  paste0(shape@data$MOJI),
                  PopDensity) %>% lapply(htmltools::HTML)

ここのラベルの定義は

> head(labels)
[[1]]
<strong>芝1丁目</strong><br/>22366.7

こういうhtmlコードにしたいからやりました。

そして,leafletでプロットします

地図のプロット

# 地図にプロット
shape %>% 
  leaflet() %>% 
  # setView() : 地図をズームした状態で表示する
  setView(lat = 35.65, lng = 139.75, zoom = 12) %>% 
  # addProviderTiles() : 背景のタイルを指定
  addProviderTiles(providers$CartoDB.Positron) %>% 
  # addPolygons() : 塗り分け地図の描画
  addPolygons(fillOpacity = 0.5,
              weight=1,
              color = "#666",
              fillColor = ~pal(PopDensity), # ここで人口密度データを使う
              label = labels,
              labelOptions = labelOptions(
                style = list("font-weight" = "normal", padding = "3px 8px"),
                textsize = "15px",
                direction = "auto"),
              highlight = highlightOptions(
                weight = 5,
                color = "#666",
                dashArray = "",
                fillOpacity = 0.7,
                bringToFront = TRUE)) %>% 
  # addLegend() : 凡例の設定
  addLegend("bottomright", pal = pal, values = ~PopDensity, # ここで人口密度データを使う
            title = "人口密度(人口/km2)")

f:id:nigimitama:20180925010851p:plain

結果はこんな感じ。マウスオーバーで詳細を表示してくれます。

Windowsでそのまま作るとMSゴシックのギザギザとしたフォントがなんだか醜いですね(フォント厨並みの感想)

オプションでfontなどを指定していきましょう

地図の装飾

# 地図にプロット
map <- shape %>% leaflet() %>% 
  # setView() : 地図をズームした状態で表示する
  setView(lat = 35.65, lng = 139.75, zoom = 13) %>% 
  # addProviderTiles() : 背景のタイルを指定
  addProviderTiles(providers$CartoDB.Positron) %>% 
  # addPolygons() : 塗り分け地図の描画
  addPolygons(fillOpacity = 0.5,
              weight=1,
              color = "#666",
              fillColor = ~pal(PopDensity), # ここで人口密度データを使う
              label = labels,
              labelOptions = labelOptions(
                style = list("font-weight" = "normal",
                             "font-family" = "Yu Gothic",
                             "box-shadow" = "3px 3px rgba(0,0,0,0.25)",
                             "padding" = "3px 8px"),
                textsize = "15px",
                direction = "auto"),
              highlight = highlightOptions(
                weight = 5,
                color = "#666",
                dashArray = "",
                fillOpacity = 0.7,
                bringToFront = TRUE)) %>% 
  # addLegend() : 凡例の設定
  addLegend("bottomright", pal = pal, values = ~PopDensity, # ここで人口密度データを使う
            title = "人口密度(人口/km2)")

ラベルの文字に関する装飾はlabelOptions = labelOptions(style = list())CSSを指定することができます。

凡例(legend)は関数としてOptionを受け入れていないので,leafletの地図オブジェクトを作った後{htmltools}CSSを追加します。

# legendも游ゴシックにする
library(htmltools)
browsable(
  tagList(list(
    tags$head(
      tags$style(
        ".leaflet .legend {
            font-family : Yu Gothic;
         }
        "
      )
    ),
    map
  ))
)

f:id:nigimitama:20180925013333p:plain

見た目がよくなりました。

Webページ制作の入門時に参考にしたサイト等まとめ

最近HTML,CSSJavascriptをちょっと勉強し,シンプルなWebサイトを作っていました。

その際に参考にしたサイトや,使ったツールをまとめます。

Webページの骨格を作る段階で参考にしたサイト

saruwakakun.com

HTMLやCSSの基本や,ちょっとした悩むポイント(色をグラデーションにするには?要素を中央に寄せるには?など)をわかりやすく解説しています。このサイト自体のデザインも非常に優れているので,デザインの勉強にもなります。

レスポンシブサイトへの移行

スマートフォンなど,パソコン以外の端末で閲覧される時への対応は,主に以下のサイトを参考にしました

ics.media

レスポンシブサイトを作るにあたって,どういう手法が選択肢に挙げられるのかといった点を把握できます。

Flexboxについて

私は結局Flexboxを使うことにしましたが,その際に参考になったのが主に以下のサイトでした。

www.webcreatorbox.com

ics.media

www.kerenor.jp

こちらのサイトはデモページがデザインの参考としても実装例としても非常に優れていました。

クロスブラウザ対応

autoprefixer.github.io

Google ChromeInternet Explorerなど,ブラウザは様々あり,それぞれに合わせたCSSの書き方が求められる場合があります。

自動でCSSを翻訳することでそこの処理を簡単にしてくれるAutoprefixerというツールがあるのですが,これはインストールが必要で,面倒です。

そこで,インストールいらずでWeb上で動作してくれるAutoprefixer CSS onlineという便利なモノが作られています。これには助けられました。

細かい部分を作る上で参考にしたサイト

総合

リファレンス

冒頭ですでに紹介しているサイトなのですが,この「レファレンス」のページを見ながらやることで,自分の作りたいCSSのボタンや見出しなど,細かい部分を簡単に作ることができました。

「やりたいこと(目的)」別に解説する構成なので,やりたいことが決まっている場合は目的の情報が探しやすいですし,やりたいことが決まっていない場合はこの辺りのページを眺めていくことで「こういうこともできるのか!」と新たな気付きにつながってやりたいことを決めるきっかけになります。

メニュー

メニューに関しては以下のサイトが参考になりました。

photoshopvip.net

photoshopvip.net

デモが多くて非常に良いページです。

favicon

realfavicongenerator.net

自分のサイトに正しくfaviconを設定できているのかをチェックしたり,faviconにしたい画像を指定してfavicon用ファイルを生成したりしてくれるWebアプリです。

Canvas

HTML5Canvas要素にJavascriptでアニメーションを書いてきれいな映像を作りたいときに参考にしました(これはまだわからないところも多く勉強中ですが…)

developer.mozilla.org

yoppa.org

こちらのサイトはDEMOがスゴいです。たとえばこれhttps://ics.media/tutorial-createjs/index.html

CreateJS入門サイト - ICS MEDIA

コードを書くときに使用したテキストエディタ

エディタはしっかり検討して選択しているわけではありませんが,主にMicrosoftのExpression Webという,開発終了とともに無料になったエディタを使っていました。

このエディタはやや古いですが,編集中のHTMLのclassやidがリンクと化してクリックすると対応したcssの対応した箇所に飛んでくれるようになるので,CSSのclassやidの管理に慣れていないうちは非常に助けられます。

Expression Webは以下でダウンロードできます。下部の「Details」をクリックすれば日本語版のリンクも展開します。

Download Microsoft Expression Web 4 (Free Version) from Official Microsoft Download Center

また,GitHubAtomも使っていました。ちゃんとコードを書くようになればこっちのほうが便利になっていくのだと思いますが,どういうパッケージを入れるべきか等は勉強中です…