在这里实现的线性判别为二分类问题,数据仍然为纤维发育时期基因表达量数据,以30天的纤维是否表达作为分类依据。
个人理解:
对于两个类别,有Xc1(N1×P),Xc2(N2×P)两类数据,线性分类的思想为通过将单个样本的特征与向量W相乘,得到一个实数z,N个样本会得到N个这样的实数。如果这些数据可以根据特征分为两类,那么与一个合适的向量W相乘得到的实数也可以鲜明地被划分为两类。N个样本得到的实数可以看做Z,若能分为两类则Z有Z1及Z2两类实数集,并且
与
之差的绝对值较大(类间样本差距大)同时
与
之和应该较小(两类别方差之和较小即为两类别类内样本差距小)。为了表示类间样本差距大,类内样本差距小,可以定义优化的目标函数如下:
其中对于分子上的两类均值可如下表示:
相应的:
对于分母上的方差(有偏估计):
相应的:
将上述展开式带入到目标函数中可以得到:
令
,
两者维度皆为为P×P,将目标函数表示为:
解出w后,即:
其中
为实数,记为k,将B展开可得:
为一个实数,记为a,则
由上述可知最终向量w的方向与
的方向相同。
在这里为了理解为啥最后只关心方向,up主给的解释是对于向量w与每一个样本的各个特征相乘后得到一个常数这一过程,可以看做将代表原单个样本的列向量投影到了向量w上,这样一来影响原向量投影后所得实数聚散程度的就只有向量w的方向,而不必关注w的模。即w的模会影响w与x相乘后所得实数的绝对大小,但是不影响所有实数之间的相对大小,无论w模为多少,如果数据可以分成两类,那么生成的实数集也会聚成两类。
自己的代码实现如下,用numpy来求矩阵的逆,较为方便:
import pandas as pd
import numpy as np
#preprocess dataframe and add bias
dataframe=pd.read_csv('F:/fiber/mean.csv',sep='\t',index_col='Gene ID')
dataframe=np.log2(dataframe+1)
dataframe['bias']=[1 for i in range(dataframe.shape[0])]
list_column=['-3DPA','-1DPA','0DPA','1DPA','3DPA','5DPA','7DPA','10DPA','15DPA','20DPA','30DPA']
dataframe_pre=pd.DataFrame()
for i in list_column:
dataframe_pre[i]=dataframe[i]
#label x and y
x_list=['-3DPA','-1DPA','0DPA','1DPA','3DPA','5DPA','7DPA','10DPA','15DPA','20DPA']
y_list='30DPA'
y=np.mat([1 if i>=1 else -1 for i in dataframe_pre[y_list]]).T
dataframe_pre[y_list]=y
class_1=np.mat(dataframe_pre.loc[dataframe_pre[y_list]==1][x_list])
class_2=dataframe_pre.loc[dataframe_pre[y_list]==-1][x_list]
class_1_average=np.mat(class_1.mean(axis=0)).T
class_2_average=np.mat(class_2.mean(axis=0)).T
s1=np.cov(class_1.T)
s2=np.cov(class_2.T)
s_within=s1+s2
s_within_inv=np.linalg.inv(s_within)
w=np.dot(s_within_inv,class_1_average-class_2_average)
up主视频:
【机器学习】【白板推导系列】【合集 1~23】_哔哩哔哩 (゜-゜)つロ 干杯~-bilibiliwww.bilibili.com