void PCA<T>::InitFromPointMatrix(DenseMatrix<T> &B) { const UINT PointCount = B.ColCount(); const UINT Dimension = B.RowCount(); Console::WriteLine(String("Initializing PCA, ") + String(B.ColCount()) + String(" points, ") + String(B.RowCount()) + String(" dimensions")); _Means.Allocate(Dimension); _Means.Clear(0.0); for(UINT PointIndex = 0; PointIndex < PointCount; PointIndex++) { for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { _Means[DimensionIndex] += B.Cell(DimensionIndex, PointIndex); } } for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { _Means[DimensionIndex] /= PointCount; } for(UINT PointIndex = 0; PointIndex < PointCount; PointIndex++) { for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { B.Cell(DimensionIndex, PointIndex) -= _Means[DimensionIndex]; } } DenseMatrix<T> C; Console::WriteLine("Building correlation matrix..."); DenseMatrix<T>::MultiplyMMTranspose(C, B); DenseMatrix<T>::MultiplyInPlace(C, T(1.0) / T(PointCount)); InitFromCorrelationMatrix(C); }
void SpectralClustering::MakeLaplacian(const DenseMatrix<double> &S, Method method, DenseMatrix<double> &L) { const UINT pointCount = S.RowCount(); Vector<double> weightSums(pointCount, 0.0); for(UINT outerPointIndex = 0; outerPointIndex < pointCount; outerPointIndex++) { for(UINT innerPointIndex = 0; innerPointIndex < pointCount; innerPointIndex++) { weightSums[outerPointIndex] += S(outerPointIndex, innerPointIndex); } } if(method == Unnormalized || method == RandomWalk) { L = S; for(UINT pointIndex = 0; pointIndex < pointCount; pointIndex++) { L(pointIndex, pointIndex) = weightSums[pointIndex] - L(pointIndex, pointIndex); } if(method == RandomWalk) { for(UINT outerPointIndex = 0; outerPointIndex < pointCount; outerPointIndex++) { for(UINT innerPointIndex = 0; innerPointIndex < pointCount; innerPointIndex++) { L(outerPointIndex, innerPointIndex) /= weightSums[outerPointIndex]; } } } } if(method == Symmetric) { Vector<double> weightInvSqrts(pointCount); for(UINT pointIndex = 0; pointIndex < pointCount; pointIndex++) { weightInvSqrts[pointIndex] = sqrt(1.0f / weightSums[pointIndex]); } for(UINT outerPointIndex = 0; outerPointIndex < pointCount; outerPointIndex++) { for(UINT innerPointIndex = 0; innerPointIndex < pointCount; innerPointIndex++) { L(outerPointIndex, innerPointIndex) = S(outerPointIndex, innerPointIndex) * weightInvSqrts[outerPointIndex] * weightInvSqrts[innerPointIndex]; } } } }
void PCA<T>::InitFromCorrelationMatrix(const DenseMatrix<T> &C) { const UINT Dimension = C.RowCount(); const bool OutputMatlabAndExit = false; if(OutputMatlabAndExit) { Console::WriteLine("Outputting MATLAB matrix and exiting..."); C.SaveToMATLAB("C:\\MATLAB7\\work\\PCA.txt"); _Means.SaveToASCIIFile("C:\\JReaderData\\RawMeanVector.txt"); exit(0); } else { Console::WriteLine("Computing eigensystem..."); C.EigenSystem(_Eigenvalues, _Eigenvectors); Console::WriteLine(C.EigenTest(_Eigenvalues, _Eigenvectors)); //_Eigenvectors.SaveToMATLAB("C:\\MATLAB7\\work\\MyEigenvectors.txt"); //_Eigenvalues.SaveToASCIIFile("C:\\MATLAB7\\work\\MyEigenvalues.txt"); } FinalizeFromEigenSystem(); }
void SpectralClustering::Cluster(const DenseMatrix<double> &S, UINT kMeansClusters, UINT reducedDimensionCount, Method method, Vector<UINT> &clusterIDs, SpectralClusteringCache *cache) { const UINT pointCount = S.RowCount(); Console::WriteLine("Spectral clustering on " + String(pointCount) + " points, " + String(kMeansClusters) + " clusters, " + String(reducedDimensionCount) + String(" dimensions")); DenseMatrix<double> L(pointCount, pointCount); MakeLaplacian(S, method, L); Vector<double> eigenvalues; DenseMatrix<double> eigenvectors; { if(cache != NULL && cache->eigenvalues.Length() == pointCount) { Console::WriteString("Loading eigensystem from cache..."); eigenvalues = cache->eigenvalues; eigenvectors = cache->eigenvectors; } else { Clock timer; Console::WriteString("Solving eigensystem..."); L.EigenSystemTNT(eigenvalues, eigenvectors); Console::WriteLine(String(timer.Elapsed()) + "s"); } if(cache != NULL) { cache->eigenvalues = eigenvalues; cache->eigenvectors = eigenvectors; } } // // Note that the eigensystem is sorted in decreasing order. // const bool useLargestEigenvector = (method == RandomWalk || method == Symmetric); Vector<VecNf> points(pointCount); for(UINT pointIndex = 0; pointIndex < pointCount; pointIndex++) { VecNf &curPoint = points[pointIndex]; curPoint.v.Allocate(reducedDimensionCount); for(UINT dimensionIndex = 0; dimensionIndex < reducedDimensionCount; dimensionIndex++) { if(useLargestEigenvector) { curPoint[dimensionIndex] = float(eigenvectors(pointIndex, pointCount - dimensionIndex - 1)); } else { curPoint[dimensionIndex] = float(eigenvectors(pointIndex, dimensionIndex)); } } } if(method == Symmetric) { for(UINT pointIndex = 0; pointIndex < pointCount; pointIndex++) { points[pointIndex] = VecNf::Normalize(points[pointIndex]); } } KMeansClustering<VecNf, VecNfKMeansMetric> clustering; clustering.Cluster(points, kMeansClusters, 100); clusterIDs.Allocate(pointCount); for(UINT pointIndex = 0; pointIndex < pointCount; pointIndex++) { clusterIDs[pointIndex] = clustering.QuantizeToNearestClusterIndex(points[pointIndex]); } }