Perceptron, изучающий алгоритм, не сходящийся к 0

Я голосовал бы за Java, являющийся более портативным, чем C#. Java определенно также имеет очень богатый набор стандартных библиотек. Существует также широкий набор библиотек открытого исходного кода 3rd party там, таких как обеспеченные Джакартским проектом ( http://jakarta.apache.org/ ).

Все обычные подозреваемые существуют для CI, Поблочного тестирования, и т.д. также. Кросс-платформенная поддержка IDE также очень хороша с подобными Eclipse, Netbeans, ИДЕЕ IntelliJ и т.д.

62
задан Osteoboon 13 January 2013 в 03:18
поделиться

4 ответа

В вашем текущем коде перцептрон успешно изучает направление границы принятия решения, НО не может преобразовать его.

    y                              y
    ^                              ^
    |  - + \\  +                   |  - \\ +   +
    | -    +\\ +   +               | -   \\  + +   +
    | - -    \\ +                  | - -  \\    +
    | -  -  + \\  +                | -  -  \\ +   +
    ---------------------> x       --------------------> x
        stuck like this            need to get like this

(как кто-то указал, вот более точная версия )

Проблема заключается в том, что ваш перцептрон не имеет члена смещения , то есть третьего компонента веса, подключенного к входу значения 1.

       w0   -----
    x ---->|     |
           |  f  |----> output (+1/-1)
    y ---->|     |
       w1   -----
               ^ w2
    1(bias) ---|

Вот как я исправил проблему:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define LEARNING_RATE    0.1
#define MAX_ITERATION    100

float randomFloat()
{
    return (float)rand() / (float)RAND_MAX;
}

int calculateOutput(float weights[], float x, float y)
{
    float sum = x * weights[0] + y * weights[1] + weights[2];
    return (sum >= 0) ? 1 : -1;
}

int main(int argc, char *argv[])
{
    srand(time(NULL));

    float x[208], y[208], weights[3], localError, globalError;
    int outputs[208], patternCount, i, p, iteration, output;

    FILE *fp;
    if ((fp = fopen("test1.txt", "r")) == NULL) {
        printf("Cannot open file.\n");
        exit(1);
    }

    i = 0;
    while (fscanf(fp, "%f %f %d", &x[i], &y[i], &outputs[i]) != EOF) {
        if (outputs[i] == 0) {
            outputs[i] = -1;
        }
        i++;
    }
    patternCount = i;

    weights[0] = randomFloat();
    weights[1] = randomFloat();
    weights[2] = randomFloat();

    iteration = 0;
    do {
        iteration++;
        globalError = 0;
        for (p = 0; p < patternCount; p++) {
            output = calculateOutput(weights, x[p], y[p]);

            localError = outputs[p] - output;
            weights[0] += LEARNING_RATE * localError * x[p];
            weights[1] += LEARNING_RATE * localError * y[p];
            weights[2] += LEARNING_RATE * localError;

            globalError += (localError*localError);
        }

        /* Root Mean Squared Error */
        printf("Iteration %d : RMSE = %.4f\n",
            iteration, sqrt(globalError/patternCount));
    } while (globalError > 0 && iteration <= MAX_ITERATION);

    printf("\nDecision boundary (line) equation: %.2f*x + %.2f*y + %.2f = 0\n",
        weights[0], weights[1], weights[2]);

    return 0;
}

... со следующим выводом:

Iteration 1 : RMSE = 0.7206
Iteration 2 : RMSE = 0.5189
Iteration 3 : RMSE = 0.4804
Iteration 4 : RMSE = 0.4804
Iteration 5 : RMSE = 0.3101
Iteration 6 : RMSE = 0.4160
Iteration 7 : RMSE = 0.4599
Iteration 8 : RMSE = 0.3922
Iteration 9 : RMSE = 0.0000

Decision boundary (line) equation: -2.37*x + -2.51*y + -7.55 = 0

А вот короткая анимация приведенного выше кода с использованием MATLAB, показывающая границу решения на каждой итерации:

screenshot

162
ответ дан 24 November 2019 в 16:36
поделиться

Это может помочь, если вы поместите заполнение генератора случайных чисел в начало yout main вместо повторного заполнения при каждом вызове randomFloat , то есть

float randomFloat()
{
    float r = (float)rand() / (float)RAND_MAX;
    return r;
}

// ...

int main(int argc, char *argv[])
{
    srand(time(NULL));

    // X, Y coordinates of the training set.
    float x[208], y[208];
6
ответ дан 24 November 2019 в 16:36
поделиться

Некоторые небольшие ошибки, которые я обнаружил в вашем исходном коде:

int patternCount = sizeof(x) / sizeof(int);

Лучше измените это на

int patternCount = i;

, чтобы вам не приходилось полагаться на массив x, чтобы иметь правильный размер.

Вы увеличиваете количество итераций внутри цикла p, тогда как исходный код C # делает это вне цикла p. Лучше переместите printf и итерацию ++ за пределы цикла p перед оператором PAUSE - также я бы удалил оператор PAUSE или изменил его на

if ((iteration % 25) == 0) system("PAUSE");

Даже после внесения всех этих изменений ваша программа по-прежнему не завершается с использованием вашего набора данных, но вывод более согласован, что дает ошибку, колеблющуюся где-то между 56 и 60.

Последнее, что вы могли бы попробовать, - это протестировать исходную программу C # на этом наборе данных, если она также не завершается, что-то не так с алгоритмом (поскольку ваш набор данных выглядит правильно, см. мой комментарий к визуализации).

3
ответ дан 24 November 2019 в 16:36
поделиться

globalError не станет равным нулю, он будет сходиться к нулю, как вы сказали, т.е. он станет очень маленьким.

Измените свой цикл следующим образом:

int maxIterations = 1000000; //stop after one million iterations regardless
float maxError = 0.001; //one in thousand points in wrong class

do {
    //loop stuff here

    //convert to fractional error
    globalError = globalError/((float)patternCount);

} while ((globalError > maxError) && (i<maxIterations));

Задайте значения maxIterations и maxError , применимые к вашей проблеме.

1
ответ дан 24 November 2019 в 16:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: