感知器算法

感知器算法是线性分类器中的一种。
这种算法的基本思想是:
对于初始的或者迭代中的增广权矢量W,用训练模式检验其合理性。当不合理时,对其进行校正,利用梯度下降法。梯度下降法也是人工神经网络中线性阈值神经元的学习算法。

感知器算法的基本步骤:

  1. 给定一个增广的训练模式集合{x1, x2, …, xN},其中每个模式类别已知,分别属于1类和2类。
  2. 输入训练模式xk,计算判别函数值WT(k)xk
  3. 训练样本分量增广化和符号规范化。
  4. 按照判别规则调整增广权矢量
  5. 如果在用全部模式训练完一轮后,如果仍有模式被错分,则需要进行第二轮、第三轮迭代,直到所有模式都能够正确分类为止

样例输入文件
in.txt

2 2 2
0 0 0 1
1 0 1 1

样例输出


输入样本维度,第一类样本个数,第二类样本个数: 
输入第一类样本:
输入第二类样本:
k = 1     x = 1     d = 1
k = 2     x = 2     d = 2
k = 3     x = 3     d = -2
更新增广权矢量:      w = (0,1,0)
k = 4     x = 4     d = -1
更新增广权矢量:      w = (-1,0,-1)
k = 5     x = 1     d = -1
更新增广权矢量:      w = (-1,0,0)
k = 6     x = 2     d = 0
更新增广权矢量:      w = (-1,1,1)
k = 7     x = 3     d = 0
更新增广权矢量:      w = (-2,1,0)
k = 8     x = 4     d = 1
k = 9     x = 1     d = 0
更新增广权矢量:      w = (-2,1,1)
k = 10    x = 2     d = 2
k = 11    x = 3     d = 1
k = 12    x = 4     d = 0
更新增广权矢量:      w = (-3,0,0)
k = 13    x = 1     d = 0
更新增广权矢量:      w = (-3,0,1)
k = 14    x = 2     d = 1
k = 15    x = 3     d = 2
k = 16    x = 4     d = 2
k = 17    x = 1     d = 1
k = 18    x = 2     d = 1
k = 19    x = 3     d = 2
k = 20    x = 4     d = 2
最终所求解向量为:   -3 0 1 

C++程序

#include "iomanip"
#include "iostream"

using namespace std;

/*
感知器算法:

1. 录入样本,每个样本属于类别c1 OR c2
2. 将训练样本增加一个分量1
3. 属于c2的样本*(-1)
4. 给增广权矢量赋值w[1]=(1,1,1),取增量p=1,迭代步数k=1
*/

int c[100][100];  //存储样本
int w[100];       //增广权矢量
int p = 1;	//增量
int k = 1;	//迭代步数
int D;		  //样本维度
int n;		  //第一类样本个数
int m;		  //第二类样本个数

//计算w'(k)X
int d(int x[]) {
    int sum = 0;
    for (int i = 0; i <= D; i++) sum += (w[i] * x[i]);
    return sum;
}

//更新增广权矢量
void add(int x[]) {
    for (int i = 0; i <= D; i++) w[i] += x[i];
}

int main() {
    freopen("in.txt", "r", stdin);
    int i, j, t;
    cout << "输入样本维度,第一类样本个数,第二类样本个数: \n";
    cin >> D >> n >> m;

    //初始化增广权矢量全为1
    for (i = 0; i <= D; i++) w[i] = 1;

    cout << "输入第一类样本:\n";
    for (i = 0; i < n; i++)
	for (j = 0; j < D; j++) cin >> c[i][j];

    cout << "输入第二类样本:\n";
    for (i = 0; i < m; i++)
	for (j = 0; j < D; j++) cin >> c[i + n][j];

    int N = n + m;

    //训练样本分量增广化
    for (i = 0; i < N; i++) c[i][D] = 1;

    //训练样本符号规范化
    for (i = n; i < N; i++)
	for (j = 0; j <= D; j++) c[i][j] = -c[i][j];

    //感知器算法训练
    while (1) {
	bool flag = false;  //标记是否有正常分类
	for (i = 0; i < N; i++) {
	    cout << "k = " << setiosflags(ios::left) << setw(6) << k++;
	    cout << "x = " << setiosflags(ios::left) << setw(6) << i + 1;

	    t = d(c[i]);
	    cout << "d = " << t << endl;
	    if (t <= 0) {  //错误分类
		//更新增广权矢量
		add(c[i]);
		cout << "更新增广权矢量:      w = (";
		// cout << "w = (" << i + 1 << endl;
		for (j = 0; j <= D; j++) {
		    cout << w[j];
		    if (j < D) cout << ',';
		}
		cout << ")\n";
		flag = true;
	    }
	}
	if (!flag) break;
    }

    //输出解向量
    cout << "最终所求解向量为:   ";
    for (i = 0; i <= D; i++) cout << w[i] << ' ';
    cout << endl;

    return 0;
}

posted @ 2017-12-23 21:21  lepeCoder  阅读(2265)  评论(0编辑  收藏  举报