5.2.3.3~5.3 評価基準とスコア
(60m)15:00~16:00
5.3評価基準とスコア
実際には偏ったデータが多い為、R2スコアではわからない部分がたくさんある。
以下に注意。
エラーの種類:
陽性 :TP(True positive 求めている成果)
偽陽性:FP(False positive)
陰性 :TN(True negative)
偽陰性:FN(False negative)
精度の種類:
精度 :TP+TN/TP+FP+TN+FP
適合率(precision):
TP/TP+NP(陽性を陽性と判断したもので割る→偽陽性を数値化)
再現率(recall):
TP/TP+NF(陽性を陽性と間違えて陰性と判断したもので割る→偽陰性を数値化)
f1_score:
2*((適合率*再現率)/適合率+再現率) これで適合率、再現率ともに総合的に判断できる。
classification_report:
使うとわかりやすい。
from sklearn.metrics import classification_report
print(classification_report(y_test,pred_logreg,target_names=["not nine","nine"]))
5.2 グリッドサーチ
(45m)09:30~10:15
5.2グリッドサーチ
5.2.3交差検証を使用したグリッドサーチ
SVCのCとgammaで一番汎化性能が高いモデルを探る。
①:for inで総当たり。
for gamma in[0.001,0.01,0.1,1,10,100]:
for C in [0.001,0.01,0.1,1,10,100]:
svm =SVC(gamma=gamma,C=C)
svm.fit(X_train,y_train)
score =svm.score(X_test,y_test)
if score>best_score:
best_score=score
best_parameters={"C":C,"gamma":gamma}
print(f"Best score:{best_score:.2f}")
print(f"Best parameters:{best_parameters}")
②:汎化性能検証で使ったデータとテストデータが同じではだめだ
X_trainval,X_test,y_trainval,y_test=train_test_split(iris.data,iris.target,random_state=0)
X_train,X_valid,y_train,y_valid=train_test_split(X_trainval,y_trainval,random_state=1)
for gamma in[0.001,0.01,0.1,1,10,100]:
for C in [0.001,0.01,0.1,1,10,100]:
svm =SVC(gamma=gamma,C=C)
svm.fit(X_train,y_train)
score =svm.score(X_valid,y_valid)
if score>best_score:
best_score=score
best_parameters={"C":C,"gamma":gamma}
test_score=svm.score(X_test,y_test)
③さらに交差検証も行う
for gamma in[0.001,0.01,0.1,1,10,100]:
for C in[0.001,0.01,0.1,1,10,100]:
svm=SVC(gamma=gamma,C=C)
scores =cross_val_score(svm,X_trainval,y_trainval,cv=5)
score =np.mean(scores)
if score >best_score:
best_score=score
best_parameters={"C":C,"gamma":gamma}
④これをまとめたのがGridSearchCV
param_grid = {"C":[0.001,0.01,0.1,1,10,100],"gamma":[0.001,0.01,0.1,1,10,100]}
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
grid_search =GridSearchCV(SVC(),param_grid,cv=5)
grid_search.fit(X_train,y_train)
#この時点ですべてが計算されてベストの形になる。以下はその説明
「IN」
print(f"best parameters:{grid_search.best_params_}")
print(f"best cross-validation score :{grid_search.best_score_:.2f}")
print(f"best estimator:\n{grid_search.best_estimator_}")
「OUT」
best parameters:{'C': 100, 'gamma': 0.01}
best cross-validation score :0.97
best estimator:
SVC(C=100, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=None, degree=3, gamma=0.01, kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
パラメータを設定して
param_grid = {"C":[0.001,0.01,0.1,1,10,100],"gamma":[0.001,0.01,0.1,1,10,100]}
GridSearchCVをつかえ。
交差検証もしてくれる。
GridSearchCVはcvパラメータを渡せる。訓練とテストの分割を一度にするにはShuffleSplitかStratifiedShuffelSpitを使ってn_iter=1にすると良い。
# 一番下は正直意味わからん。
・ヒートマップでもチェックできる
import pandas as pd
results = pd.DataFrame(grid_search.cv_results_)
scores=np.array(results.mean_test_score).reshape(6,6)
mglearn.tools.heatmap(scores,xlabel="gamma",xticklabels=param_grid["gamma"],ylabel="C",yticklabels=param_grid["C"],cmap="viridis")
・場合分けでパラメータを渡すこともできる。
param_grid=[{"kernel":["rbf"],"C":[0.001,0.01,0.1,1,10,100],"gamma":[0.001,0.01,0.1,1,10,100]},
{"kernel":["linear"],"C":[0.001,0.01,0.1,1,10,100]}]grid_search=GridSearchCV(SVC(),param_grid,cv=5)
#SVCはkernelによって"C","gamma"が関わる場合とそうでない場合がある。その事前パラメータ分け
5.2.3.3異なる検証手法を用いたグリッドサーチ
GridSearchCVはcvパラメータを渡せる。訓練とテストの分割を一度にするにはShuffleSplitかStratifiedShuffelSpitを使ってn_iter=1にすると良い。
# 正直意味わからん。
5.2.3.4
scores =cross_val_score(GridSearchCV(SVC(),param_grid,cv=5),iris.data,iris.target,cv=5)
グリッドサーチしたパラメータで交差検証。
5.2.3.5交差検証とグリッドサーチの並列化
GridSearchCVとcross_val_scoreはn_jobsで複数コア使用可(n_jobs=-1で最大限使用)
ただしscikit-learnではサポートされていないのでsklearnのモデルでは不可。
5章 モデルの改良と評価 5.1交差検証
(60m)07:00~08:00
5.1 交差検証
k分割交差検証:KFold
データを分割し、訓練とテストに振り分け評価を繰り返す。
例:①~⑤に分割→①をテスト残りを訓練→②をテスト残りを訓練→繰り返し
層化k分割交差検証:StratifiedKFold
ターゲットの分類が均一だとただの分割では評価できない。
例:iris label を3分割すると答えは均一になり学習できない。
Iris labels:
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
KFold分類器:
kfold= KFold(n_splits=X)
をcvで渡す。
cross_val_score(logreg,iris.data,iris.target,cv=kfold)
1つ抜き交差検証:
テストサンプルを1つだけにして繰り返す。
LeaveOneoutをcvとして渡す。
from sklearn.model_selection import LeaveOneOut
loo =LeaveOneOut()
scores=cross_val_score(logreg,iris.data,iris.target,cv=loo)
シャッフル分割交差検証:
train_size個を訓練として選び、test_size個をテストとして選び、n_iter回繰り返す。
ShuffleSplitをcvで渡す。
from sklearn.model_selection import ShuffleSplit
shuffle_split=ShuffleSplit(test_size=.5,train_size=.5,n_splits=10)
# 割合でもできる。この場合は0.5=50%
scores=cross_val_score(logreg,iris.data,iris.target,cv=shuffle_split)
グループ付き交差検証:GroupKFold
グループを設定し、グループ内では分割がかからないようにする。
groupsを設定。GroupKFoldをcvで渡す。
from sklearn.model_selection import GroupKFold
X,y =make_blobs(n_samples=12,random_state=0)
groups=[0,0,0,1,1,1,1,2,2,3,3,3]
scores=cross_val_score(logreg,X,y,groups,cv=GroupKFold(n_splits=3))
基本的には以下3つを試そう。
k分割交差検証:KFold
層化k分割交差検証:StratifiedKFold
グループ付き交差検証:GroupKFold
わからん
R2スコア0~1
テストデータは訓練データよりPOSIX時刻が後である。決定木は訓練セットの外まで外挿できない。
#interaction_only=Trueで各要素が交互作用のみ?
poly_transformer=PolynomialFeatures(degree=2,interaction_only=True,include_bias=False)
# %ってなんやねん。文字を縛る?
plt.xticks(range(0,len(X),8),xticks.strftime("%a %m-%d"),rotation=90,ha="left")
hour=["%02d:00"% i for i in range(0,24,3)]
#coefってなんや。係数0を消すのもよくわからん。
coef_nonzero=lr.coef_[lr.coef_ !=0]
4.6 専門家知識の利用
(60m)16:30~17:30
4.6
自転車レンタルを例に総合。
ランダムフォレストでの推測
↓
時間要素を追加
[0],[3],[6],...
#[0時],[3時]...
↓
曜日要素を追加
X_hour_week=np.hstack([citibike.index.dayofweek.values.reshape(-1,1),citibike.index.hour.values.reshape(-1,1)])
[ 5, 0],
[ 5, 3],
[ 5, 6],
[ 5, 9],...
#[土曜,0時],[土曜,3時]...
↓
線形モデルで解析
↓
線形で解釈できない部分をワンホットエンコーダーで変換
enc=OneHotEncoder()
X_hour_week_onehot=enc.fit_transform(X_hour_week).toarray()
[ 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 0., 0., 0.,
0., 0.],
[ 0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0.,
0., 0.],
[ 0., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0.,
0., 0.],...
#各項目をダミー[月,火,水,木,金,土,日,0,3,6,9,12,15,18,21]
↓
交互作用特徴量で曜日かける時刻を作成
from sklearn.preprocessing import PolynomialFeatures
poly_transformer=PolynomialFeatures(degree=2,interaction_only=True,include_bias=False)
X_hour_week_onehot_poly=poly_transformer.fit_transform(X_hour_week_onehot)
↓
Ridge
↓
線形とランダムフォレストが同等に。
ここできちんと復習しよう。
いろいろと打ち込んでいるだけなので。
4.4単変量非線形変換~4.5自動特徴量変換
(60m)05:30~06:30
4.4
乗数の変換が有用であったように、log,sin,cosの変換も有用である(前回同様場合による)
(???)
ほとんどのモデルは「ガウス分布」に従っているときに最もうまく機能する。
つまり見慣れた「ベルカーブ」になる場合である。
確率的な立場からは「ポワソン分布」「ポワソン回帰」を使ったほうが良い。
4.5
特徴量の追加は過剰適合も引き起こす。特徴量を減らして汎化性能を上げるのもあり。
方法は3つ。単変量統計、モデルベース選択、反復選択。
4.5.1 単変量統計
分散分析。個々の特徴量との関係から取捨選択。相互関係は無視されてしまう。
特徴量が多すぎる場合や多くの特徴量が全く関係ないと思われるような場合に有用である。
4.5.2 モデルベース選択
L1ペナルティを用いた線形モデルに似てる。
あるモデルを用いて特徴量を選択する。選択モデルと学習モデルは違っても構わない(選択モデル:決定木 学習モデル:ロジ 等)
4.5.3 反復選択
0から1つずつ特徴量を加えていき基準を満たすモデルをつくる、もしくは全てを含む特徴量から1つずつ減らしていき基準を満たすモデルをつくる。
再帰的特徴量削減(RFE):すべての特徴量からモデルをつくり、そのモデルで最も重要度が低い特徴量を削除する。これを事前に定めた数になるまで繰り返す。
自動特徴量選択は
・どの特徴量が必要か判断できない場合
・予測を高速化したい
・解釈しやすいモデルを構築したい(特徴量を減らす)
などの際に有用であるが、実世界で性能が大幅に向上することはあまりない。
#調べること:「ガウス分布」「ベルカーブ」「ポワソン分布」
4.3 交互作用と多項式
(60m)13:00~14:00
ビニング毎の傾き:
binsはダミーして0or1状態なので
X_product=np.hstack([X_binned,X*X_binned])で
bin + bin*特徴量を作ると傾きも出る。
Plynomial Features:
(degree=X)に応じて特徴量を拡張する。
どのような拡張したかは
poly.get_feature_names()で確認。
二乗していったり特徴量をかけ合わせたり。
多項式化は1次元のデータに対し有用であるが
複雑なモデル(SVR・・・)などを使えば特徴量の拡張を行わずとも
同様の結果を導き出せる。
RidgeとRandomForesstRegressorとの比較でも明らかで
①特徴量を拡張しないRidge
②特徴量を拡張したRidge
③特徴量を拡張しないrf
④特徴量を拡張したrf
スコアは以下である。
③>④>②>①
(rfでは特徴量を拡張すると性能が下がる)
多項式化は単純な線形モデルに対して有用である。