- 实验目的
1. 划分测试集(600)和训练集(148),对数据集进行线性判别分析
2. 将模型结果的投影方向 w 进行输出
3. 输出测试集的准确率acc
4. 最好能够将数据的分析结果进行可视化
- 实验内容:
1、数据是存储在txt文件中,使用np.loadtxt将其读出并存入array中,文件中的数据是由’,’分隔,函数默认是空格分隔,所以参数delimiter=','。
然后使用切片,分割数据。
2、根据公式求出w。首先使用布尔索引将分离出两类的数据,并取均值得到均值向量u0和u1。然后根据公式进行Sw和w的求解,在矩阵运算时可以把ndarray使用asmatrix转换为矩阵,可以直接进行*、T、I等运算。得出w并输出。在运算过程中要注意矩阵的维度,防止出现错误。
3、已经得出了w向量,根据公式可以求出两个样本的中心在直线上的投影值,为后面预测做准备。
4、对测试集进行测试,得出准确率,并对结果进行可视化处理。由wT*x可以得出测试集的数据的投影值,根据LDA的原理:数据在低维度上进行投影,投影后希望每一种类别数据的投影点尽可能的接近,而不同类别的数据的类别中心之间的距离尽可能的大。那么找预测值离得最近的样本中心点,就是这个数据的预测类别。之后和标签进行比较并求出准确率。
可以使用matplotlib进行可视化输出,由于值都是一个标量,所以可以只在一个维度表示出来之间的关系。只要x轴,但是matplotlib是默认二维的,可以使用ax.axis[:].set_visible(False) 隐藏默认坐标轴,并自己创建x轴;使用xlim限定x轴的范围,之后找出各类的点并画在坐标轴上,两个中心使用红色,预测值分别使用蓝绿两色标出。
运行结果:(python版本为3.8,可能在运算精度等方面存在偏差)
可视化结果:
可以看到分类是根据离中心点远近进行分类的。
- 实验原理:
- 心得体会:
通过这次实验,我对于LDA算法的思想有了更清晰的了解,即数据在低维度上进行投影,投影后希望每一种类别数据的投影点尽可能的接近,而不同类别的数据的类别中心之间的距离尽可能的大。推导过程也根据南瓜书有了一定的了解。经过实践,可以对这个算法掌握地更加熟练。
同时在实验中也对python的一些操作,如布尔值索引、切片、列表推导式以及numpy函数等进一步熟悉。也学习了matplotlib进行数据的可视化处理。巩固所学知识,为以后的学习打下坚实的基础。
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axisartist as axisartist
def get_w(x, y):
"""
根据公式得到w,和均值向量
:param x:训练集
:param y:训练集的标签
:return:w和均值向量u0,u1
"""
u0 = np.asmatrix(np.average(x[y[:] == 0], axis=0))
u1 = np.asmatrix(np.average(x[y[:] == 1], axis=0))
x0 = np.asmatrix(x[y[:] == 0])
x1 = np.asmatrix(x[y[:] == 1])
Sw = (x0 - u0).T * (x0 - u0) + (x1 - u1).T * (x1 - u1)
w = Sw.I * np.asmatrix(u0 - u1).T
print("w : ", w)
return w, u0, u1
def get_centre(w, u0, u1):
"""
求样本中心
:param w: w向量
:param u0: 均值向量u0
:param u1: 均值向量u1
:return: 样本中心投影值centre0、centre1
"""
centre0 = np.array(w.T * u0.T)
centre1 = np.array(w.T * u1.T)
return centre0[0][0], centre1[0][0]
def test(w, x, lable, c0, c1):
"""
进行预测和可视化
:param w: w向量
:param x: 训练集
:param lable: 训练集标签
:param c0: 样本0中心投影值
:param c1: 样本1中心投影值
"""
predict_value = np.array(np.asmatrix(w).T * x.T)
y = [0 if abs(c0 - i) < abs(c1 - i) else 1 for i in predict_value[0]]
acc = np.mean([y == lable])
print("acc : ", acc)
fig = plt.figure()
ax = axisartist.Subplot(fig, 1, 1, 1)
fig.add_axes(ax)
ax.axis[:].set_visible(False) # 隐藏默认坐标轴
ax.axis["x"] = ax.new_floating_axis(0, 0) # 创建X轴,通过(0,0)点
# ax.axis["y"] = ax.new_floating_axis(1, 0) # 创建Y轴,通过(0,0)点
ax.axis["x"].set_axis_direction('top') # 设置X轴刻度方向为上方
# ax.axis["y"].set_axis_direction('left') # 设置Y轴刻度方向为左侧
plt.xlim([-0.001, 0.01])
class0 = [i for i in predict_value[0] if abs(c0 - i) < abs(c1 - i)]
class1 = [i for i in predict_value[0] if abs(c0 - i) >= abs(c1 - i)]
ax.scatter(class0, np.zeros(len(class0)), color='green', alpha=0.5)
ax.scatter(class1, np.zeros(len(class1)), color='blue', alpha=0.5)
ax.scatter((c0, c1), (0, 0), color='red', alpha=1)
plt.show()
if __name__ == '__main__':
data = np.loadtxt(r'D:\A学习\机器学习\实验\实验2'
r'\输血服务中心数据集\blood_data.txt', delimiter=',')
train_x = data[:600, :4]
train_y = data[:600, 4]
test_x = data[600:, :4]
test_y = data[600:, 4]
w, u0, u1 = get_w(train_x, train_y)
centre0, centre1 = get_centre(w, u0, u1)
test(w, test_x, test_y, centre0, centre1)