import matplotlib.pyplot as plt
import numpy as np
import xlrd
table = xlrd.open_workbook('xian.xlsx').sheets()[0]#读取Excel数据
data = []
for i in range(1,table.nrows):#假设第一行是表头不读入
data.append(table.row_values(i))
class0 = []
class1 = []
#划分正反特征集,编号第一列,类别最后一列,特征在中间
for i in data:
if i[-1] == 0:
class0.append(i[1:-1])
else:
class1.append(i[1:-1])
data = np.array(data) #转为数字矩阵
class0 = np.array(class0) #特征都是行向量,组成矩阵
class1 = np.array(class1)
# %%
#计算相应类别特征的平均
n0 = len(class0)
n1 = len(class1)
miu0 = np.dot(np.ones([1,n0]),class0)/n0
miu1 = np.dot(np.ones([1,n1]),class1)/n1
#%%
#计算类内散度矩阵
s0 = class0 - miu0
s1 = class1 - miu1
Sw = np.dot(s0.transpose(),s0)+np.dot(s1.transpose(),s1)
W = np.dot(np.linalg.pinv(Sw),(miu0-miu1).transpose()) #计算W
#输出W、miu0和miu1在映射后的值
miu0_LDA = np.dot(miu0,W)
miu1_LDA = np.dot(miu1,W)
print("变换向量W:")
print(W)
print("0类的LDA均值:"+str(miu0_LDA[0,0]))
print("1类的LDA均值:"+str(miu1_LDA[0,0]))
#%%
#判断类别
c_discrim = np.dot(data[:,1:-1],W)
#统计正确率
right = 0
for i in range(len(data)):
if np.abs(miu0_LDA[0,0] - c_discrim[i]) < np.abs(miu1_LDA[0,0] - c_discrim[i]):
if data[i][-1] == 0:
right +=1
else:
if data[i][-1] == 1:
right +=1
print("正确率:"+str(right / len(data)))
#%%
#画图(仅适用于二维特征)
##################图一
fig = plt.figure()
ax = fig.add_subplot(121,projection = '3d')
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
ax.plot(class0[:,0],class0[:,1],'o',label = 'Class0',color = "red") #0类
ax.plot([miu0[0,0]],[miu0[0,1]],'*',label = 'Class0 average',color = "black",markersize = 10) #0类平均
ax.plot(class1[:,0],class1[:,1],'o',label = 'Class1',color = "blue") #1类
ax.plot([miu1[0,0]],[miu1[0,1]],'*',label = 'Class1 average',color = "green",markersize = 10) #1类平均
#映射平面
t = np.linspace(-5,10,10)
X,Y = np.meshgrid(t,t)
ax.plot_surface(X,Y,X*W[0]+Y*W[1],alpha = 0.5)
ax.legend(loc = 'upper left')
##################图二
ax = fig.add_subplot(122,projection = '3d')
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
ax.plot(class0[:,0],class0[:,1],np.dot(class0,W)[:,0],'o',label = 'Mapping Class0',color = "red") #0类映射
ax.plot([miu0[0,0]],[miu0[0,1]],np.dot(miu0[0],W),'*',label = 'Mapping class0 average',color = "black",markersize = 10) #0类平均映射
ax.plot(class1[:,0],class1[:,1],np.dot(class1,W)[:,0],'o',label = 'Mapping Class1',color = "blue") #1类映射
ax.plot([miu1[0,0]],[miu1[0,1]],np.dot(miu1[0],W),'*',label = 'Mapping class1 average',color = "green",markersize = 10) #1类平均映射
ax.plot(np.zeros([len(class0)]),np.zeros([len(class0)]),np.dot(class0,W)[:,0],'o',color = "red",alpha = 0.5) #0类映射值
ax.plot(np.zeros([len(class1)]),np.zeros([len(class1)]),np.dot(class1,W)[:,0],'o',color = "blue",alpha = 0.5) #1类映射值
ax.plot([np.zeros([1])],np.zeros([1]),np.dot(miu0[0],W),'*',color = "black",alpha = 0.5,markersize = 10) #0类平均映射值
ax.plot([np.zeros([1])],np.zeros([1]),np.dot(miu1[0],W),'*',color = "green",alpha = 0.5,markersize = 10) #1类平均映射值
#映射平面
X,Y = np.meshgrid(t,t)
ax.plot_surface(X,Y,X*W[0]+Y*W[1],alpha = 0.5)
ax.legend(loc = 'upper left')
plt.show()