UniGram, BiGram, TriGram passed.

This commit is contained in:
Oceania2018 2018-08-18 00:44:18 -05:00
parent f8a93f225d
commit cf5c0e0535
2 changed files with 130 additions and 40 deletions

View file

@ -13,7 +13,7 @@ namespace BotSharp.NLP.UnitTest
public class NGramTaggerTest
{
[TestMethod]
public void TagInCoNLL2000()
public void UniGramInCoNLL2000()
{
// tokenization
var tokenizer = new TokenizerFactory<RegexTokenizer>(new TokenizationOptions
@ -21,26 +21,88 @@ namespace BotSharp.NLP.UnitTest
Pattern = RegexTokenizer.WORD_PUNC
}, SupportedLanguage.English);
var tokens = tokenizer.Tokenize("How are you doing?");
var tokens = tokenizer.Tokenize("Chancellor of the Exchequer Nigel Lawson's restated commitment");
// test tag
var tagger = new TaggerFactory<NGramTagger>(new TagOptions
{
NGram = 1,
Tag = "NN",
Corpus = GetTaggedCorpus()
}, SupportedLanguage.English);
tagger.Tag(new Sentence { Words = tokens });
Assert.IsTrue(tokens[0].Pos == "NNP");
Assert.IsTrue(tokens[1].Pos == "IN");
Assert.IsTrue(tokens[2].Pos == "DT");
Assert.IsTrue(tokens[3].Pos == "NNP");
}
[TestMethod]
public void BiGramInCoNLL2000()
{
// tokenization
var tokenizer = new TokenizerFactory<RegexTokenizer>(new TokenizationOptions
{
Pattern = RegexTokenizer.WORD_PUNC
}, SupportedLanguage.English);
var tokens = tokenizer.Tokenize("Chancellor of the Exchequer Nigel Lawson's restated commitment");
// test tag
var tagger = new TaggerFactory<NGramTagger>(new TagOptions
{
NGram = 2,
Tag = "NN",
Corpus = GetTaggedCorpus()
}, SupportedLanguage.English);
tagger.Tag(new Sentence { Words = tokens });
Assert.IsTrue(tokens[0].Pos == "NNP");
Assert.IsTrue(tokens[1].Pos == "IN");
Assert.IsTrue(tokens[2].Pos == "DT");
Assert.IsTrue(tokens[3].Pos == "NNP");
}
[TestMethod]
public void TriGramInCoNLL2000()
{
// tokenization
var tokenizer = new TokenizerFactory<RegexTokenizer>(new TokenizationOptions
{
Pattern = RegexTokenizer.WORD_PUNC
}, SupportedLanguage.English);
var tokens = tokenizer.Tokenize("Chancellor of the Exchequer Nigel Lawson's restated commitment");
// test tag
var tagger = new TaggerFactory<NGramTagger>(new TagOptions
{
NGram = 3,
Tag = "NN",
Corpus = GetTaggedCorpus()
}, SupportedLanguage.English);
tagger.Tag(new Sentence { Words = tokens });
Assert.IsTrue(tokens[0].Pos == "NNP");
Assert.IsTrue(tokens[1].Pos == "IN");
Assert.IsTrue(tokens[2].Pos == "DT");
Assert.IsTrue(tokens[3].Pos == "NNP");
}
private List<Sentence> GetTaggedCorpus()
{
// get training corpus
string corpusDir = Environment.GetEnvironmentVariable("BOTSHARP_CORPUS_PATH", EnvironmentVariableTarget.User);
var sentences = new CoNLLReader()
return new CoNLLReader()
.Read(new ReaderOptions
{
DataDir = Path.Combine(corpusDir, "CoNLL"),
FileName = "conll2000_chunking_train.txt"
});
// start tag
var tagger = new TaggerFactory<NGramTagger>(new TagOptions
{
NGram = 2,
Tag = "NN",
Corpus = sentences
}, SupportedLanguage.English);
tagger.Tag(new Sentence { Words = tokens });
}
}
}

View file

@ -21,64 +21,92 @@ namespace BotSharp.NLP.Tag
{
Train(options.Corpus, options);
}
Fill(sentence, options);
for (int pos = options.NGram - 1; pos < sentence.Words.Count; pos++)
{
sentence.Words[pos].Pos = _contextMapping.FirstOrDefault(x => x.Context == GetContext(pos, sentence.Words, options))?.Tag;
// set default tag
if(sentence.Words[pos].Pos == null)
{
sentence.Words[pos].Pos = options.Tag;
}
}
for(int pos = 0; pos < options.NGram - 1; pos++)
{
sentence.Words.RemoveAt(0);
}
}
public void Train(List<Sentence> sentences, TagOptions options)
{
_contextMapping = new List<NGramFreq>();
var cache = new List<NGramFreq>();
for (int idx = 0; idx < options.Corpus.Count; idx++)
{
var sent = options.Corpus[idx];
for (int ngram = 1; ngram < options.NGram; ngram++)
{
sent.Words.Insert(0, new Token { Text = "NIL", Pos = options.Tag, Start = (ngram - 1) * 3 });
}
Fill(sent, options);
int pos = options.NGram - 1;
for (pos = 1; pos < sent.Words.Count; pos++)
for (int pos = options.NGram - 1; pos < sent.Words.Count; pos++)
{
var freq = new NGramFreq
{
PrecedingTokens = new List<Token> { sent.Words[pos - 1] },
Token = sent.Words[pos],
Count = 0
Context = GetContext(pos, sent.Words, options),
Tag = sent.Words[pos].Pos,
Count = 1
};
_contextMapping.Add(freq);
cache.Add(freq);
}
}
/*var results = (from c in cache
group c by c.Item1 into g
select new { g.Key, Count = g.Count() }).ToList();*/
_contextMapping = (from c in cache
group c by new { c.Context, c.Tag } into g
select new NGramFreq
{
Context = g.Key.Context,
Tag = g.Key.Tag,
Count = g.Count()
}).OrderByDescending(x => x.Count)
.ToList();
}
private string GetContext(int pos, List<Token> words, TagOptions options)
{
string context = words[pos].Text;
for (int ngram = options.NGram - 1; ngram > 0; ngram--)
{
context = words[pos - ngram].Pos + " " + context;
}
return context;
}
private void Fill(Sentence sent, TagOptions options)
{
for (int ngram = 1; ngram < options.NGram; ngram++)
{
sent.Words.Insert(0, new Token { Text = "NIL", Pos = options.Tag, Start = (ngram - 1) * 3 });
}
}
private class NGramFreq
{
/// <summary>
/// Tokens prior current token
/// </summary>
public List<Token> PrecedingTokens { get; set; }
/// <summary>
/// Current token tag
/// </summary>
public Token Token { get; set; }
public string Tag { get; set; }
/// <summary>
/// Occurence frequency
/// </summary>
public int Count { get; set; }
public string Context
{
get
{
return $"{PrecedingTokens.First().Pos} {Token.Text} {Token.Pos}";
}
}
public string Context { get; set; }
}
}
}