我需要使用Fisher线性判别分析将高维矩阵的示例A和B降维到二维,这与LDA非常相似。每个示例都有A和B类别,因此如果我有第三个示例,它们也有A和B类别,第四个、第五个和第n个示例也总是有A和B类别。因此,我想通过简单地使用Fisher线性判别分析来分离它们。我对机器学习还比较新手,所以不知道如何分离我的类别,我一直在根据公式直观地进行编程。在我读到的内容中,我需要对我的数据应用线性变换,以便找到一个好的阈值,但首先我需要找到最大化函数。为此任务,我设法找到了Sw和Sb,但不知道接下来该怎么做…
我还需要找到最大化函数。
该最大化函数为我提供了一个特征值解:
每个类别我有的都是2个示例的5×2矩阵。例如:
示例1 Class_A = [201, 103,40, 43,23, 50,12, 123,99, 78]Class_B = [ 201, 129, 114, 195, 180, 90, 69, 62, 76, 90]示例2 Class_A = [68, 98,201, 203,78, 212,49, 5,204, 78] Class_B = [ 52, 19, 220, 219, 159, 195, 99, 23, 46, 50]
我尝试像这样找到上面的示例的Sw:
Example_1_Class_A = np.dot(Example_1_Class_A, np.transpose(Example_1_Class_A))Example_1_Class_B = np.dot(Example_1_Class_B, np.transpose(Example_1_Class_B))Example_2_Class_A = np.dot(Example_2_Class_A, np.transpose(Example_2_Class_A))Example_2_Class_B = np.dot(Example_2_Class_B, np.transpose(Example_2_Class_B))Sw = sum([Example_1_Class_A, Example_1_Class_B, Example_2_Class_A, Example_2_Class_B], axis=0)
至于Sb,我尝试像这样:
Example_1_Class_A_mean = Example_1_Class_A.mean(axis=0)Example_1_Class_B_mean = Example_1_Class_B.mean(axis=0) Example_2_Class_A_mean = Example_2_Class_A.mean(axis=0)Example_2_Class_B_mean = Example_2_Class_B.mean(axis=0) Example_1_Class_A_Sb = np.dot(Example_1_Class_A_mean, np.transpose(Example_1_Class_A_mean))Example_1_Class_B_Sb = np.dot(Example_1_Class_B_mean, np.transpose(Example_1_Class_B_mean)) Example_2_Class_A_Sb = np.dot(Example_2_Class_A_mean, np.transpose(Example_2_Class_A_mean))Example_2_Class_B_Sb = np.dot(Example_2_Class_B_mean, np.transpose(Example_2_Class_B_mean))Sb = sum([Example_1_Class_A_Sb, Example_1_Class_B_Sb, Example_2_Class_A_Sb, Example_2_Class_B_Sb], axis=0)
问题是,我不知道如何处理我的Sw和Sb,我完全迷失了。基本上,我需要从这里做到这个:
对于给定的示例A和示例B,如何仅为类别A和仅为类别B分离一个聚类?
回答:
在回答你的问题之前,我先简单介绍一下PCA和(F)LDA的基本区别。在PCA中,你对底层类别一无所知,但你假设类别可分性信息存在于数据的方差中。因此,你旋转原始轴(有时称为将所有数据投影到新的轴上),使你的第一个新轴指向最大方差方向,第二个轴与第一个轴垂直并指向最大残差方差方向,依此类推。这样,PCA变换的结果是一个与原始数据维度相同的(子)空间。然后你可以只取前两个维度,拒绝其余的,从而实现从k维到仅2维的降维。
LDA的工作方式略有不同。在这种情况下,你提前知道数据中有多少个类别,并且你可以找到它们的均值和协方差矩阵。Fisher判据所做的是找到一个方向,使类别之间的均值最大化,同时同时总体变异性最小化(总体变异性是类内协方差矩阵的均值)。对于每个两个类别,只有一条这样的线。这就是为什么当你的数据有C个类别时,LDA最多可以为你提供C-1维,无论原始数据维度如何。在你的情况下,这意味着由于你只有A和B两个类别,你将得到一个一维投影,即一条线。这正是你图片中所展示的:原始的二维数据被投影到一条线上。线的方向是特征问题解的解。让我们生成类似于你图片的数据:
a = np.random.multivariate_normal((1.5, 3), [[0.5, 0], [0, .05]], 30)b = np.random.multivariate_normal((4, 1.5), [[0.5, 0], [0, .05]], 30)plt.plot(a[:,0], a[:,1], 'b.', b[:,0], b[:,1], 'r.')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)res = inv_S.dot(mu_a-mu_b) # the trick##### more general solution## Sb = (mu_a-mu_b)*((mu_a-mu_b).T)# eig_vals, eig_vecs = np.linalg.eig(inv_S.dot(Sb))# res = sorted(zip(eig_vals, eig_vecs), reverse=True)[0][1] # take only eigenvec corresponding to largest (and the only one) eigenvalue# res = res / np.linalg.norm(res)plt.plot([-res[0], res[0]], [-res[1], res[1]]) # this is the solutionplt.plot(mu_a[0], mu_a[1], 'cx')plt.plot(mu_b[0], mu_b[1], 'yx')plt.gca().axis('square')# let's project data point on itr = res.reshape(2,)n2 = np.linalg.norm(r)**2for pt in a: prj = r * r.dot(pt) / n2 plt.plot([prj[0], pt[0]], [prj[1], pt[1]], 'b.:', alpha=0.2)for pt in b: prj = r * r.dot(pt) / n2 plt.plot([prj[0], pt[0]], [prj[1], pt[1]], 'r.:', alpha=0.2)
生成的投影是使用一个巧妙的技巧计算的,适用于两个类别的问题。你可以在这里的第1.6节阅读更多细节。
关于你在问题中提到的“示例”。我认为你需要为每个示例重复这个过程,因为这是一组不同的数据点,可能具有不同的分布。还要注意,估计的均值(mu_a, mu_b)和类协方差矩阵与生成数据时使用的可能略有不同,特别是在样本量较小的情况下。