感知机介绍及实现

感知机(perceptron)由Rosenblatt于1957年提出,是神经网络与支持向量机的基础。

感知机是最早被设计并被实现的人工神经网络。感知机是一种非常特殊的神经网络,它在人工神经网络的发展史上有着非常重要的地位,尽管它的能力非常有限,主要用于线性分类。

感知机还包括多层感知机,简单的线性感知机用于线性分类器,多层感知机(含有隐层的网络)可用于非线性分类器。本文中介绍的均是简单的线性感知机。

图 1

感知机工作方式

(1)、学习阶段:修改权值和偏置,根据”已知的样本”对权值和偏置不断修改----有监督学习。当给定某个样本的输入/输出模式对时,感知机输出单元会产生一个实际输出向量,用期望输出(样本输出)与实际输出之差来修正网络连接权值和偏置。

(2)、工作阶段:计算单元变化,由响应函数给出新输入下的输出。

感知机学习策略

感知机学习的目标就是求得一个能够将训练数据集中正负实例完全分开的分类超平面,为了找到分类超平面,即确定感知机模型中的参数w和b,需要定义一个基于误分类的损失函数,并通过将损失函数最小化来求w和b。

(1)、数据集线性可分性:在二维平面中,可以用一条直线将+1类和-1类完美分开,那么这个样本空间就是线性可分的。因此,感知机都基于一个前提,即问题空间线性可分;

(2)、定义损失函数,找到参数w和b,使得损失函数最小。

损失函数的选取

(1)、损失函数的一个自然选择就是误分类点的总数,但是这样的点不是参数w,b的连续可导函数,不易优化;

(2)、损失函数的另一个选择就是误分类点到划分超平面S(w*x+b=0)的总距离。

以上理论部分主要来自: http://staff.ustc.edu.cn/~qiliuql/files/DM2013/2013SVM.pdf

以下代码根据上面的描述实现:

#include <iostream>
#include <vector>
#include <assert.h>
#include <time.h>

typedef std::vector<float> feature;
typedef int label;

class Perceptron {
private:
	std::vector<feature> feature_set;
	std::vector<label> label_set;
	int iterates;
	float learn_rate;
	std::vector<float> weight;
	int size_weight;
	float bias;

	void initWeight();
	float calDotProduct(const feature feature_, const std::vector<float> weight_);
	void updateWeight(const feature feature_, int label_);

public:
	Perceptron(int iterates_, float learn_rate_, int size_weight_, float bias_);
	void getDataset(const std::vector<feature> feature_set_, const std::vector<label> label_set_);
	bool train();
	label predict(const feature feature_);
};

void Perceptron::updateWeight(const feature feature_, int label_)
{
	for (int i = 0; i < size_weight; i++) {
		weight[i] += learn_rate * feature_[i] * label_; // formula 5
	}

	bias += learn_rate * label_; // formula 5
}

float Perceptron::calDotProduct(const feature feature_, const std::vector<float> weight_)
{
	assert(feature_.size() == weight_.size());
	float ret = 0.;

	for (int i = 0; i < feature_.size(); i++) {
		ret += feature_[i] * weight_[i];
	}

	return ret;
}

void Perceptron::initWeight()
{
	srand(time(0));
	float range = 100.0;
	for (int i = 0; i < size_weight; i++) {
		float tmp = range * rand() / (RAND_MAX + 1.0);
		weight.push_back(tmp);
	}
}

Perceptron::Perceptron(int iterates_, float learn_rate_, int size_weight_, float bias_)
{
	iterates = iterates_;
	learn_rate = learn_rate_;
	size_weight = size_weight_;
	bias = bias_;
	weight.resize(0);
	feature_set.resize(0);
	label_set.resize(0);
}

void Perceptron::getDataset(const std::vector<feature> feature_set_, const std::vector<label> label_set_)
{
	assert(feature_set_.size() == label_set_.size());

	feature_set.resize(0);
	label_set.resize(0);

	for (int i = 0; i < feature_set_.size(); i++) {
		feature_set.push_back(feature_set_[i]);
		label_set.push_back(label_set_[i]);
	}
}

bool Perceptron::train()
{
	initWeight();

	for (int i = 0; i < iterates; i++) {
		bool flag = true;

		for (int j = 0; j < feature_set.size(); j++) {
			float tmp = calDotProduct(feature_set[j], weight) + bias;
			if (tmp * label_set[j] <= 0) {
				updateWeight(feature_set[j], label_set[j]);
				flag = false;
			}
		}

		if (flag) {
			std::cout << "iterate: " << i << std::endl;
			std::cout << "weight: ";
			for (int m = 0; m < size_weight; m++) {
				std::cout << weight[m] << "    ";
			}
			std::cout << std::endl;
			std::cout << "bias: " << bias << std::endl;

			return true;
		}
	}

	return false;
}

label Perceptron::predict(const feature feature_)
{
	assert(feature_.size() == size_weight);

	return calDotProduct(feature_, weight) + bias >= 0 ? 1 : -1; //formula 2
}

int main(int argc, char* argv[])
{
	// prepare data
	const int len_data = 20;
	const int feature_dimension = 2;
	float data[len_data][feature_dimension] = { { 10.3, 10.7 }, { 20.1, 100.8 }, { 44.9, 8.0 }, { -2.2, 15.3 }, { -33.3, 77.7 },
						    { -10.4, 111.1 }, { 99.3, -2.2 }, { 222.2, -5.5 }, { 10.1, 10.1 }, {66.6, 30.2},
						    { 0.1, 0.2 }, { 1.2, 0.03 }, { 0.5, 4.6 }, { -22.3, -11.1 }, {-88.9, -12.3},
						    { -333.3, -444.4 }, { -111.2, 0.5 }, { -6.6, 2.9 }, { 3.3, -100.2 }, {5.6, -88.8} };
	int label_[len_data] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
				 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };

	std::vector<feature> set_feature;
	std::vector<label> set_label;

	for (int i = 0; i < len_data; i++) {
		feature feature_single;
		for (int j = 0; j < feature_dimension; j++) {
			feature_single.push_back(data[i][j]);
		}

		set_feature.push_back(feature_single);
		set_label.push_back(label_[i]);

		feature_single.resize(0);
	}

	// train
	int iterates = 1000;
	float learn_rate = 0.5;
	int size_weight = feature_dimension;
	float bias = 2.5;
	Perceptron perceptron(iterates, learn_rate, size_weight, bias);
	perceptron.getDataset(set_feature, set_label);
	bool flag = perceptron.train();
	if (flag) {
		std::cout << "data set is linearly separable" << std::endl;
	}
	else {
		std::cout << "data set is linearly inseparable" << std::endl;
		return -1;
	}

	// predict
	feature feature1;
	feature1.push_back(636.6);
	feature1.push_back(881.8);
	std::cout << "the correct result label is 1, " << "the real result label is: " << perceptron.predict(feature1) << std::endl;

	feature feature2;
	feature2.push_back(-26.32);
	feature2.push_back(-255.95);
	std::cout << "the correct result label is -1, " << "the real result label is: " << perceptron.predict(feature2) << std::endl;

	std::cout << "ok" << std::endl;
	return 0;
}

运行结果如下图:

时间: 2024-10-14 01:43:29

感知机介绍及实现的相关文章

Neural Network学习(一) 最早的感知机:Perceptron of Rosenblatt

1. Frank Rosenblatt 首先介绍的是神经网络的开山祖师,先放张图拜拜 Frank Rosenblatt出生在纽约,父亲是医生,其1956年在Cornell大学拿到博士学位后,留校任教,研究方向为心理学和认知心理学.1957年,Frank提出了Perceptron的理论.1960年,在计算机运算能力还不强的时候,其使用基于硬件结构搭建了一个神经网络,大概长下面这样(跪).   但是和所有先驱一样,Frank开创性的工作并没有在当时得到认可.当时两位科学家 Marvin Minksy

python感知机分类乳腺癌数据集

一.感知机介绍 感知器(英语:Perceptron)是Frank Rosenblatt在1957年就职于康奈尔航空实验室(Cornell Aeronautical Laboratory)时所发明的一种人工神经网络.它可以被视为一种最简单形式的前馈神经网络,是一种二元线性分类器.Frank Rosenblatt给出了相应的感知机学习算法,常用的有感知机学习.最小二乘法和梯度下降法.譬如,感知机利用梯度下降法对损失函数进行极小化,求出可将训练数据进行线性划分的分离超平面,从而求得感知机模型.感知机是

17-占领记忆,从更新权重开始——小而美的感知机

一个人和另一个人的相遇是很奇妙的.人生若只如初见,Wi全都是0.有的人之间自带化学反应,初次见面就噼里啪啦更新权重,经过激活函数得出--1:看你顺眼:-1:负分滚粗(原谅群主的简单粗暴).所谓权重,深藏于生活的每个细节中.曾经看过一篇文章,说即使关系亲密的人之间也是自带评分表的:今天你做了一件事让我开心,score++:明天你惹到我让我不爽,score--.所以无论和关系多好的人相处我们都需要反省,不断调整自己的行为,且行且珍惜.机器学习也是有温度的,你可以把它看作一个活生生的人,感觉触角多且灵

使用感知机训练加法模型

感知机此处不介绍,这里只是简单的做了一个使用感知机思路,训练一个y=a+b计算模型. 1 # -*-coding:utf-8-*- 2 '@author: xijun.gong' 3 import numpy as np 4 import random 5 import math 6 7 8 class Perceptron: 9 def __init__(self, learnRate, maxIter, bit_len): 10 """ 11 :param bit_len

统计学习方法:感知机

作者:桂. 时间:2017-04-16  11:53:22 链接:http://www.cnblogs.com/xingshansi/p/6718503.html 前言 今天开始学习李航的<统计学习方法>,考虑到之前看<自适应滤波>,写的过于琐碎,拓展也略显啰嗦,这次的学习笔记只记录书籍有关的内容.前段时间朋友送了一本<机器学习实战>,想着借此增加点文中算法的代码实现,以加深对内容的理解.本文梳理书本第二章:感知机(Perceptron). 1)原理介绍 2)代码实现

感知机的简单理解

一,感知机模型 1,超平面的定义 令w1,w2,...wn,v都是实数(R) ,其中至少有一个wi不为零,由所有满足线性方程w1*x1+w2*x2+...+wn*xn=v 的点X=[x1,x2,...xn]组成的集合,称为空间R的超平面. 从定义可以看出:超平面就是点的集合.集合中的某一点X,与向量w=[w1,w2,...wn]的内积,等于v 特殊地,如果令v等于0,对于训练集中某个点X: w*X=w1*x1+w2*x2+...+wn*xn>0,将X标记为一类 w*X=w1*x1+w2*x2+.

机器学习-感知机实现(1)

前提 这系列文章不是为了去研究那些数学公式怎么推导,而是为了能将机器学习的思想快速用代码实现.最主要是梳理一下自己的想法. 感知机 感知机,就是接受每个感知元(神经元)传输过来的数据,当数据到达某个阀值的时候就会产生对应的行为如下图,对应每个感知元有一个对应的权重,当数据到达阀值u的时候就会执行对应的行为. u = w0 + w1x1 + w2x2 +......wnxn 对应到垃圾邮件处理上,当u > 0时就是正常邮件.相反则为垃圾邮件 对于这样的模型就可以称之为简单的感知机.也就是一个神经网

(转)神经网络和深度学习简史(第一部分):从感知机到BP算法

深度|神经网络和深度学习简史(第一部分):从感知机到BP算法 2016-01-23 机器之心 来自Andrey Kurenkov 作者:Andrey Kurenkov 机器之心编译出品 参与:chenxiaoqing.范娜Fiona.杨超.微胖.汪汪.赵巍 导读:这是<神经网络和深度学习简史>第一部分.这一部分,我们会介绍1958年感知机神经网络的诞生,70年代人工智能寒冬以及1986年BP算法让神经网络再度流行起来. 深度学习掀起海啸 如今,深度学习浪潮拍打计算机语言的海岸已有好几年,但是,

(转)统计学习-2 感知机知识准备(模型类型、超平面与梯度下降法)

判别模型与生成模型 前面也有过介绍,回顾一下,判别模型的意思就是它不关心数据是怎么产生的,不关心数据之间有何概率关系,它只关心数据之间有什么不同,这种不同会造成什么结果.比如说给你一堆水果,让你把它们中相同种类的放在一个篮子里,判别模型的话,我们直接通过分辨两个果子之间的差别,是黄的还是红的,是大的还是小的来分类,而如果是生成模型,那么我们就需要学习水果的品种,认识水果,那么就可以这样,哦,这个果子看上去更像苹果,那么它就是苹果啦来分类. 从数学的角度来讲,判别模型直接学习条件概率模型 P(Y|