Multinomial Naive Bayes
This commit is contained in:
parent
553d5c231e
commit
1f5bdbbc82
|
|
@ -1,5 +1,6 @@
|
||||||
using BotSharp.Algorithm.Extensions;
|
using BotSharp.Algorithm.Estimators;
|
||||||
using BotSharp.Algorithm.Formulas;
|
using BotSharp.Algorithm.Features;
|
||||||
|
using BotSharp.Algorithm.Statistics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
@ -10,12 +11,12 @@ namespace BotSharp.Algorithm.Bayes
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// https://en.wikipedia.org/wiki/Bayes%27_theorem
|
/// https://en.wikipedia.org/wiki/Bayes%27_theorem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class NaiveBayes<Smoother> where Smoother : ISmoother, new()
|
public class NaiveBayes<Estimator> where Estimator : IEstimator, new()
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// smoothing function
|
/// smoothing function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Smoother smoother;
|
private Estimator estomator;
|
||||||
|
|
||||||
public List<FeaturesDistribution> FeaturesDist { get; set; }
|
public List<FeaturesDistribution> FeaturesDist { get; set; }
|
||||||
|
|
||||||
|
|
@ -23,7 +24,7 @@ namespace BotSharp.Algorithm.Bayes
|
||||||
|
|
||||||
public NaiveBayes()
|
public NaiveBayes()
|
||||||
{
|
{
|
||||||
smoother = new Smoother();
|
estomator = new Estimator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -40,7 +41,7 @@ namespace BotSharp.Algorithm.Bayes
|
||||||
double prob = 0;
|
double prob = 0;
|
||||||
|
|
||||||
// prior probability
|
// prior probability
|
||||||
prob = Math.Log(smoother.Prob(LabelDist, Y), 2);
|
prob = Math.Log(estomator.Prob(LabelDist, Y), 2);
|
||||||
|
|
||||||
// posterior probability P(X1,...,Xn|Y) = Sum(P(X1|Y) +...+ P(Xn|Y)
|
// posterior probability P(X1,...,Xn|Y) = Sum(P(X1|Y) +...+ P(Xn|Y)
|
||||||
var featuresIfY = FeaturesDist.Where(fd => fd.Label == Y).ToList();
|
var featuresIfY = FeaturesDist.Where(fd => fd.Label == Y).ToList();
|
||||||
|
|
@ -52,46 +53,10 @@ namespace BotSharp.Algorithm.Bayes
|
||||||
var fv = featuresIfY.First(fd => fd.FeatureName == Xn.Name).FeatureValues;
|
var fv = featuresIfY.First(fd => fd.FeatureName == Xn.Name).FeatureValues;
|
||||||
|
|
||||||
// features are independent, so calculate every feature prob and sum them
|
// features are independent, so calculate every feature prob and sum them
|
||||||
prob += Math.Log(smoother.Prob(fv, Xn.Value), 2);
|
prob += Math.Log(estomator.Prob(fv, Xn.Value), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return prob;
|
return prob;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Feature
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Value { get; set; }
|
|
||||||
|
|
||||||
public Feature(string name, string value)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FeaturesWithLabel
|
|
||||||
{
|
|
||||||
public List<Feature> Features { get; set; }
|
|
||||||
public string Label { get; set; }
|
|
||||||
public FeaturesWithLabel()
|
|
||||||
{
|
|
||||||
this.Features = new List<Feature>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FeaturesDistribution
|
|
||||||
{
|
|
||||||
public string Label { get; set; }
|
|
||||||
|
|
||||||
public string FeatureName { get; set; }
|
|
||||||
|
|
||||||
public List<Probability> FeatureValues { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{Label} {FeatureName} {FeatureValues.Count}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
using System;
|
using BotSharp.Algorithm.Statistics;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace BotSharp.Algorithm
|
namespace BotSharp.Algorithm.Estimators
|
||||||
{
|
{
|
||||||
public interface ISmoother
|
public interface IEstimator
|
||||||
{
|
{
|
||||||
double Prob(List<Probability> dist, string sample);
|
double Prob(List<Probability> dist, string sample);
|
||||||
}
|
}
|
||||||
|
|
@ -16,20 +16,22 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using BotSharp.Algorithm.Statistics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace BotSharp.Algorithm.Formulas
|
namespace BotSharp.Algorithm.Estimators
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Lidstone smoothing is a technique used to smooth categorical data.
|
/// Lidstone smoothing is a technique used to smooth categorical data.
|
||||||
/// In statistics, it's called additive smoothing or Laplace smoothing.
|
/// In statistics, it's called additive smoothing or Laplace smoothing.
|
||||||
/// Given an observation x = (x1, …, xd) from a multinomial distribution with N trials, a "smoothed" version of the data gives the estimator.
|
/// Given an observation x = (x1, …, xd) from a multinomial distribution with N trials, a "smoothed" version of the data gives the estimator.
|
||||||
/// https://en.wikipedia.org/wiki/Additive_smoothing
|
/// https://en.wikipedia.org/wiki/Additive_smoothing
|
||||||
|
/// Used as Multinomial Naive Bayes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Lidstone : ISmoother
|
public class Lidstone : IEstimator
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// α > 0 is the smoothing parameter
|
/// α > 0 is the smoothing parameter
|
||||||
18
BotSharp.Algorithm/Features/Feature.cs
Normal file
18
BotSharp.Algorithm/Features/Feature.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BotSharp.Algorithm.Features
|
||||||
|
{
|
||||||
|
public class Feature
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
public Feature(string name, string value)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
BotSharp.Algorithm/Features/FeaturesDistribution.cs
Normal file
21
BotSharp.Algorithm/Features/FeaturesDistribution.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
using BotSharp.Algorithm.Statistics;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BotSharp.Algorithm.Features
|
||||||
|
{
|
||||||
|
public class FeaturesDistribution
|
||||||
|
{
|
||||||
|
public string Label { get; set; }
|
||||||
|
|
||||||
|
public string FeatureName { get; set; }
|
||||||
|
|
||||||
|
public List<Probability> FeatureValues { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Label} {FeatureName} {FeatureValues.Count}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace BotSharp.Algorithm
|
namespace BotSharp.Algorithm.Statistics
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// In probability theory and statistics, a probability distribution is a mathematical function
|
/// In probability theory and statistics, a probability distribution is a mathematical function
|
||||||
|
|
@ -10,6 +10,10 @@
|
||||||
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA</Configurations>
|
<Configurations>Debug;Release;RASA NLU;DIALOGFLOW;RASA</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="wordvec_enu.bin" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.1.1" />
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,13 @@ namespace BotSharp.NLP.UnitTest
|
||||||
FileName = "cooking.stackexchange.txt"
|
FileName = "cooking.stackexchange.txt"
|
||||||
});
|
});
|
||||||
|
|
||||||
var tokenizer = new TokenizerFactory<TreebankTokenizer>(new TokenizationOptions { }, SupportedLanguage.English);
|
var tokenizer = new TokenizerFactory<TreebankTokenizer>(new TokenizationOptions { }, SupportedLanguage.English);
|
||||||
sentences.ForEach(x => x.Words = tokenizer.Tokenize(x.Text));
|
var newSentences = tokenizer.Tokenize(sentences.Select(x => x.Text).ToList());
|
||||||
|
for(int i = 0; i < newSentences.Count; i++)
|
||||||
|
{
|
||||||
|
newSentences[i].Label = sentences[i].Label;
|
||||||
|
}
|
||||||
|
sentences = newSentences;
|
||||||
|
|
||||||
sentences.Shuffle();
|
sentences.Shuffle();
|
||||||
|
|
||||||
|
|
@ -34,7 +39,7 @@ namespace BotSharp.NLP.UnitTest
|
||||||
{
|
{
|
||||||
TrainingCorpusDir = Path.Combine(Configuration.GetValue<String>("MachineLearning:dataDir"), "Text Classification", "cooking.stackexchange")
|
TrainingCorpusDir = Path.Combine(Configuration.GetValue<String>("MachineLearning:dataDir"), "Text Classification", "cooking.stackexchange")
|
||||||
};
|
};
|
||||||
var classifier = new ClassifierFactory<NaiveBayesClassifier>(options, SupportedLanguage.English);
|
var classifier = new ClassifierFactory<NaiveBayesClassifier, SentenceFeatureExtractor>(options, SupportedLanguage.English);
|
||||||
var dataset = sentences.Split(0.7M);
|
var dataset = sentences.Split(0.7M);
|
||||||
classifier.Train(dataset.Item1);
|
classifier.Train(dataset.Item1);
|
||||||
|
|
||||||
|
|
@ -58,7 +63,7 @@ namespace BotSharp.NLP.UnitTest
|
||||||
{
|
{
|
||||||
TrainingCorpusDir = Path.Combine(Configuration.GetValue<String>("MachineLearning:dataDir"), "Gender")
|
TrainingCorpusDir = Path.Combine(Configuration.GetValue<String>("MachineLearning:dataDir"), "Gender")
|
||||||
};
|
};
|
||||||
var classifier = new ClassifierFactory<NaiveBayesClassifier>(options, SupportedLanguage.English);
|
var classifier = new ClassifierFactory<NaiveBayesClassifier, WordFeatureExtractor>(options, SupportedLanguage.English);
|
||||||
|
|
||||||
var corpus = GetLabeledCorpus(options);
|
var corpus = GetLabeledCorpus(options);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using BotSharp.Algorithm.Bayes;
|
using BotSharp.Algorithm.Features;
|
||||||
using BotSharp.NLP.Corpus;
|
|
||||||
using BotSharp.NLP.Tokenize;
|
using BotSharp.NLP.Tokenize;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
@ -8,7 +7,9 @@ using System.Text;
|
||||||
|
|
||||||
namespace BotSharp.NLP.Classify
|
namespace BotSharp.NLP.Classify
|
||||||
{
|
{
|
||||||
public class ClassifierFactory<IClassify> where IClassify : IClassifier, new()
|
public class ClassifierFactory<IClassify, IFeatureExtractor>
|
||||||
|
where IClassify : IClassifier, new()
|
||||||
|
where IFeatureExtractor : ITextFeatureExtractor, new()
|
||||||
{
|
{
|
||||||
private SupportedLanguage _lang;
|
private SupportedLanguage _lang;
|
||||||
|
|
||||||
|
|
@ -16,16 +17,19 @@ namespace BotSharp.NLP.Classify
|
||||||
|
|
||||||
private ClassifyOptions _options;
|
private ClassifyOptions _options;
|
||||||
|
|
||||||
|
private IFeatureExtractor featureExtractor;
|
||||||
|
|
||||||
public ClassifierFactory(ClassifyOptions options, SupportedLanguage lang)
|
public ClassifierFactory(ClassifyOptions options, SupportedLanguage lang)
|
||||||
{
|
{
|
||||||
_lang = lang;
|
_lang = lang;
|
||||||
_options = options;
|
_options = options;
|
||||||
_classifier = new IClassify();
|
_classifier = new IClassify();
|
||||||
|
featureExtractor = new IFeatureExtractor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Tuple<string, double>> Classify(Sentence sentence)
|
public List<Tuple<string, double>> Classify(Sentence sentence)
|
||||||
{
|
{
|
||||||
var classes = _classifier.Classify(GetFeatures(sentence.Words), new ClassifyOptions
|
var classes = _classifier.Classify(featureExtractor.GetFeatures(sentence.Words), new ClassifyOptions
|
||||||
{
|
{
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -37,20 +41,8 @@ namespace BotSharp.NLP.Classify
|
||||||
_classifier.Train(sentences.Select(x => new FeaturesWithLabel
|
_classifier.Train(sentences.Select(x => new FeaturesWithLabel
|
||||||
{
|
{
|
||||||
Label = x.Label,
|
Label = x.Label,
|
||||||
Features = GetFeatures(x.Words)
|
Features = featureExtractor.GetFeatures(x.Words)
|
||||||
}).ToList(), _options);
|
}).ToList(), _options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Feature> GetFeatures(List<Token> words)
|
|
||||||
{
|
|
||||||
string text = words[0].Text;
|
|
||||||
var features = new List<Feature>();
|
|
||||||
|
|
||||||
features.Add(new Feature("alwayson", "True"));
|
|
||||||
features.Add(new Feature("startswith", text[0].ToString().ToLower()));
|
|
||||||
features.Add(new Feature("endswith", text[text.Length - 1].ToString().ToLower()));
|
|
||||||
|
|
||||||
return features;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using BotSharp.Algorithm.Bayes;
|
using BotSharp.Algorithm.Features;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
|
||||||
16
BotSharp.NLP/Classify/ITextFeatureExtractor.cs
Normal file
16
BotSharp.NLP/Classify/ITextFeatureExtractor.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
using BotSharp.Algorithm.Features;
|
||||||
|
using BotSharp.NLP.Tokenize;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BotSharp.NLP.Classify
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Featuring text
|
||||||
|
/// </summary>
|
||||||
|
public interface ITextFeatureExtractor
|
||||||
|
{
|
||||||
|
List<Feature> GetFeatures(List<Token> words);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,8 +18,10 @@
|
||||||
|
|
||||||
using BotSharp.Algorithm;
|
using BotSharp.Algorithm;
|
||||||
using BotSharp.Algorithm.Bayes;
|
using BotSharp.Algorithm.Bayes;
|
||||||
|
using BotSharp.Algorithm.Estimators;
|
||||||
using BotSharp.Algorithm.Extensions;
|
using BotSharp.Algorithm.Extensions;
|
||||||
using BotSharp.Algorithm.Formulas;
|
using BotSharp.Algorithm.Features;
|
||||||
|
using BotSharp.Algorithm.Statistics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
@ -52,6 +54,7 @@ namespace BotSharp.NLP.Classify
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var fNames = featureSets[0].Features.Select(x => x.Name)
|
var fNames = featureSets[0].Features.Select(x => x.Name)
|
||||||
|
.Distinct()
|
||||||
.OrderBy(x => x)
|
.OrderBy(x => x)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|
@ -120,4 +123,14 @@ namespace BotSharp.NLP.Classify
|
||||||
return labelDist.Select(x => new Tuple<string, double>(x.Value, x.Prob)).ToList();
|
return labelDist.Select(x => new Tuple<string, double>(x.Value, x.Prob)).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class FeaturesWithLabel
|
||||||
|
{
|
||||||
|
public List<Feature> Features { get; set; }
|
||||||
|
public string Label { get; set; }
|
||||||
|
public FeaturesWithLabel()
|
||||||
|
{
|
||||||
|
this.Features = new List<Feature>();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using BotSharp.Algorithm.Bayes;
|
using BotSharp.Algorithm.Features;
|
||||||
using SVM.BotSharp.MachineLearning;
|
using SVM.BotSharp.MachineLearning;
|
||||||
using Txt2Vec;
|
using Txt2Vec;
|
||||||
|
|
||||||
|
|
|
||||||
23
BotSharp.NLP/Classify/SentenceFeatureExtractor.cs
Normal file
23
BotSharp.NLP/Classify/SentenceFeatureExtractor.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using BotSharp.Algorithm.Features;
|
||||||
|
using BotSharp.NLP.Tokenize;
|
||||||
|
|
||||||
|
namespace BotSharp.NLP.Classify
|
||||||
|
{
|
||||||
|
public class SentenceFeatureExtractor : ITextFeatureExtractor
|
||||||
|
{
|
||||||
|
public List<Feature> GetFeatures(List<Token> words)
|
||||||
|
{
|
||||||
|
var features = new List<Feature>();
|
||||||
|
|
||||||
|
words.Where(x => x.Text.Length > 1)
|
||||||
|
.ToList()
|
||||||
|
.ForEach(w => features.Add(new Feature("contains", w.Text.ToLower())));
|
||||||
|
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
BotSharp.NLP/Classify/WordFeatureExtractor.cs
Normal file
23
BotSharp.NLP/Classify/WordFeatureExtractor.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using BotSharp.Algorithm.Features;
|
||||||
|
using BotSharp.NLP.Tokenize;
|
||||||
|
|
||||||
|
namespace BotSharp.NLP.Classify
|
||||||
|
{
|
||||||
|
public class WordFeatureExtractor : ITextFeatureExtractor
|
||||||
|
{
|
||||||
|
public List<Feature> GetFeatures(List<Token> words)
|
||||||
|
{
|
||||||
|
string text = words[0].Text;
|
||||||
|
var features = new List<Feature>();
|
||||||
|
|
||||||
|
features.Add(new Feature("alwayson", "True"));
|
||||||
|
features.Add(new Feature("startswith", text[0].ToString().ToLower()));
|
||||||
|
features.Add(new Feature("endswith", text[text.Length - 1].ToString().ToLower()));
|
||||||
|
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,19 +32,16 @@ namespace BotSharp.NLP.Tokenize
|
||||||
return _tokenizer.Tokenize(sentence, _options);
|
return _tokenizer.Tokenize(sentence, _options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<List<Token>> Tokenize(List<String> sentences)
|
public List<Sentence> Tokenize(List<String> sentences)
|
||||||
{
|
{
|
||||||
var sents = sentences.Select(s => new ParallelToken { Text = s }).ToList();
|
var sents = sentences.Select(s => new Sentence { Text = s }).ToList();
|
||||||
|
|
||||||
Parallel.ForEach(sents, (sentence) =>
|
Parallel.ForEach(sents, (sentence) =>
|
||||||
{
|
{
|
||||||
sentence.Tokens = Tokenize(sentence.Text);
|
sentence.Words = Tokenize(sentence.Text);
|
||||||
});
|
});
|
||||||
|
|
||||||
List<List<Token>> result = new List<List<Token>>();
|
return sents;
|
||||||
sents.ForEach(x => result.Add(x.Tokens));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ParallelToken
|
private class ParallelToken
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue