问题描述
下面是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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!