用python实现fisher线性判别_shuhuai008线性判别实现(基于python)

在这里实现的线性判别为二分类问题,数据仍然为纤维发育时期基因表达量数据,以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】_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com用python实现fisher线性判别_shuhuai008线性判别实现(基于python)_第1张图片

你可能感兴趣的:(用python实现fisher线性判别_shuhuai008线性判别实现(基于python))