2016-11-06 2 views
0

Einige Hintergrund:C++ Single-Layer-Multi-Output Perzeptron seltsames Verhalten

Ich schrieb eine einzelne Schicht Multi-Output-Perzeptron-Klasse in C++. Es verwendet die typische WX + b Diskriminantenfunktion und ermöglicht benutzerdefinierte Aktivierungsfunktionen. Ich habe alles ziemlich gründlich getestet und alles scheint so zu funktionieren, wie ich es erwarte. Ich bemerkte einen kleinen logischen Fehler in meinem Code, und als ich versuchte, es zu reparieren, hat das Netzwerk viel schlechter als vorher funktioniert. Der Fehler ist wie folgt:

ich den Wert an jedem Ausgang Neuron bewerten den folgenden Code verwenden:

output[i] = 
      activate_(std::inner_product(weights_[i].begin(), weights_[i].end(), 
             features.begin(), -1 * biases_[i])); 

Hier behandeln ich den Bias-Eingang als Fest -1, aber wenn ich gelten die Lernregel Bei jeder Vorspannung behandle ich die Eingabe als +1.

// Bias can be treated as a weight with a constant feature value of 1. 
biases_[i] = weight_update(1, error, learning_rate_, biases_[i]); 

So versuchte ich meinen Fehler zu beheben, indem Sie den Anruf Wechsel weight_updated mit der Ausgabe Auswertung werden conistent:

biases_[i] = weight_update(-1, error, learning_rate_, biases_[i]); 

Aber in einem 20% igen Rückgang der Genauigkeit so Ergebnisse zu tun! Ich habe mir in den letzten paar Tagen die Haare geraubt und versucht, einen anderen logischen Fehler in meinem Code zu finden, der dieses seltsame Verhalten erklären könnte, aber mit leeren Händen aufgetaucht ist. Kann jemand mit mehr Wissen als ich Einblick in das geben? Ich habe die gesamte Klasse als Referenz zur Verfügung gestellt. Vielen Dank im Voraus.

#ifndef SINGLE_LAYER_PERCEPTRON_H 
#define SINGLE_LAYER_PERCEPTRON_H 

#include <cassert> 
#include <functional> 
#include <numeric> 
#include <vector> 
#include "functional.h" 
#include "random.h" 

namespace qp { 
namespace rf { 

namespace { 

template <typename Feature> 
double weight_update(const Feature& feature, const double error, 
        const double learning_rate, const double current_weight) { 
    return current_weight + (learning_rate * error * feature); 
} 

template <typename T> 
using Matrix = std::vector<std::vector<T>>; 

} // namespace 

template <typename Feature, typename Label, typename ActivationFn> 
class SingleLayerPerceptron { 
public: 
    // For testing only. 
    SingleLayerPerceptron(const Matrix<double>& weights, 
         const std::vector<double>& biases, double learning_rate) 
     : weights_(weights), 
     biases_(biases), 
     n_inputs_(weights.front().size()), 
     n_outputs_(biases.size()), 
     learning_rate_(learning_rate) {} 

    // Initialize the layer with random weights and biases in [-1, 1]. 
    SingleLayerPerceptron(std::size_t n_inputs, std::size_t n_outputs, 
         double learning_rate) 
     : n_inputs_(n_inputs), 
     n_outputs_(n_outputs), 
     learning_rate_(learning_rate) { 
    weights_.resize(n_outputs_); 
    std::for_each(
     weights_.begin(), weights_.end(), [this](std::vector<double>& wv) { 
      generate_back_n(wv, n_inputs_, 
          std::bind(random_real_range<double>, -1, 1)); 
     }); 

    generate_back_n(biases_, n_outputs_, 
        std::bind(random_real_range<double>, -1, 1)); 
    } 

    std::vector<double> predict(const std::vector<Feature>& features) const { 
    std::vector<double> output(n_outputs_); 
    for (auto i = 0ul; i < n_outputs_; ++i) { 
     output[i] = 
      activate_(std::inner_product(weights_[i].begin(), weights_[i].end(), 
             features.begin(), -1 * biases_[i])); 
    } 
    return output; 
    } 

    void learn(const std::vector<Feature>& features, 
      const std::vector<double>& true_output) { 
    const auto actual_output = predict(features); 
    for (auto i = 0ul; i < n_outputs_; ++i) { 
     const auto error = true_output[i] - actual_output[i]; 
     for (auto weight = 0ul; weight < n_inputs_; ++weight) { 
     weights_[i][weight] = weight_update(
      features[weight], error, learning_rate_, weights_[i][weight]); 
     } 
     // Bias can be treated as a weight with a constant feature value of 1. 
     biases_[i] = weight_update(1, error, learning_rate_, biases_[i]); 
    } 
    } 

private: 
    Matrix<double> weights_;  // n_outputs x n_inputs 
    std::vector<double> biases_; // 1 x n_outputs 
    std::size_t n_inputs_; 
    std::size_t n_outputs_; 
    ActivationFn activate_; 
    double learning_rate_; 
}; 

struct StepActivation { 
    double operator()(const double x) const { return x > 0 ? 1 : -1; } 
}; 

} // namespace rf 
} // namespace qp 

#endif /* SINGLE_LAYER_PERCEPTRON_H */ 

Antwort

0

Ich landete es herauszufinden ...

war meine fix in der Tat richtig, und der Genauigkeitsverlust war nur eine Folge des einen glücklichen (oder Pech) Datensatz mit.