我正在对从CNN不同层提取的特征使用主成分分析(PCA)。我已经从这里下载了降维工具箱。
我总共有11232张训练图像,每张图像的特征维度为6532。因此,特征矩阵的形状为11232x6532
。如果我想保留前90%的特征,我可以轻松做到这一点,并且使用SVM对降维后的数据进行训练,准确率为81.73%,这还算不错。然而,当我尝试使用测试数据时,测试数据有2408张图像,每张图像的特征维度为6532。因此,测试数据的特征矩阵形状为2408x6532
。在这种情况下,前90%特征的输出结果不正确,显示为2408x2408
,并且测试准确率为25%。在不使用降维的情况下,训练准确率为82.17%,测试准确率为79%。
更新:其中X
是数据,no_dims
是输出所需的维度数。这个PCA函数的输出是变量mappedX
和结构mapping
。
% Make sure data is zero mean mapping.mean = mean(X, 1); X = bsxfun(@minus, X, mapping.mean); % Compute covariance matrix if size(X, 2) < size(X, 1) C = cov(X); else C = (1 / size(X, 1)) * (X * X'); % if N>D, we better use this matrix for the eigendecomposition end % Perform eigendecomposition of C C(isnan(C)) = 0; C(isinf(C)) = 0; [M, lambda] = eig(C); % Sort eigenvectors in descending order [lambda, ind] = sort(diag(lambda), 'descend'); if no_dims < 1 no_dims = find(cumsum(lambda ./ sum(lambda)) >= no_dims, 1, 'first'); disp(['Embedding into ' num2str(no_dims) ' dimensions.']); end if no_dims > size(M, 2) no_dims = size(M, 2); warning(['Target dimensionality reduced to ' num2str(no_dims) '.']); end M = M(:,ind(1:no_dims)); lambda = lambda(1:no_dims); % Apply mapping on the data if ~(size(X, 2) < size(X, 1)) M = bsxfun(@times, X' * M, (1 ./ sqrt(size(X, 1) .* lambda))'); % normalize in order to get eigenvectors of covariance matrix end mappedX = X * M; % Store information for out-of-sample extension mapping.M = M; mapping.lambda = lambda;
根据你的建议,我已经计算了训练数据的向量。
numberOfDimensions = round(0.9*size(Feature,2));[mapped_data, mapping] = compute_mapping(Feature, 'PCA', numberOfDimensions);
然后使用相同的向量处理测试数据:
mappedX_test = Feature_test * mapping.M;
准确率仍然是32%
通过进行减法操作解决了问题:
Y = bsxfun(@minus, Feature_test, mapping.mean);mappedX_test = Y * mapping.M;
回答:
看起来你是在对训练数据和测试数据分别进行降维。在训练过程中,你应该记住训练样本的主成分得分或基向量。请记住,你是在基于训练数据寻找数据的新表示,使用一组新的正交轴。在测试过程中,你需要重复训练数据的相同过程,因为你是在相对于这些基向量表示数据。因此,你应该使用训练数据的基向量来降低数据维度。你之所以得到2408 x 2408
的矩阵,是因为你在测试样本上执行PCA,而你无法生成超过矩阵秩的基向量(即2408)。
保留训练阶段的基向量,在测试阶段进行分类时,必须使用训练阶段的相同基向量。请记住,在PCA中,你必须在降维之前通过减去均值来中心化数据。在你的代码中,我们注意到基向量存储在mapping.M
中,相关的均值向量存储在mapping.mean
中。在测试阶段,确保使用训练阶段的mapping.mean
对测试数据进行均值减法:
Y = bsxfun(@minus, Feature_test, mapping.mean);
完成这一步后,最后进行数据降维:
mappedX_test = Y * mapping.M;