diff --git a/DeepLearning.sln b/DeepLearning.sln
index 8dda2c5..5f84494 100644
--- a/DeepLearning.sln
+++ b/DeepLearning.sln
@@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A71E9C
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLParser", "MLParser\MLParser.csproj", "{65C6935B-C55F-4208-88C8-61574DAD1D7C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -22,6 +24,10 @@ Global
{B06BDCBB-94F7-49F2-B7A6-D9D472F9179D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B06BDCBB-94F7-49F2-B7A6-D9D472F9179D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B06BDCBB-94F7-49F2-B7A6-D9D472F9179D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {65C6935B-C55F-4208-88C8-61574DAD1D7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {65C6935B-C55F-4208-88C8-61574DAD1D7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {65C6935B-C55F-4208-88C8-61574DAD1D7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {65C6935B-C55F-4208-88C8-61574DAD1D7C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/DeepLearning/Accuracy.cs b/DeepLearning/Accuracy.cs
new file mode 100644
index 0000000..cc56c56
--- /dev/null
+++ b/DeepLearning/Accuracy.cs
@@ -0,0 +1,100 @@
+using Accord.MachineLearning.VectorMachines;
+using Accord.Neuro.Networks;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DeepLearning
+{
+ public static class Accuracy
+ {
+ ///
+ /// Calculates the accuracy for a trainined SVM against the data.
+ ///
+ /// MulticlassSupportVectorMachine
+ /// List of DigitData
+ /// double
+ public static double CalculateAccuracy(MulticlassSupportVectorMachine machine, double[][] inputs, int[] outputs)
+ {
+ double correct = 0;
+
+ for (int i = 0; i < inputs.Length; i++)
+ {
+ int output = machine.Compute(inputs[i]);
+ if (output == outputs[i])
+ {
+ correct++;
+ }
+ }
+
+ return (correct / (double)inputs.Length);
+ }
+
+ ///
+ /// Calculates the accuracy for a trainined DNN against the data.
+ ///
+ /// DeepBeliefNetwork
+ /// List of DigitData
+ /// double
+ public static double CalculateAccuracy(DeepBeliefNetwork network, double[][] inputs, double[][] outputs)
+ {
+ double correct = 0;
+
+ for (int i = 0; i < inputs.Length; i++)
+ {
+ double[] outputValues = network.Compute(inputs[i]);
+ if (DataManager.FormatOutputResult(outputValues) == DataManager.FormatOutputResult(outputs[i]))
+ {
+ correct++;
+ }
+ }
+
+ return (correct / (double)inputs.Length);
+ }
+
+ ///
+ /// Calculates the output for the svm and saves each result to a text file, one per line.
+ ///
+ /// MulticlassSupportVectorMachine
+ /// double[][]
+ /// string
+ /// int - number of rows processed
+ public static int SaveOutput(MulticlassSupportVectorMachine machine, double[][] inputs, string path)
+ {
+ File.AppendAllText(path, "ImageId,Label\r\n");
+
+ for (int i = 0; i < inputs.Length; i++)
+ {
+ int output = machine.Compute(inputs[i]);
+ File.AppendAllText(path, (i + 1) + "," + output.ToString() + "\r\n");
+ }
+
+ return inputs.Length;
+ }
+
+ ///
+ /// Calculates the output for the neural network and saves each result to a text file, one per line.
+ ///
+ /// DeepBeliefNetwork
+ /// double[][]
+ /// string
+ /// int - number of rows processed
+ public static int SaveOutput(DeepBeliefNetwork network, double[][] inputs, string path)
+ {
+ File.AppendAllText(path, "ImageId,Label\r\n");
+
+ for (int i = 0; i < inputs.Length; i++)
+ {
+ double[] outputValues = network.Compute(inputs[i]);
+ double output = DataManager.FormatOutputResult(outputValues);
+
+ File.AppendAllText(path, (i + 1) + "," + output.ToString() + "\r\n");
+ }
+
+ return inputs.Length;
+ }
+ }
+}
diff --git a/DeepLearning/App.config b/DeepLearning/App.config
index fad249e..b30b34c 100644
--- a/DeepLearning/App.config
+++ b/DeepLearning/App.config
@@ -1,6 +1,19 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DeepLearning/DataManager.cs b/DeepLearning/DataManager.cs
index 7e308ea..1f61ceb 100644
--- a/DeepLearning/DataManager.cs
+++ b/DeepLearning/DataManager.cs
@@ -54,7 +54,7 @@ public static double[][] Load(string pathName, out double[][] outputs)
else
{
// Read output label.
- output.Add(FormatOutputVector(Double.Parse(ch.ToString())));
+ output.Add(FormatOutputVector(Double.Parse(ch.ToString()), 10));
// Set flag to read inputs for next row.
readOutput = false;
@@ -78,10 +78,11 @@ public static double[][] Load(string pathName, out double[][] outputs)
/// Converts a numeric output label (0, 1, 2, 3, etc) to its cooresponding array of doubles, where all values are 0 except for the index matching the label (ie., if the label is 2, the output is [0, 0, 1, 0, 0, ...]).
///
/// double
+ /// int - number of unique classes (ie., 10 for digits 0-9, 2 for true or false, etc).
/// double[]
- public static double[] FormatOutputVector(double label)
+ public static double[] FormatOutputVector(double label, int classCount)
{
- double[] output = new double[10];
+ double[] output = new double[classCount];
for (int i = 0; i < output.Length; i++)
{
diff --git a/DeepLearning/DeepLearning.csproj b/DeepLearning/DeepLearning.csproj
index 61875a1..eb0a0a8 100644
--- a/DeepLearning/DeepLearning.csproj
+++ b/DeepLearning/DeepLearning.csproj
@@ -62,6 +62,7 @@
..\packages\AForge.Neuro.2.2.5\lib\AForge.Neuro.dll
+
@@ -70,14 +71,22 @@
+
+
+
+
+ {65c6935b-c55f-4208-88c8-61574dad1d7c}
+ MLParser
+
+
+
\ No newline at end of file
diff --git a/MLParser/Parser.cs b/MLParser/Parser.cs
new file mode 100644
index 0000000..079ea7a
--- /dev/null
+++ b/MLParser/Parser.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CsvHelper;
+using MLParser.Interface;
+using MLParser.Types;
+
+namespace MLParser
+{
+ public class Parser
+ {
+ private IRowParser _rowParser = null;
+
+ public Parser(IRowParser rowParser)
+ {
+ _rowParser = rowParser;
+ }
+
+ ///
+ /// Parses a csv file containing inputs and an output label, returning a list of MLData.
+ ///
+ /// string
+ /// int - max number of rows to read
+ /// List of MLData
+ public List Parse(string path, int maxRows = 0)
+ {
+ List dataList = new List();
+
+ using (FileStream f = new FileStream(path, FileMode.Open))
+ {
+ using (StreamReader streamReader = new StreamReader(f, Encoding.GetEncoding(1252)))
+ {
+ using (CsvReader csvReader = new CsvReader(streamReader))
+ {
+ csvReader.Configuration.HasHeaderRecord = false;
+
+ while (csvReader.Read())
+ {
+ MLData row = new MLData()
+ {
+ Label = _rowParser.ReadLabel(csvReader),
+ Data = _rowParser.ReadData(csvReader)
+ };
+
+ dataList.Add(row);
+
+ if (maxRows > 0 && dataList.Count >= maxRows)
+ break;
+ }
+ }
+ }
+ }
+
+ return dataList;
+ }
+ }
+}
diff --git a/MLParser/Parsers/BaseParser.cs b/MLParser/Parsers/BaseParser.cs
new file mode 100644
index 0000000..ff2b347
--- /dev/null
+++ b/MLParser/Parsers/BaseParser.cs
@@ -0,0 +1,52 @@
+using CsvHelper;
+using MLParser.Interface;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MLParser.Parsers
+{
+ public abstract class BaseParser : IRowParser
+ {
+ public abstract int ReadLabel(CsvReader reader);
+ public abstract List ReadData(CsvReader reader);
+
+ ///
+ /// Helper method for reading a row of data from a csv file. Reading starts at the startColumn and ends at the endColumn.
+ ///
+ /// CsvReader
+ /// int - start index to begin reading fields from.
+ /// int - end index to stop reading fields at. Set to null to read until the end of the row.
+ /// List of double
+ protected List ReadData(CsvReader reader, int startColumn, int? endColumn = null)
+ {
+ List data = new List();
+
+ if (endColumn == null)
+ {
+ // Read until the end of the row.
+ endColumn = reader.Parser.FieldCount;
+ }
+
+ // Start at index to begin reading data from.
+ for (int i = startColumn; i < endColumn; i++)
+ {
+ // Read the value.
+ double value = Double.Parse(reader[i]);
+
+ // Store the normalized value in our data list.
+ data.Add(Normalize(value));
+ }
+
+ return data;
+ }
+
+ protected double Normalize(double value)
+ {
+ // Normalize the value (0 - 1): X = (X - min) / (max - min) => X = X / 255. Alternate method (-0.5 - 0.5): X = (X - avg) / max - min => X = (X - 127) / 255. http://en.wikipedia.org/wiki/Feature_scaling
+ return value / 255d;
+ }
+ }
+}
diff --git a/MLParser/Parsers/EndStringEndLabelParser.cs b/MLParser/Parsers/EndStringEndLabelParser.cs
new file mode 100644
index 0000000..ddc2ce1
--- /dev/null
+++ b/MLParser/Parsers/EndStringEndLabelParser.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CsvHelper;
+using MLParser.Interface;
+using MLParser.Types;
+
+namespace MLParser.Parsers
+{
+ ///
+ /// Parses a csv file, assuming the last 2 columns consist of a string (filename) followed by the label, and the remaining columns contain the data.
+ ///
+ public class EndStringEndLabelParser : BaseParser
+ {
+ public override int ReadLabel(CsvReader reader)
+ {
+ return Int32.Parse(reader[reader.Parser.FieldCount - 1]);
+ }
+
+ public override List ReadData(CsvReader reader)
+ {
+ // Start at index 0, and read up to the last 2 columns, which are the string (filename) and label.
+ return ReadData(reader, 0, reader.Parser.FieldCount - 2);
+ }
+ }
+}
diff --git a/MLParser/Parsers/FrontLabelParser.cs b/MLParser/Parsers/FrontLabelParser.cs
new file mode 100644
index 0000000..2f00849
--- /dev/null
+++ b/MLParser/Parsers/FrontLabelParser.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CsvHelper;
+using MLParser.Interface;
+using MLParser.Types;
+
+namespace MLParser.Parsers
+{
+ ///
+ /// Parses a csv file, assuming column 0 contains the label and the remaining columns contain the data.
+ ///
+ public class FrontLabelParser : BaseParser
+ {
+ public override int ReadLabel(CsvReader reader)
+ {
+ return Int32.Parse(reader[0]);
+ }
+
+ public override List ReadData(CsvReader reader)
+ {
+ // Start at index 1, as the index 0 contains the label.
+ return ReadData(reader, 1);
+ }
+ }
+}
diff --git a/MLParser/Parsers/TestParser.cs b/MLParser/Parsers/TestParser.cs
new file mode 100644
index 0000000..9f2fd13
--- /dev/null
+++ b/MLParser/Parsers/TestParser.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CsvHelper;
+using MLParser.Interface;
+using MLParser.Types;
+
+namespace MLParser.Parsers
+{
+ ///
+ /// Parses a csv file in its entirety as data. Assumes no label is present and all columns will be data points. Useful for test.csv files (which usually do not contain labels).
+ ///
+ public class TestParser : BaseParser
+ {
+ public override int ReadLabel(CsvReader reader)
+ {
+ return 0;
+ }
+
+ public override List ReadData(CsvReader reader)
+ {
+ return ReadData(reader, 0);
+ }
+ }
+}
diff --git a/MLParser/Properties/AssemblyInfo.cs b/MLParser/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..3ff3401
--- /dev/null
+++ b/MLParser/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("MLParser")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MLParser")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[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("667bf2c2-d7b8-479b-91a1-333ad738c8d4")]
+
+// 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("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/MLParser/Types/MLData.cs b/MLParser/Types/MLData.cs
new file mode 100644
index 0000000..a06376a
--- /dev/null
+++ b/MLParser/Types/MLData.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MLParser.Types
+{
+ ///
+ /// Data-type for holding machine learning data from a csv file, consisting of an array of doubles (input) and a label (output).
+ ///
+ public class MLData
+ {
+ ///
+ /// Input
+ ///
+ public List Data { get; set; }
+ ///
+ /// Output
+ ///
+ public int Label { get; set; }
+
+ public MLData()
+ {
+ Data = new List();
+ }
+ }
+}
diff --git a/readme.md b/readme.md
index 05f0620..3c6be49 100644
--- a/readme.md
+++ b/readme.md
@@ -10,7 +10,7 @@ Checkout the master branch for a slightly less-basic example of training on an A
Deep-Learning Strategy
----------------------
-1. Start with a neural network with multiple RestrictedBoltzman machine layers.
+1. Start with a neural network with multiple RestrictedBoltzmann machine layers.
2. Use unsupervised training on each layer in the network, one at a time, except for the output layer. This allows each layer to learn specific features about the input data.
3. If you ran unsupervised training on the whole network, including the output layer, add an additional (untrained) layer to the network to serve as the output layer. Otherwise, skip this step.
4. Run back-propagation on the entire network to fine-tune for classification.