From ab9dcfbd356bfa2e2054309ea0fdab31f9180497 Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 1 Nov 2015 12:36:23 +0100 Subject: [PATCH 1/8] Clean learner-thread termination on program exit --- gui/NeuroUI/netlearner.cpp | 9 ++++++++- gui/NeuroUI/netlearner.h | 6 ++++++ gui/NeuroUI/neuroui.cpp | 6 ++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/gui/NeuroUI/netlearner.cpp b/gui/NeuroUI/netlearner.cpp index b0956e1..3e7d5f9 100644 --- a/gui/NeuroUI/netlearner.cpp +++ b/gui/NeuroUI/netlearner.cpp @@ -24,7 +24,7 @@ void NetLearner::run() timer.start(); size_t numIterations = 100000; - for (size_t iteration = 0; iteration < numIterations; ++iteration) + for (size_t iteration = 0; iteration < numIterations && cancel == false; ++iteration) { auto trainingSample = mnistLoader.getRandomSample(); @@ -76,4 +76,11 @@ void NetLearner::run() logString.append(ex.what()); emit logMessage(logString); } + + cancel = false; +} + +void NetLearner::cancelLearning() +{ + cancel = true; } diff --git a/gui/NeuroUI/netlearner.h b/gui/NeuroUI/netlearner.h index 70378a4..018c3bf 100644 --- a/gui/NeuroUI/netlearner.h +++ b/gui/NeuroUI/netlearner.h @@ -7,6 +7,9 @@ class NetLearner : public QThread { Q_OBJECT +private: + bool cancel = false; + private: void run() Q_DECL_OVERRIDE; @@ -15,6 +18,9 @@ signals: void progress(double progress); void currentNetError(double error); void sampleImageLoaded(const QImage &image); + +public slots: + void cancelLearning(); }; #endif // NETLEARNER_H diff --git a/gui/NeuroUI/neuroui.cpp b/gui/NeuroUI/neuroui.cpp index c057984..b366c65 100644 --- a/gui/NeuroUI/neuroui.cpp +++ b/gui/NeuroUI/neuroui.cpp @@ -12,6 +12,12 @@ NeuroUI::NeuroUI(QWidget *parent) : NeuroUI::~NeuroUI() { + if (m_netLearner != nullptr) + { + m_netLearner->cancelLearning(); + m_netLearner->wait(); + } + delete ui; } From eecd7a0fe6dce7e2374074345c54d827824ba955 Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 1 Nov 2015 14:49:02 +0100 Subject: [PATCH 2/8] Querying of a single MNIST sample --- gui/NeuroUI/mnistloader.cpp | 15 +++++++++++++++ gui/NeuroUI/mnistloader.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/gui/NeuroUI/mnistloader.cpp b/gui/NeuroUI/mnistloader.cpp index 67c4c1f..91ffa65 100644 --- a/gui/NeuroUI/mnistloader.cpp +++ b/gui/NeuroUI/mnistloader.cpp @@ -8,6 +8,21 @@ void MnistLoader::load(const std::string &databaseFileName, const std::string &l loadLabels(labelsFileName); } +size_t MnistLoader::getSamleCount() const +{ + return samples.size(); +} + +const MnistLoader::MnistSample &MnistLoader::getSample(size_t index) const +{ + if (index >= samples.size()) + { + throw std::runtime_error("MNIST sample index out of range"); + } + + return *(samples[index].get()); +} + const MnistLoader::MnistSample &MnistLoader::getRandomSample() const { size_t sampleIndex = (std::rand() * (samples.size() - 1)) / RAND_MAX; diff --git a/gui/NeuroUI/mnistloader.h b/gui/NeuroUI/mnistloader.h index d2a1e2b..6b1b57d 100644 --- a/gui/NeuroUI/mnistloader.h +++ b/gui/NeuroUI/mnistloader.h @@ -31,6 +31,8 @@ private: public: void load(const std::string &databaseFileName, const std::string &labelsFileName); + size_t getSamleCount() const; + const MnistSample &getSample(size_t index) const; const MnistSample &getRandomSample() const; private: From 1d343a079a166c1f9b9c7c188b087314ab35a23e Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 1 Nov 2015 15:00:32 +0100 Subject: [PATCH 3/8] Moved MNIST sample to QImage conversion to MNIST loader --- gui/NeuroUI/mnistloader.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gui/NeuroUI/mnistloader.h b/gui/NeuroUI/mnistloader.h index 6b1b57d..3e0f46f 100644 --- a/gui/NeuroUI/mnistloader.h +++ b/gui/NeuroUI/mnistloader.h @@ -6,6 +6,8 @@ #include #include +#include + class MnistLoader { private: @@ -21,6 +23,11 @@ public: public: uint8_t label; uint8_t data[SAMPLE_WIDTH * SAMPLE_HEIGHT]; + + QImage toQImage() const + { + return QImage(data, SAMPLE_WIDTH, SAMPLE_HEIGHT, QImage::Format_Grayscale8); + } }; using MnistSample = Sample; From 44760d0402077d3ccb85349b8832f3da15e17b9a Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 1 Nov 2015 15:01:43 +0100 Subject: [PATCH 4/8] Debugging-setup with a single training sample to check the lack of learning progress --- gui/NeuroUI/netlearner.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/NeuroUI/netlearner.cpp b/gui/NeuroUI/netlearner.cpp index 3e7d5f9..1ef8deb 100644 --- a/gui/NeuroUI/netlearner.cpp +++ b/gui/NeuroUI/netlearner.cpp @@ -26,10 +26,10 @@ void NetLearner::run() size_t numIterations = 100000; for (size_t iteration = 0; iteration < numIterations && cancel == false; ++iteration) { - auto trainingSample = mnistLoader.getRandomSample(); + auto trainingSample = mnistLoader.getSample(0); - QImage trainingImage(trainingSample.data, 28, 28, QImage::Format_Grayscale8); - emit sampleImageLoaded(trainingImage); + emit logMessage(QString("training sample ") + QString::number(trainingSample.label)); + emit sampleImageLoaded(trainingSample.toQImage()); std::vector targetValues = { From 5e32724b1a54337b9c5163df8ee45a7327624f78 Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 15 Nov 2015 16:08:49 +0100 Subject: [PATCH 5/8] Layers average their output sums --- Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Layer.cpp b/Layer.cpp index f4b7319..5c7b660 100644 --- a/Layer.cpp +++ b/Layer.cpp @@ -41,7 +41,7 @@ double Layer::getWeightedSum(size_t outputNeuron) const sum += neuron.getWeightedOutputValue(outputNeuron); } - return sum; + return sum / size(); } void Layer::connectTo(const Layer & nextLayer) From 0f7c617f9ce93941ba439dea4cebda73cb867f8c Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 15 Nov 2015 16:09:25 +0100 Subject: [PATCH 6/8] Back to learning all samples --- gui/NeuroUI/netlearner.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/gui/NeuroUI/netlearner.cpp b/gui/NeuroUI/netlearner.cpp index 1ef8deb..65acf0c 100644 --- a/gui/NeuroUI/netlearner.cpp +++ b/gui/NeuroUI/netlearner.cpp @@ -26,9 +26,9 @@ void NetLearner::run() size_t numIterations = 100000; for (size_t iteration = 0; iteration < numIterations && cancel == false; ++iteration) { - auto trainingSample = mnistLoader.getSample(0); + auto trainingSample = mnistLoader.getRandomSample(); - emit logMessage(QString("training sample ") + QString::number(trainingSample.label)); +// emit logMessage(QString("training sample ") + QString::number(trainingSample.label)); emit sampleImageLoaded(trainingSample.toQImage()); std::vector targetValues = @@ -49,12 +49,7 @@ void NetLearner::run() double error = outputValues[0] - targetValues[0]; - QString logString; - - logString.append("Error: "); - logString.append(QString::number(std::abs(error))); - - emit logMessage(logString); + emit logMessage(QString("Error: ") + QString::number(std::abs(error))); emit currentNetError(error); emit progress((double)iteration / (double)numIterations); From c5fbe764a6314d9b7cf0511d8ef090dfb7c96893 Mon Sep 17 00:00:00 2001 From: mandlm Date: Mon, 16 Nov 2015 17:27:42 +0100 Subject: [PATCH 7/8] Limited ErrorPlotter buffer size --- gui/NeuroUI/errorplotter.cpp | 5 +++++ gui/NeuroUI/errorplotter.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/gui/NeuroUI/errorplotter.cpp b/gui/NeuroUI/errorplotter.cpp index 4e6f0b3..0bd05ed 100644 --- a/gui/NeuroUI/errorplotter.cpp +++ b/gui/NeuroUI/errorplotter.cpp @@ -28,6 +28,11 @@ void ErrorPlotter::clear() void ErrorPlotter::addErrorValue(double errorValue) { + if (m_errorValues.size() == m_bufferSize) + { + m_errorValues.pop_front(); + } + m_errorValues.push_back(errorValue); m_maxErrorValue = std::max(m_maxErrorValue, errorValue); diff --git a/gui/NeuroUI/errorplotter.h b/gui/NeuroUI/errorplotter.h index 47c5093..ac4488f 100644 --- a/gui/NeuroUI/errorplotter.h +++ b/gui/NeuroUI/errorplotter.h @@ -11,6 +11,8 @@ private: std::list m_errorValues; double m_maxErrorValue; + size_t m_bufferSize = 10000; + public: explicit ErrorPlotter(QWidget *parent = 0); From 6a23b6a4ae0011fa2cec1759a8b138e3559e3d85 Mon Sep 17 00:00:00 2001 From: mandlm Date: Mon, 16 Nov 2015 17:49:40 +0100 Subject: [PATCH 8/8] Limited log window size --- gui/NeuroUI/neuroui.cpp | 5 +++++ gui/NeuroUI/neuroui.h | 1 + 2 files changed, 6 insertions(+) diff --git a/gui/NeuroUI/neuroui.cpp b/gui/NeuroUI/neuroui.cpp index b366c65..54b00ea 100644 --- a/gui/NeuroUI/neuroui.cpp +++ b/gui/NeuroUI/neuroui.cpp @@ -46,6 +46,11 @@ void NeuroUI::on_runButton_clicked() void NeuroUI::logMessage(const QString &logMessage) { + if (ui->logView->count() == static_cast(m_logSize)) + { + delete ui->logView->item(0); + } + ui->logView->addItem(logMessage); ui->logView->scrollToBottom(); } diff --git a/gui/NeuroUI/neuroui.h b/gui/NeuroUI/neuroui.h index 0799c53..92861ac 100644 --- a/gui/NeuroUI/neuroui.h +++ b/gui/NeuroUI/neuroui.h @@ -17,6 +17,7 @@ class NeuroUI : public QMainWindow private: std::unique_ptr m_netLearner; + size_t m_logSize = 128; public: explicit NeuroUI(QWidget *parent = 0);