public List <Cluster> Clustering(List <SimilarityRow> rows, int threshold) { if (threshold == 0) { threshold = THRESHOLD; } List <Cluster> clusters = new List <Cluster>(); int size = rows.Count(); //пока есть нераспределенные документы while (size > 0) { //ищем строку с максимальной суммой int maxSumSimilarity = rows.Max(y => y.GetSumSimilarity()); SimilarityRow maxRow = rows.Find(x => x.GetSumSimilarity() == maxSumSimilarity); Cluster cluster = new Cluster(); foreach (var entry in maxRow.Similarity) { //если коэффициент схожести больше заданного порогового значения - добавляем документ в кластер if (entry.Value >= threshold) { cluster.Docs.Add(entry.Key); } } //кластер не пустой if (cluster.Docs.Count != 0) { clusters.Add(cluster); } //удаляем документы, которые попали в кластер DeleteRows(rows, cluster.Docs); size = rows.Count(); } return(clusters); }
public List <SimilarityRow> MakeSimilarityRows(List <Doc> docs, int termCount) { var rows = new List <SimilarityRow>(); if (termCount == 0) { termCount = TERM_COUNT; } //получим список термов для каждого документа var doc2Terms = GetDocumentShingle(docs, termCount); var doc2Similarity = new Dictionary <string, int>(); //на случай, если ключевых слов меньше, чем задано var minSize = doc2Terms.Values.Min(x => x.Count); //if (minSize < termCount) //{ // termCount = minSize; // foreach (var e in doc2Terms) // { // List<String> lst = e.Value; // if (lst.Count() > termCount) // { // lst = lst.GetRange(0, termCount); // doc2Terms.Add(e.Key, lst); // } // } //} for (var i = 0; i < docs.Count(); i++) { var doc = docs[i]; var row = new SimilarityRow(); row.Doc = doc; //список термов для данного документа var terms = doc2Terms[row.Doc.DocIndex]; var arrX = Initionalize(termCount); //сравнение с другими документами for (var j = 0; j < docs.Count(); j++) { //ид документа var doc2 = docs[j]; //набор термов для документа, с которым сравниваем var terms2 = doc2Terms[doc2.DocIndex]; //схожесть одинаковых документов можно не считать. всегда = 100 if (row.Doc.Equals(doc2)) { //сам с собой можно не считать. всегда 100 row.Similarity.Add(doc2, 100); continue; } //уже считали раньше if (doc2Similarity.ContainsKey(GetUniqueKey(i, j))) { row.Similarity.Add(doc2, doc2Similarity[GetUniqueKey(i, j)]); continue; } var arrY = new int[termCount]; //если i-е слово из N - списка присутствует в документе, //то значением i - го элемента образа документа считается 1, в противном случае — 0. foreach (var term in terms) { arrY[terms.IndexOf(term)] = terms2.Contains(term) ? 1 : 0; } if (arrY.Length < termCount) { for (var k = arrY.Length; k < termCount; k++) { arrY[k] = 0; } } //считаем коэффициент схожести var coeff = GetSimilarityCoefficient(arrX, arrY); //добавляем в матрицу row.Similarity.Add(doc2, coeff); doc2Similarity.Add(GetUniqueKey(i, j), coeff); } rows.Add(row); } return(rows); }
public List <SimilarityRow> MakeSimilarityRows(List <Doc> docs, int shingleLength) { var rows = new List <SimilarityRow>(); //получим список шинглов для каждого документа var doc2Terms = GetDocumentShingle(docs, shingleLength); var doc2similarity = new Dictionary <string, int>(); for (var i = 0; i < docs.Count(); i++) { var doc = docs[i]; var row = new SimilarityRow { Doc = doc }; //список шинглов для данного документа var shingles1 = doc2Terms[row.Doc.DocIndex]; //сравнение с другими документами for (var j = 0; j < docs.Count(); j++) { //ид документа var doc2 = docs[j]; if (!row.Similarity.ContainsKey(doc2)) { //схожесть одинаковых документов можно не считать. всегда = 100 if (row.Doc.Equals(doc2)) { //сам с собой можно не считать. всегда 100 row.Similarity.Add(doc2, 100); continue; } //уже считали раньше if (doc2similarity.ContainsKey(GetUniqueKey(i, j))) { row.Similarity.Add(doc2, doc2similarity[GetUniqueKey(i, j)]); continue; } //набор шинглов для документа, с которым сравниваем var shingles2 = doc2Terms[doc2.DocIndex]; var same = 0; for (var k = 0; k < shingles1.Count(); k++) { for (var l = 0; l < shingles2.Count(); l++) { if (shingles1[k].Equals(shingles2[l])) { same++; } } } double s = same * 2; double count = shingles1.Count() + shingles2.Count(); var res = s / count; var coeff = (int)Math.Round(res * 100); //добавляем в матрицу doc2similarity.Add(GetUniqueKey(i, j), coeff); row.Similarity.Add(doc2, coeff); } } rows.Add(row); } return(rows); }