使用Python来编写一个简单的感知机

https://blog.dbrgn.ch/2013/3/26/perceptrons-in-python/

目前,我在HSR上参加了一个神经网络和机器学习的课程,其中学习到一个最简单的神经网络模型,就是感知机(perceptronperceptronperceptron)。

背景资料

最简单的神经网络的模型就是感知机分类器,它有不同的输入(x1, x2,......xn),然后有不同的权重值(w1, w2,......Wn),如下式计算:

每个对应的权重值与输入值进行相乘,再相加在一起,然后通过一个阶梯函数f:

为了理解整个过程,下面就是它的简化版本的流程图:

用Python代码来编写

下面是使用Python和NumPy库来编写最简单的感知机,它由两个输入值,接着使用它来学习布尔运算OR的操作,第一步,先导入要使用的库:

from random import choice

from numpy import array, dot, random

接着编写阶梯函数,把它的定义为unit_step:

unit_step = lambda x: 0 if x < 0 else 1

http://reference.wolfram.com/language/ref/UnitStep.html

接着下来编写输入与输出的映射关系的数据,使用Numpy数组来表示,第一个元素是一个三个元素的元组表示,而这个元组的前两个值表示了两个输入值,第三个元素是表示偏差值(主要针对阈值计算),总是使用值1来表示;第二个元素是表示期望输出的值。这个数组定义如下:

training_data = [

(array([0,0,1]), 0),

(array([0,1,1]), 1),

(array([1,0,1]), 1),

(array([1,1,1]), 1),

]

从上训练数据可以看到布尔运算符OR的关系如下:

接着下来使用随机函数来生成三个0和1之间的权重值,作为初始化值:

w = random.rand(3)

到现在可以声明一些变量了,列表变量errors是保存着误差值,同时也为后面绘图使用的,如果你不想绘图,也没有关系,就让它这样留着。变量eta控制着学习速率,变量n是定义了迭代学习多少遍:

errors = []

eta = 0.2

n = 100

为了找到合适的权重值w,需要把误差值减小到0。在这个例子里,迭代100次是足够了,如果输入是一个非常多噪声的数据集,需要把这个迭代数量增加到更大的值。

首先为了训练这个感知机,要生成随机的数据集作为输入。接着计算输入值与权重值向量之间的点积运算,从而得到可以与期望值进行比较的结果值。如果期望值是比较大,需要把权重值增加,如果期望值是比较小,需要把权重值减小。此校正因子计算在最后一行,其中的误差乘以学习速率(eta)和输入向量(x),再把这些权重值的误差值加到权重值向量里,这样就可以为了下一次的计算输出值向更接近期望值的方向进行调整。

for i in xrange(n):

x, expected = choice(training_data)

result = dot(w, x)

error = expected - unit_step(result)

errors.append(error)

w += eta * error * x

所有基础的代码都编写好了,接着下来就是训练这个感知机,让它来学习或操作:

for x, _ in training_data:

result = dot(x, w)

print("{}: {} -> {}".format(x[:2], result, unit_step(result)))

[0 0]: -0.0714566687173 -> 0

[0 1]: 0.829739696273 -> 1

[1 0]: 0.345454042997 -> 1

[1 1]: 1.24665040799 -> 1

如果对误差值也感兴趣,可以采用可视化的库来显示出来:

from pylab import plot, ylim

ylim([-1,1])

plot(errors)

可以从上图看到,从第60次迭代就没有误差值了,如果你感觉这个误差值,还不行,再计算小一些,可以把训练的次数修改为500次,或者更多的次数:

另外,你也可以动手把训练数据改为学习布尔运算AND,NOR或NOT,不过,你要注意的一点,它不能模拟XOR运算,因为XOR运算不是线性可划分的,如果你想模拟XOR运算必须使用多层的神经元感知机(基本上就是一个小型的神经网络了)。

总结

全部代码如下:

from random import choice 
from numpy import array, dot, random 

unit_step = lambda x: 0 if x < 0 else 1 

training_data = [ 
(array([0,0,1]), 0), 
(array([0,1,1]), 1), 
(array([1,0,1]), 1), 
(array([1,1,1]), 1), 
] 

w = random.rand(3) 
errors = [] 
eta = 0.2 
n = 100

for i in range(n): 
    x, expected = choice(training_data) 
    result = dot(w, x) 
    error = expected - unit_step(result) 
    errors.append(error) 
    w += eta * error * x 
    
for x, _ in training_data: 
    result = dot(x, w) 
    print("{}: {} -> {}".format(x[:2], result, unit_step(result)))

1. TensorFlow API攻略

http://edu.csdn.net/course/detail/4495

2. TensorFlow入门基本教程

http://edu.csdn.net/course/detail/4369

3. C++标准模板库从入门到精通

http://edu.csdn.net/course/detail/3324

4.跟老菜鸟学C++

http://edu.csdn.net/course/detail/2901

5. 跟老菜鸟学python

http://edu.csdn.net/course/detail/2592

6. 在VC2015里学会使用tinyxml库

http://edu.csdn.net/course/detail/2590

7. 在Windows下SVN的版本管理与实战

http://edu.csdn.net/course/detail/2579

8.Visual Studio 2015开发C++程序的基本使用

http://edu.csdn.net/course/detail/2570

9.在VC2015里使用protobuf协议

http://edu.csdn.net/course/detail/2582

10.在VC2015里学会使用MySQL数据库

http://edu.csdn.net/course/detail/2672

时间: 2024-08-24 09:27:04

使用Python来编写一个简单的感知机的相关文章

Python学习 - 编写一个简单的web框架(二)

在上一篇日志中已经讨论和实现了根据url执行相应应用,在我阅读了bottle.py官方文档后,按照bottle的设计重写一遍,主要借鉴大牛们的设计思想. 一个bottle.py的简单实例 来看看bottle是如何使用的,代码来自http://www.bottlepy.org/docs/0.12/index.html: from bottle import route, run, template @route('/hello/<name>') def index(name): return t

Python学习 - 编写一个简单的web框架(一)

自己动手写一个web框架,因为我是菜鸟,对于python的一些内建函数不是清楚,所以在写这篇文章之前需要一些python和WSGI的预备知识,这是一系列文章.这一篇只实现了如何处理url. 参考这篇文章:http://www.cnblogs.com/russellluo/p/3338616.html 预备知识 web框架主要是实现web服务器和web应用之间的交互.底层的网络协议主要有web服务器完成.譬如监听端口,填充报文等等. Python内建函数__iter__和__call__和WSGI

【C++】编写一个简单的类。包含构造函数,成员函数等。

<pre name="code" class="cpp">//编写一个简单的类.包含构造函数,成员函数等. #include <iostream> using namespace std; class Rec { public: Rec(int l,int w); int Area(); void Print(); private: int length,wide; }; Rec::Rec(int l,int w) { length=l; w

【C++】编写一个简单的函数实现重载。

//编写一个简单的函数实现重载. #include <iostream> using namespace std; int max(int a,int b) { return a>b?a:b; } int max(int a,int b,int c) { int x=max(a,b); return max(x,c); } double max(double a,double b) { return a>b?a:b; } int main() { cout<<"

编写一个简单的内核驱动模块时报错 “/lib/modules/3.13.0-32-generic/bulid: 没有那个文件或目录。 停止。”

编写一个简单的内核驱动模块 1 static int hello_init() 2 { 3 printk("hello,I am in kernel now\n"); 4 return 0; 5 } 6 void addfunc(int a,int b) 7 {return a+b;} 8 static void hello_exit() 9 { 10 printk("hello ,I will leave the kernel now\n"); 11 } 12 m

手把手教你编写一个简单的PHP模块形态的后门

看到Freebuf 小编发表的用这个隐藏于PHP模块中的rootkit,就能持久接管服务器文章,很感兴趣,苦无作者没留下PoC,自己研究一番,有了此文 0×00. 引言 PHP是一个非常流行的web server端的script语言.目前很多web应用程序都基于php语言实现.由于php是个开源软件并易于扩展,所以我们可以通过编写一个PHP模块(module 或者叫扩展 extension)来实现一个Backdoor. 本文就简单介下如何一步步编写一个简单的php 动态扩展后门. 0×01. p

编写一个简单的jdbc例子程序

1 package it.cast.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 import java.sql.Statement; 8 9 public class Base { 10 11 public static void main(String[] args) th

【Python】 做一个简单的 http 服务器

# coding=utf-8 ''' Created on 2014年6月15日 @author: Yang ''' import socket import datetime # 初始化socket s = socket.socket() # 获取主机名, 也可以使用localhost # host = socket.gethostname() host = "localhost" # 默认的http协议端口号 port = 80 # 绑定服务器socket的ip和端口号 s.bin

编写一个简单的javaEE加法程序

一 .javaEE的安装及环境配置 工具: 32位系统准备eclipse-jee-mars-2-win32.zip,64位系统准备eclipse-jee-mars-2-win32-x86_64.zip jdk1.7 maven3.3.9.rar m2.rar 环境配置: 1. 设置eclipse的配置文件eclipse.ini,修改虚拟机路径,在-vmargs之前添加 -vm E:\jee\jdk1.7\bin\javaw.exe 注意:用写字板打开修改,-vm有的电脑要换行,有的电脑不用换行