使用MATLAB对Indian Pines数据集进行PCA分类
1. 数据加载和预处理
% 清除环境
clear; close all; clc;
% 加载Indian Pines数据集
load('Indian_pines.mat'); % 加载高光谱数据
load('Indian_pines_gt.mat'); % 加载地面真实标签
% 查看数据信息
disp('数据信息:');
disp(['高光谱数据大小: ', num2str(size(indian_pines))]);
disp(['标签数据大小: ', num2str(size(indian_pines_gt))]);
% 将3D高光谱数据转换为2D矩阵 (像素数 × 波段数)
[num_rows, num_cols, num_bands] = size(indian_pines);
X = reshape(indian_pines, num_rows * num_cols, num_bands);
y = indian_pines_gt(:);
% 移除背景像素 (标签为0)
non_background = y ~= 0;
X_clean = X(non_background, :);
y_clean = y(non_background);
disp(['有效像素数量: ', num2str(length(y_clean))]);
disp(['波段数量: ', num2str(num_bands)]);
disp(['类别数量: ', num2str(length(unique(y_clean)))]);
2. 数据标准化和PCA分析
% 数据标准化
X_scaled = zscore(X_clean); % 标准化数据
% 计算协方差矩阵和特征值
cov_matrix = cov(X_scaled);
[eigenvectors, eigenvalues] = eig(cov_matrix);
% 按特征值大小排序
eigenvalues = diag(eigenvalues);
[eigenvalues, idx] = sort(eigenvalues, 'descend');
eigenvectors = eigenvectors(:, idx);
% 计算方差解释率
explained_variance = eigenvalues / sum(eigenvalues);
cumulative_variance = cumsum(explained_variance);
% 绘制方差解释率图
figure('Position', [100, 100, 1200, 500]);
subplot(1,2,1);
plot(explained_variance(1:50), 'b-o', 'LineWidth', 1.5, 'MarkerSize', 4);
xlabel('主成分序号');
ylabel('方差解释率');
title('各主成分方差解释率');
grid on;
subplot(1,2,2);
plot(cumulative_variance(1:50), 'r-o', 'LineWidth', 1.5, 'MarkerSize', 4);
hold on;
plot([1, 50], [0.95, 0.95], 'k--', 'LineWidth', 1.5);
xlabel('主成分数量');
ylabel('累计方差解释率');
title('累计方差解释率');
legend('累计方差', '95%阈值', 'Location', 'southeast');
grid on;
% 找到达到95%方差所需的主成分数量
n_components_95 = find(cumulative_variance >= 0.95, 1);
disp(['达到95%方差解释率所需的主成分数量: ', num2str(n_components_95)]);
3. PCA变换和特征提取
% 选择主成分数量
n_components_list = [5, 10, 15, 20, 30, 50];
results = struct();
for i = 1:length(n_components_list)
n_comp = n_components_list(i);
fprintf('\n使用 %d 个主成分进行处理...\n', n_comp);
% 选择前n_comp个主成分
selected_eigenvectors = eigenvectors(:, 1:n_comp);
% 进行PCA变换
X_pca = X_scaled * selected_eigenvectors;
% 保存结果
results(i).n_components = n_comp;
results(i).X_pca = X_pca;
results(i).eigenvectors = selected_eigenvectors;
results(i).explained_variance = cumulative_variance(n_comp);
end
4. 使用分类器进行分类
% 设置随机种子确保结果可重现
rng(42);
% 准备不同数量的主成分数据进行分类
accuracy_results = zeros(length(n_components_list), 3); % [n_comp, SVM_acc, Tree_acc]
for i = 1:length(n_components_list)
n_comp = results(i).n_components;
X_pca = results(i).X_pca;
fprintf('\n=== 使用 %d 个主成分进行分类 ===\n', n_comp);
% 分割数据集 (70%训练, 30%测试)
cv = cvpartition(y_clean, 'HoldOut', 0.3);
idx_train = training(cv);
idx_test = test(cv);
X_train = X_pca(idx_train, :);
X_test = X_pca(idx_test, :);
y_train = y_clean(idx_train);
y_test = y_clean(idx_test);
% 方法1: 使用SVM分类器
fprintf('训练SVM分类器...\n');
svm_model = fitcecoc(X_train, y_train, ...
'Learners', 'svm', ...
'Coding', 'onevsone', ...
'Verbose', 0);
% 预测
y_pred_svm = predict(svm_model, X_test);
accuracy_svm = sum(y_pred_svm == y_test) / length(y_test);
% 方法2: 使用决策树分类器
fprintf('训练决策树分类器...\n');
tree_model = fitctree(X_train, y_train);
% 预测
y_pred_tree = predict(tree_model, X_test);
accuracy_tree = sum(y_pred_tree == y_test) / length(y_test);
% 保存结果
accuracy_results(i, :) = [n_comp, accuracy_svm, accuracy_tree];
fprintf('SVM准确率: %.4f\n', accuracy_svm);
fprintf('决策树准确率: %.4f\n', accuracy_tree);
% 保存每个结果的详细预测
results(i).y_test = y_test;
results(i).y_pred_svm = y_pred_svm;
results(i).y_pred_tree = y_pred_tree;
results(i).accuracy_svm = accuracy_svm;
results(i).accuracy_tree = accuracy_tree;
end
5. 结果可视化和分析
% 绘制分类准确率随主成分数量的变化
figure('Position', [100, 100, 1000, 600]);
subplot(2,2,1);
plot(accuracy_results(:,1), accuracy_results(:,2), 'o-', 'LineWidth', 2, 'MarkerSize', 8);
hold on;
plot(accuracy_results(:,1), accuracy_results(:,3), 's-', 'LineWidth', 2, 'MarkerSize', 8);
xlabel('主成分数量');
ylabel('分类准确率');
title('分类准确率 vs 主成分数量');
legend('SVM', '决策树', 'Location', 'southeast');
grid on;
% 找到最佳结果
[best_svm_acc, best_svm_idx] = max(accuracy_results(:,2));
[best_tree_acc, best_tree_idx] = max(accuracy_results(:,3));
best_n_comp_svm = accuracy_results(best_svm_idx, 1);
best_n_comp_tree = accuracy_results(best_tree_idx, 1);
fprintf('\n=== 最佳结果总结 ===\n');
fprintf('SVM最佳准确率: %.4f (使用 %d 个主成分)\n', best_svm_acc, best_n_comp_svm);
fprintf('决策树最佳准确率: %.4f (使用 %d 个主成分)\n', best_tree_acc, best_n_comp_tree);
% 绘制最佳结果的混淆矩阵
subplot(2,2,2);
best_result = results(best_svm_idx);
cm = confusionmat(best_result.y_test, best_result.y_pred_svm);
imagesc(cm);
colorbar;
xlabel('预测标签');
ylabel('真实标签');
title(sprintf('SVM混淆矩阵 (%d个主成分)', best_n_comp_svm));
% 绘制特征空间前2个主成分的散点图
subplot(2,2,3);
if size(results(1).X_pca, 2) >= 2
scatter(results(1).X_pca(:,1), results(1).X_pca(:,2), 20, y_clean, 'filled');
xlabel('第一主成分');
ylabel('第二主成分');
title('前两个主成分的特征空间');
colorbar;
end
% 绘制计算效率比较
subplot(2,2,4);
training_time = zeros(length(n_components_list), 2);
for i = 1:length(n_components_list)
n_comp = results(i).n_components;
X_pca = results(i).X_pca;
% SVM训练时间
tic;
svm_model = fitcecoc(X_pca(training(cv), :), y_clean(training(cv)), 'Verbose', 0);
training_time(i, 1) = toc;
% 决策树训练时间
tic;
tree_model = fitctree(X_pca(training(cv), :), y_clean(training(cv)));
training_time(i, 2) = toc;
end
plot(accuracy_results(:,1), training_time(:,1), 'o-', 'LineWidth', 2);
hold on;
plot(accuracy_results(:,1), training_time(:,2), 's-', 'LineWidth', 2);
xlabel('主成分数量');
ylabel('训练时间(秒)');
title('训练时间比较');
legend('SVM', '决策树');
grid on;
% 保存重要结果
save('pca_classification_results.mat', 'results', 'accuracy_results', 'n_components_list');
6. 高级分析:不同分类器比较
% 使用最佳主成分数量进行更详细的分类器比较
fprintf('\n=== 详细分类器比较 ===\n');
best_n_comp = best_n_comp_svm;
best_idx = find([results.n_components] == best_n_comp);
X_pca_best = results(best_idx).X_pca;
% 准备多种分类器
classifiers = {
'SVM (线性)', @(X,y) fitcecoc(X, y, 'Learners', 'linear', 'Verbose', 0);
'SVM (RBF)', @(X,y) fitcecoc(X, y, 'Learners', 'svm', 'Verbose', 0);
'决策树', @fitctree;
'k-NN (k=5)', @(X,y) fitcknn(X, y, 'NumNeighbors', 5);
'随机森林', @(X,y) TreeBagger(50, X, y, 'Method', 'classification');
};
classifier_names = classifiers(:,1);
classifier_funcs = classifiers(:,2);
classifier_results = cell(length(classifier_names), 3);
for i = 1:length(classifier_names)
fprintf('训练 %s...\n', classifier_names{i});
try
% 训练分类器
if i == 5 % 随机森林特殊处理
model = classifier_funcs{i}(X_pca_best(idx_train, :), y_train);
y_pred = predict(model, X_pca_best(idx_test, :));
y_pred = str2double(y_pred);
else
model = classifier_funcs{i}(X_pca_best(idx_train, :), y_train);
y_pred = predict(model, X_pca_best(idx_test, :));
end
accuracy = sum(y_pred == y_test) / length(y_test);
classifier_results{i, 1} = classifier_names{i};
classifier_results{i, 2} = accuracy;
classifier_results{i, 3} = y_pred;
fprintf('%s 准确率: %.4f\n', classifier_names{i}, accuracy);
catch ME
fprintf('训练 %s 时出错: %s\n', classifier_names{i}, ME.message);
classifier_results{i, 1} = classifier_names{i};
classifier_results{i, 2} = NaN;
classifier_results{i, 3} = [];
end
end
% 显示最终结果表格
fprintf('\n=== 最终结果总结 ===\n');
fprintf('%-15s %-10s\n', '分类器', '准确率');
fprintf('%-15s %-10s\n', '-------', '------');
for i = 1:size(classifier_results, 1)
if ~isnan(classifier_results{i, 2})
fprintf('%-15s %.4f\n', classifier_results{i, 1}, classifier_results{i, 2});
end
end
参考代码 PCA_进行indian_pines数据集合分类 www.3dddown.com/cna/59763.html
使用
- 数据准备:确保
Indian_pines.mat和Indian_pines_gt.mat文件在当前工作目录中 - 运行顺序:按顺序执行各个代码段
- 参数调整:可以修改
n_components_list来测试不同的主成分数量 - 分类器选择:代码提供了多种分类器供比较
浙公网安备 33010602011771号