# Machine Learning Homework 2 LDA Department : Forsetry Student ID : M10912004 Name : De-Kai Kao (高得愷) E-mail : block58697@gmail.com ## 介紹 線性判別分析(Linear Discriminate Analysis, LDA)是一種常用的統計分析方法,主要用於分類問題。它是一種監督式學習方法,即需要有已知類別的樣本作為訓練數據,以建立分類模型。LDA通常用於二元分類(binary classification),但也可以擴展到多類別分類(multiclass classification)。 <br/> LDA基於貝葉斯定理,假設不同類別的樣本分布是高斯分布(Gaussian Distribution),且各類別的協方差相等(equal covariance)。在這個假設下,LDA可以通過計算樣本的平均值、標準差和協方差矩陣等統計量,得到一個判別函數(discriminant function),用於將新的樣本分到類別中。 <br/> LDA將訓練數據中每一個類別的樣本視為一個高斯分布,假設不同類別的高斯分布具有相同的協方差矩陣,即同一類別的樣本具有相同的變異程度,而不同類別之間的協方差矩陣相等。這樣可以將類別的判別函數表示為線性函數,並且可以通過最大化類別之間的分離程度來得到判別函數。 <br/> 在使用LDA進行分類時,將新的樣本投影到判別函數上,並計算其所在的類別,即為該樣本的分類結果。此外,LDA還可以計算出分類錯誤率和ROC曲線等評價指標,以評估分類模型的性能。 <br/> 優點: 1. 可以處理高維數據,對於數據的線性分離效果較好。 2. 在滿足假設條件的情況下,LDA具有較高的分類準確率。 3. 可以得到判別函數的解析式,計算方便。 <br/> 缺點: 1. 對數據的假設比較嚴格,假設各類別的樣本分布是高斯分布且協方差矩陣相等,如果這些假設不成立,可能會導致分類結果不準確。 2. 在處理類別不平衡的問題時效果不佳,即某一類別的樣本數遠遠多於其他類別的樣本數。 3. LDA是一種線性模型,對於非線性問題的分類效果不佳。如果數據呈現非線性分布,可能需要使用其他非線性分類器,如支持向量機(Support Vector Machine, SVM)或神經網絡(Neural Network)等。 4. 對特徵選擇較為敏感,如果選擇的特徵不具有顯著差異,可能會導致分類效果不佳。 <br/> <br/> <br/> ## Python實作 ### Import ``` import numpy as np import matplotlib.pyplot as plt ``` ### 生成隨機資料 ``` # Set up the parameters for the normal distributions mean1 = 20 std1 = 5 mean2 = 50 std2 = 14 n = 200 # Generate n random samples of x1 and x2 x1 = np.random.normal(mean1, std1, n) y1 = np.random.normal(mean1, std1, n) x2 = np.random.normal(mean2, std2, n) y2 = np.random.normal(mean2, std2, n) # stack a = np.stack((x1, y1), axis=1) b = np.stack((x2, y2), axis=1) a.shape # (200, 2) plt.plot(a[:,0], a[:,1], 'g.', b[:,0], b[:,1], 'y.') plt.gca().axis('equal') ``` ![](https://i.imgur.com/PELzq9X.png) ### 計算特徵向量 ``` # calclate each class of mean vector mu_a, mu_b = a.mean(axis=0).reshape(-1,1), b.mean(axis=0).reshape(-1,1) Sw = np.cov(a.T) + np.cov(b.T) inv_S = np.linalg.inv(Sw) Sb = (mu_a-mu_b)*((mu_a-mu_b).T) eig_vals, eig_vecs = np.linalg.eig(inv_S.dot(Sb)) res = np.array([-eig_vecs[0].max(), -eig_vecs[1].min()]).reshape(-1,1) ``` Unit Vector: [-0.77810883 -0.62812948] ### Plot ``` # plot the project axis with an infinitely line plt.axline((-res[0], -res[1]), (res[0], res[1]), color='red', label='by points') # project data point on new axis r = res.reshape(2,) n2 = np.linalg.norm(r)**2 aprj = [] bprj = [] for pt in a: prj = r * r.dot(pt) / n2 aprj += [prj] # plt.plot([x1, x2], [y1, y2]) plt.plot([prj[0], pt[0]], [prj[1], pt[1]], 'g.:', alpha=0.5) for pt in b: prj = r * r.dot(pt) / n2 bprj += [prj] plt.plot([prj[0], pt[0]], [prj[1], pt[1]], 'y.:', alpha=0.5) # get boundary point mu_aprj, mu_bprj = np.array(aprj).mean(axis=0).reshape(-1,1), np.array(bprj).mean(axis=0).reshape(-1,1) muprj = (mu_aprj + mu_bprj) / 2 plt.plot(muprj[0], muprj[1], 'ro') print('boundary point:', muprj[0], muprj[1]) # plot the decision boundary on boundary point muprj = muprj.reshape(2, ) x1 = -res[1] + muprj[0] y1 = res[0] + muprj[1] x2 = muprj[0] y2 = muprj[1] plt.axline((x1, y1), (x2, y2), color='green', label='by points') ``` ![](https://i.imgur.com/LbcVlXl.png) ### Decision ``` x0 = 20 y0 = 40 m = (y2-y1)/(x2-x1) x = np.linspace(plt.xlim()[0], plt.xlim()[1], 100) y = m * (x - x2) + y2 if m * (x0 - x2) + y2 -y0 <0: plt.fill_between(x, y, max(plt.ylim()), color='green', alpha=0.2) plt.plot(x0, y0, 'bo') elif m * (x0 - x2) + y2 -y0 >0: plt.fill_between(x, y, min(plt.ylim()), color='yellow', alpha=0.2) plt.plot(x0, y0, 'bo') else: plt.plot(x0, y0, 'bo') ``` ![](https://i.imgur.com/6eCSHJH.png) --- https://hackmd.io/IoZA6SnWT-WW4AYmyjGweA?view ![](https://i.imgur.com/CyDE0k6.png)