まさなみブログ

主にweb系開発の記事を適当に書いてます。

Pythonではじめる機械学習で機械学習を学習してみた  ~~第2章①~~

2週間くらいで一通り学習終わるだろと思っていたが、二章だけで2週間以上かかっている。がんばってペース上げたい。


・mglearn.discrete_scatter(X[:, 0], X[:, 1], y_train) #x値、y値、label
ndarray[a, b] で普通の2次配列のlリスト list[a][b]と同じような意味。


・plt.legend(["Class 0", "Class 1"], loc=4)
凡例。loc=1~4で表示する四隅を指定

参考:
Python - mglearnにおけるdiscrete_scatterとlegendについて|teratail


・{n: v for n, v in zip(cancer.target_names, np.bincount(cancer.target))}
内包表記。整理するとこんな感じ
 (n: v) for (n, v) in ...


・zip(...)
複数のリストやタプルなどをまとめる関数。多い分の要素が無視される。
参考:
Python, zip関数の使い方: 複数のリストの要素をまとめて取得 | note.nkmk.me


・np.bincount(array)
要素内の最頻値を求める。今回は"malignant" が0、"benign"が1のため、0と1の個数を取得している。
参考:
numpyでarrayの要素内の最頻値を求める - Qiita


・plt.subplots(rows、cols、axes)
figをrows * colsに分割し、axesにてfigを表示する位置を決定。
本章では側だけ3つ作って、for文でfigを作成して中にいれてる。
参考:
matplotlib の figure(図) と axes(座標軸)-python | コード7区


・mglearn.plots.plot_2d_separator(classifier, X, fill=False, ax=None, eps=None, alpha=1,cm=cm2, linewidth=None, threshold=None, linestyle="solid")
指定されたn_neighborsの値とXに渡されたデータから、分類結果の境界線(決定境界)を作成するメソッド。
参考:
https://github.com/amueller/mglearn/blob/master/mglearn/plot_2d_separator.py


・k-近傍回帰

k-近傍法の回帰モデル。特徴量に連続性があるデータを対象とした近傍法。以下サンプル。

from sklearn.neighbors import KNeighborsRegressor
reg = KNeighborsRegressor(n_neighbors=3)
reg.fit(X_train, y_train)
reg.score(X_test, y_test)
reg.predict(X_test)

・線形回帰(通常最小二乗法)

予測と回帰ターゲットyとの平均二乗誤差が最小となるような線形モデルを作る。LinearRegressionクラスを用いる。
モデル式: y=w[0]*x[0] + w[1]*x[1] + ... +w[p]*x[p] + b

from sklearn.linear_model import LinearRegression
lr = LinearRegression().fit(X_train, y_train) 
print(lr.coef_) #係数(傾き)、各特徴量に対する値が配列で格納。
print(lr.intercept_) #切片
print(lr.score(X_train, y_train)) #スコア

・リッジ回帰

係数(w)の絶対値の大きさをできるかぎり小さくし、個々の特徴量が出力に与える影響をなるべく小さくすることで過剰適合を防ぎたい線形回帰のモデル。Ridgeクラス。

from sklearn.linear_model import Ridge
ridge = Ridge(alpha=1).fit(X_train, y_train) #alphaで係数への制約の強さを指定する。
print(ridge.score(X_train, y_train))
print(ridge.score(X_test, y_test))


・plt.hlines([value1, value2, ...], xmin, xmax, linestyle="dashed")
 補助線を作成するメソッド。
【Python@matplotlib】matplotlib にて横、縦の補助線を描く方法について - Qiita


・plt.xlim(x1, x2) plt.ylim(y1, y2) 
ある特定の範囲を見せる等、グラフの横軸、縦軸を調整するメソッド。それぞれy軸、x軸


・Lasso

リッジと同様係数の値を0に近づけるのだが、制約のかけ方が異なる。L1正則化。(リッジ回帰はL2正則化)
いくつかn係数が完全に0になる。

from sklearn.linear_model import Lasso
lasso001= Lasso(alpha=0.01, max_iter=100000).fit(X_train, y_train)
print(lasso001.score(X_train, y_train))
print(lasso001.score(X_test, y_test))

・ロジスティック回帰

予測モデルをシグモイド関数を使って作成するクラス分類アルゴリズム

from sklearn.linear_model import LogisticRegression
logreg100 = LogisticRegression(C=1, penalty="l2").fit(X_train, y_train) #C:正則化パラメータ, penalty="l2"
print(logreg100.score(X_train, y_train))
print(logreg100.score(X_test, y_test))

参考:
やる夫で学ぶ機械学習 - ロジスティック回帰 - · けんごのお屋敷


・線形サポートベクターマシン

サポートベクタマシン(SVM)を使った線形クラス分類アルゴリズム
SVMとは各クラスのデータ集合が決定境界からどの程度離れているかを分類の良さの基準として、訓練データからモデルを作成する手法。

from sklearn.svm import LinearSVC
linear_svc = LinearSVC(penalty='l2', loss='squared_hinge', dual=True, tol=1e-4, C=1.0).fit(X, y)
linear_svc = LinearSVC().score(X_test, y_test)

参考:
線形SVM - Qiita


・ナイーブベイズ

線形モデルより高速。汎化性能は他線形モデルより劣る。
GuassianNB:任意の連続値データ
BernoulliNB:2値データ
MultinomialNB:カウントデータ
参考:
ナイーブベイズについて勉強したのでざっくりまとめ | DevelopersIO


・決定木

DecisionTreeClassifierを使った決定木

from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
import graphviz

tree = DecisionTreeClassifier(max_depth=4, random_state=0) #max_depthで指定した階層で分岐を止める。
tree.fit(X_train, y_train)
print(tree.score(X_train, y_train))
print(tree.score(X_test, y_test))
export_graphviz(tree, out_file="tree.dot", class_names=["malignant", "benign"], feature_names=cancer.feature_names, impurity=False, filled=True) #可視化
with open("tree.dot") as f:
    dot_graph = f.read()
graphviz.Source(dot_graph)
print(tree.feature_importances_) #特徴量の重要度
tree.predict(X)

mglearn.plots.plot_animal_tree()と打つとimport graphvizでエラー。モジュールないとのこと。
conda list python-graphvizで調べるとモジュールが入ってなかったのでインストールするも解消されない。
python-graphvizがあるところにパスを通して無事解決。
以下サイトを参考:
Graphvizパッケージのエラーの対処法(Windows) - The Cinema, Actually


・ランダムフォレスト

異なった方向に過剰適合した決定木をたくさんつくり、結果を平均する感じ。
決定木建築課程で乱数を導入し、差異を導入。

from sklearn.ensemble import RandomForestClassifier
forest = RandomForestClassifier(n_estimators=5, random_state=2) #n_estimators 決定木の本数
forest.fit(X_train, y_train)
print(forest.score(X_train, y_train))
print(forest.score(X_test, y_test))
print(forest.prediect(X_test))

・勾配ブースティングマシン

複数の決定木を順番に作っていき、ひとつ前の決定木の誤りを次の木が修正していく手法。

gbrt = GradientBoostingClassifier(n_estimators=100, random_state=0, max_depth=3, 
learning_rate=0.1) #max_depth 最大の枝の数 #learning_rate 学習率 #n_estimatorsデフォルトで100
gbrt.fit(X_train, y_train)
print(gbrt.score(X_train, y_train))
print(gbrt.score(X_test, y_test))

カーネル法を用いたサポートベクターマシン

平面だけでなく、より複雑なモデルを可能とするため線形SVMを拡張したもの。
・LinearSVCの特徴量を追加(z軸)して決定境界を作成

X_new = np.hstack([X, X[:, 1:] ** 2]) #3つ目の特徴量  X[:1]^2 を追加
from mpl_toolkits.mplot3d import Axes3D, axes3d 
figure = plt.figure() 
ax = Axes3D(figure, elev=-152, azim=-26) #elev:z軸方向から見た仰角 #azim:x, y軸方向の方位角
linear_svm_3d = LinearSVC().fit(X_new, y)
coef, intercept = linear_svm_3d.coef_.ravel(), linear_svm_3d.intercept_
xx = np.linspace(X_new[:, 0].min() - 2, X_new[:, 0].max() + 2, 50)
yy = np.linspace(X_new[:, 1].min() - 2, X_new[:, 1].max() + 2, 50)
XX, YY = np.meshgrid(xx, yy) #x,yの格子点を作成
ZZ = (coef[0] * XX + coef[1] * YY + intercept) / -coef[2]
ax.plot_surface(XX, YY, ZZ, rstride=8, cstride=8, alpha=0.3)
mask = y == 0
ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c= 'b', cmap=mglearn.cm2, s=60)
ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c='r', marker='^', cmap=mglearn.cm2, s=60) #[~mask] の~はビット反転子


・np.hstack(tup)
水平方向にタプルを結合。
参考:
配列同士を連結する、NumPyのvstackとhstack関数の使い方 - DeepAge


カーネルトリックを使ったSVM

個々のデータポイントが、2つのクラスの決定境界を表現するのにどの程度重要かを学習する。
多くは境界線付近のデータポイントが決定境界を決定する。これらのデータポイントをサポートベクタと呼ぶ。

from sklearn.svm import SVC
#C 正則化パラメータ #gamma ガウネシアンカーネルの幅(データポイントの距離が遠いと判定された場合サポートベクタになるってことだと思う)
svm = SVC(kernel='rbf', C=10, gamma=0.1).fit(X, y) 
mglearn.plots.plot_2d_separator(svm, X, eps=.5)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
sv = svm.support_vectors_ #サポートベクタ
sv_labels = svm.dual_coef_.ravel() > 0
mglearn.discrete_scatter(sv[:, 0], sv[:, 1], sv_labels, s=15, markeredgewidth=3) #サポートベクタを描画
print(svm.score(X_test, y_test))
print(svm.predict(X_test))


svmのためのデータ前処理
特徴量が桁違いにサイズが異なる場合、だいたい同じスケールとなるようにそれぞれスケール変換する。
・MinMaxScalar すべての特徴量を0-1の間となるよう変換


第二章は量が多いので分割。。