///
/// 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;
}
}
}