在深入探讨深度学习之前,理解感知器的概念至关重要。感知器是深度学习的一个基础组件,其实现有助于更好地掌握深度学习的基础。本文将详细介绍感知器的工作原理,并展示如何从零开始实现一个感知器模型。将通过解决AND门的经典问题来验证感知器的能力。
感知器的概念最早由Warren McCullock和Walter Pitts提出,他们在论文《a logical calculus immanent in nervous activity》中首次探讨了大脑活动是否可以用数学模型来理解。他们提出,如果大脑能够被数学建模,那么它就能从周围环境中学习并提高性能。这与学习走路的过程相似,出生时不会走路,但随着时间的推移,学会了走路,并且现在能够很好地行走。McCullock和Pitts尝试将这一理念用数学方式实现。
感知器由Frank Rosenblatt在1957年引入,它类似于人工神经网络,但只有一个神经元单元在隐藏层。接下来,将深入了解感知器的工作原理,以便更好地理解其功能。
感知器的输入是数据(x, y, z),权重(wo, w1, w2)是随机分配的。输入数据与权重相乘后,传递给感知器激活函数,该函数将帮助得到结果。感知器用于二元和线性结果的情况。二元意味着有两个类别:真或假,高或低。线性意味着可以通过画一条线来分隔类别。
在图像A中,类别是线性的。在图像B中,类别是非线性的。当输入进入感知器激活函数时,激活函数将对类别进行正负(高或低/开或关)分类。使用了一个简单的步进函数,如果输入为负,则将其分类为类别0;如果输入为正,则分类为类别1。
已经介绍了感知器的前向传播,但如果得到错误的结果怎么办?将学习(就像走路时会跌倒,但仍然会站起来学习),类似于生活,神经网络也会学习并调整权重,直到损失函数最小化。
损失函数是一个衡量模型预测与实际结果差异的函数。在这里,为了简单起见,使用最简单的损失函数。有许多损失函数,甚至可以创建自己的损失函数。损失函数将根据权重进行优化,使用以下方程式:
weights = weights - eta * (error * X)
所有的计算都在矩阵和向量的上下文中进行,因此矩阵空间中的方程式变为:
weights = weights - eta * np.dot(X.T, error)
引入了一个新的术语eta,即学习率。学习率是一个“在优化算法中确定每次迭代步长的调整参数,同时向损失函数的最小值移动”。它通常取值在0到1之间。
简而言之,有数据(应该是线性的,试图解决一个二元分类问题),将输入传递给感知器,并使用反向传播更新权重。现在,输出取决于权重,因此正确的权重分配变得至关重要。
提示:始终记住,当类别分离是线性的时候,感知器的效果最好(这在日常工作中的频率较低,这也解释了深度学习的演变)。但无论如何,它是学习的一个重要部分。
已经讨论了很多理论,现在应该转向编码实现。将尝试从头开始实现一切,以便事情变得非常清晰。在编码之前,必须理解试图解决的是AND门的经典案例。许多逻辑门在深度学习进化的初期扮演了非常重要的角色,因为模型在损失函数和权重方面的可解释性很高。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.colors import ListedColormap
class Perceptron:
def __init__(self, eta, epochs):
self.weights = np.random.randn(3) * 1e-4
self.eta = eta
self.epochs = epochs
def activationFunction(self, inputs, weights):
z = np.dot(inputs, weights)
return np.where(z > 0, 1, 0)
def fit(self, X, y):
self.X = X
self.y = y
X_with_bias = np.c_[self.X, -np.ones((len(self.X), 1))]
for epoch in range(self.epochs):
y_hat = self.activationFunction(X_with_bias, self.weights)
self.error = self.y - y_hat
self.weights = self.weights + self.eta * np.dot(X_with_bias.T, self.error)
def predict(self, X):
X_with_bias = np.c_[X, -np.ones((len(X), 1))]
return self.activationFunction(X_with_bias, self.weights)
def prepare_data(df):
X = df.drop("y", axis=1)
y = df["y"]
return X, y
AND = {
"x1": [0, 0, 1, 1],
"x2": [0, 1, 0, 1],
"y": [0, 0, 0, 1],
}
df = pd.DataFrame(AND)
X, y = prepare_data(df)
ETA = 0.3
EPOCHS = 10
model = Perceptron(eta=ETA, epochs=EPOCHS)
model.fit(X, y)