I would like to share my class IDF with experts. Sorry for the poor data structure, but we are humans and still learning. Any Suggestion/ Modification please ?? many Thanks.
public class IDFMeasure
{
private readonly string[] _docs;
private readonly int _numDocs;
private int _numTerms;
private List<string> _terms;
private float[][] _InverseDocFreq;
private int[] _docFreq;
private readonly Dictionary<string, int> _wordsIndex = new Dictionary<string, int>();
public IDFMeasure(string[] documents)
{
_docs = documents;
_numDocs = documents.Length;
MyInit();
}
private List<string> GenerateTerms(string[] docs)
{
return docs.SelectMany(doc => ProcessDocument(doc)).Distinct().ToList();
}
private IEnumerable<string> ProcessDocument(string doc)
{
return doc.Split(' ')
.GroupBy(word => word)
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
}
private int GetTermIndex(string term)
{
return _wordsIndex[term];
}
private void MyInit()
{
_terms = GenerateTerms(_docs);
_numTerms = _terms.Count;
_docFreq = new int[_numTerms];
for (var i = 0; i < _terms.Count; i++)
{
_wordsIndex.Add(_terms[i], i);
}
GenerateDocumentFrequency();
GenerateInverseDocfrequency();
}
private float Log(float num)
{
return (float) Math.Log(num); //log2
}
private void GenerateDocumentFrequency()
{
_InverseDocFreq = new float[_numDocs][];
for (var i = 0; i < _numDocs; i++)
{
_InverseDocFreq[i] = new float[_numTerms];
var curDoc = _docs[i];
var freq = GetWordFrequency(curDoc);
foreach (var entry in freq)
{
var word = entry.Key;
var termIndex = GetTermIndex(word);
_docFreq[termIndex]++;
}
}
}
private void GenerateInverseDocfrequency()
{
for (var i = 0; i < _numDocs; i++)
{
var curDoc = _docs[i];
var freq = GetWordFrequency(curDoc);
foreach (var entry in freq)
{
var word = entry.Key;
var termIndex = GetTermIndex(word);
_InverseDocFreq[i][termIndex] = Log((_numDocs)/
(float) _docFreq[termIndex]);
}
}
}
private Dictionary<string, int> GetWordFrequency(string input)
{
return input.Split(' ').GroupBy(x => x)
.OrderByDescending(g => g.Count())
.ToDictionary(g => g.Key, g => g.Count());
}
}