感知算法的訓練過程就是對判斷好的樣本集求解權矢量W,這實際是一個線性聯立不等式的求解問題。
具體算法如下:
1. 初始權矢量 W = 0;
2. 第k次輸入一個樣本X(K), 計算第k次迭代的過爲:
d[X(k)] = W'[k] * X(k),
3. 根據欲劃分類和d值進行權值修正:
當d<=0時: W[k+1] = W[k] + X[k];
當d>0時: W[k+1] = W[k] -
X[k];
4. 循環執行第二步,直到輸入所有樣本後,權重都不需要修改爲止。
本代碼的測試用例爲,胃病和非胃病測試樣例(1爲胃病,-1爲非胃病)
228 134 20 11 1 1
245 134 10 40 1 1
200 167 12 27 1 1
170 150 7 8 1 1
100 167 20 14 1 1
150 117 7 6 1 -1
165 142 5 3 1 -1
185 108 2 12 1 -1
120 133 10 26 1 -1
160 100 5 10 1 -1
185 115 5 19 1 -1
170 125 6 4 1 -1
待測樣品爲:
225 125 7 14 1 0
100 117 7 2 1 0
130 100 6 12 1 0
c代碼如下:(訓練會需要一些時間)
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "vector"
using namespace std;
typedef vector<double> doubleVector;
#define alpha 0.2
#define dimNum 6 //樣本的維數
vector<doubleVector> getSample(char *File); //獲取樣本
double matMul(doubleVector Mat1, doubleVector Mat2); //矩陣相乘
doubleVector matAdd(doubleVector Mat1, doubleVector Mat2); //矩陣相加
void Perceptron(vector<doubleVector> sample); //感知算法開始引擎
doubleVector matSub(doubleVector Mat1, doubleVector Mat2); //矩陣相減
void main()
{
char *File = "胃病.txt";
vector<doubleVector> sample;
sample = getSample(File);
Perceptron(sample);
}
//感知算法開始引擎
void Perceptron(vector<doubleVector> sample)
{
doubleVector W(dimNum-1, 0); //權重
double mulResult;
int i;
bool flag = false;
while(!flag) //輸入所有樣本後權重都不改變
{
flag = true;
for(i=0; i<sample.size(); i++)
{
mulResult = matMul(W, sample[i]); //計算權值
if(sample[i][dimNum-1]==1)
{
if(mulResult<=0)
{
W = matAdd(W, sample[i]);
flag = false;
}
}
else
{
if(mulResult>0)
{
W = matSub(W, sample[i]);
flag = false;
}
}
}
}
vector<doubleVector> test;
char *File = "待判樣品.txt";
test = getSample(File);
for(i=0; i<test.size(); i++)
{
mulResult = matMul(W, test[i]);
if(mulResult>0)
printf("胃病\n");
else
printf("非胃病\n");
}
}
//獲取樣本
vector<doubleVector> getSample(char *File)
{
int i=1;
vector<doubleVector> dst;
doubleVector temp;
FILE *fp = fopen(File, "r");
if(fp == NULL)
{
printf("Open file error!!!\n");
return dst;
}
double num;
while(fscanf(fp, "%lf", &num)!=EOF)
{
temp.push_back(num);
if(i%dimNum==0)
{
dst.push_back(temp);
temp.clear();
}
i++;
}
return dst;
}
//矩陣相乘
double matMul(doubleVector Mat1, doubleVector Mat2)
{
int i;
double sum=0;
for(i=0; i<dimNum-1; i++)
sum += Mat1[i]*Mat2[i];
return sum;
}
//矩陣相加
doubleVector matAdd(doubleVector Mat1, doubleVector Mat2)
{
int i;
doubleVector dstMat;
for(i=0; i<dimNum-1; i++)
dstMat.push_back(Mat1[i]+Mat2[i]*alpha);
return dstMat;
}
//矩陣相減
doubleVector matSub(doubleVector Mat1, doubleVector Mat2)
{
int i;
doubleVector dstMat;
for(i=0; i<dimNum-1; i++)
dstMat.push_back(Mat1[i]-Mat2[i]*alpha);
return dstMat;
}