---
# System prepended metadata

title: Machine Learning Homework 2 LDA

---

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