fisher线性判别python实现

题目:Iris也称鸢尾花卉数据集,是一类多重变量分析的数据集。每个数据包含4个属性,分别是花萼长度,花萼宽度,花瓣长度,花瓣宽度,通过这4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类。现在给定IRIS训练数据集,该数据集包含135个数据,每个类别有45个训练数据,分为三种类型,假设IRIS数据中各类别符合正态分布。测试数据集中一共15个数据,每个类别也包含5个测试数据。

实验要求:

  1. 使用fisher判别准则,从每个类别的4个特征中选取3个特征,分别针对其中的两种类别设计线性分类器,即设计第一类和第二类,第二类和第三类,第一类和第三类之间的分类面。
  2. 并用测试样本计算分类器的性能。
  3. 在确定w0时可以尝试使用不同的经验值,比较分类结果是否不同?
  4. 要求画出投影前的样本点,以及投影后的测试样本点、投影方向及分类面。
  5. 使用python语言来完成实验
import numpy as np
import matplotlib.colors
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

f_train = np.loadtxt("iris训练数据.txt", dtype=np.double, delimiter='\t')

# 存类别
category1 = f_train[:25, 0].T
category2 = f_train[50:75, 0].T
category = np.r_[category1, category2]
# print(category)
# 已知1、3分别为两个类别的数据 各为25个(行) 选第三、第四个(列)
# 转置 25*2 -->  2*25
X1 = f_train[:25, 3:5].T
X3 = f_train[50:75, 3:5].T

a = X1[0,:]
b = X1[1,:]
c = X3[0,:]
d = X3[1,:]
# print(a.shape)

# 画出两类训练数据的空间分布
# scatter方法用于绘制散点图,与plot方法不同之处在于,scatter主要用于绘制点的颜色和大小呈现梯度变化的散点图,也就是我们常说的气泡图
# plt.title("train examples")
# plt.scatter(a, b, c='orange')
# plt.scatter(c, d, c='red')


# 矩阵化
x1 = np.matrix(X1)   # 2*25  两个特征 25个样本
x3 = np.matrix(X3)
# print(x1[0,:])

# 求基本参量
# 均值向量
m = np.zeros((2, 2)) # 均值   1、3类   3、4特征
# for i in range(2):# 特征遍历
#     m[0, i] = np.mean(x1[i, :])
#     m[1, i] = np.mean(x3[i, :])
# print("均值为:\n", m)
# 按行进行求和并除以n,最终m1是一个二维的列向量
m1 = np.sum(x1, axis=1) / 25 # 2*1
m3 = np.sum(x3, axis=1) / 25

# 离散度矩阵
# 计算类内离散度矩阵
S1 = (x1 - m1) * (x1 - m3).T
# print("S1:\n", S1)
S3 = (X3 - m3) * (X3 - m3).T
# print("S3:\n", S3)

# 总类内离散度矩阵
Sw = S1 + S3  # 2*2
# print("Sw",Sw.shape)
# 类间离散度矩阵
Sb = (m1 - m3) * (m1 - m3).T

# 计算 w*  ----最优投影方向
w = Sw.I * (m1 - m3)  # 2*1
print("w:",w)

# 确定分类面位置还需确定分类阈值 w0
# 根据经验中的2) 先验概率已知 且相等 即 1)
# 求 m~
mm1 = w.T * m1
mm3 = w.T * m3
w0 = -0.5 * (mm1 + mm3)
print("w0:",w0[0,0]) # 取出数

# # 第一种方法  N d 很大 贝叶斯分类器
# # 注意这里的0是ln(P(w2)/P(w1))的结果,因为两者先验概率相同
# w0 = np.matrix(-0.5 * (m1+m3).T*Sw.I*(m1-m3)-0)
# w0 = w0[0, 0]  # 这里是将值取出
# print("1. w0:\n", w0)

# 判别函数 G(x) = w.T * x + w0  一维
f_test = np.loadtxt("iris测试数据.txt", dtype=np.double, delimiter='\t')
y1 = f_test[0:25, 3:5]# 0-25
y3 = f_test[50:75, 3:5]
a = y1[:,0]
b = y1[:,1]
c = y3[:,0]
d = y3[:,1]
# print("hh",a.shape)
y1 = np.matrix(f_test[0:25, 3:5].T)# 0-25
y3 = np.matrix(f_test[50:75, 3:5].T)
# 这里将两类X合并为一个
# np.r_是按行连接两个矩阵,就是把两矩阵上下相加,要求列数相等。
# np.c_是按列连接两个矩阵,就是把两矩阵左右相加,要求行数相等。
X = np.c_[y1, y3] # 2*50  两个特征
# print(X[:,0])
g = np.zeros(50)
ans1 = 0
Ans = np.zeros(50)
ans3 = 0
# print(np.array(X.shape))
wrong = 0
for i in range(50):
    g[i] = w.T * X[:,i] + w0[0,0] # 1*2  2*1
    if(g[i] > 0):
        ans1 = ans1 + 1
        Ans[i] = 1
        print("第%d个样本分类:√",i)
        if(Ans[i] != category[i]):
            wrong += 1
            print("第%d个样本分类:×",i)
    else:
        ans3 = ans3 + 1
        Ans[i] = 3
        print("第%d个样本分类:√",i)
        if (Ans[i] != category[i]):
            wrong += 1
            print("第%d个样本分类:×",i)
# print(wrong)
print("错误率为:",wrong/50)
# print("第一类有:\n",ans1,"\n第三类有:\n",ans3,"\n",Ans,)


# # %归一化,变为模为1的单 位矢
w_k = w / (np.sqrt(sum(w.T * w)))
# w_k = w[0:2] / (np.sqrt(sum(np.power(w[0:2], 2))))
wd1 = np.matrix(np.zeros((2,25)))
wd3 = np.matrix(np.zeros((2,25)))
for i in range(25) :
    # wd[:,i] = X[:,i].T *( w_k.T *w_k)
    wd1[:, i] = w_k * (np.dot(w_k.T, y1[:,i])) / np.dot(w_k.T, w_k)
    wd3[:, i] = w_k * (np.dot(w_k.T, y3[:, i])) / np.dot(w_k.T, w_k)
print("投影点wd1:",wd1.shape) # 2*50

# 最佳投影方向
print("最佳投影方向:",w,"\n分类面位置:",w0)
# 投影方向
plt.plot([0,10*w[0,]],[0,10*w[1,]],label = 'touying direction')
# 分类面
# plt.plot([0,-10*w[0,]],[0,10*w[1,]]) # 两个点间一个取反 就是垂线
# 样本点
# plt.title("test examples")
plt.scatter(a, b, c='yellow',label = 'example 1')   # x y
plt.scatter(c, d, c='green',label = 'example 3')
# 投影点
plt.scatter(np.array(wd1[0,0:25]), np.array(wd1[1,0:25]), c='orange')
plt.scatter(np.array(wd3[0,0:25]), np.array(wd3[1,0:25]), c='blue')
# plt.plot(a = -w[0,]/w[1,] * X1.T + w0)

# plt.axhline(y=0,xmin=0,xmax=1,color='k',linestyle='dashed')
# plt.show()

#
# 4、绘图      --分类面     -------------------------------------参考1)
# plt.scatter(a, b, c='red')
# plt.scatter(c, d, c='blue')
line_x = np.arange(min(np.min(a), np.min(c)),
                   max(np.max(a), np.max(c)),
                   step=1)  # 6*1
line_y = (-(w[0,0]*line_x) / w[1,0] + w0 ).T # 6*1   # 按理+w0但效果不好所以加了两个w0
# print(line_y.shape)
print("line_x:\n",line_x,"\nline_y:\n",line_y)
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.xlim([-7, 7])
# plt.ylim([-5, 5])
plt.show()

你可能感兴趣的:(模式识别,算法,人工智能)