/// /// Copyright (c) 2018 Bo Peng /// /// Permission is hereby granted, free of charge, to any person obtaining /// a copy of this software and associated documentation files (the /// "Software"), to deal in the Software without restriction, including /// without limitation the rights to use, copy, modify, merge, publish, /// distribute, sublicense, and/or sell copies of the Software, and to /// permit persons to whom the Software is furnished to do so, subject to /// the following conditions: /// /// The above copyright notice and this permission notice shall be /// included in all copies or substantial portions of the Software. /// /// using BotSharp.NLP.Tokenize; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Text.RegularExpressions; namespace BotSharp.NLP.Txt2Vec { public class TFIDF { public List Sentences { get; set; } public List Words { get; set; } public void Encode(Sentence sentence) { InitDictionary(); // var featureSets = Sentences.Select(x => new Tuple(x.Label, x.Vector)).ToList(); var labelDist = Sentences.Select(x => x.Label).Distinct().ToList(); labelDist.ForEach(label => { // https://zhuanlan.zhihu.com/p/31197209 // calculate TF // all words in the article List words = new List(); Sentences.Where(x => x.Label == label).ToList().ForEach(sent => { words.AddRange(sent.Words.Select(w => w.Text)); }); List> tfs = new List>(); words.Distinct().ToList().ForEach(w => { // TF int c1 = words.Count(x => x == w); double tf = (c1 + 1.0) / words.Count(); // IDF var sents = Sentences.Where(s => s.Words.Select(x => x.Text).Contains(w)).ToList(); double idf = Math.Log(Sentences.Count / (sents.Count() + 1.0)); tfs.Add(new Tuple(w, tf * idf)); }); tfs = tfs.OrderByDescending(x => x.Item2).Take(words.Count / 10).ToList(); }); sentence.Words.ForEach(w => { int index = Words.IndexOf(w.Text.ToLower()); }); } public List EncodeAll() { InitDictionary(); Sentences.ForEach(sent => Encode(sent)); //Parallel.ForEach(Sentences, sent => Encode(sent)); return Words; } private List InitDictionary() { if (Words == null) { Words = new List(); Sentences.ForEach(x => { Words.AddRange(x.Words.Where(w => w.IsAlpha).Select(w => w.Text.ToLower())); }); Words = Words.Distinct().OrderBy(x => x).ToList(); } return Words; } /// /// Normalizes a TF*IDF array of vectors using L2-Norm. /// Xi = Xi / Sqrt(X0^2 + X1^2 + .. + Xn^2) /// /// List> /// List> public static List> Normalize(List> vectors) { // Normalize the vectors using L2-Norm. List> normalizedVectors = new List>(); foreach (var vector in vectors) { var normalized = Normalize(vector); normalizedVectors.Add(normalized); } return normalizedVectors; } /// /// Normalizes a TF*IDF vector using L2-Norm. /// Xi = Xi / Sqrt(X0^2 + X1^2 + .. + Xn^2) /// /// List /// List public static List Normalize(List vector) { List result = new List(); double sumSquared = 0; foreach (var value in vector) { sumSquared += value * value; } double SqrtSumSquared = Math.Sqrt(sumSquared); foreach (var value in vector) { // L2-norm: Xi = Xi / Sqrt(X0^2 + X1^2 + .. + Xn^2) result.Add(value / SqrtSumSquared); } return result; } } }