diff --git a/src/DynAI.sln b/src/DynAI.sln new file mode 100644 index 0000000..ba08782 --- /dev/null +++ b/src/DynAI.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.16 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynAI", "DynAI\MachineLearning.csproj", "{5990DC45-28B6-4E1E-B3EA-C6549EE270F7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5990DC45-28B6-4E1E-B3EA-C6549EE270F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5990DC45-28B6-4E1E-B3EA-C6549EE270F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5990DC45-28B6-4E1E-B3EA-C6549EE270F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5990DC45-28B6-4E1E-B3EA-C6549EE270F7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/DynAI/MachineLearning.cs b/src/DynAI/MachineLearning.cs new file mode 100644 index 0000000..463e740 --- /dev/null +++ b/src/DynAI/MachineLearning.cs @@ -0,0 +1,201 @@ +using Accord.MachineLearning.Bayes; +using Accord.Math; +using Accord.Math.Random; +using Accord.Statistics.Filters; +using Accord.Statistics.Models.Regression.Linear; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AI.MachineLearning +{ + #region Linear Regression + + /// + /// Class providing support for linear regression ML algorithms + /// + public class LinearRegression + { + #region public properties + // dataset + public double[] inputs { get; private set; } + public double[] outputs { get; private set; } + public double testValue { get; private set; } + + // regression + public SimpleLinearRegression regression { get; private set; } + public OrdinaryLeastSquares ols; + + // state & result + public bool learned { get; private set; } + public double result { get; private set; } + #endregion + + /// + /// Constructs a new LinearRegression machine. + /// + public LinearRegression(List inputList, List outputList) + { + // validation + if (inputList == null || outputList == null) throw new ArgumentNullException("Neither the input list nor the output list can be NULL"); + + // initialise seed value + Generator.Seed = new Random().Next(); + + // process input and output lists into arrays + inputs = inputList.ToArray(); + outputs = outputList.ToArray(); + + // set up linear regression using OLS + regression = new SimpleLinearRegression(); + ols = new OrdinaryLeastSquares(); + + // nulls + testValue = new double(); + result = new double(); + this.learned = false; + } + + /// + /// Use the object's inputs and outputs to learn the model of the linear regression, using OrdinaryLeastSquares + /// + public LinearRegression Learn() + { + regression = this.ols.Learn(inputs, outputs); + learned = true; + + return this; + } + + /// + /// Using the learned model, predict an output for the specified input + /// + /// The value to use as input for the prediction + /// The predicted value + public double Predict(double test) + { + // don't predict if we haven't learned the model yet + if (this.learned != true) throw new Exception("Cannot predict before the machine has learned."); + + // check we haven't already predicted for this input + if (test == this.testValue && this.learned == true) return this.result; + + // predict + this.testValue = test; + this.result = this.regression.Transform(this.testValue); + + return this.result; + } + } + #endregion + + #region Classifiers + /// + /// Class providing support for Naive Bayes classification machines. + /// + public class NaiveBayes + { + #region public properties + // dataset + public string[][] dataset { get; private set; } + public string[] columns { get; private set; } + public string outputColumn { get; private set; } + public int[][] inputs; + public int[] outputs; + + // classifier + public Accord.MachineLearning.Bayes.NaiveBayes classifier; + public NaiveBayesLearning learner; + public Codification codebook { get; private set; } + + // state & result + public bool learned { get; private set; } + public string[] testValue { get; private set; } + public string result { get; private set; } + public double[] probs { get; private set; } + #endregion + + /// + /// Constructs a new NaiveBayes classification machine. + /// + public NaiveBayes(string[][] data, List columnList, string outputColumn) + { + // validation + if (data == null || columnList == null || outputColumn==null) throw new ArgumentNullException("Neither the input list nor the column list can be NULL"); + + // initialise seed value + Generator.Seed = new Random().Next(); + + // process input and output lists into arrays + this.dataset = data; + this.columns = columnList.ToArray(); + this.outputColumn = outputColumn; + + // Create a new codification codebook to + // convert strings into discrete symbols + this.codebook = new Codification(columns, this.dataset); + + // Extract input and output pairs to train + int[][] symbols = this.codebook.Transform(this.dataset); + this.inputs = symbols.Get(null, 0, -1); // Gets all rows, from 0 to the last (but not the last) + this.outputs = symbols.GetColumn(-1); // Gets only the last column + + // Create a new Naive Bayes learning + this.learner = new NaiveBayesLearning(); + + // nulls + testValue = null; + result = null; + probs = null; + this.learned = false; + } + + /// + /// Use the object's inputs and outputs to learn the model of the linear regression, using OrdinaryLeastSquares + /// + public NaiveBayes Learn() + { + this.classifier = this.learner.Learn(inputs, outputs); + this.learned = true; + + return this; + } + + /// + /// Using the learned model, predict an output for the specified input + /// + /// The value to use as input for the prediction + /// The predicted value + public string Predict(string[] test) + { + // don't predict if we haven't learned the model yet + if (this.learned != true) throw new Exception("Cannot predict before the machine has learned."); + + // check we haven't already predicted for this input + if (test == this.testValue && this.learned == true) return this.result; + + // predict + // First encode the test instance + int[] instance = this.codebook.Transform(test); + + // Let us obtain the numeric output that represents the answer + int codeword = this.classifier.Decide(instance); + + // Now let us convert the numeric output to an actual answer + this.result = this.codebook.Revert(this.outputColumn, codeword); + + // We can also extract the probabilities for each possible answer + this.probs = this.classifier.Probabilities(instance); + + return this.result; + } + } + #endregion + + #region Helpers + + #endregion + +} diff --git a/src/DynAI/MachineLearning.csproj b/src/DynAI/MachineLearning.csproj new file mode 100644 index 0000000..6070aa0 --- /dev/null +++ b/src/DynAI/MachineLearning.csproj @@ -0,0 +1,75 @@ + + + + + Debug + AnyCPU + {5990DC45-28B6-4E1E-B3EA-C6549EE270F7} + Library + Properties + AI + AI + v4.5.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + bin\Debug\AI.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Accord.3.7.0\lib\net45\Accord.dll + + + ..\packages\Accord.MachineLearning.3.7.0\lib\net45\Accord.MachineLearning.dll + + + ..\packages\Accord.Math.3.7.0\lib\net45\Accord.Math.dll + + + ..\packages\Accord.Math.3.7.0\lib\net45\Accord.Math.Core.dll + + + ..\packages\Accord.Statistics.3.7.0\lib\net45\Accord.Statistics.dll + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/DynAI/Properties/AssemblyInfo.cs b/src/DynAI/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b7398ff --- /dev/null +++ b/src/DynAI/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DynAI Machine Learning")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DynAI Machine Learning")] +[assembly: AssemblyCopyright("Copyright © Radu Gidei 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5990dc45-28b6-4e1e-b3ea-c6549ee270f7")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.1.0.0")] +[assembly: AssemblyFileVersion("0.1.0.0")] diff --git a/src/DynAI/packages.config b/src/DynAI/packages.config new file mode 100644 index 0000000..f3163e0 --- /dev/null +++ b/src/DynAI/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file