python代码实现Fisher判别推导
python代码实现Fisher判别推导目录python代码实现Fisher判别推导一、Fisher判别法1、Fisher判别法基本定义二、Fisher判别法求解步骤1、计算各类样本均值向量2、计算样本类内离散度矩阵SiS_iSi和总类内离散度矩阵SωS_\omegaSω3、计算样本类间离散度矩阵SbS_bSb4、求投影方向向量W5、将训练集内所有样本进行投影6、计算在投影空间上的分割阈值.
python代码实现Fisher判别推导
一、Fisher判别法
1、Fisher判别法基本定义
Fisher判别法是根据方差分析的思想建立起来的一种能较好区分各个总体的线性判别法,由Fisher在1936年提出。该判别方法对总体的分布不做任何要求。
Fisher判别法是一种投影方法,把高维空间的点向低维空间投影。在原来的坐标系下,可能很难把样品分开,而投影后可能区别明显。一般说,可以先投影到一维空间(直线)上,如果效果不理想,在投影到另一条直线上(从而构成二维空间),依此类推。每个投影可以建立一个判别函数。
二、Fisher判别法求解步骤
1、计算各类样本均值向量
m i = 1 N i ∑ x j ∈ ω i x j ,i=1,2 m_i = \frac{1}{N_i}\sum_{x_j\in\omega_i}x_j \text {,i=1,2} mi=Ni1xj∈ωi∑xj,i=1,2
m i m_i mi是各个类的均值, N i N_i Ni是 ω i \omega_i ωi类的样本个数
2、计算样本类内离散度矩阵 S i S_i Si和总类内离散度矩阵 S ω S_\omega Sω
m i = ∑ x j ∈ ω i ( x j − m i ) ( x j − m i ) T ,i=1,2 m_i = \sum_{x_j\in\omega_i}(x_j-m_i)(x_j-m_i)^T \text {,i=1,2} mi=xj∈ωi∑(xj−mi)(xj−mi)T,i=1,2
S ω = S 1 + S 2 S_\omega=S_1+S_2 Sω=S1+S2
3、计算样本类间离散度矩阵 S b S_b Sb
S b = ( m 1 − m 2 ) ( m 1 − m 2 ) T S_b=(m_1-m_2)(m_1-m_2)^T Sb=(m1−m2)(m1−m2)T
4、求投影方向向量W
J F ( ω ) = ω T S b ω ω T S ω ω J_F(\omega)= \frac{\omega^TS_b\omega}{\omega^TS_\omega\omega} JF(ω)=ωTSωωωTSbω
当 J F ( ω ) J_F(\omega) JF(ω)取得最大值时, ω \omega ω为
ω = S ω − 1 ( m 1 − m 2 ) \omega=S_\omega^{-1}(m_1-m_2) ω=Sω−1(m1−m2)
5、将训练集内所有样本进行投影
y = ω T x y=\omega^Tx y=ωTx
6、计算在投影空间上的分割阈值 y 0 y_0 y0
在一维Y空间中,各类样本均值 m i ~ \tilde{m_i} mi~为:
m i ~ = 1 N i ∑ y i ∈ ω i y j = 1 N i ∑ x j ∈ ω i ω T x j = ω T m i \tilde{m_i}=\frac{1}{N_i}\sum_{y_i\in\omega_i}y_j =\frac{1}{N_i}\sum_{x_j\in\omega_i}\omega^Tx_j=\omega^Tm_i mi~=Ni1yi∈ωi∑yj=Ni1xj∈ωi∑ωTxj=ωTmi
由于 S ω S_\omega Sω, S b S_b Sb都是对称矩阵,则 S ω = S ω T S_\omega=S_\omega^T Sω=SωT
S b = S b T S_b=S_b^T Sb=SbT
样本类内离散度 S ~ i 2 \tilde S_i^2 S~i2 和总类内离散度 S ~ ω \tilde S_\omega S~ω
S ~ i 2 = ∑ y ∈ ω i ( y − m ~ i ) 2 ,i=1,2 \tilde S_i^2=\sum_{y\in\omega_i}(y-\tilde m_i)^2 \text {,i=1,2} S~i2=y∈ωi∑(y−m~i)2,i=1,2
S ~ ω = S ~ 1 2 + S ~ 2 2 \tilde S_\omega=\tilde S_1^2+\tilde S_2^2 S~ω=S~12+S~22
此时类间离散度:
S ~ b 2 = ( m ~ 1 − m ~ 2 ) 2 \tilde S_b^2=(\tilde m_1-\tilde m_2)^2 S~b2=(m~1−m~2)2
阈值 y 0 y_0 y0
y 0 = N 1 m ~ 1 + N 2 m ~ 2 N 1 + N 2 y_0=\frac{N_1\tilde m_1+N_2\tilde m_2}{N_1+N_2} y0=N1+N2N1m~1+N2m~2
7、对于给定的测试样本 x x x,计算出它在 ω \omega ω上的投影点 y y y
y = ω T x y=\omega^Tx y=ωTx
8、根据决策规则分类
{ y > y 0 ⇒ X ∈ ω 1 y < y 0 ⇒ X ∈ ω 2 \begin{cases} y>y_0\Rightarrow X\in \omega_1 \\ y<y_0 \Rightarrow X\in \omega_2 \end{cases} {y>y0⇒X∈ω1y<y0⇒X∈ω2
三、python代码实现Fisher判别推导
1、数据生成
from sklearn.datasets import make_multilabel_classification
import numpy as np
x, y = make_multilabel_classification(n_samples=20, n_features=2,
n_labels=1, n_classes=1,
random_state=2) # 设置随机数种子,保证每次产生相同的数据。
# 根据类别分个类
index1 = np.array([index for (index, value) in enumerate(y) if value == 0]) # 获取类别1的indexs
index2 = np.array([index for (index, value) in enumerate(y) if value == 1]) # 获取类别2的indexs
c_1 = x[index1] # 类别1的所有数据(x1, x2) in X_1
c_2 = x[index2] # 类别2的所有数据(x1, x2) in X_2
2、Fisher算法实现
# 2、Fisher算法实现
def cal_cov_and_avg(samples):
"""
给定一个类别的数据,计算协方差矩阵和平均向量
:param samples:
:return:
"""
u1 = np.mean(samples, axis=0)
cov_m = np.zeros((samples.shape[1], samples.shape[1]))
for s in samples:
t = s - u1
cov_m += t*t.reshape(2, 1)
return cov_m, u1
def fisher(c_1, c_2):
"""
fisher算法实现(参考上面的推导公式进行理解)
:param c_1:
:param c_2:
:return:
"""
cov_1, u1 = cal_cov_and_avg(c_1)
cov_2, u2 = cal_cov_and_avg(c_2)
s_w = cov_1 + cov_2 # 总类内离散度矩阵。
u, s, v = np.linalg.svd(s_w) # 下面的参考公式(4-10)
s_w_inv = np.dot(np.dot(v.T, np.linalg.inv(np.diag(s))), u.T)
return np.dot(s_w_inv, u1 - u2)
3、类别判断
def judge(sample, w, c_1, c_2):
"""
返回值:ture 属于1;false 属于2
:param sample:
:param w:
:param c_1:
:param c_2:
:return:
"""
u1 = np.mean(c_1, axis=0)
u2 = np.mean(c_2, axis=0)
center_1 = np.dot(w.T, u1) # 参考公式(2-8)
center_2 = np.dot(w.T, u2)
pos = np.dot(w.T, sample) # 新样本进来判断
return abs(pos - center_1) < abs(pos - center_2)
w = fisher(c_1, c_2) # 调用函数,得到参数w
out = judge(c_2[1], w, c_1, c_2) # 判断所属的类别。
print(out)
4、相关图片绘制
# 4、绘图
plt.scatter(c_1[:, 0], c_1[:, 1], c='red')
plt.scatter(c_2[:, 0], c_2[:, 1], c='blue')
line_x = np.arange(min(np.min(c_1[:, 0]), np.min(c_2[:, 0])),
max(np.max(c_1[:, 0]), np.max(c_2[:, 0])),
step=1)
line_y = -(w[0]*line_x) / w[1]
plt.plot(line_x, line_y, linewidth=3.0, label = 'fisher boundary line ')
plt.legend(loc='upper right')
plt.xlabel('feature 1')
plt.ylabel('feature 2')
plt.show()
5、程序运行结果

更多推荐


所有评论(0)