感知学习算法不收敛于0 [英] Perceptron learning algorithm not converging to 0

查看:253
本文介绍了感知学习算法不收敛于0的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是ANSI C我的感知实现:

 的#include< stdio.h中>
#包括< stdlib.h中>
#包括<文件math.h>

浮动randomFloat()
{
    函数srand(时间(NULL));
    浮动R =(浮点)兰特()/(浮点)RAND_MAX;
    返回ř;
}

INT calculateOutput(浮动权[],浮法X,浮动Y)
{
    浮总和= X *重量[0] + Y *权重[1];
    返回(总和> = 0)? 1:-1;
}

INT主(INT ARGC,字符* argv的[])
{
    // X,Y训练集的坐标。
    浮法X [208],Y [208];

    //训练集输出。
    INT输出[208];

    INT I = 0; //迭代器

    FILE * FP;

    如果((FP = FOPEN(test1.txt的,R))== NULL)
    {
        的printf(不能打开文件\ñ。);
    }
    其他
    {
        而(的fscanf(FP,%F%F%D,&安培; X [I]中,&安培;值Y [i],&安培;!输出[I])= EOF)
        {
            如果(输出[I] == 0)
            {
                输出[I] = -1;
            }
            输出(%F%F%D \ñ中,x [I]中,值Y [i],输出[I]);
            我++;
        }
    }

    系统(暂停);

    INT patternCount = sizeof的(X)/的sizeof(INT);

    浮动权[2];
    权重[0] = randomFloat();
    权重[1] = randomFloat();

    浮learningRate = 0.1;

    INT迭代= 0;
    浮动globalError;

    做 {
        globalError = 0;
        INT p值= 0; //迭代器
        为(p值= 0; P&所述; patternCount,P ++)
        {
            //计算输出。
            INT输出= calculateOutput(权重中,x [P],Y [P]);

            //计算错误。
            浮localError =输出[P]  - 输出;

            如果(localError!= 0)
            {
                //更新的权重。
                对于(I = 0; I&2;我+ +)
                {
                    浮点加法= learningRate * localError;
                    如果(我== 0)
                    {
                        添加* = X [P]。
                    }
                    否则,如果(ⅰ== 1)
                    {
                        添加* = Y [P]。
                    }
                    权重[I] + =增加;
                }
            }

            //转换误差绝对值。
            globalError + =晶圆厂(localError);

            的printf(迭代%D误差%.2f%.2f \ N,迭代,globalError,localError);

            迭代++;
        }

        系统(暂停);

    }而(globalError!= 0);

    系统(暂停);
    返回0;
}
 

训练集我使用的是:数据集

我已删除所有无关的code。基本上现在做什么它读 test1.txt的文件并加载值从中三​​个数组: X 输出

然后有一个感知学习算法其中,由于某种原因,没有收敛于0( globalError 应该收敛于0),因此我得到一个无限做while循环。

当我使用一个较小的训练集(比如5分),它的工作原理pretty的好。任何想法的地方可能是问题?

我写这个算法非常相似,这 C#感知算法


编辑:

下面是一个较小的训练集一个例子:

 的#include< stdio.h中>
#包括< stdlib.h中>
#包括<文件math.h>

浮动randomFloat()
{
    浮动R =(浮点)兰特()/(浮点)RAND_MAX;
    返回ř;
}

INT calculateOutput(浮动权[],浮法X,浮动Y)
{
    浮总和= X *重量[0] + Y *权重[1];
    返回(总和> = 0)? 1:-1;
}

INT主(INT ARGC,字符* argv的[])
{
    函数srand(时间(NULL));

    // X坐标训练集。
    浮×〔] = {-3.2,1.1,2.7,-1};

    // Y中的训练集的坐标。
    浮动Y [] = {1.5,3.3,5.12,2.1};

    //训练集输出。
    INT输出[] = {1,-1,-1,1};

    INT I = 0; //迭代器

    FILE * FP;

    系统(暂停);

    INT patternCount = sizeof的(X)/的sizeof(INT);

    浮动权[2];
    权重[0] = randomFloat();
    权重[1] = randomFloat();

    浮learningRate = 0.1;

    INT迭代= 0;
    浮动globalError;

    做 {
        globalError = 0;
        INT p值= 0; //迭代器
        为(p值= 0; P&所述; patternCount,P ++)
        {
            //计算输出。
            INT输出= calculateOutput(权重中,x [P],Y [P]);

            //计算错误。
            浮localError =输出[P]  - 输出;

            如果(localError!= 0)
            {
                //更新的权重。
                对于(I = 0; I&2;我+ +)
                {
                    浮点加法= learningRate * localError;
                    如果(我== 0)
                    {
                        添加* = X [P]。
                    }
                    否则,如果(ⅰ== 1)
                    {
                        添加* = Y [P]。
                    }
                    权重[I] + =增加;
                }
            }

            //转换误差绝对值。
            globalError + =晶圆厂(localError);

            的printf(迭代%D误差%.2f \ N,迭代,globalError);
        }

        迭代++;

    }而(globalError!= 0);

    //显示网络推广。
    的printf(X Y输出的\ n);
    浮J,K;
    为(J = -1; J< = 1; J + = 0.5)
    {
        为(J = -1; J< = 1; J + = 0.5)
        {
            //计算输出。
            INT输出= calculateOutput(重量,J,K);
            的printf(%2F%.2f%S \ N,J,K,(输出== 1)蓝:红?);
        }
    }

    //显示修改权重。
    的printf(修改权重:%.2f%.2f \ N,重量[0],权重[1]);

    系统(暂停);
    返回0;
}
 

解决方案

在你目前的code,感知成功学的决策边界的方向,但不能的翻译的吧。

    Y Y
    ^ ^
    | -  + \\ + | -  \\ +
    | -  + \\ + | -  \\ +++
    | -   -  \\ + | -   -  \\ +
    | -   -  + \\ + | -   -  \\ +
    ---------------------系列> X --------------------系列> X
        坚持这样的需要得到这样的

问题在于,你的感知没有偏项,即连接到价值1输入第三组份的事实。

       W0 -----
    x ----> | |
           | F | ---->输出(+ 1 / -1)
    Ÿ----> | |
       W1 -----
               ^ W2
    1(偏差)--- |

下面是我如何修正这个问题:

 的#include< stdio.h中>
#包括< stdlib.h中>
#包括<文件math.h>
#包括< time.h中>

#定义LEARNING_RATE 0.1
#定义MAX_ITERATION 100

浮动randomFloat()
{
    返程(浮点)兰特()/(浮点)RAND_MAX;
}

INT calculateOutput(浮动权[],浮法X,浮动Y)
{
    浮总和= X *重量[0] + Y *权重[1] +砝码[2];
    返回(总和> = 0)? 1:-1;
}

INT主(INT ARGC,字符* argv的[])
{
    函数srand(时间(NULL));

    浮法X [208],Y [208],权重[3],localError,globalError;
    INT输出[208],patternCount,I,P,迭代,输出;

    FILE * FP;
    如果((FP = FOPEN(test1.txt的,R))== NULL){
        的printf(不能打开文件\ñ。);
        出口(1);
    }

    I = 0;
    而(的fscanf(FP,%F%F%D,&安培; X [I]中,&安培;值Y [i],&安培;输出[I])= EOF!){
        如果(输出[I] == 0){
            输出[I] = -1;
        }
        我++;
    }
    patternCount =我;

    权重[0] = randomFloat();
    权重[1] = randomFloat();
    权重[2] = randomFloat();

    迭代= 0;
    做 {
        迭代++;
        globalError = 0;
        为(p值= 0; P&所述; patternCount,P ++){
            输出= calculateOutput(权重中,x [P],Y [P]);

            localError =输出[P]  - 输出;
            权重[0] + = LEARNING_RATE * localError * X [P];
            权重[1] + = LEARNING_RATE * localError * Y [P];
            权重[2] + = LEARNING_RATE * localError;

            globalError + =(localError * localError);
        }

  / *均方根误差* /
  的printf(迭代%D:RMSE =%.4f \ N,迭代,
                     的sqrt(globalError / patternCount));
    }而(globalError = 0&放大器;!&安培;迭代< = MAX_ITERATION);

 的printf(\ nDecision边界(线)公式:%.2f * X +%.2f * Y +%.2f = 0 \ N,
             权重[0],权重[1],权重[2]);

    返回0;
}
 

......与下面的输出:

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

决策边界(线)公式:-2.37 * X + -2.51 * Y + -7.55 = 0
 


编辑:我创建的code以上使用MATLAB一个动画短片。请查看以下视频

Here is my perceptron implementation in ANSI C:

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

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

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

int main(int argc, char *argv[])
{
    // X, Y coordinates of the training set.
    float x[208], y[208];

    // Training set outputs.
    int outputs[208];

    int i = 0; // iterator

    FILE *fp;

    if ((fp = fopen("test1.txt", "r")) == NULL)
    {
        printf("Cannot open file.\n");
    }
    else
    {
        while (fscanf(fp, "%f %f %d", &x[i], &y[i], &outputs[i]) != EOF)
        {
            if (outputs[i] == 0)
            {
                outputs[i] = -1;
            }
            printf("%f   %f   %d\n", x[i], y[i], outputs[i]);
            i++;
        }
    }

    system("PAUSE");

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

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

    float learningRate = 0.1;

    int iteration = 0;
    float globalError;

    do {
        globalError = 0;
        int p = 0; // iterator
        for (p = 0; p < patternCount; p++)
        {
            // Calculate output.
            int output = calculateOutput(weights, x[p], y[p]);

            // Calculate error.
            float localError = outputs[p] - output;

            if (localError != 0)
            {
                // Update weights.
                for (i = 0; i < 2; i++)
                {
                    float add = learningRate * localError;
                    if (i == 0)
                    {
                        add *= x[p];
                    }
                    else if (i == 1)
                    {
                        add *= y[p];
                    }
                    weights[i] +=  add;
                }
            }

            // Convert error to absolute value.
            globalError += fabs(localError);

            printf("Iteration %d Error %.2f %.2f\n", iteration, globalError, localError);

            iteration++;
        }

        system("PAUSE");

    } while (globalError != 0);

    system("PAUSE");
    return 0;
}

The training set I'm using: Data Set

I have removed all irrelevant code. Basically what it does now it reads test1.txt file and loads values from it to three arrays: x, y, outputs.

Then there is a perceptron learning algorithm which, for some reason, is not converging to 0 (globalError should converge to 0) and therefore I get an infinite do while loop.

When I use a smaller training set (like 5 points), it works pretty well. Any ideas where could be the problem?

I wrote this algorithm very similar to this C# Perceptron algorithm:


EDIT:

Here is an example with a smaller training set:

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

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

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

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

    // X coordinates of the training set.
    float x[] = { -3.2, 1.1, 2.7, -1 };

    // Y coordinates of the training set.
    float y[] = { 1.5, 3.3, 5.12, 2.1 };

    // The training set outputs.
    int outputs[] = { 1, -1, -1, 1 };

    int i = 0; // iterator

    FILE *fp;

    system("PAUSE");

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

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

    float learningRate = 0.1;

    int iteration = 0;
    float globalError;

    do {
        globalError = 0;
        int p = 0; // iterator
        for (p = 0; p < patternCount; p++)
        {
            // Calculate output.
            int output = calculateOutput(weights, x[p], y[p]);

            // Calculate error.
            float localError = outputs[p] - output;

            if (localError != 0)
            {
                // Update weights.
                for (i = 0; i < 2; i++)
                {
                    float add = learningRate * localError;
                    if (i == 0)
                    {
                        add *= x[p];
                    }
                    else if (i == 1)
                    {
                        add *= y[p];
                    }
                    weights[i] +=  add;
                }
            }

            // Convert error to absolute value.
            globalError += fabs(localError);

            printf("Iteration %d Error %.2f\n", iteration, globalError);          
        }

        iteration++;

    } while (globalError != 0);

    // Display network generalisation.
    printf("X       Y     Output\n");
    float j, k;
    for (j = -1; j <= 1; j += .5)
    {
        for (j = -1; j <= 1; j += .5)
        {
            // Calculate output.
            int output = calculateOutput(weights, j, k);
            printf("%.2f  %.2f  %s\n", j, k, (output == 1) ? "Blue" : "Red");
        }
    }

    // Display modified weights.
    printf("Modified weights: %.2f %.2f\n", weights[0], weights[1]);

    system("PAUSE");
    return 0;
}

解决方案

In your current code, the perceptron successfully learns the direction of the decision boundary BUT is unable to translate it.

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

The problem lies in the fact that your perceptron has no bias term, i.e. a third weight component connected to an input of value 1.

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

The following is how I corrected the problem:

#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;
}

... with the following output:

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


EDIT: I created a short animation of the code above using MATLAB. Check out the following video:

这篇关于感知学习算法不收敛于0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆