Tôi đang cố gắng tính toán 2 thành phần chính chính từ tập dữ liệu trong C++ với Eigen.Phân tích thành phần chính với Thư viện Eigen
Cách tôi thực hiện tại thời điểm này là chuẩn hóa dữ liệu giữa [0, 1]
và sau đó căn giữa giá trị trung bình. Sau đó tôi tính toán ma trận hiệp phương sai và chạy phân tách giá trị riêng trên đó. Tôi biết SVD nhanh hơn, nhưng tôi nhầm lẫn về các thành phần được tính toán.
Đây là mã lớn về cách tôi làm điều đó (nơi traindata
là MxN ma trận có kích thước đầu vào của tôi):
Eigen::VectorXf normalize(Eigen::VectorXf vec) {
for (int i = 0; i < vec.size(); i++) { // normalize each feature.
vec[i] = (vec[i] - minCoeffs[i])/scalingFactors[i];
}
return vec;
}
// Calculate normalization coefficients (globals of type Eigen::VectorXf).
maxCoeffs = traindata.colwise().maxCoeff();
minCoeffs = traindata.colwise().minCoeff();
scalingFactors = maxCoeffs - minCoeffs;
// For each datapoint.
for (int i = 0; i < traindata.rows(); i++) { // Normalize each datapoint.
traindata.row(i) = normalize(traindata.row(i));
}
// Mean centering data.
Eigen::VectorXf featureMeans = traindata.colwise().mean();
Eigen::MatrixXf centered = traindata.rowwise() - featureMeans;
// Compute the covariance matrix.
Eigen::MatrixXf cov = centered.adjoint() * centered;
cov = cov/(traindata.rows() - 1);
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> eig(cov);
// Normalize eigenvalues to make them represent percentages.
Eigen::VectorXf normalizedEigenValues = eig.eigenvalues()/eig.eigenvalues().sum();
// Get the two major eigenvectors and omit the others.
Eigen::MatrixXf evecs = eig.eigenvectors();
Eigen::MatrixXf pcaTransform = evecs.rightCols(2);
// Map the dataset in the new two dimensional space.
traindata = traindata * pcaTransform;
Kết quả của mã này là một cái gì đó như thế này:
Để xác nhận kết quả của tôi, tôi đã thử cùng với WEKA. Vì vậy, những gì tôi đã làm là sử dụng bình thường hóa và bộ lọc trung tâm, theo thứ tự này. Sau đó, bộ lọc thành phần chính và lưu + vẽ đầu ra. Kết quả là thế này:
Về mặt kỹ thuật tôi nên đã làm điều tương tự, tuy nhiên kết quả là rất khác nhau. Có ai có thể thấy nếu tôi phạm sai lầm không?
Một điều cần thêm: Tôi khá chắc chắn rằng WEKA đang sử dụng SVD. Nhưng điều này không nên giải thích sự khác biệt trong kết quả hay? – Chris