实现单层感知器的完整指南

165 阅读3分钟

要了解单层感知器,必须了解人工神经网络(ANN)。人工神经网络是一个信息处理系统,其机制受到生物神经回路功能的启发。人工神经网络有许多相互连接的计算单元。人工神经网络的原理图如下:

该图显示,隐藏实体与外部层进行交流。而输入和输出单元则只通过网络的隐藏层进行交流。

与节点的连接模式、层的总数、输入和输出之间的节点层次以及每层的神经元数量,定义了神经网络的架构。

有两种类型的架构。这些类型侧重于功能的人工神经网络,如下所示:

  • 单层感知器
  • 多层感知器

单层感知器

单层是最早提出的神经模型。神经元的局部存储器的内容由权重向量组成。单层的计算,是通过将每个值的输入向量之和乘以权重向量的相应元素来完成。输出中显示的值激活函数的输入。

单层感知器**(SLP**)是一个基于阈值传递函数的前馈网络。SLP是最简单的人工神经网络类型,只能对具有二进制目标(1 , 0)的线性可分离情况进行分类。

激活函数和它的意义

激活函数是神经网络的决策单元。它们计算一个神经节点的净输出。在这里,Heaviside阶梯函数是神经网络中最常见的激活函数之一。该函数产生二进制输出。这就是为什么它也被称为二进制步骤函数的原因。当输入通过阈值限制时,该函数产生1(或真),而当输入没有通过阈值时,它产生0(或假)。这就是为什么它们对二元分类研究非常有用。

它是一种非线性转换,我们在将输入发送到下一层神经元或最终确定为输出之前,对其进行非线性转换。一个神经元的激活函数决定了它是否应该被打开或关闭。非线性函数通常将神经元的输出转化为0到1或-1到1之间的数字。激活函数的目的是在神经元的输出中引入非线性。

海维塞德阶跃函数通常只在单层感知器中有用,这是一种早期的神经网络类型,在输入数据是线性可分离的情况下可用于分类。

激活函数的类型

算法

单层感知器没有先验知识,所以初始权重是随机分配的。SLP对所有加权的输入进行求和,如果求和高于阈值(一些预定的值),则称SLP被激活(输出=1)。

输入值被提交给感知器,如果预测的输出与期望的输出相同,那么性能被认为是令人满意的,不需要对权重进行改变。然而,如果输出与期望输出不一致,那么就需要改变权重以减少误差。

因为SLP是一个线性分类器,如果案例不是线性可分离的,那么学习过程将永远不会达到所有案例都被正确分类的程度。最著名的例子是XOR问题,说明感知器无法解决具有线性不可分离的情况的问题。

实现单层感知器的完整代码----

import numpy as np
import pandas as pd

data=pd.read_csv('iris.csv')
data.columns=['Sepal_len_cm','Sepal_wid_cm','Petal_len_cm','Petal_wid_cm','Type']


# I am using Sigmoid function as the activation function

def activation_func(value):    #Tangent Hypotenuse
    #return (1/(1+np.exp(-value)))
    return ((np.exp(value)-np.exp(-value))/(np.exp(value)+np.exp(-value)))


def perceptron_train(in_data,labels,alpha):
    X=np.array(in_data)
    y=np.array(labels)
    weights=np.random.random(X.shape[1])
    original=weights
    bias=np.random.random_sample()
    for key in range(X.shape[0]):
        a=activation_func(np.matmul(np.transpose(weights),X[key]))
        yn=0
        if a>=0.7:
            yn=1
        elif a<=(-0.7):
            yn=-1
        weights=weights+alpha*(yn-y[key])*X[key]
        print('Iteration '+str(key)+': '+str(weights))
    print('Difference: '+str(weights-original))
    return weights

#  Testing and Score

def perceptron_test(in_data,label_shape,weights):
    X=np.array(in_data)
    y=np.zeros(label_shape)
    for key in range(X.shape[1]):
        a=activation_func((weights*X[key]).sum())
        y[key]=0
        if a>=0.7:
            y[key]=1
        elif a<=(-0.7):
            y[key]=-1
    return y


def score(result,labels):
    difference=result-np.array(labels)
    correct_ctr=0
    for elem in range(difference.shape[0]):
        if difference[elem]==0:
            correct_ctr+=1
    score=correct_ctr*100/difference.size
    print('Score='+str(score))


# Main code

divider = np.random.rand(len(data)) < 0.70
d_train = data[divider]
d_test = data[~divider]

# Dividing d_train into data and labels/targets
d_train_y = d_train['Type']
d_train_X = d_train.drop(['Type'], axis=1)

    # Dividing d_train into data and labels/targets
d_test_y = d_test['Type']
d_test_X = d_test.drop(['Type'], axis=1)

    # Learning rate
alpha = 0.001

    # Train
weights = perceptron_train(d_train_X, d_train_y, alpha)

    # Test
result_test = perceptron_test(d_test_X, d_test_y.shape, weights)

    # Calculate score
score(result_test, d_test_y)

输出