SVD est l'abréviation de Singular Value Decomposition (Décomposition de la valeur singulière). Il est dit être la technique populaire pour effectuer la réduction des caractéristiques dans la classification des textes. Je connais le principe comme this link.Comment utiliser SVD correctement dans Accord.net
J'ai utilisé C#, en utilisant la bibliothèque Accord.Net et j'avais un tableau dentelé double[][]
de calculer TF-IDF déjà.
Je sais déjà qu'il y a 4 sujets dans mes documents. Je veux tester la méthode Kmean avec le nombre de clusters k = 4. Avant d'utiliser Kmean, je veux utiliser SVD pour effectuer la réduction des fonctionnalités. Lorsque les résultats apparaissent, près de 90% des documents sont groupés en un groupe, d'autres sont regroupés en trois autres groupes. C'est un très mauvais résultat. J'ai essayé de relancer un certain nombre de fois mais les résultats ne changent pas beaucoup. Si j'utilise PCA au lieu de SDV, tout s'est bien passé comme prévu.
Donc, où je me trompe. Toute personne qui sait cela peut me guider un exemple de code. Merci beaucoup.
Note: mon original TF-IDF a des lignes représentant les documents, colonne représentant termes
Voici mon code:
//to matrix because the function SVD requiring input of matrix, not jagged array
//transpose because the TF-IDF used for SVD has rows representing terms, columns representing documents;
var svd = new SingularValueDecomposition(tfidf.ToMatrix().Transpose());
double[,] U = svd.LeftSingularVectors;
double[,] S = svd.DiagonalMatrix;
double[,] V = svd.RightSingularVectors;
//find the optimal cutoff y so that we retain enough singular values to make up 90% of the energy in S
//http://infolab.stanford.edu/~ullman/mmds/ch11.pdf, page 18-20
double energy = 0;
for (int i = 0; i < S.GetLength(0); i++)
{
energy += Math.Pow(S[i, i], 2);
}
double percent;
int y = S.GetLength(0);
do
{
y--;
double test = 0;
for (int i = 0; i < y; i++)
{
test += Math.Pow(S[i, i], 2);
}
percent = test/energy;
} while (percent >= 0.9);
y = y + 1;
//Uk gets all rows, y first columns of U; Sk get y first rows, y first columns of S; Vk get y first rows, all columns of V
double[,] Uk = U.Submatrix(0, U.GetLength(0) - 1, 0, y - 1);
double[,] Sk = S.Submatrix(0, y - 1, 0, y - 1);
double[,] Vk = V.Submatrix(0, y - 1, 0, V.GetLength(1) - 1);
//reduce dimension according to http://stats.stackexchange.com/questions/107533/how-to-use-svd-for-dimensionality-reduction-to-reduce-the-number-of-columns-fea
//we tranpose again to have the rows being document, columns being term as original TF-IDF
//ToArray because the Kmean below acquiring input of jagged array
tfidf = Uk.Multiply(Sk).Transpose().ToArray();
// if tfidf = Uk.Multiply(Sk).Multiply(Vk).Transpose().ToArray()
// result still bad
// Create a K-Means algorithm using given k and a square Euclidean distance as distance metric.
var kmeans = new KMeans(4, Distance.SquareEuclidean) { Tolerance = 0.05 };
int[] labels = kmeans.Compute(tfidf);
Après cela, nous faisons quelques pas de savoir quels documents Appartient à quels groupes selon les étiquettes.