LDA线性判别分析的思想十分简单,将给定的训练样例集投影到一条直线上,我们希望投影过后,不同类的数据点尽量远离,同类数据点尽量聚合。设Xi表示i类数据的集合i∈(0,1),μi为i类数据集合的均值向量 

类内散度的定义:

使用方差来度量类内的离散程度,因为都是向量表示形式,所以平方和用向量乘向量的转置表示

类间散度矩阵:

使用均值的方差表示两种数据类之间的离散程度

 我们要使类间散度越大越好,类内散度越小越好。

所以我们的最小化目标是:

我们只要求出投影后,对应数据点的位置,就可以得到我们想要的模型。

设投影直线为:


 我们以二维图像为例:


(x’,y’)为(x,y)在直线上的投影,要直接求出(x’,y’)是比较复杂的,可以求但没必要



 上式的意义都是两点之间的距离的平方,所以我们直接求距离就可以了

因为投影后,所有的点在一条直线上,所以,点与点之间的距离,等于两点到原点的距离之差,而投影点到原点的距离就很好求了。

我们用向量乘积的形式表示一下:

(x,y)到原点的距离:|(x,y)|

(x’,y’)到原点的距离:cosθ|(x,y)|

cosθ可以表示为:



所以:



看上去,好像没有解决问题,但是我们有一下考虑:



向量除以向量的模,等于单位向量,我们不能直接求得单位向量,但是我们已知直线的方向向量 (投影直线的方向,它的参数):



则我们加入一个未知量(0<λ<1 )来表示单位向量:



所以:



我们将(x,y)这样的点表示的向量直接表示为一个参数向量,就和 我们的样例中的一个X=(x0,x1,….,xn)这样,所以一个向量表示的样例参数经过投影后到原点的距离为:



所以,投影后的类内散度矩阵应该表示为:







用Sw表示投影前的类内散度矩阵,所以投影后的类内散度矩阵为:



类间散度矩阵表示为:







用Sb表示投影前的类间散度矩阵,所以投影后的类间散度矩阵为:



所以我们的优化函数为:




我们的最优化函数得出来了,我们只要解出来就可以了(解出最优化参数ω)。


此时我们就可以使用拉格朗日乘子法来求解了


 观察发现分数上下都有



所以结果与ω 向量的模(大小)无关,只与它的方向有关,那么分子分母可以取任意值,会产生无穷多解,所以我们将分母限制为1,并作为拉格朗日的约束条件


所以我们令:



优化函数等价为:



由 拉格朗日乘数法有:


拉格朗日函数为:



对ω求导等于0:



根据Sb的定义式,可以看出他的方向恒为(μ0-μ1) ,所以我们令:




因为Sw为向量,所以两边同乘,Sw的逆,所以:



因为有些矩阵是没有逆矩阵的,所以我们使用广义逆矩阵,来确保有解。


 推导过程一大串,但是实现却很简单:


我们自己生成一个数据集:


  1. def createDataSet():
  2. #类别1
  3. X1 = np.mat(np.random.random((8, 2)) _ 5 + 15)
  4. #类别2
  5. X2 = np.mat(np.random.random((8, 2)) _ 5 + 2)
  6. return X1, X2


求各个属性的均值:


  1. def average(dataset):
  2. ave = []
  3. a, b = np.shape(dataset)
  4. for i in range(b):
  5. n = np.sum(dataset[:,i]) / a
  6. ave.append(n)
  7. return np.array(ave)

求单一类的类内散度矩阵:

  1. def compute_sw(dataset, ave):
  2. sw = 0
  3. a, b = np.shape(dataset)
  4. for i in range(a - 1):
  5. sw += np.dot(dataset[i,:] - ave, (dataset[i,:] - ave).T)
  6. return np.array(sw)

因为有些矩阵是没有逆矩阵的,为了使任意数据集都有结果,我们使用广义逆矩阵:

  1. x1_sw = compute_sw(x1_x, x1_x_ave)
  2. x2_sw = compute_sw(x2_x, x2_x_ave)
  3. Sw = x1_sw + x2_sw
  4. #求广义逆
  5. pinv = np.linalg.pinv(Sw)
  6. w = np.multiply(x1_x_ave - x2_x_ave, pinv)[0,:]

我们就得到了,最优投影直线的参数w ,从而得到最优投影直线