diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/MLP_MVS/MLP_MVS.sln b/MLP_MVS/MLP_MVS.sln new file mode 100644 index 0000000..59a6e7f --- /dev/null +++ b/MLP_MVS/MLP_MVS.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MLP_MVS", "MLP_MVS.vcxproj", "{6BFA9D94-B136-4985-83A1-EE76FFF6F374}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6BFA9D94-B136-4985-83A1-EE76FFF6F374}.Debug|x64.ActiveCfg = Debug|x64 + {6BFA9D94-B136-4985-83A1-EE76FFF6F374}.Debug|x64.Build.0 = Debug|x64 + {6BFA9D94-B136-4985-83A1-EE76FFF6F374}.Debug|x86.ActiveCfg = Debug|Win32 + {6BFA9D94-B136-4985-83A1-EE76FFF6F374}.Debug|x86.Build.0 = Debug|Win32 + {6BFA9D94-B136-4985-83A1-EE76FFF6F374}.Release|x64.ActiveCfg = Release|x64 + {6BFA9D94-B136-4985-83A1-EE76FFF6F374}.Release|x64.Build.0 = Release|x64 + {6BFA9D94-B136-4985-83A1-EE76FFF6F374}.Release|x86.ActiveCfg = Release|Win32 + {6BFA9D94-B136-4985-83A1-EE76FFF6F374}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/MLP_MVS/MLP_MVS.vcxproj b/MLP_MVS/MLP_MVS.vcxproj new file mode 100644 index 0000000..4b79bac --- /dev/null +++ b/MLP_MVS/MLP_MVS.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {6BFA9D94-B136-4985-83A1-EE76FFF6F374} + Win32Proj + MLP_MVS + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MLP_MVS/MLP_MVS.vcxproj.filters b/MLP_MVS/MLP_MVS.vcxproj.filters new file mode 100644 index 0000000..5e3ac27 --- /dev/null +++ b/MLP_MVS/MLP_MVS.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/README.md b/README.md index 331adb9..26c581b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ # MLP + Simple multilayer perceptron c++ implementation. + + +David Nogueira, 2016.01.16 diff --git a/src/Main.cpp b/src/Main.cpp new file mode 100644 index 0000000..05b9074 --- /dev/null +++ b/src/Main.cpp @@ -0,0 +1,130 @@ +//============================================================================ +// Name : Main.cpp +// Author : David Nogueira +//============================================================================ + +#include "MLP.h" +#include +#include +#include +#include +#include +#include +#include +#include + +void LearnAND() { + std::cout << "Train AND function with mlp." << std::endl; + + std::vector training_set = + { + {{ 1, 0, 0 },{1,0}}, + {{ 1, 0, 1 },{1,0}}, + {{ 1, 1, 0 },{1,0}}, + {{ 1, 1, 1 },{0,1}} + }; + + MLP my_mlp(0.1, 100, 0.5); + my_mlp.Train(training_set, 1, 1); + + assert(my_mlp.GetOutput({ 1, 0, 0 }) == 0); + assert(my_mlp.GetOutput({ 1, 0, 1 }) == 0); + assert(my_mlp.GetOutput({ 1, 1, 0 }) == 0); + assert(my_mlp.GetOutput({ 1, 1, 1 }) == 1); + std::cout << "Trained with success." << std::endl; + std::cout << std::endl; +} + +void LearnNAND() { + std::cout << "Train NAND function with mlp." << std::endl; + + std::vector training_set = + { + {{ 1, 0, 0 },{0,1}}, + {{ 1, 0, 1 },{0,1}}, + {{ 1, 1, 0 },{0,1}}, + {{ 1, 1, 1 },{1,0}} + }; + + MLP my_mlp(0.1, 100, 0.5); + my_mlp.Train(training_set, 1, 1); + + assert(my_mlp.GetOutput({ 1, 0, 0 }) == 1); + assert(my_mlp.GetOutput({ 1, 0, 1 }) == 1); + assert(my_mlp.GetOutput({ 1, 1, 0 }) == 1); + assert(my_mlp.GetOutput({ 1, 1, 1 }) == 0); + std::cout << "Trained with success." << std::endl; + std::cout << std::endl; +} + +void LearnOR() { + std::cout << "Train OR function with mlp." << std::endl; + + std::vector training_set = + { + {{ 1, 0, 0 },{1,0}}, + {{ 1, 0, 1 },{0,1}}, + {{ 1, 1, 0 },{0,1}}, + {{ 1, 1, 1 },{0,1}} + }; + + MLP my_mlp(0.1, 100, 0.5); + my_mlp.Train(training_set, 1, 1); + + assert(my_mlp.GetOutput({ 1, 0, 0 }) == 0); + assert(my_mlp.GetOutput({ 1, 0, 1 }) == 1); + assert(my_mlp.GetOutput({ 1, 1, 0 }) == 1); + assert(my_mlp.GetOutput({ 1, 1, 1 }) == 1); + std::cout << "Trained with success." << std::endl; + std::cout << std::endl; +} + +void LearnNOR() { + std::cout << "Train NOR function with mlp." << std::endl; + + std::vector training_set = + { + {{ 1, 0, 0 },{0,1}}, + {{ 1, 0, 1 },{1,0}}, + {{ 1, 1, 0 },{1,0}}, + {{ 1, 1, 1 },{1,0}} + }; + + MLP my_mlp(0.1, 100, 0.5); + my_mlp.Train(training_set, 1, 1); + + assert(my_mlp.GetOutput({ 1, 0, 0 }) == 1); + assert(my_mlp.GetOutput({ 1, 0, 1 }) == 0); + assert(my_mlp.GetOutput({ 1, 1, 0 }) == 0); + assert(my_mlp.GetOutput({ 1, 1, 1 }) == 0); + std::cout << "Trained with success." << std::endl; + std::cout << std::endl; +} + +void LearnNOT() { + std::cout << "Train NOT function with mlp." << std::endl; + + std::vector training_set = + { + {{ 1, 0},{0,1}}, + {{ 1, 1},{1,1}} + }; + + MLP my_mlp(0.1, 100, 0.5); + my_mlp.Train(training_set, 1, 1); + + assert(my_mlp.GetOutput({ 1, 0 }) == 1); + assert(my_mlp.GetOutput({ 1, 1 }) == 0); + std::cout << "Trained with success." << std::endl; + std::cout << std::endl; +} + +int main() { + LearnAND(); + LearnNAND(); + LearnOR(); + LearnNOR(); + LearnNOT(); + + return 0; +} \ No newline at end of file diff --git a/src/Sample.h b/src/Sample.h new file mode 100644 index 0000000..f4ca12e --- /dev/null +++ b/src/Sample.h @@ -0,0 +1,45 @@ +#ifndef TRAININGSAMPLE_H +#define TRAININGSAMPLE_H + +#include +#include + +class Sample { +public: + Sample(const std::vector & input_vector) { + + m_input_vector = input_vector; + } + std::vector & input_vector() { + return m_input_vector; + } + uint32_t GetInputVectorSize() const { + return m_input_vector.size(); + } + void AddBiasValue(double bias_value) { + m_input_vector.insert(m_input_vector.begin(), bias_value); + } +protected: + std::vector m_input_vector; +}; + + +class TrainingSample : public Sample { +public: + TrainingSample(const std::vector & input_vector, + const std::vector & output_vector) : + Sample(input_vector) { + m_output_vector = output_vector; + } + std::vector & output_vector() { + return m_output_vector; + } + uint32_t GetOutputVectorSize() const { + return m_output_vector.size(); + } +protected: + std::vector m_output_vector; +}; + + +#endif // TRAININGSAMPLE_H \ No newline at end of file diff --git a/src/Utils.h b/src/Utils.h new file mode 100644 index 0000000..c663c41 --- /dev/null +++ b/src/Utils.h @@ -0,0 +1,62 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace utils { + +struct gen_rand { + double factor; +public: + gen_rand(double r = 1.0) : factor(r / RAND_MAX) {} + double operator()() { + return rand() * factor; + } +}; + +inline double sigmoid(double x) { + //Typical sigmoid function created from input x + //param x: input value + //return: sigmoided value + return 1 / (1 + exp(-x)); +} + +// Derivative of sigmoid function +inline double deriv_sigmoid(double x) { + return sigmoid(x)*(1 - sigmoid(x)); +}; + +class Chronometer { +public: + Chronometer() { + time_span = std::chrono::steady_clock::duration::zero(); + }; + virtual ~Chronometer() {}; + + void GetTime() { + clock_begin = std::chrono::steady_clock::now(); + } + void StopTime() { + std::chrono::steady_clock::time_point clock_end = std::chrono::steady_clock::now(); + time_span += clock_end - clock_begin; + } + //Return elapsed time in seconds + double GetElapsedTime() { + return double(time_span.count()) * + std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den; + } +protected: + std::chrono::steady_clock::time_point clock_begin; + std::chrono::steady_clock::duration time_span; +}; + +} +#endif // UTILS_H \ No newline at end of file