项目源码链接【传送门
如果帮到你欢迎点亮右上角的星星,助力小蒟蒻的职业梦想😘

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

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐