diff --git a/BotSharp.Algorithm.UnitTest/BayesianTest.cs b/BotSharp.Algorithm.UnitTest/BayesianTest.cs
deleted file mode 100644
index 1665a43b..00000000
--- a/BotSharp.Algorithm.UnitTest/BayesianTest.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-using BotSharp.Algorithm.Bayesian;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BotSharp.Algorithm.UnitTest
-{
- [TestClass]
- public class BayesianTest
- {
- ///
- /// The training set
- ///
- private ITrainingSet _trainingSet;
-
- ///
- /// The classifier
- ///
- private IClassifier _classifier;
-
- ///
- /// The spam class
- ///
- private static IClass _spamClass;
-
- ///
- /// The ham class
- ///
- private static IClass _hamClass;
-
- ///
- /// Sets up.
- ///
- public void SetUp()
- {
- _trainingSet = BuildTrainingSet();
- _classifier = BuildClassifier(_trainingSet);
- }
-
- ///
- /// Builds the classifier.
- ///
- /// Classifier<StringClass, StringToken>.
- private IClassifier BuildClassifier(ITrainingSetAccessor trainingSet)
- {
- var classifier = new NaiveClassifier(trainingSet)
- {
- // disable smoothing for exact probabilities
- SmoothingAlpha = 0.0D
- };
-
- return classifier;
- }
-
- ///
- /// Builds the training set.
- ///
- /// ITrainingSet<StringClass, StringToken>.
- private static ITrainingSet BuildTrainingSet()
- {
- var trainingSet = new TrainingSet();
-
- // build data sets
- var spamSet = BuildSpamDataSet();
- var hamSet = BuildHamDataSet();
-
- // monkey test
- //spamSet.SetSize.Should()
- //.Be(hamSet.SetSize, "because this test relies on identical set sizes for exact probability testing");
-
- // register classes
- _spamClass = spamSet.Class;
- _hamClass = hamSet.Class;
-
- // add the sets and return
- trainingSet.Add(spamSet, hamSet);
- return trainingSet;
- }
-
- ///
- /// Builds the spam data set.
- ///
- /// IDataSet<StringClass, StringToken>.
- private static IDataSet BuildSpamDataSet()
- {
- return BuildDataSet("spam", 0.5D, "rolex", "watches", "viagra", "prince", "money", "send", "xyzzy");
- }
-
- ///
- /// Builds the spam data set.
- ///
- /// IDataSet<StringClass, StringToken>.
- private static IDataSet BuildHamDataSet()
- {
- return BuildDataSet("ham", 0.5D, "love", "flowers", "unicorn", "friendship", "money", "send", "send");
- }
-
- ///
- /// Builds the data set.
- ///
- /// Name of the class.
- /// The class probability.
- /// The token.
- /// The additional tokens.
- /// IDataSet<StringClass, StringToken>.
- private static IDataSet BuildDataSet(string className, double classProbability, string token, params string[] additionalTokens)
- {
- var @class = new StringClass(className, classProbability);
- var dataSet = new DataSet(@class);
-
- dataSet.AddToken(new StringToken(token));
- dataSet.AddToken(additionalTokens.Select(t => new StringToken(t)));
-
- return dataSet;
- }
-
- [TestMethod]
- public void CalculateProbabilityReturnsOneHundredPercentForAKnownSpamWord()
- {
- var token = new StringToken("rolex");
-
- var probability = _classifier.CalculateProbability(_spamClass, token);
- //probability.Should().BeApproximately(1.0D, 0.0001D, "because the word is known the be a spam word");
- }
-
- [TestMethod]
- public void CalculateProbabilityReturnsOneHundredPercentForAKnownHamWord()
- {
- var token = new StringToken("unicorn");
-
- var probability = _classifier.CalculateProbability(_hamClass, token);
- //probability.Should().BeApproximately(1.0D, 0.0001D, "because the word is known the be a ham word");
- }
-
- [TestMethod]
- public void CalculateProbabilitiesWithHamWordReturnsProbabilitiesForAllClasses()
- {
- var token = new StringToken("unicorn");
-
- var probabilities = _classifier.CalculateProbabilities(token).ToList();
- /*probabilities.Single(p => p.Class.Equals(_spamClass))
- .Probability.Should()
- .BeApproximately(0D, 0.000001D, "because the token is known to be a ham word");
-
- probabilities.Single(p => p.Class.Equals(_hamClass))
- .Probability.Should()
- .BeApproximately(1D, 0.000001D, "because the token is known to be a ham word");*/
- }
-
- [TestMethod]
- public void CalculateProbabilitiesWithMixedWordReturnsProbabilitiesForAllClasses()
- {
- var token = new StringToken("money");
-
- var probabilities = _classifier.CalculateProbabilities(token).ToList();
- /*probabilities.Single(p => p.Class.Equals(_spamClass))
- .Probability.Should()
- .BeApproximately(0.5D, 0.000001D, "because the token is known to be a ham and spam word");
-
- probabilities.Single(p => p.Class.Equals(_hamClass))
- .Probability.Should()
- .BeApproximately(0.5D, 0.000001D, "because the token is known to be a ham and spam word");*/
- }
-
- [TestMethod]
- public void CalculateProbabilitiesWithMixedWordThatIsMoreLikelyHamThanSpamReturnsProbabilitiesForAllClasses()
- {
- var token = new StringToken("send");
-
- var probabilities = _classifier.CalculateProbabilities(token).ToList();
- /*probabilities.Single(p => p.Class.Equals(_spamClass))
- .Probability.Should()
- .BeApproximately(1 / 3D, 0.000001D, "because the token is more likely to be a ham than spam word");
-
- probabilities.Single(p => p.Class.Equals(_hamClass))
- .Probability.Should()
- .BeApproximately(2 / 3D, 0.000001D, "because the token is more likely to be a ham than spam word");*/
- }
-
- [TestMethod]
- public void CalculateProbabilitiesWithRareTokensAndSmoothingAlphaIsUnambiguous()
- {
- var token1 = new StringToken("rolex");
- var token2 = new StringToken("unicorn");
- var token3 = new StringToken("send");
-
- const double smoothingAlpha = 1.0D;
- var probabilities = _classifier.CalculateProbabilities(new IToken[] { token1, token2, token3 }, smoothingAlpha).ToList();
-
- /*probabilities.Single(p => p.Class.Equals(_spamClass))
- .Probability.Should()
- .BeLessThan(0.5D, "because we used more ham than spam tokens");
-
- probabilities.Single(p => p.Class.Equals(_hamClass))
- .Probability.Should()
- .BeGreaterThan(0.5D, "because we used more ham than spam tokens");*/
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayes/NaiveBayes.cs b/BotSharp.Algorithm/Bayes/NaiveBayes.cs
new file mode 100644
index 00000000..764b14f9
--- /dev/null
+++ b/BotSharp.Algorithm/Bayes/NaiveBayes.cs
@@ -0,0 +1,91 @@
+using BotSharp.Algorithm.Extensions;
+using BotSharp.Algorithm.Formulas;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BotSharp.Algorithm.Bayes
+{
+ ///
+ /// https://en.wikipedia.org/wiki/Bayes%27_theorem
+ ///
+ public class NaiveBayes
+ {
+ ///
+ /// smoothing function
+ ///
+ private Lidstone smoother;
+
+ public List FeatureDist { get; set; }
+
+ public List LabelDist { get; set; }
+
+ public NaiveBayes()
+ {
+ smoother = new Lidstone();
+ }
+
+ ///
+ /// calculate posterior probability P(Y|X)
+ /// X is feature set, Y is label
+ /// P(X1,...,Xn|Y) = Sum(P(X1|Y) +...+ P(Xn|Y)
+ /// P(X, Y) = P(Y|X)P(X) = P(X|Y)P(Y) => P(Y|X) = P(Y)P(X|Y)/P(X)
+ ///
+ /// label
+ ///
+ ///
+ public double PosteriorProb(string Y, LabeledFeatureSet featureSet)
+ {
+ double prob = 0;
+
+ // prior probability
+ prob = smoother.Log2Prob(LabelDist, Y);
+
+ // posterior probability P(X1,...,Xn|Y) = Sum(P(X1|Y) +...+ P(Xn|Y)
+ featureSet.Features.ForEach(f =>
+ {
+ var fv = FeatureDist.Find(x => x.Label == Y && x.FeatureName == f.Name).FeatureValues;
+ prob += smoother.Log2Prob(fv, f.Value);
+ });
+
+ 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 FeatureFrequencyDistribution
+ {
+ public string Label { get; set; }
+
+ public string FeatureName { get; set; }
+
+ public List FeatureValues { get; set; }
+
+ public override string ToString()
+ {
+ return $"{Label} {FeatureName} {FeatureValues.Count}";
+ }
+ }
+
+ public class LabeledFeatureSet
+ {
+ public List Features { get; set; }
+ public string Label { get; set; }
+ public LabeledFeatureSet()
+ {
+ this.Features = new List();
+ }
+ }
+}
diff --git a/BotSharp.Algorithm/Bayesian/ClassBase.cs b/BotSharp.Algorithm/Bayesian/ClassBase.cs
deleted file mode 100644
index 47e95e6a..00000000
--- a/BotSharp.Algorithm/Bayesian/ClassBase.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using System.Diagnostics;
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Class ClassBase.
- ///
- [DebuggerDisplay("Class {Name}, base P = {Probability}")]
- public abstract class ClassBase : IClass
- {
- ///
- /// Gets the name.
- ///
- /// The name.
- public string Name { get; private set; }
-
- ///
- /// Gets the class' base probability.
- ///
- /// The probability.
- public double Probability { get; set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The name.
- /// The probability.
- /// name
- ///
- /// probability;Class base probability must be greater than or equal to zero.
- /// or
- /// probability;Class base probability must be less than or equal to one.
- ///
- protected ClassBase(string name, double probability)
- {
- if (ReferenceEquals(name, null)) throw new ArgumentNullException("name");
- if (probability < 0) throw new ArgumentOutOfRangeException("probability", "Class base probability must be greater than or equal to zero.");
- if (probability > 1) throw new ArgumentOutOfRangeException("probability", "Class base probability must be less than or equal to one.");
-
- Name = name;
- Probability = probability;
- }
-
- ///
- /// Indicates whether the current object is equal to another object of the same type.
- ///
- /// An object to compare with this object.
- /// true if the current object is equal to the parameter; otherwise, false.
- public abstract bool Equals(IClass other);
- }
-}
\ No newline at end of file
diff --git a/BotSharp.Algorithm/Bayesian/CombinedConditionalProbabilities.cs b/BotSharp.Algorithm/Bayesian/CombinedConditionalProbabilities.cs
deleted file mode 100644
index f5ee13fe..00000000
--- a/BotSharp.Algorithm/Bayesian/CombinedConditionalProbabilities.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Struct CombinedConditionalProbability
- ///
- [DebuggerDisplay("P({Class}|{TokenProbabilities.Count} tokens)={Probability}")]
- public struct CombinedConditionalProbability
- {
- ///
- /// The class
- ///
- public readonly IClass Class;
-
- ///
- /// The token probabilities
- ///
- public ICollection TokenProbabilities;
-
- ///
- /// The probability
- ///
- public double Probability;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The class.
- /// The probability.
- /// The tokenProbabilities.
- public CombinedConditionalProbability(IClass @class, double probability, ICollection tokenProbabilities)
- {
- if (ReferenceEquals(@class, null)) throw new ArgumentNullException("class");
- if (ReferenceEquals(tokenProbabilities, null)) throw new ArgumentNullException("tokenProbabilities");
- if (probability < 0) throw new ArgumentOutOfRangeException("probability", probability, "Probability must greater than or equal to zero");
- if (probability > 1) throw new ArgumentOutOfRangeException("probability", probability, "Probability must less than or equal to one");
-
- Class = @class;
- TokenProbabilities = tokenProbabilities;
- Probability = probability;
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/ConditionalProbability.cs b/BotSharp.Algorithm/Bayesian/ConditionalProbability.cs
deleted file mode 100644
index a1788c78..00000000
--- a/BotSharp.Algorithm/Bayesian/ConditionalProbability.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-using System;
-using System.Diagnostics;
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Struct ConditionalProbability
- ///
- [DebuggerDisplay("P({Class}|{Token})={Probability}")]
- public struct ConditionalProbability : IEquatable
- {
- ///
- /// The class
- ///
- public readonly IClass Class;
-
- ///
- /// The token
- ///
- public readonly IToken Token;
-
- ///
- /// The conditional probability
- ///
- public readonly double Probability;
-
- ///
- /// The occurrence of the token during the training phase.
- ///
- public readonly long Occurrence;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The class.
- /// The token.
- /// The probability.
- /// The occurrence.
- /// @class
- /// or
- /// token
- /// probability;Probability must greater than or equal to zero
- /// or
- /// probability;Probability must less than or equal to one
- public ConditionalProbability(IClass @class, IToken token, double probability, long occurrence)
- {
- if (ReferenceEquals(@class, null)) throw new ArgumentNullException("class");
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
- if (probability < 0) throw new ArgumentOutOfRangeException("probability", probability, "Probability must greater than or equal to zero");
- if (probability > 1) throw new ArgumentOutOfRangeException("probability", probability, "Probability must less than or equal to one");
- if (probability < 0) throw new ArgumentOutOfRangeException("occurrence", occurrence, "Occurrence must greater than or equal to zero");
-
- Class = @class;
- Token = token;
- Probability = probability;
- Occurrence = occurrence;
- }
-
- ///
- /// Determines whether the specified is equal to this instance.
- ///
- /// Another object to compare to.
- /// if the specified is equal to this instance; otherwise, .
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(obj, null)) return false;
- return obj is ConditionalProbability && Equals((ConditionalProbability) obj);
- }
-
- ///
- /// Indicates whether the current object is equal to another object of the same type.
- ///
- /// An object to compare with this object.
- /// true if the current object is equal to the parameter; otherwise, false.
- public bool Equals(ConditionalProbability other)
- {
- return Class.Equals(other.Class)
- && Token.Equals(other.Token)
- && Probability.Equals(other.Probability);
- }
-
- ///
- /// Returns a hash code for this instance.
- ///
- /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
- public override int GetHashCode()
- {
- var hash = 27;
- hash = (13 * hash) + Class.GetHashCode();
- hash = (13 * hash) + Token.GetHashCode();
- hash = (13 * hash) + Probability.GetHashCode();
- return hash;
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- /// A that represents this instance.
- public override string ToString()
- {
- return String.Format("P({0}|{1})={2:P}", Class, Token, Probability);
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/DataSet.cs b/BotSharp.Algorithm/Bayesian/DataSet.cs
deleted file mode 100644
index 91a56ac7..00000000
--- a/BotSharp.Algorithm/Bayesian/DataSet.cs
+++ /dev/null
@@ -1,358 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Class DataSet.
- ///
- [DebuggerDisplay("Data set for class P({Class.Name})={Class.Probability}")]
- public sealed class DataSet : IDataSet
- {
- ///
- /// The default smoothing alpha
- ///
- public const double DefaultSmoothingAlpha = 0D;
-
- ///
- /// The token count
- ///
- private readonly ConcurrentDictionary _tokenCount = new ConcurrentDictionary();
-
- ///
- /// The set size, i.e. the number of all tokens
- ///
- private long _setSize;
-
- ///
- /// Gets the number of distinct tokens,
- /// i.e. every token counted at exactly once.
- ///
- /// The token count.
- ///
- public long TokenCount
- {
- get { return _tokenCount.Count; }
- }
-
- ///
- /// Gets the size of the set.
- ///
- /// The size of the set.
- ///
- public long SetSize
- {
- get { return _setSize; }
- }
-
- ///
- /// Gets the class.
- ///
- /// The class.
- public IClass Class { get; private set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The class.
- /// @class
- public DataSet(IClass @class)
- {
- if (ReferenceEquals(@class, null)) throw new ArgumentNullException("class");
- Class = @class;
- }
-
- ///
- /// Gets the with the specified token.
- ///
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// TokenInformation<IToken>.
- /// token
- public TokenInformation this[IToken token, double alpha = DefaultSmoothingAlpha]
- {
- get
- {
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
-
- long count;
- if (!_tokenCount.TryGetValue(token, out count))
- {
- return new TokenInformation(token, 0L, 0D);
- }
-
- var percentage = GetPercentage(count, alpha);
- return new TokenInformation(token, count, percentage);
- }
- }
-
- ///
- /// Gets the number of occurrences of the given token.
- ///
- /// The token.
- /// System.Int64.
- ///
- public long GetCount(IToken token)
- {
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
-
- long count;
- return !_tokenCount.TryGetValue(token, out count) ? 0 : count;
- }
-
- ///
- /// Gets the approximated percentage of the given
- /// in this data set
- /// by determining its occurrence count over the whole population.
- ///
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// System.Double.
- /// token
- ///
- public double GetPercentage(IToken token, double alpha = DefaultSmoothingAlpha)
- {
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
- if (alpha < 0) throw new ArgumentOutOfRangeException("alpha", alpha, "Smoothing parameter alpha must be greater than or equal to zero.");
-
- var count = GetCount(token);
- return GetPercentage(count, alpha);
- }
-
- ///
- /// Gets the approximated percentage of the given
- /// in this data set
- /// by determining its occurrence count over the whole population.
- ///
- /// The token count.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// System.Double.
- /// token
- ///
- private double GetPercentage(long tokenCount, double alpha = DefaultSmoothingAlpha)
- {
- Debug.Assert(alpha >= 0, "alpha >= 0");
- Debug.Assert(tokenCount >= 0, "tokenCount >= 0");
-
- var totalCount = _setSize; // TODO: cache inverse set size
- var vocabularySize = TokenCount;
-
- return (double)(tokenCount + alpha)/(double)(totalCount + alpha*vocabularySize);
- }
-
- ///
- /// Adds the given tokens a single time, incrementing the
- /// and, at the first addition, the .
- ///
- /// The token.
- /// The additional tokens.
- ///
- /// token
- /// or
- /// additionalTokens
- ///
- public void AddToken(IToken token, params IToken[] additionalTokens)
- {
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
- if (ReferenceEquals(additionalTokens, null)) throw new ArgumentNullException("additionalTokens");
-
- _tokenCount.AddOrUpdate(token, AddFirsIToken, IncremenITokenCount);
- Interlocked.Increment(ref _setSize);
-
- AddToken(additionalTokens);
- }
-
- ///
- /// Adds the given tokens a single time, incrementing the
- /// and, at the first addition, the .
- ///
- /// The tokens.
- /// tokens
- public void AddToken(IEnumerable tokens)
- {
- if (ReferenceEquals(tokens, null)) throw new ArgumentNullException("tokens");
-
- foreach (var token in tokens)
- {
- _tokenCount.AddOrUpdate(token, AddFirsIToken, IncremenITokenCount);
- Interlocked.Increment(ref _setSize);
- }
- }
-
- ///
- /// Removes the given tokens a single time, decrementing the and,
- /// eventually, the .
- ///
- /// The token.
- /// The additional tokens.
- ///
- /// token
- /// or
- /// additionalTokens
- ///
- ///
- public void RemoveTokenOnce(IToken token, params IToken[] additionalTokens)
- {
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
- if (ReferenceEquals(additionalTokens, null)) throw new ArgumentNullException("additionalTokens");
-
- RemoveSingleTokenInternal(token);
- RemoveTokenOnce(additionalTokens);
- }
-
- ///
- /// Removes the given tokens a single time, decrementing the and,
- /// eventually, the .
- ///
- /// The tokens.
- /// tokens
- ///
- public void RemoveTokenOnce(IEnumerable tokens)
- {
- if (ReferenceEquals(tokens, null)) throw new ArgumentNullException("tokens");
-
- foreach (var token in tokens)
- {
- RemoveSingleTokenInternal(token);
- }
- }
-
- ///
- /// Removes the given tokens a single time, decrementing the and,
- /// eventually, the .
- ///
- /// The token.
- /// The additional tokens.
- ///
- /// token
- /// or
- /// additionalTokens
- ///
- ///
- public void PurgeToken(IToken token, params IToken[] additionalTokens)
- {
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
- if (ReferenceEquals(additionalTokens, null)) throw new ArgumentNullException("additionalTokens");
-
- PurgeTokenInternal(token);
- PurgeToken(additionalTokens);
- }
-
- ///
- /// Removes the given tokens a single time, decrementing the and,
- /// eventually, the .
- ///
- /// The tokens.
- /// tokens
- ///
- public void PurgeToken(IEnumerable tokens)
- {
- if (ReferenceEquals(tokens, null)) throw new ArgumentNullException("tokens");
-
- foreach (var token in tokens)
- {
- PurgeTokenInternal(token);
- }
- }
-
- ///
- /// Purges the tokens fulfilling the given predicate.
- ///
- /// The predicate.
- public void PurgeWhere(Predicate predicate)
- {
- var candidateForPurge = from pair in _tokenCount
- let tokenCount = new TokenCount(pair.Key, pair.Value)
- where predicate(tokenCount)
- select pair.Key;
- PurgeToken(candidateForPurge);
- }
-
- ///
- /// Removes the single token internally.
- ///
- /// The token.
- private void RemoveSingleTokenInternal(IToken token)
- {
- long count;
- while (_tokenCount.TryGetValue(token, out count))
- {
- var newValue = count - 1;
- var collectionUpdated = _tokenCount.TryUpdate(token, newValue: newValue, comparisonValue: count);
- if (!collectionUpdated) continue;
- Interlocked.Decrement(ref _setSize);
-
- if (newValue == 0)
- {
- // explicit removal if the count is zero
- var collection = _tokenCount as ICollection>;
- collection.Remove(new KeyValuePair(token, 0));
- }
-
- break;
- }
- }
-
- ///
- /// Purges a single token internally.
- ///
- /// The token.
- private void PurgeTokenInternal(IToken token)
- {
- long count;
- if (!_tokenCount.TryRemove(token, out count)) return;
-
- // decrement 'count' times
- // TODO: use Interlocked.CompareExchange
- for (int i = 0; i < count; ++i)
- {
- Interlocked.Decrement(ref _setSize);
- }
- }
-
- ///
- /// Factory to initialize the value in for the given .
- ///
- /// The token.
- /// System.Int64.
- private static long AddFirsIToken(IToken token)
- {
- return 1;
- }
-
- ///
- /// Factory to increment the value in for the given .
- ///
- /// The token.
- /// The number of tokens.
- /// System.Int64.
- private static long IncremenITokenCount(IToken token, long count)
- {
- return count + 1;
- }
-
- ///
- /// Returns an enumerator that iterates through the collection.
- ///
- /// A that can be used to iterate through the collection.
- public IEnumerator GetEnumerator()
- {
- return _tokenCount.Select(token => new TokenCount(token.Key, token.Value)).GetEnumerator();
- }
-
- ///
- /// Returns an enumerator that iterates through a collection.
- ///
- /// An object that can be used to iterate through the collection.
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/EmptyDataSet.cs b/BotSharp.Algorithm/Bayesian/EmptyDataSet.cs
deleted file mode 100644
index a9a2690d..00000000
--- a/BotSharp.Algorithm/Bayesian/EmptyDataSet.cs
+++ /dev/null
@@ -1,148 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Class EmptyDataSet. This class cannot be inherited.
- ///
- internal sealed class EmptyDataSet : IDataSet
- {
- ///
- /// Returns an enumerator that iterates through the collection.
- ///
- /// A that can be used to iterate through the collection.
- public IEnumerator GetEnumerator()
- {
- yield break;
- }
-
- ///
- /// Returns an enumerator that iterates through a collection.
- ///
- /// An object that can be used to iterate through the collection.
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- ///
- /// Gets the token count.
- ///
- /// The token count.
- public long TokenCount { get { return 0; } }
-
- ///
- /// Gets the size of the set.
- ///
- /// The size of the set.
- public long SetSize { get { return 0; } }
-
- ///
- /// Gets the class.
- ///
- /// The class.
- public IClass Class { get; private set; }
-
- ///
- /// Gets the with the specified token.
- ///
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// TokenInformation<IToken>.
- public TokenInformation this[IToken token, double alpha = 0D]
- {
- get { return new TokenInformation(token, 0L, 0D); }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The class.
- /// class
- public EmptyDataSet(IClass @class)
- {
- if (ReferenceEquals(null, @class)) throw new ArgumentNullException("class");
- Class = @class;
- }
-
- ///
- /// Gets the count.
- ///
- /// The token.
- /// System.Int64.
- public long GetCount(IToken token)
- {
- return 0L;
- }
-
- ///
- /// Gets the percentage.
- ///
- /// The token.
- /// The alpha.
- /// System.Double.
- ///
- public double GetPercentage(IToken token, double alpha = 0)
- {
- return 0D;
- }
-
- ///
- /// Adds the token.
- ///
- /// The token.
- /// The additional tokens.
- /// Adding data to the empty data set is not allowed.
- public void AddToken(IToken token, params IToken[] additionalTokens)
- {
- throw new InvalidOperationException("Adding data to the empty data set is not allowed.");
- }
-
- ///
- /// Adds the token.
- ///
- /// The tokens.
- /// Adding data to the empty data set is not allowed.
- public void AddToken(IEnumerable tokens)
- {
- throw new InvalidOperationException("Adding data to the empty data set is not allowed.");
- }
-
- ///
- /// Removes the token once.
- ///
- /// The token.
- /// The additional tokens.
- public void RemoveTokenOnce(IToken token, params IToken[] additionalTokens)
- {
- }
-
- ///
- /// Removes the token once.
- ///
- /// The tokens.
- public void RemoveTokenOnce(IEnumerable tokens)
- {
- }
-
- ///
- /// Purges the token.
- ///
- /// The token.
- /// The additional tokens.
- public void PurgeToken(IToken token, params IToken[] additionalTokens)
- {
- }
-
- ///
- /// Purges the token.
- ///
- /// The tokens.
- public void PurgeToken(IEnumerable tokens)
- {
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/IClass.cs b/BotSharp.Algorithm/Bayesian/IClass.cs
deleted file mode 100644
index e0d9c0fd..00000000
--- a/BotSharp.Algorithm/Bayesian/IClass.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-using System.ComponentModel;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Interface IClass
- ///
- public interface IClass : IEquatable
- {
- ///
- /// Gets the name.
- ///
- /// The name.
- string Name { get; }
-
- ///
- /// Gets or sets the class' base probability.
- ///
- /// The probability.
- [DefaultValue(1)]
- double Probability { get; set; }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/IClassifier.cs b/BotSharp.Algorithm/Bayesian/IClassifier.cs
deleted file mode 100644
index f1a2fa79..00000000
--- a/BotSharp.Algorithm/Bayesian/IClassifier.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Interface IClassifier
- ///
- public interface IClassifier
- {
- ///
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- ///
- /// Laplace smoothing is required in the context or rare (i.e. untrained) tokens or tokens
- /// that do not appear in some classes. With smoothing disabled, these tokens result
- /// in a zero probability for the whole class. To counter that, a positive ("alpha")
- /// value for smoothing can be set.
- ///
- ///
- double SmoothingAlpha { get; set; }
-
- ///
- /// Calculates the probability of having the
- /// given the occurrence of the .
- ///
- /// The class under test.
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied, setting to defaults to the values set in .
- /// System.Double.
- double CalculateProbability(IClass classUnderTest, IToken token, double? alpha = null);
-
- ///
- /// Calculates the probability of having the
- ///
- /// given the occurrence of the
- /// .
- ///
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied, setting to defaults to the values set in .
- /// System.Double.
- IEnumerable CalculateProbabilities(IToken token, double? alpha = null);
-
- ///
- /// Calculates the probability of having the
- ///
- /// given the occurrence of the
- /// .
- ///
- /// The tokens.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied, setting to defaults to the values set in .
- /// System.Double.
- IEnumerable CalculateProbabilities(ICollection tokens, double? alpha = null);
- }
-}
\ No newline at end of file
diff --git a/BotSharp.Algorithm/Bayesian/IDataSet.cs b/BotSharp.Algorithm/Bayesian/IDataSet.cs
deleted file mode 100644
index f9118c50..00000000
--- a/BotSharp.Algorithm/Bayesian/IDataSet.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Interface IDataSet
- ///
- public interface IDataSet : IDataSetAccessor, ITokenRegistration
- {
- }
-}
\ No newline at end of file
diff --git a/BotSharp.Algorithm/Bayesian/IDataSetAccessor.cs b/BotSharp.Algorithm/Bayesian/IDataSetAccessor.cs
deleted file mode 100644
index 3278bb60..00000000
--- a/BotSharp.Algorithm/Bayesian/IDataSetAccessor.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Interface IDataSetAccessor
- ///
- public interface IDataSetAccessor : IEnumerable
- {
- ///
- /// Gets the number of distinct tokens,
- /// i.e. every token counted at exactly once.
- ///
- /// The token count.
- ///
- long TokenCount { get; }
-
- ///
- /// Gets the size of the set.
- ///
- /// The size of the set.
- ///
- long SetSize { get; }
-
- ///
- /// Gets the class.
- ///
- /// The class.
- IClass Class { get; }
-
- ///
- /// Gets the with the specified token.
- ///
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// TokenInformation<IToken>.
- /// token
- TokenInformation this[IToken token, double alpha] { get; }
-
- ///
- /// Gets the number of occurrences of the given token.
- ///
- /// The token.
- /// System.Int64.
- /// token
- ///
- long GetCount(IToken token);
-
- ///
- /// Gets the approximated percentage of the given
- /// in this data set
- /// by determining its occurrence count over the whole population.
- ///
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// System.Double.
- /// token
- ///
- double GetPercentage(IToken token, double alpha);
- }
-}
\ No newline at end of file
diff --git a/BotSharp.Algorithm/Bayesian/IToken.cs b/BotSharp.Algorithm/Bayesian/IToken.cs
deleted file mode 100644
index 165191ab..00000000
--- a/BotSharp.Algorithm/Bayesian/IToken.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Interface IToken
- ///
- public interface IToken : IEquatable
- {
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/ITokenRegistration.cs b/BotSharp.Algorithm/Bayesian/ITokenRegistration.cs
deleted file mode 100644
index bf2e53d9..00000000
--- a/BotSharp.Algorithm/Bayesian/ITokenRegistration.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System.Collections.Generic;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Interface ITokenRegistration
- ///
- public interface ITokenRegistration
- {
- ///
- /// Adds the given tokens a single time, incrementing the
- /// and, at the first addition, the .
- ///
- /// The token.
- /// The additional tokens.
- ///
- /// token
- /// or
- /// additionalTokens
- ///
- void AddToken(IToken token, params IToken[] additionalTokens);
-
- ///
- /// Adds the given tokens a single time, incrementing the
- /// and, at the first addition, the .
- ///
- /// The tokens.
- /// tokens
- void AddToken(IEnumerable tokens);
-
- ///
- /// Removes the given tokens a single time, decrementing the and,
- /// eventually, the .
- ///
- /// The token.
- /// The additional tokens.
- ///
- /// token
- /// or
- /// additionalTokens
- ///
- ///
- void RemoveTokenOnce(IToken token, params IToken[] additionalTokens);
-
- ///
- /// Removes the given tokens a single time, decrementing the and,
- /// eventually, the .
- ///
- /// The tokens.
- /// tokens
- ///
- void RemoveTokenOnce(IEnumerable tokens);
-
- ///
- /// Removes the given tokens a single time, decrementing the and,
- /// eventually, the .
- ///
- /// The token.
- /// The additional tokens.
- ///
- /// token
- /// or
- /// additionalTokens
- ///
- ///
- void PurgeToken(IToken token, params IToken[] additionalTokens);
-
- ///
- /// Removes the given tokens a single time, decrementing the and,
- /// eventually, the .
- ///
- /// The tokens.
- /// tokens
- ///
- void PurgeToken(IEnumerable tokens);
- }
-}
\ No newline at end of file
diff --git a/BotSharp.Algorithm/Bayesian/ITrainingSet.cs b/BotSharp.Algorithm/Bayesian/ITrainingSet.cs
deleted file mode 100644
index dd6b0353..00000000
--- a/BotSharp.Algorithm/Bayesian/ITrainingSet.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Collections.Generic;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Interface ITrainingSet
- ///
- public interface ITrainingSet : ITrainingSetAccessor
- {
- ///
- /// Adds the specified data set.
- ///
- /// The data set.
- /// The additional data sets.
- /// dataSet
- /// A data set for a given class was already registered.
- void Add(IDataSet dataSet, params IDataSet[] additionalDataSets);
-
- ///
- /// Adds the specified data sets.
- ///
- /// The data sets.
- /// dataSets
- /// A data set for a given class was already registered.
- void Add(IEnumerable dataSets);
- }
-}
\ No newline at end of file
diff --git a/BotSharp.Algorithm/Bayesian/ITrainingSetAccessor.cs b/BotSharp.Algorithm/Bayesian/ITrainingSetAccessor.cs
deleted file mode 100644
index 3eebfe42..00000000
--- a/BotSharp.Algorithm/Bayesian/ITrainingSetAccessor.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Collections.Generic;
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Interface ITrainingSetAccerssor
- ///
- public interface ITrainingSetAccessor : IEnumerable
- {
- ///
- /// Gets the with the specified class.
- ///
- /// The class.
- /// IDataSet<TClass, TToken>.
- /// No data set was registered for the given class;class
- IDataSet this[IClass @class] { get; }
- }
-}
\ No newline at end of file
diff --git a/BotSharp.Algorithm/Bayesian/LinqExtensions.cs b/BotSharp.Algorithm/Bayesian/LinqExtensions.cs
deleted file mode 100644
index d97440ac..00000000
--- a/BotSharp.Algorithm/Bayesian/LinqExtensions.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Reflection;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- internal static class LinqExtensions
- {
- ///
- /// Converts an enumerable to a collection
- ///
- ///
- /// The enumerable.
- /// ICollection<T>.
- public static ICollection ToCollection(this IEnumerable enumerable)
- {
- var type = enumerable.GetType();
- if (type.IsGenericCollectionType()) return (ICollection)enumerable;
-
- var collection = new Collection();
- foreach (var t in enumerable)
- {
- collection.Add(t);
- }
- return collection;
- }
-
- ///
- /// Forces evaluation of the enumerable
- ///
- ///
- /// The enumerable.
- public static void Run(this IEnumerable enumerable)
- {
- var type = enumerable.GetType();
- if (type.IsGenericCollectionType()) return;
-
- foreach (var item in enumerable)
- {
- }
- }
-
- ///
- /// The cache for
- ///
- private static readonly ConcurrentDictionary IsGenericCollectionTypeCache = new ConcurrentDictionary();
-
- ///
- /// Determines whether the specified type is a (generic) collection.
- ///
- /// The type.
- /// true if the specified type is collection; otherwise, false.
- public static bool IsGenericCollectionType(this Type type)
- {
- return IsGenericCollectionTypeCache.GetOrAdd(type, t => type.GetInterfaces()
- .Any(ti => ti.IsGenericType
- &&
- ti.GetGenericTypeDefinition() ==
- typeof (ICollection<>)));
-
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/NaiveClassifier.cs b/BotSharp.Algorithm/Bayesian/NaiveClassifier.cs
deleted file mode 100644
index f045503d..00000000
--- a/BotSharp.Algorithm/Bayesian/NaiveClassifier.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Linq;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Class NaiveClassifier. This class cannot be inherited.
- ///
- /// Assumes that all token occurrences are statistically independent.
- ///
- ///
- public sealed class NaiveClassifier : IClassifier
- {
- ///
- /// The training sets
- ///
- private readonly ITrainingSetAccessor _trainingSets;
-
- ///
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- ///
- private double _smoothingAlpha = 0.01D;
-
- ///
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- ///
- [DefaultValue(0.01D)]
- public double SmoothingAlpha
- {
- get { return _smoothingAlpha; }
- set
- {
- if (value <= 0) throw new ArgumentOutOfRangeException("value", value, "Value must be greater than zero.");
- _smoothingAlpha = value;
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The training sets.
- /// trainingSets
- public NaiveClassifier(ITrainingSetAccessor trainingSets)
- {
- if (ReferenceEquals(trainingSets, null)) throw new ArgumentNullException("trainingSets");
- _trainingSets = trainingSets;
- }
-
- ///
- /// Calculates the probability of having the
- /// given the occurrence of the .
- ///
- /// The class under test.
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// System.Double.
- public double CalculateProbability(IClass classUnderTest, IToken token, double? alpha = null)
- {
- var smoothingAlpha = alpha ?? _smoothingAlpha;
-
- ICollection remainingSets;
- var setForClassUnderTest = SplitDataSets(classUnderTest, out remainingSets);
-
- // calculate the token's probability in the class under test
- var percentageInClassUnderTest = setForClassUnderTest.GetPercentage(token, smoothingAlpha);
- var probabilityInClassUnderTest = percentageInClassUnderTest * classUnderTest.Probability;
-
- // calculate the token's probabilities for the remaining classes
- double sumOfRemainingProbabilites;
- CalculateTokenProbabilityGivenClass(token, remainingSets, out sumOfRemainingProbabilites, smoothingAlpha).Run();
-
- // calculate total probability
- var totalProbability = probabilityInClassUnderTest + sumOfRemainingProbabilites;
-
- // calculate the class' probability given the token
- var probabilityForClass = probabilityInClassUnderTest/totalProbability;
-
- // correct for rare words
- return probabilityForClass;
- }
-
- ///
- /// Calculates the probability of having the
- ///
- /// given the occurrence of the
- /// .
- ///
- /// The token.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// System.Double.
- public IEnumerable CalculateProbabilities(IToken token, double? alpha = null)
- {
- var smoothingAlpha = alpha ?? _smoothingAlpha;
-
- // calculate the token's probabilities for all classes
- double totalProbability;
- var probabilities = CalculateTokenProbabilityGivenClass(token, _trainingSets, out totalProbability, smoothingAlpha);
-
- // apply Bayes theorem
- var inverseOfTotalProbability = 1.0D/totalProbability;
- return from cp in probabilities
- let conditionalProbability = cp.Probability * inverseOfTotalProbability
- select new ConditionalProbability(cp.Class, cp.Token, conditionalProbability, cp.Occurrence);
- }
-
- ///
- /// Calculates the probability of having the
- ///
- /// given the occurrence of the
- /// .
- ///
- /// The tokens.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// System.Double.
- public IEnumerable CalculateProbabilities(ICollection tokens, double? alpha = null)
- {
- var smoothingAlpha = alpha ?? _smoothingAlpha;
-
- var cpgs = tokens
- .SelectMany(token => CalculateProbabilities(token, smoothingAlpha))
- .GroupBy(cp => cp.Class)
- .ToCollection();
-
- return from @group in cpgs
- let cps = @group.ToCollection()
- let eta = cps.Select(cp => cp.Probability)
- .Sum(p => Math.Log(1 - p) - Math.Log(p))
- let probability = 1/(1 + Math.Exp(eta))
- select new CombinedConditionalProbability(@group.Key, probability, cps);
- }
-
- ///
- /// Calculates the token probabilities given a class.
- ///
- /// The token.
- /// The sets.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// IEnumerable<ConditionalProbability<IClass, IToken>>.
- private IEnumerable CalculateTokenProbabilityGivenClass(IToken token, IEnumerable sets, double alpha)
- {
- return from set in sets
- let @class = set.Class
- let classProbability = @class.Probability
- let percentageInClass = set.GetPercentage(token, alpha)
- let countInClass = set.GetCount(token)
- let probabilityInClass = percentageInClass*classProbability
- select new ConditionalProbability(@class, token, probabilityInClass, countInClass);
- }
-
- ///
- /// Calculates the token probabilities given a class.
- ///
- /// The token.
- /// The sets.
- /// Additive smoothing parameter. If set to zero, no Laplace smoothing will be applied.
- /// The total probability for the given classes.
- /// IEnumerable<ConditionalProbability<IClass, IToken>>.
- private IEnumerable CalculateTokenProbabilityGivenClass(IToken token, IEnumerable sets, out double totalProbability, double alpha)
- {
- var probabilities = CalculateTokenProbabilityGivenClass(token, sets, alpha).ToCollection();
- totalProbability = probabilities.Sum(p => p.Probability);
- return probabilities;
- }
-
- ///
- /// Splits the data sets.
- ///
- /// The class under test.
- /// The remaining sets.
- /// IDataSet<IClass, IToken>.
- private IDataSetAccessor SplitDataSets(IClass classUnderTest, out ICollection remainingSets)
- {
- IDataSet setForClassUnderTest = null;
- remainingSets = new Collection();
-
- // split data sets by selected class and other classes
- foreach (var trainingSet in _trainingSets)
- {
- // select the set for the class under test
- if (trainingSet.Class.Equals(classUnderTest))
- {
- Debug.Assert(setForClassUnderTest == null,
- "The class under test must not have multiple sets registered in the DataSet");
- setForClassUnderTest = trainingSet;
- continue;
- }
-
- // select remaining sets
- remainingSets.Add(trainingSet);
- }
-
- // return the found set or an empty set
- return setForClassUnderTest ?? new EmptyDataSet(classUnderTest);
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/StringClass.cs b/BotSharp.Algorithm/Bayesian/StringClass.cs
deleted file mode 100644
index 7f0b9fa1..00000000
--- a/BotSharp.Algorithm/Bayesian/StringClass.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-using System;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Class StringClass. This class cannot be inherited.
- ///
- public sealed class StringClass : ClassBase
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The name.
- /// The probability.
- /// name
- ///
- /// probability;Class base probability must be greater than or equal to zero.
- /// or
- /// probability;Class base probability must be less than or equal to one.
- ///
- public StringClass(string name, double probability)
- : base(name, probability)
- {
- }
-
- ///
- /// Determines whether the specified is equal to this instance.
- ///
- /// The to compare with the current .
- /// if the specified is equal to this instance; otherwise, .
- public override bool Equals(IClass other)
- {
- var otherAsObject = (object) other;
- return Equals(otherAsObject);
- }
-
- ///
- /// Determines whether the specified is equal to this instance.
- ///
- /// The to compare with the current .
- /// if the specified is equal to this instance; otherwise, .
- private bool Equals(StringClass other)
- {
- if (ReferenceEquals(other, null)) return false;
- if (ReferenceEquals(other, this)) return true;
- return String.Equals(Name, other.Name)
- && Math.Abs(Probability - other.Probability) < 0.0001D;
- }
-
- ///
- /// Determines whether the specified is equal to this instance.
- ///
- /// The to compare with the current .
- /// if the specified is equal to this instance; otherwise, .
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- return obj is StringClass && Equals((StringClass) obj);
- }
-
- ///
- /// Returns a hash code for this instance.
- ///
- /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
- public override int GetHashCode()
- {
- var hash = 27;
- hash = (13 * hash) + Name.GetHashCode();
- hash = (13 * hash) + Probability.GetHashCode();
- return hash;
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- /// A that represents this instance.
- public override string ToString()
- {
- return Name;
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/StringToken.cs b/BotSharp.Algorithm/Bayesian/StringToken.cs
deleted file mode 100644
index 6f19633c..00000000
--- a/BotSharp.Algorithm/Bayesian/StringToken.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using System;
-using System.Diagnostics;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Class StringToken. This class cannot be inherited.
- ///
- [DebuggerDisplay("{Value}")]
- public sealed class StringToken : IToken
- {
- ///
- /// Gets the value.
- ///
- /// The value.
- public string Value { get; private set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The value.
- public StringToken(string value)
- {
- if (ReferenceEquals(value, null)) throw new ArgumentNullException("value");
- Value = value;
- }
-
- ///
- /// Determines whether the specified is equal to this instance.
- ///
- /// The to compare with the current .
- /// if the specified is equal to this instance; otherwise, .
- private bool Equals(StringToken other)
- {
- return string.Equals(Value, other.Value);
- }
-
- ///
- /// Determines whether the specified is equal to this instance.
- ///
- /// The to compare with the current .
- /// if the specified is equal to this instance; otherwise, .
- bool IEquatable.Equals(IToken other)
- {
- var otherAsObject = (object)other;
- return Equals(otherAsObject);
- }
-
- ///
- /// Determines whether the specified is equal to this instance.
- ///
- /// The to compare with the current .
- /// if the specified is equal to this instance; otherwise, .
- public override bool Equals(object obj)
- {
- // ReSharper disable once ConditionIsAlwaysTrueOrFalse
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- return obj is StringToken && Equals((StringToken) obj);
- }
-
- ///
- /// Returns a hash code for this instance.
- ///
- /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
- public override int GetHashCode()
- {
- return Value.GetHashCode();
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- /// A that represents this instance.
- public override string ToString()
- {
- return Value;
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/TokenCount.cs b/BotSharp.Algorithm/Bayesian/TokenCount.cs
deleted file mode 100644
index bc72d351..00000000
--- a/BotSharp.Algorithm/Bayesian/TokenCount.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Struct TokenCount
- ///
- public struct TokenCount
- {
- ///
- /// The token
- ///
- public readonly IToken Token;
-
- ///
- /// The number of occurrences
- ///
- public readonly long Count;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The token.
- /// The count.
- /// token
- /// count;Count must be positive or zero.
- public TokenCount(IToken token, long count)
- {
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
- if (count < 0) throw new ArgumentOutOfRangeException("count", count, "Count must be positive or zero.");
-
- Token = token;
- Count = count;
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/TokenInformation.cs b/BotSharp.Algorithm/Bayesian/TokenInformation.cs
deleted file mode 100644
index 44fbad95..00000000
--- a/BotSharp.Algorithm/Bayesian/TokenInformation.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Struct TokenInformation
- ///
- public struct TokenInformation
- where TToken: IToken
- {
- ///
- /// The token
- ///
- public readonly TToken Token;
-
- ///
- /// The count in the class
- ///
- public long Count;
-
- ///
- /// The occurrence percentage of the token in the class.
- ///
- public double Percentage;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The token.
- /// The count.
- /// The percentage.
- /// token
- ///
- /// count;Count must be positive or zero
- /// or
- /// percentage;Percentage must be positive or zero
- ///
- public TokenInformation(TToken token, long count, double percentage)
- {
- if (ReferenceEquals(token, null)) throw new ArgumentNullException("token");
- if (count < 0) throw new ArgumentOutOfRangeException("count", count, "Count must be positive or zero");
- if (percentage < 0) throw new ArgumentOutOfRangeException("percentage", percentage, "Percentage must be positive or zero");
-
- Token = token;
- Count = count;
- Percentage = percentage;
- }
- }
-}
diff --git a/BotSharp.Algorithm/Bayesian/TrainingSet.cs b/BotSharp.Algorithm/Bayesian/TrainingSet.cs
deleted file mode 100644
index 8d9984fc..00000000
--- a/BotSharp.Algorithm/Bayesian/TrainingSet.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-
-
-namespace BotSharp.Algorithm.Bayesian
-{
- ///
- /// Class TrainingSet. This class cannot be inherited.
- ///
- public sealed class TrainingSet : ITrainingSet
- {
- ///
- /// The data sets
- ///
- private readonly ConcurrentDictionary _dataSets = new ConcurrentDictionary();
-
- ///
- /// Initializes a new instance of the class.
- ///
- public TrainingSet()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The data sets.
- public TrainingSet(IEnumerable dataSets)
- {
- Add(dataSets);
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The data set.
- /// The additional data sets.
- public TrainingSet(IDataSet dataSet, params IDataSet[] additionalDataSets)
- {
- Add(dataSet, additionalDataSets);
- }
-
- ///
- /// Gets the with the specified class.
- ///
- /// The class.
- /// IDataSet<IClass, IToken>.
- /// No data set was registered for the given class;class
- public IDataSet this[IClass @class]
- {
- get
- {
- IDataSet set;
- if (_dataSets.TryGetValue(@class, out set)) return set;
- throw new ArgumentException("No data set was registered for the given class", "class");
- }
- }
-
- ///
- /// Adds the specified data set.
- ///
- /// The data set.
- /// The additional data sets.
- /// dataSet
- /// A data set for a given class was already registered.
- public void Add(IDataSet dataSet, params IDataSet[] additionalDataSets)
- {
- if (ReferenceEquals(dataSet, null)) throw new ArgumentNullException("dataSet");
-
- try
- {
- AddInternal(dataSet);
- }
- catch (ArgumentException e)
- {
- throw new ArgumentException("A data set for a given class was already registered.", e);
- }
-
- // may throw, that's anticipated
- Add(additionalDataSets);
- }
-
- ///
- /// Adds the specified data sets.
- ///
- /// The data sets.
- /// dataSets
- /// A data set for a given class was already registered.
- public void Add(IEnumerable dataSets)
- {
- if (ReferenceEquals(dataSets, null)) throw new ArgumentNullException("dataSets");
-
- try
- {
- foreach (var dataSet in dataSets)
- {
- AddInternal(dataSet);
- }
- }
- catch (ArgumentException e)
- {
- throw new ArgumentException("A data set for a given class was already registered.", e);
- }
- }
-
-
- ///
- /// Adds the data set internally.
- ///
- /// The data set.
- /// Data set for the given class was already registered.
- private void AddInternal(IDataSet dataSet)
- {
- if (!_dataSets.TryAdd(dataSet.Class, dataSet))
- {
- throw new ArgumentException("Data set for the given class was already registered.");
- }
- }
-
- ///
- /// Returns an enumerator that iterates through the collection.
- ///
- /// A that can be used to iterate through the collection.
- public IEnumerator GetEnumerator()
- {
- return _dataSets.Select(dataSet => dataSet.Value).GetEnumerator();
- }
-
- ///
- /// Returns an enumerator that iterates through a collection.
- ///
- /// An object that can be used to iterate through the collection.
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
-}
diff --git a/BotSharp.Core/Engines/BotSharp/BotSharpSVMClassifier.cs b/BotSharp.Core/Engines/BotSharp/BotSharpSVMClassifier.cs
index d0dfcd34..b7dcc0ac 100644
--- a/BotSharp.Core/Engines/BotSharp/BotSharpSVMClassifier.cs
+++ b/BotSharp.Core/Engines/BotSharp/BotSharpSVMClassifier.cs
@@ -1,4 +1,5 @@
-using BotSharp.Core.Abstractions;
+using BotSharp.Algorithm.Bayes;
+using BotSharp.Core.Abstractions;
using BotSharp.Core.Agents;
using BotSharp.NLP.Classify;
using DotNetToolkit;
@@ -29,10 +30,10 @@ namespace BotSharp.Core.Engines.BotSharp
string predictFileName = Path.Combine(Settings.TempDir, "svm-predict-tempfile.txt");
File.WriteAllText(predictFileName, doc.Sentences[0].Text);
- NLP.Classify.SVMClassifier svmClassifier = new NLP.Classify.SVMClassifier();
+ var svmClassifier = new NLP.Classify.SVMClassifier();
Args args = new Args();
args.ModelFile = Path.Combine(Configuration.GetValue("BotSharpSVMClassifier:wordvec"), "wordvec_enu.bin");
- LabeledFeatureSet featureSet = svmClassifier.FeatureSetsGenerator(new VectorGenerator(args).SingleSentence2Vec(doc.Sentences[0].Text), "");
+ var featureSet = svmClassifier.FeatureSetsGenerator(new VectorGenerator(args).SingleSentence2Vec(doc.Sentences[0].Text), "");
/*
//
var client = new RestClient("http://10.2.21.200:5005");
diff --git a/BotSharp.NLP.UnitTest/NaiveBayesClassifierTest.cs b/BotSharp.NLP.UnitTest/NaiveBayesClassifierTest.cs
index 44979a00..8c16a8e1 100644
--- a/BotSharp.NLP.UnitTest/NaiveBayesClassifierTest.cs
+++ b/BotSharp.NLP.UnitTest/NaiveBayesClassifierTest.cs
@@ -69,9 +69,10 @@ namespace BotSharp.NLP.UnitTest
corpus.ForEach(x => x.Words = tokenizer.Tokenize(x.Text));
- // classifier.Train(corpus);
- // string text = "Bridget";
- // classifier.Classify(new Sentence { Text = text, Words = tokenizer.Tokenize(text) });
+ classifier.Train(corpus);
+ string text = "Bridget";
+ classifier.Classify(new Sentence { Text = text, Words = tokenizer.Tokenize(text) });
+
corpus.Shuffle();
var trainingData = corpus.Skip(2000).ToList();
classifier.Train(trainingData);
diff --git a/BotSharp.NLP/Classify/ClassifierFactory.cs b/BotSharp.NLP/Classify/ClassifierFactory.cs
index 24df05e2..4cf2247a 100644
--- a/BotSharp.NLP/Classify/ClassifierFactory.cs
+++ b/BotSharp.NLP/Classify/ClassifierFactory.cs
@@ -1,4 +1,5 @@
-using BotSharp.NLP.Corpus;
+using BotSharp.Algorithm.Bayes;
+using BotSharp.NLP.Corpus;
using BotSharp.NLP.Tokenize;
using System;
using System.Collections.Generic;
diff --git a/BotSharp.NLP/Classify/IClassifier.cs b/BotSharp.NLP/Classify/IClassifier.cs
index fc72882e..833a2732 100644
--- a/BotSharp.NLP/Classify/IClassifier.cs
+++ b/BotSharp.NLP/Classify/IClassifier.cs
@@ -1,4 +1,5 @@
-using System;
+using BotSharp.Algorithm.Bayes;
+using System;
using System.Collections.Generic;
using System.Text;
diff --git a/BotSharp.NLP/Classify/NaiveBayesClassifier.cs b/BotSharp.NLP/Classify/NaiveBayesClassifier.cs
index a565cb99..afbb51d1 100644
--- a/BotSharp.NLP/Classify/NaiveBayesClassifier.cs
+++ b/BotSharp.NLP/Classify/NaiveBayesClassifier.cs
@@ -17,6 +17,7 @@
*/
using BotSharp.Algorithm;
+using BotSharp.Algorithm.Bayes;
using BotSharp.Algorithm.Extensions;
using BotSharp.Algorithm.Formulas;
using System;
@@ -33,8 +34,6 @@ namespace BotSharp.NLP.Classify
/// This technique works well for topic classification;
/// say we have a set of academic papers, and we want to classify them into different topics (computer science, biology, mathematics).
/// Naive Bayes is best for Less training data
- /// P(X, Y) = P(Y|X)P(X) = P(X|Y)P(Y) => P(Y|X) = P(Y)P(X|Y)/P(X)
- /// Y is label, X is features.
///
public class NaiveBayesClassifier : IClassifier
{
@@ -95,19 +94,14 @@ namespace BotSharp.NLP.Classify
public List> Classify(LabeledFeatureSet featureSet, ClassifyOptions options)
{
- var estimator = new Lidstone();
+ var nb = new NaiveBayes();
+ nb.LabelDist = labelDist;
+ nb.FeatureDist = featureDist;
labelDist.ForEach(lf =>
{
// prior probability
- lf.Prob = estimator.Log2Prob(labelDist, lf.Value);
-
- // post probability P(X1,...,Xn|Y) = Sum(P(X1|Y) +...+ P(Xn|Y)
- featureSet.Features.ForEach(f =>
- {
- var fv = featureDist.Find(x => x.Label == lf.Value && x.FeatureName == f.Name).FeatureValues;
- lf.Prob += estimator.Log2Prob(fv, f.Value);
- });
+ lf.Prob = nb.PosteriorProb(lf.Value, featureSet);
});
// add log
@@ -129,54 +123,4 @@ namespace BotSharp.NLP.Classify
return labelDist.Select(x => new Tuple(x.Value, x.Prob)).ToList();
}
}
-
- public class LabeledFeatureSet
- {
- public List Features { get; set; }
- public string Label { get; set; }
- public LabeledFeatureSet()
- {
- this.Features = new List();
- }
- }
-
- 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 FeatureProbabilityDistribution
- {
- public string Label { get; set; }
-
- public string FeatureName { get; set; }
-
- public int Count { get; set; }
-
- public override string ToString()
- {
- return $"{Label} {FeatureName} {Count}";
- }
- }
-
- public class FeatureFrequencyDistribution
- {
- public string Label { get; set; }
-
- public string FeatureName { get; set; }
-
- public List FeatureValues { get; set; }
-
- public override string ToString()
- {
- return $"{Label} {FeatureName} {FeatureValues.Count}";
- }
- }
}
diff --git a/BotSharp.NLP/Classify/SVMClassifier.cs b/BotSharp.NLP/Classify/SVMClassifier.cs
index 6ab2c8ff..26bd1dd4 100644
--- a/BotSharp.NLP/Classify/SVMClassifier.cs
+++ b/BotSharp.NLP/Classify/SVMClassifier.cs
@@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
+using BotSharp.Algorithm.Bayes;
using SVM.BotSharp.MachineLearning;
using Txt2Vec;