Перцептрон, реализованный в C ++, не работает должным образом. (И пример логических элементов AND) - PullRequest
2 голосов
/ 08 октября 2019

Ниже моя реализация Perceptron.

Последняя итерация цикла FOR дает результат:

Вход: 0 Вход: 0

Выход: 0.761594

Ошибка: -0,761594

Что, очевидно, неправильно после стольких обучающих выборок.

Последние несколько строк кода дают

Вход: 1 Вход: 1

Выход: 0,379652

Ошибка: 0,620348

Что снова не так и выключается ...

(Все по отношению к случайным значениям веса в конструкторе.)

Но, если я буду выполнять итерацию только для значений примера (1,1,1), результат будет приближаться к 1 с каждой итерацией, и вот какдолжно работать.

Итак, я хотел бы знать, что может быть причиной этого? Потому что Perceptron должен уметь изучать AND Gate, потому что выходы линейно разделимы.

#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <Windows.h>
#include <math.h>


#define println(x) std::cout<<x<<std::endl;
#define print(x) std::cout<<x;
#define END system("PAUSE"); return 0
#define delay(x) Sleep(x*1000);

typedef unsigned int uint;



class perceptron
{
public:
    perceptron() :learningRate(0.15),biasValue(1),outputVal(0)
    {
        srand((uint)time(0));
        weights = new double[2];
        weights[0] = rand() / double(RAND_MAX);
        weights[1] = rand() / double(RAND_MAX); 
    }
    ~perceptron()
    {
        delete[] weights;
    }
    void train(double x0, double x1, double target)
    {
        backProp(x0, x1, target);
    }
private:
    double biasValue;
    double  outputVal;
    double* weights;
    double learningRate;
private:
    double activationFunction(double sum)
    {
        return tanh(sum);
    }
    void backProp(double x0, double x1, double target)
    {
        println("");

        guess(x0, x1); //Setting outputVal to activationFunction value

        //Calculating Error;

        auto error = target - outputVal;

        //Recalculating weights;

        weights[0] = weights[0] + error * x0 * learningRate;   
        weights[1] = weights[1] + error * x1 * learningRate;

        //Printing values;

        std::cout << "Input:  " << x0 << "   Input:   " << x1 << std::endl;
        std::cout << " Output:   " << outputVal << std::endl;
        std::cout << "Error:   " << error << std::endl;
    }
    double guess(double x0, double x1)
    {
        //Calculating outputValue

        outputVal = activationFunction(x0 * weights[0] + x1 * weights[1]+biasValue);

        return outputVal;
    }
};

int main()
{
    perceptron* p = new perceptron();
    for (auto i = 0; i < 1800; i++)
    {
        p->train(1, 1, 1);
        p->train(0, 1, 0);
        p->train(1, 0, 0);
        p->train(0, 0, 0);
    }
    println("-------------------------------------------------------");
    delay(2);
    p->train(1, 1, 1);
    END;
}

1 Ответ

2 голосов
/ 08 октября 2019

Я вижу несколько проблем:

  1. Активация восприятия не должна быть tanh(). Если вы используете это, вам нужно будет правильно рассчитать градиенты. Но вы можете заменить активацию на
double activationFunction(double sum)
{
    return sum > 0;
}

. Возвращает 1, если сумма> 0, в противном случае возвращается 0.

При обновлении весов biasValue также должен быть обновлен, так как персептрон должен узнать его значение из ваших тренировочных данных. Вы можете обновить его, используя
biasValue += error * learningRate;

. Эти изменения позволят персептрону изучить ворота И.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...