UniGram, BiGram, TriGram passed.
This commit is contained in:
parent
f8a93f225d
commit
cf5c0e0535
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue