项目源码链接【传送门】
如果帮到你欢迎点亮右上角的星星,助力小蒟蒻的职业梦想😘
PCA
PCA主要的原理非常简单,实验要求用的数据集是AR人脸数据
def PCA(data,feat_num):
"""
对AR数据集进行实验
:param data: array格式,二维(数量id,特征)
:return:降维结果
"""
print("PCA之前数据维度:",data.shape)
m,n=np.shape(data)
# 取平均值,每一列
avg=np.mean(data,axis=0)
# 拓展均值
avgs=np.tile(avg,(m,1))
# 原始数据-均值
data_sub=data-avgs
# 求data的协方差矩阵的特征值和特征向量
cov=np.cov(data_sub.T)
fea_value,fea_vec=np.linalg.eig(cov)
# 选择最大的K个特征值对应的k个特征向量
index=np.argsort(-fea_value)
# 因为特征向量是列向量,这里转化为横向量
select_vec=np.matrix(fea_vec.T[index[:feat_num]])
# 将样本点投影到选取的特征向量上
pca_data=data_sub@select_vec.T
"""计算重构误差"""
# 还原对应投影后的数据
recon_data=(pca_data*select_vec)+avgs
err_mat=data-recon_data
err1=np.sum(np.array(err_mat)**2)/n
# print("重构误差:",err1)
# # 计算n
# err2=np.sum(data_sub**2)/n
# print(err2)
# print("保留信息:",1-err1/err2)
return pca_data
Fisher
Fisher理论讲解
课本上还有老师给的材料都是二维的二分类情况(结果考试问一般情况……😱俺考完试才写实验当然就……当场去世)
上面博客讲解得非常好,我的代码是按照他思路来的,KNN验证结果应该是写对了~但是判零我没有设置阈值,直接就人为指定降维维度,导致结果就是,1000维度精度会小于20维度……emm😇可能是冗余数据无效降维叭,20维度以下效果都很nice
class Fisher():
def __init__(self,w):
"""
:param w: 降维的维度
"""
self.w=w
def fit(self,X,y):
# 形状(1680,xxx)
# 计算组间方差矩阵B
self.m={}# 存储均值的
self.m0=X.mean(axis=0)
kind=-1
C=X[0]
for i in range(y.shape[0]):
if y[i]!=kind:
if kind!=-1:
self.m[str(kind)]=np.mean(C,axis=0)
kind=y[i]
C=X[i]
continue
C=np.vstack((C,X[i]))
self.m[str(kind)] = np.mean(C, axis=0)
self.W=None
for i in range(y.shape[0]):
mat=np.matrix(X[i]-self.m[str(y[i])])
S_wi=mat.T@mat
if self.W is None:
self.W=S_wi
else:
self.W+=S_wi
# 计算组间方差矩阵B
self.B=None
for key,value in self.m.items():
mat=np.matrix(value-self.m0)
S_bi=mat.T@mat
if self.B is None:
self.B=S_bi
else:
self.B+=S_bi
# 计算W.I·B
print(self.W.I.shape,self.B.shape)
self.WI_B=self.W.I@self.B
# 将得到的特征值从大到小排列,取非零的特征值对应的特征向量
fea_value,fea_vector=np.linalg.eig(self.WI_B)
index = np.argsort(-fea_value)# 重新排序
print("被选中的特征值的下标",index)
# 这边需要选取非0的:资料上说是接近0的……自己指定叭
select_vec=np.matrix(fea_vector.T[index[:self.w]])
# 将样本点投射到选取的特征向量上
print(select_vec.shape,X.shape)
data=X@select_vec.T
return data,y