運動・勉強・記録

python勉強中。

ゼロから作るディープラーニング

区民プールで泳ぐようになる。

新しい本を買った。

 

3章 ニューラルネットワーク

np.exp(a)

e(ネイピア数)のa乗

ソフトマックス関数

np.exp(a)/np.sum(np.exp(a))

 

ソフトマックス関数を使う出力は総和が1であり確率的な分類ができる。

7章 テキストデータの処理

7章

コードにわからない部分が多い。導入も苦労した。

 

・BOW(bag of  words)

1-トークン分割

スぺースや句読点で句切り、細かい単位(単語…)にする。

2-ボキャブラリ構築

ボキャブラリとして整理し番号をつける。

3-エンコード

個々の文章に現れる回数を数える。

 

・CountVectorizer

トークン分割とボキャブラリの構築を行う。

from sklearn.feature_extraction.text import CountVectorizer
vect=CountVectorizer()
vect.fit(bards_words)

print(f"Vocabulary size:{len(vect.vocabulary_)}")
print(f"Vocabulary content:{vect.vocabulary_}")

 

bag_of_words =vect.transform(bards_words)
print(f"bag_of_words:{repr(bag_of_words)}")

#単語それぞれを特徴量とした疎行列ができる。

 

・min_df=N

vect =CountVectorizer(min_df=N).fit(text_train)

N回以上の出現率のみの単語でボキャブリを構築できる。

 

・stop words

あらかじめ定められた頻出単語を省略できる。

from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS

 

・tf-idf

全文書の頻出単語を別として特定の文章にのみ頻出する単語に重みを与える前処理。

from sklearn.feature_extraction.text import TfidfVectorizer

 

・ngram_range

単語の組み合わせ数を指定する。

cv=CountVectorizer(ngram_range=(1,1)).fit(bards_words)

#ngram_range=(n,N) n以上N以下の連続した単語組み合わせを指定する。

 

・語幹処理(stemming)、見出し語(lemma)

単複、時制などの語尾変化対応として、特定の単語末尾を取り除くのが語幹処理(stemming)、文章での役割を考慮するのが見出し語(lemma)。

この前処理は正規化の一種である。

 

※7.8から入力で躓く。ここで終わりでもいいか?

6章 アルゴリズムチェーンとパイプライン

間が空いてしまって色々忘れる。

継続しなければならない。

 

6章

f:id:jahjha:20190504162736j:plain

前処理を検証用テストデータにも適用してしまうと過度な汎化が起きる。(?

例えばMinMaxを全データにかけてしまうと、汎化能力が上がる(場合もある)が

実際にはテストデータは未知なものであり、訓練データの最小最大を越えることだってあり得る。

その意味で前処理は訓練データのみに適用し.fitしなければならない。

 

・Pipeline

便利。今までやってきたことはこれで省略化できる。

from sklearn.pipeline import Pipeline

pipe=Pipeline([("scaler",MinMaxScaler()),("svm",SVC())])

"scaler"のインスタンス、"svm"のインスタンスを作成し順次処理していく。

このインスタンスは2つに限られるわけではない。

(6.4汎用パイプラインインターフェイスに詳しいがよくわからん。たぶん意味はあってる)

・make_pipeline

インスタンスに名前をつけるのが面倒なのでこれもイケる。

from sklearn.pipeline import make_pipeline
pipe_long =Pipeline([("scaler",MinMaxScaler()),("svm",SVC(C=100))])
pipe_short=make_pipeline(MinMaxScaler(),SVC(C=100))

#pipe_longとpipe_shortは全く同じ動作を行う。make_pipeline作成時、各インスタンスは全小文字に自動命名される。

 

6.5グリッドサーチ

以下例でグリッドサーチできる。

pipe=make_pipeline(StandardScaler(),PolynomialFeatures(),Ridge())

param_grid={"polynomialfeatures__degree":[1,2,3],"ridge__alpha":[0.001,0.01,0.1,1,10,100]}

#XXX__YYY __はアンダーバー2つ

grid =GridSearchCV(pipe,param_grid=param_grid,cv=5,n_jobs=-1)
grid.fit(X_train,y_train)

 

6.6モデル選択のグリッドサーチ

以下例でモデル選択のグリッドサーチもできる。

(もう少し例が欲しい。これでRFのほうが良ければ結果にRFが出てくる?それを見てもう一度Pipeでセットするということか?)

pipe=Pipeline([("preprocessing",StandardScaler()),("classifier",SVC())])

param_grid =[
{"classifier":[SVC()],"preprocessing":[StandardScaler(),None],
"classifier__gamma":[0.001,0.01,0.1,1,10,100],
"classifier__C":[0.001,0.01,0.1,1,10,100]},
{"classifier":[RandomForestClassifier(n_estimators=100)],
"preprocessing":[None],"classifier__max_features":[1,2,3]}
]

#RFは前処理がいらないので"preprocessing"は[None]。

 

grid = GridSearchCV(pipe,param_grid,cv=5)
grid.fit(X_train,y_train)

 # ↓結果↓
Best params:
{'classifier': SVC(C=10, 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), 'classifier__C': 10, 'classifier__gamma': 0.01, 'preprocessing': StandardScaler(copy=True, with_mean=True, with_std=True)}
Best cross-validattion score:0.9859154929577465
Test set score:0.9790209790209791

5.3.2.6受信者動作特性(ROC)とAUC

(30m)12:00~12:30

5.3.2.6受信者動作特性(ROC)とAUC

 

ROCカーブ:

全てのスレッショルドを考慮して偽陽性率(FPR)と真陽性率(TPR)をプロットする。

FPR=FP/FP+TN(偽陽性を全ての陰性で割る)

AUC:

カーブ下の領域を呼ぶ。ROCの場合は0~1の範囲に収まり高いほうが良い。

from sklearn.metrics import roc_auc_score

5.3.2.4 不確実性を考慮する~ 5.3.2.5 適合率-再現率カーブとROCカーブ

(60m)06:00~07:00

5.3.2.4

decision_function(決定指向数 0を境に分類強度を図る)

predict_proba(1~0の間で分類強度を図る)

のthresholdを変更することで

precison(適合率),recall(再現率)の能力を変動できる。

predict_probaがある場合は割合で指定するのが簡単だ。

 

5.3.2.5 適合率-再現率カーブとROCカーブ

precision_recall_curve:適合率-再現率カーブ

from sklearn.metrics import precision_recall_curve

f:id:jahjha:20190420080053j:plain

上記表から読み取れるものは以下である。
SVCは再現率が高いまま適合率0.5程度まで保持できる。

RFは再現率、適合率ともに極端な分類がうまくいっている。

 

average precision(平均適合率):カーブ以下を積分して導き出す。

平均適合率でみるとRFのほうが適正があることになる。

ただしF1スコアでみるとSVCが上である。

カーブなどを見て適正なモデル選択をするべき。

from sklearn.metrics import average_precision_score
ap_rf =average_precision_score(y_test,rf.predict_proba(X_test)[:,1])
ap_svc =average_precision_score(y_test,svc.decision_function(X_test))

from sklearn.metrics import f1_score
print(f"f1_score of random forest :{f1_score(y_test,rf.predict(X_test)):.3f}")
print(f"f1_score of SVC:{f1_score(y_test,svc.predict(X_test)):.3f}")

 
Average precision of random forest:0.666
Average precision of SVC:0.663
f1_score of random forest :0.610 f1_score of SVC:0.656

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"]))

 
             precision    recall  f1-score   support
             (適合率) (再現率)(f1スコア)(支持度 サンプル数)
   not nine       0.98      1.00      0.99       403
       nine       0.95      0.83      0.89        47

avg / total       0.98      0.98      0.98       450

 

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")

f:id:jahjha:20190413163414p:plain
 

・場合分けでパラメータを渡すこともできる。

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のモデルでは不可。