机器学习----PCA

一、PCA思想

           PCA是将n维特征映射到k维上(k<n),这k维是全新的正交特征。这k维特征称为主成分,是重新构造出来的k维特征,而不是简单地从n维特征中去除其余n-k维特征。(数据降维方法)

二、PCA算法步骤

        围绕问题:如何去寻找适合的K才能最大程度保留原有的信息??

        思路:希望投影后的投影值尽可能分散,因为如果重叠就会有样本消失。

                   当然这个也可以从熵的角度进行理解,熵越大所含信息越多。        

具体相关步骤详细推导借鉴看此篇:https://blog.csdn.net/QENGFENG/article/details/127311694?ops_request_misc=&request_id=&biz_id=102&utm_term=PCA&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-127311694.nonecase&spm=1018.2226.3001.4187

PCA算法步骤:

举例:

三、代码实现

1、数据预处理


clear;
% 1.人脸数据集的导入与数据处理(400张图,一共40人,一人10张)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
reshaped_faces=[];
for i=1:40    
    for j=1:10       
        if(i<10)
           a=imread(strcat('C:\AR_Gray_50by40\AR00',num2str(i),'-',num2str(j),'.tif'));     
        else
            a=imread(strcat('C:\AR_Gray_50by40\AR0',num2str(i),'-',num2str(j),'.tif'));  
        end          
        b = reshape(a,2000,1); %将每一张人脸拉成列向量
        b=double(b); %utf-8转换为double类型,避免人脸展示时全灰的影响       
        reshaped_faces=[reshaped_faces, b];  
    end
end
 
% 取出前30%作为测试数据,剩下70%作为训练数据
test_data_index = [];
train_data_index = [];
for i=0:39
    test_data_index = [test_data_index 10*i+1:10*i+3];
    train_data_index = [train_data_index 10*i+4:10*(i+1)];
end
 
train_data = reshaped_faces(:,train_data_index);
test_data = reshaped_faces(:, test_data_index);


% 2.图像求均值,中心化
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
% 求平均脸
mean_face = mean(train_data,2);
%waitfor(show_face(mean_face)); %平均脸展示,测试用
 
% 中心化
centered_face = (train_data - mean_face);
%用于展示中心化后某些训练图片 测试用
%waitfor(show_faces(centered_face));


% 3.求协方差矩阵、特征值与特征向量并排序
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
% 协方差矩阵
cov_matrix = centered_face * centered_face';
[eigen_vectors, dianogol_matrix] = eig(cov_matrix);
% 从对角矩阵获取特征值
eigen_values = diag(dianogol_matrix);
% 对特征值按索引进行从大到小排序
[sorted_eigen_values, index] = sort(eigen_values, 'descend'); 
% 获取排序后的征值对应的特征向量
sorted_eigen_vectors = eigen_vectors(:, index);
% 特征脸(所有)
all_eigen_faces = sorted_eigen_vectors;
%用于展示某些特征脸 测试用
waitfor(show_faces(all_eigen_faces));

2、重构


%%人脸重构
 
% 取出第一个人的人脸,用于重构
single_face = centered_face(:,1);
 
index = 1;
for dimensionality=20:20:160
 
    % 取出相应数量特征脸(前n大的特征向量,用于重构人脸)
    eigen_faces = all_eigen_faces(:,1:dimensionality);
 
    % 重建人脸并显示
        rebuild_face = eigen_faces * (eigen_faces' * single_face) + mean_face;
        subplot(2, 4, index); %两行四列
        index = index + 1;
        fig = show_face(rebuild_face);
        title(sprintf("dimensionality=%d", dimensionality));    
        if (dimensionality == 160)
            waitfor(fig);
        end
end

3、识别


% 人脸识别
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
index = 1;       
Y = [];
% KNN
for k=1:6
 
    for i=10:10:160
    % 取出相应数量特征脸
   eigen_faces = all_eigen_faces(:,1:i);
    % 测试、训练数据降维
    projected_train_data = eigen_faces' * (train_data - mean_face);
    projected_test_data = eigen_faces' * (test_data - mean_face);
        % 用于保存最小的k个值的矩阵
        % 用于保存最小k个值对应的人标签的矩阵
        minimun_k_values = zeros(k,1);
        label_of_minimun_k_values = zeros(k,1);
 
        % 测试脸的数量
        test_face_number = size(projected_test_data, 2);
 
        % 识别正确数量
        correct_predict_number = 0;
 
        % 遍历每一个待测试人脸
        for each_test_face_index = 1:test_face_number
 
            each_test_face = projected_test_data(:,each_test_face_index);
 
            % 先把k个值填满,避免在迭代中反复判断
            for each_train_face_index = 1:k
                minimun_k_values(each_train_face_index,1) = norm(each_test_face - projected_train_data(:,each_train_face_index));
                label_of_minimun_k_values(each_train_face_index,1) = floor((train_data_index(1,each_train_face_index) - 1) / 10) + 1;
            end
 
            % 找出k个值中最大值及其下标
            [max_value, index_of_max_value] = max(minimun_k_values);
 
            % 计算与剩余每一个已知人脸的距离
            for each_train_face_index = k+1:size(projected_train_data,2)
 
                % 计算距离
                distance = norm(each_test_face - projected_train_data(:,each_train_face_index));
 
                % 遇到更小的距离就更新距离和标签
                if (distance < max_value)
                    minimun_k_values(index_of_max_value,1) = distance;
                    label_of_minimun_k_values(index_of_max_value,1) = floor((train_data_index(1,each_train_face_index) - 1) / 10) + 1;
                    [max_value, index_of_max_value] = max(minimun_k_values);
                end
            end
 
            % 最终得到距离最小的k个值以及对应的标签
            % 取出出现次数最多的值,为预测的人脸标签
            predict_label = mode(label_of_minimun_k_values);
            real_label = floor((test_data_index(1,each_test_face_index) - 1) / 10)+1;
 
            if (predict_label == real_label)
                %fprintf("预测值:%d,实际值:%d,正确\n",predict_label,real_label);
                correct_predict_number = correct_predict_number + 1;
            else
                %fprintf("预测值:%d,实际值:%d,错误\n",predict_label,real_label);
            end
        end
        % 单次识别率
        correct_rate = correct_predict_number/test_face_number;
 
        Y = [Y correct_rate];
 
        fprintf("k=%d,i=%d,总测试样本:%d,正确数:%d,正确率:%1f\n", k, i,test_face_number,correct_predict_number,correct_rate);
    end
end
% 求不同k值不同维度下的人脸识别率及平均识别率
Y = reshape(Y,k,16);
waitfor(waterfall(Y));
avg_correct_rate=mean(Y);
waitfor(plot(avg_correct_rate));

4、降维可视化

% 人脸数据二三维可视化(可推广到不同数据集)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
for i=[2 3]
 
    % 取出相应数量特征脸
    eigen_faces = all_eigen_faces(:,1:i);
 
    % 投影
    projected_test_data = eigen_faces' * (test_data - mean_face);
    color = [];
    for j=1:120
        color = [color floor((j-1)/4)*5];
    end
    % 显示
    if (i == 2)
        waitfor(scatter(projected_test_data(1, :), projected_test_data(2, :), [], color));
    else
        waitfor(scatter3(projected_test_data(1, :), projected_test_data(2, :), projected_test_data(3, :), [], color));
    end
end

结果:降至三维可视化图。

四、总结

这里对PCA算法做一个总结。作为一个非监督学习的降维方法,它只需要特征值分解,就可以对数据进行压缩,去噪。因此在实际场景应用很广泛。为了克服PCA的一些缺点,出现了很多PCA的变种,比如为解决非线性降维的KPCA,还有解决内存限制的增量PCA方法Incremental PCA,以及解决稀疏数据降维的PCA方法Sparse PCA等。

PCA算法的主要优点有:

              1)仅仅需要以方差衡量信息量,不受数据集以外的因素影响。 

    2)各主成分之间正交,可消除原始数据成分间的相互影响的因素。

    3)计算方法简单,主要运算是特征值分解,易于实现。

PCA算法的主要缺点有:

    1)主成分各个特征维度的含义具有一定的模糊性,不如原始样本特征的解释性强。

    2)方差小的非主成分也可能含有对样本差异的重要信息,因降维丢弃可能对后续数据处理有影响。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值