ML:基礎技法學習
Package:scikit-learn
課程:
機器學習技法
簡介:第十四講 Radial Basis Function Network
RBF Network Hypothesis
故 Radial Basis Function (RBF) Network 就是 radial hypotheses 的線性組合
而 RBF Network 在歷史上其實只是 NNet 的其中一個分支
如下圖,內積 + tanh (NNet) vs 與中心的距離 + RBF (RBF Network)
Gaussian kernel 為其中一種 Radial Basis Function (RBF) kernel
所以將 套進 RBF 基本模型,可參考
[ML] 機器學習技法:第三講 Kernel SVM
- RBF:Gaussian
- Output:sign
- M:SV 的數量
- :SVM SVs
- :
事實上,機器學習一直在對相似性進行處理
Regularized Full RBF Network
full RBF Network for ridge regression
,也就是將所有的訓練點 皆為中心點
這邊將 ,且為了偷懶,將所有的訓練點 都當作中心點
所有點都有影響力,決定輸入 的
先討論一個特殊的情況,假設 ,且 RBF 為 Gaussian
這就是一個 uniform 形式的 RBF,取每個點的平均意見
但因為 RBF 是 Gaussian ,通常最靠近的 將決定絕大部分的結果
那麼何不直接挑 最大值的
這也就是 nearest neighbor model
只用一個 決定似乎不保險,那用 k 個呢?k nearest neighbor (KNN)
這是個偷懶的方法,訓練時很簡單,記住 就好,但預測時就得找出最接近的幾個值了
回過頭來,若取 square error
先轉換訓練資料
可得
借由
[ML] 機器學習基石:第九講 Linear Regression
可得
為對稱矩陣,且當 都不一樣時, 必有其 inverse
將其代入
看起來很完美,但記得,對於 Machine learning 這將造成 overfitting
所以加入 ridge regression 也就是 regularization 為 L2
借由
矩陣微分
區域最佳解,微分等於 0,故
這個解與 KRR 的解 極度相似
可參考
[ML] 機器學習技法:第六講 Support Vector Regression (SVR)
事實上
兩者差異的原因在於 regularization 針對 的維度不同
KRR 是在無限維度上處理,而 regularized full RBFNet 是在有限維度上處理的
無限維度的原因,可參考
[ML] 機器學習技法:第三講 Kernel SVM
全部的點都拿來當中心點,容易 overfitting,且計算量又太大
適當的只選擇其中的點做為代表,像是 SVM 的 support vectors
並且限制 的大小,才會更加準確
k-Means Algorithm
- 初始化
- 隨機從 挑選出 k 個, k 用 validation 決定
- 交替優化 ,直到 不再有改變
- 最佳化
將每個 都個別分類至最近的
- 最佳化
從分完類的 計算出
此為 unsupervised learning,且非常受歡迎
希望將 分群 M 個,並從其中選出代表
這個最佳化很困難,因為同時具有數值的最佳化 ,還需分群的最佳化
數值的最佳化需要的是微分,但分群的最佳化需要的是所有的排列組合找出最好的
那是否可以個別最佳化呢?
假設 固定
那麼只需要決定 ,怎麼決定 屬於哪個群呢?
很簡單, 離哪個 最近,就是屬於那個
再來 固定
為集合共有幾個 ,所以 其實就是 的平均
因為在過程中, 是逐漸往下的,而 的下限為 0,故確定會收斂
歷史上,最先是用 k,所以將 M 改為 k
此為 unsupervised learning,因跟 無關
對 k 與初始值非常敏感,需特別注意
RBF Network Using k-Means
- 執行 k-Means,將 k=M 得到
- 建立 ,利用 RBF(例:Gaussian) 和
- 建立 linear mode 得到
- 回傳
需適當的選擇中心點的數目,不然可能會像第一張圖,都認為是叉叉
比較,但因為 Full RBF Network 以及 nearest neighbor 計算複雜,實務上並不常用
實務上並不常用 RBF Network,因與 Gaussian SVM or NNet 的表現差不多,但仍不失為一個好的想法
程式碼
- import numpy as np
- import matplotlib.pyplot as plt
-
- from sklearn.cluster import KMeans
- from sklearn.datasets import make_blobs
-
- plt.figure(figsize=(8, 8))
- # 用来正常顯示中文標簽
- plt.rcParams['font.sans-serif']=['SimHei']
- # 用来正常顯示負號
- plt.rcParams['axes.unicode_minus']=False
-
- n_samples = 1500
- random_state = 170
- # 產生 1500 筆資料,共有三群
- X, y = make_blobs(n_samples=n_samples, random_state=random_state)
-
- # 不正確的群數
- y_pred = KMeans(n_clusters=2, random_state=random_state).fit_predict(X)
-
- plt.subplot(221)
- plt.scatter(X[:, 0], X[:, 1], c=y_pred)
- plt.title("Incorrect Number of Blobs (錯誤的 k)")
-
- # Anisotropically distributed data
- # 非同方向縮放一致的分佈
- transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]
- X_aniso = np.dot(X, transformation)
- y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_aniso)
-
- plt.subplot(222)
- plt.scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred)
- plt.title("Anisotropically Distributed Blobs (非等比例分佈)")
-
- # 不同標準差
- X_varied, y_varied = make_blobs(n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state)
- y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_varied)
-
- plt.subplot(223)
- plt.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)
- plt.title("Unequal Variance (不同標準差)")
-
- # Unevenly sized blobs
- # >>> a = np.array([1, 2, 3])
- # >>> b = np.array([2, 3, 4])
- # >>> np.vstack((a,b))
- # array([[1, 2, 3],
- # [2, 3, 4]])
- # vstack 在第二個維度堆疊
- X_filtered = np.vstack((X[y == 0][:500], X[y == 1][:100], X[y == 2][:10]))
- y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_filtered)
-
- plt.subplot(224)
- plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
- plt.title("Unevenly Sized Blobs (數量不同)")
-
- plt.show()
- import numpy as np
- import matplotlib.pyplot as plt
- from sklearn.cluster import KMeans
- from sklearn.metrics import pairwise_distances_argmin
- from sklearn.datasets import load_sample_image
- from sklearn.utils import shuffle
- from time import time
-
- # 壓縮為 64 個顏色
- n_colors = 64
-
- # 讀取照片
- china = load_sample_image("china.jpg")
-
- # 轉換為浮點數,範圍為 [0-1]
- china = np.array(china, dtype=np.float64) / 255
-
- # 讀取長寬與一個 pixel 的顏色數目
- w, h, d = original_shape = tuple(china.shape)
- assert d == 3
- # 轉成 array
- image_array = np.reshape(china, (w * h, d))
-
- print("用原圖的小部分當樣本訓練 model")
- t0 = time()
- image_array_sample = shuffle(image_array, random_state=0)[:1000]
- kmeans = KMeans(init='random', n_clusters=n_colors, random_state=0).fit(image_array_sample)
- print("done in %0.3fs." % (time() - t0))
-
- # 處理整張圖
- print("在整張圖上預測顏色")
- t0 = time()
- # 預測,只會回傳中心點對應的 index
- labels = kmeans.predict(image_array)
- print("done in %0.3fs." % (time() - t0))
-
- # 處理整張圖,但從原圖隨機挑出顏色
- codebook_random = shuffle(image_array, random_state=0)[:n_colors + 1]
- print("在整張圖上預測顏色 (隨機版)")
- t0 = time()
- # 挑選出 X 最接近 Y 的顏色,並送出 Y 的 index
- labels_random = pairwise_distances_argmin(X=image_array, Y=codebook_random)
- print("done in %0.3fs." % (time() - t0))
-
- def recreate_image(codebook, labels, w, h):
- """用 codebook 和 labels 重新建立圖"""
- d = codebook.shape[1]
- image = np.zeros((w, h, d))
- label_idx = 0
- for i in range(w):
- for j in range(h):
- image[i][j] = codebook[labels[label_idx]]
- label_idx += 1
- return image
-
- # 畫圖
- # 用来正常顯示中文標簽
- plt.rcParams['font.sans-serif']=['SimHei']
- fig, axes = plt.subplots(1, 3)
-
- axes[0].xaxis.set_visible(False)
- axes[0].yaxis.set_visible(False)
- axes[0].set_title('原始圖 (96,615 colors)')
- axes[0].imshow(china)
-
- axes[1].xaxis.set_visible(False)
- axes[1].yaxis.set_visible(False)
- axes[1].set_title('壓縮圖 (64 colors, K-Means)')
- axes[1].imshow(recreate_image(kmeans.cluster_centers_, labels, w, h))
-
- axes[2].xaxis.set_visible(False)
- axes[2].yaxis.set_visible(False)
- axes[2].set_title('壓縮圖 (64 colors, Random)')
- axes[2].imshow(recreate_image(codebook_random, labels_random, w, h))
-
- plt.show()
參考
sklearn.cluster.KMeans
留言
張貼留言