人工神经网络的设计与实现(二) 感知机

感知机

感知机(perceptron)是ANN的基本单元,至少我现在是这么觉得的,如果我学到后来发现不是,会来更正的。

感知机(如下图)就是伸出几只小触手去感知这个世界~感知~感知~然后触手获取数据的加权和通过函数 f,得到的值即为该感知机的输出。就是如果用一个数表示这个世界的话,感知机唰唰唰就得出结论了。

加权和好算,那 f 怎么办?选什么样的函数好呢?其实可以乱七八糟随便选,只要你能说的出道理就行。最简单的可以用符号函数,加权和小于0为输出为-1,加权和大于0输出为+1。等于0,等于0,怎么可能等于0。如果你选择了这个函数说明你想用感知机来区分两类问题,以为输出为+1,另一类为-1。加权和等于0说明还没有训练好,感知机需要继续学习。还有其他的一些函数如下,下表是抄的。。。来自 自己动手写神经网络

好了,不管有多少种,不管用什么函数,我们可以发现归根到底我们要解决一个问题:一类事物(应该叫模式,专业点嘛)加权和小于0,另一类事务(后面都叫模式了)加权和大于0。我们先解决这个问题。怎么解决呢?我们让感知机自己学习,每次往好的目标挪一点。引出梯度下降法。

梯度下降法

梯度下降法是求最小值的一种方法,就好像你站在山上,你想要前往山底,最快速的路线是从最陡的地方走,这就是梯度下降。 知乎上有个哥们(杨涛)解释的很好
根据一阶泰勒展开,对于一个可微函数,对于任意的x,有:
,其中g(x)是梯度,如果一维情况就是一阶导数。
而其中 , 是两向量之间的夹角。 为180度得时候,g(x)*p可取到最小值,即为下降最快的方向。
所以,负梯度方向为函数f(x)下降最快的方向。 如果f(x)是 凸函数,则局部最优解就是全局最优解。
到这里就直到梯度下降的原理了吧~你一定会说那 为0不是梯度上升了嘛?对!没错,梯度上升求最大值,棒棒的。
什么局部最优,全局最优,引入模拟退火之类额随机算法就能解决了,这里就不说了。
损失函数是:
上式的意思是如果我们分类错了则x属于M,M是一个分错类的点的集合。分错类的意思是wx+b小于0,但是y却为1;或者相反wx+b大于0,但y却为-1。我们把这些点求和得到损失函数,取反为正值。则L函数值越小,感知机感知的越精确。我们的问题就是怎样调整 w、b 使 L(w,b) 最小。这就用到刚刚说的梯度下降法啦~
 
已经得到两个变量的梯度如上,所以迭代公式可得:
其中n(就是那个长尾巴的,懒得找了)就是步长,决定速度用的。
之后工作就是按照这个迭代公式更新 w 和 b 就可以了,直到所有模式都分对则结束。这是梯度下降法的一种实现,还有很多变种,这里就不说了。
#include <iostream>
using namespace std;
#define  count  3
//input
	double	x[count][3]={{1,1,-1},{3,3,1},{4,3,1}};
//weight
	double w1 = 0;
	double w2 = 0;
	double b=0;
	
//deal with input ,we use sum with weight:w1*x1+w2*x2
double InputValue(int i){
	return w1*x[i][0]+w2*x[i][1]+b;
}

int Distinguish(int x1,int x2){
	
}
int main(int argc, char const *argv[])
{
	int test = 0;
	
	//value of input
	double input = 0;
	//value of output.This is a two-class problem,we use 0/1 to express them
	int output = 0;
	// train
	for (int flag = 0; flag != count; )
	{
		test++;
		cout<<test<<endl;
		flag = 0;
	for (int i = 0; i < count; ++i)
	{
		double sum = InputValue(i);
		if(x[i][2]*sum<=0){
			w1 += x[i][2]*x[i][0];
			w2 += x[i][2]*x[i][1];
			b += x[i][2];
		}else{
			flag++;
		}
	}
	}
	cout<<"w1:"<<w1<<"  w2:"<<w2<<"  b:"<<b<<endl;
	for (int i = 0; i < 10; ++i)
	{
		int x1,x2=0;
		cin>>x1>>x2;
		// cout<<Distinguish(x1,x2)<<endl;
	}
	return 0;
}


线性不可分

上面我们好像做了什么不得了的事情,当时人们研究perceptron时也是这么觉得,好像在当时这是一次浪潮~但是有一天有一个哥们说这个感知机怎么不能解决异或问题,浪潮一下就被扑灭了,有兴趣的可以查一查那哥们,我试了试结果如下,果然不行。。我靠博主重启电脑来上图!!直接跑死机了。。。。ctrl+z不是终止进程了嘛。。。查了查好像不完全是。。。哎不管了。

截图时已经迭了100多万代了,还没收敛,最后跑死机了,你们也是知道的。这个问题可以归为一类,就是线性不可分。(如果你观察仔细,这里步长取了0.2,感觉不这样,就算理论上能找到我们也找不到,步子太大,直接过了。。)
三张图一看就一目了然了。感知机得到的线性分界面,And啊,Or啊,都可以得到满意的结果,可是Xor我们人都不能划一道线把它们分开,所以感知机就一直学啊学啊,学啊学啊,然后就死机了。。要解决这个问题我们就要引入多层感知机,就是多几层嘛,我们下章再讲。多层感知机,基本张这样:

本人一边学,一边写,算是给自己动力吧~~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值