機械学習_教師あり/なし学習
教師なし学習
主成分分析
特徴
教師なし学習であり、次元削減を行うための手法である.
分散共分散行列の固有ベクトルの基に新たな座標軸を複数作成し、新たな座標軸から構成される低次元空間へデータを写像する.
寄与率:各主成分の固有値を固有値の総和で割った値
計算
2次元空間で(-2,2),(-1,-1),(0,0),(1,1),(2,-2)という5つのデータ点がある
第一主成分: (1/√2, -1/√2)
第二主成分: (1/√2, 1/√2)
(1/√2,-1/√2)のx軸とy軸をそれぞれのデータ点と掛けた和である
第1主成分によって張られる1次元空間へ5つのデータ点を射影すると
1/√2*(-2)-1/√2*(2)=-2√2
1/√2*(-1)-1/√2*(-1)=0
1/√2*0-1/√2*0=0
1/√2*1-1/√2*1=0
1/√2*2-1/√2*(-2)=2√2
第2主成分によって張られる1次元空間へ5つのデータ点を射影すると、
1/√2*(-2)+1/√2*(2)=0
1/√2*(-1)+1/√2*(-1)=-√2
1/√2*0+1/√2*0=0
1/√2*1+1/√2*1=√2
1/√2*2+1/√2*(-2)=0
第1主成分と第2主成分による張られる2次元空間へ5つデータ点を射影すると、
(-2√2,0),(0,√2),(0,0)(0,√2),(2√2,0)である。
再構成誤差は、2次元空間に射影することによりも、1次元空間に射影されるデータのほうが大きい.
http://ibis.t.u-tokyo.ac.jp/suzuki/lecture/2015/dataanalysis/L7.pdf
def pca(X, n_components): X = X - X.mean(axis=0) # データから平均を引く cov = np.cov(X, rowvar=False) # 共分散行列の作成 l, v = np.linalg.eig(cov) # 固有値と固有ベクトルを計算 l_index = np.argsort(l)[ : : -1] #★ 固有値を降順でソートするためのインデックスを求める v_ = v[ : , l_index] #★ 固有ベクトルを降順でソートする components = v_[ : , : n_components] #★ 固有ベクトルを取得する処理, 出力の次元数分の固有ベクトルを取り出し、低次元空間へ写像 T = np.dot(X, components) return T
n_componentsの個数だけ、固有ベクトルを切り出す
データを低次元空間に射影する
K-means
特徴
<アルゴリズム>
1. 各点xiに対してランダムにクラスタを割り振る
2. 各クラスタに割り当てられた点について重心を計算する
3. 各点について上記で計算された重心からの距離を計算し、距離が一番近いクラスタに割り当て直す
4. 2と3の工程を、割り当てられるクラスタが変化しなくなるまで行う
【E資格対策】k-meansの実装方法について詳しく見る
def init_centroid(X, k, n_data): # 各データ点の中からクラスタの重心となる点をk個ランダムに選択 permutation 重複なしランダムデータ idx = np.random.permutation(n_data)[:k] #★ centroids = X[idx] return centroids def compute_distances(X, k, n_data, centroids): distances = np.zeros((n_data, k)) for idx_centroids in range(k): #すべてのデータ点との距離の二乗を計算 dist = np.sqrt(np.sum((X - centroids[idx_centroids]) **2, axis=1)) #★ def k_means(X, k, max_iter=300): centroids = init_centroid(X, k, n_data) for epoch in range(max_iter): distances = compute_distances(X, k, n_data, centroids) new_cluster = np.argmin(distances, axis = 1) # ★新たな所属クラスタを計算 for idx_centroids in range(k): centroids[idx_centroids] = X[new_cluster == idx_centroids].mean(axis=0) #★
K-means++
特徴
K-means法でははじめてのセントロイドの位置が近い場合、うまく分類できないケースがある.
そのため、K-means++では各セントロイド同士の距離がなるべく遠くなるように決める.
probabilites = np.sum(distances, axis=1) / np.sum(distances) # 列ごとに演算行うためaxis=1
distancesのすべての要素の和でdistancesの要素を割ることで各要素は0から1の間に正則化される.
さらに、今までのセントロイドの距離を考慮して行ごとに和を取るで、初期化として選ばれる確率を表すProbabilitiesを得ることができる.
この初期値の選択方法を、ルーレット選択という呼ばれる.
closet_dist_sq = np.min(distance ** 2, axis =1) #各データ点と最も近い重心との距離に二乗を計算 weights = closet_dist_sq.sum() # 距離の二乗の和を計算 rand_vals = np.random.random_sample() * weights # [0,1)の乱数と距離の二乗和をかける candidate_ids = np.serchsorted(np.cumsum(closest_dist_sq), rand_vals) # 距離の二乗の累積和を計算し、rand_valsと最も値が近いデータ点のindexを取得
k-meansとk-means++を視覚的に理解する~Pythonにてスクラッチから~ - 医療職からデータサイエンティストへ
SVM
2クラス分類問題であり、決定的な出力をする分類器である.(他クラス分類や回帰にも使える)
特徴
1. ハードマージン
- マージンの最大となる境界のパラメータw,b を学習
- 識別面を構成するために使われるマージンの上にあるデータ点をサポートベクトルと呼ぶ.
- サポートベクトルの数は学習全数データより少なく、最小値は2である
- SVMの出力はそのままでは確率値として解釈できない、ロジスティック回帰のように事後的に境界面を調整できない.
- マージンの外側のデータは予測影響を与えない(それは、識別では決定境界から近い点のデータもしくはマージンの上の点が予測に利用されるため)
- SVMにおいて射影手法を利用して、特徴空間が高次元であるほど、表現力が上がるが、計算コストが高い。計算コストを抑制するため、カーネルトリックを導入
カーネルトリック: ガウシアンカーネル、多項式カーネル、Sigmoidカーネル
2.ソフトマージン
学習データが線形分離が不可能となる場合、すべての制約を満たすことができない.スラック変数を導入して誤分類を許容する.
SVMにおいて最小化する目的関数Lの数式
- Cがになると、マージン内に訓練データが入ることで、誤分類を一切許容しない
- Cが0になると、誤分類が許容しやすく、誤分類が多くなる.
- Cが小さいすると、過学習を抑制できる.
- Cが大きくすると、誤分類の許容が大きくなる.テストの正解率が低くなる.完全に分離することで汎用性能が小さいくなる.