目录
简介
对我来说,感知器听起来像是变形金刚系列中的一个角色,确实在变形金刚中有一个赛博坦星球。在机器学习中,感知器是由Frank Rosenblatt在1958年创建的一个智能决策单元。它本质上是一个二分类器。感知器最早的应用之一是垃圾邮件过滤。我们以"免费"或"中奖"等警示词的频率、邮件发送者的信誉、邮件长度等特征作为输入,输出1(垃圾邮件)或0(非垃圾邮件)。
(感知器如何处理输入并产生输出的可视化表示)
什么是感知器?
感知器是一个决策单元,它接收输入(如邮件中的垃圾词)并输出二元决策(是或否)。它首先计算加权和:
z = ( w 1 × x 1 ) + ( w 2 × x 2 ) + … + ( w n × x n ) + 偏置 z = (w_1 \times x_1) + (w_2 \times x_2) + \ldots + (w_n \times x_n) + \text{偏置} z=(w1×x1)+(w2×x2)+…+(wn×xn)+偏置
或者用求和符号表示:
z = ∑ i = 1 n w i x i + b z = \sum_{i=1}^{n} w_i x_i + b z=i=1∑nwixi+b
然后它应用所谓的阶跃(激活)函数将和"强制"转换为0或1,我们就得到了一个二分类器。
输出 = { 1 , 如果 z ≥ 0 0 , 如果 z < 0 \text{输出} = \begin{cases} 1, & \text{如果 } z \geq 0 \\ 0, & \text{如果 } z < 0 \end{cases} 输出={1,0,如果 z≥0如果 z<0
其中:
- 如果加权和 (z) 大于或等于零,感知器输出1。
- 如果加权和小于零,感知器输出0。
示例:垃圾邮件检测器
假设我们有两个关于邮件的线索(输入):
- 是否包含垃圾词(如"免费赚钱!")?(是则为1,否则为0)
- 发送者是否可疑?(是则为1,否则为0)
假设只有当两个条件都为真时,邮件才是垃圾邮件(这就像逻辑"与"运算)。
import numpy as np
import matplotlib.pyplot as plt # 用于后面的酷炫图表!
class Perceptron:
def __init__(self, learning_rate=0.1, n_epochs=10):
# 学习速度和训练轮数
self.lr = learning_rate
self.n_epochs = n_epochs
self.weights = None # 我们还不知道最佳权重!
self.bias = 0 # 也不知道最佳偏置!
# 这里是学习发生的地方
# 函数名fit表示我们正在拟合系数(权重)到正确的结果
def fit(self, X, y): # X是输入数据,y是正确答案
n_features = X.shape[1] # 我们有多少个特征
self.weights = np.zeros(n_features) # 从猜测权重为零开始
for _ in range(self.n_epochs): # 多次遍历数据
for x_i, target_label in zip(X, y): # 查看每个邮件样本
# 做出预测
weighted_sum = np.dot(x_i, self.weights) + self.bias
prediction = 1 if weighted_sum >= 0 else 0
# 我们错得有多离谱?
error = target_label - prediction
# 调整权重和偏置以在下一次做得更好
update_amount = self.lr * error
self.weights += update_amount * x_i
self.bias += update_amount
# 学习后,如何做出预测?
def predict(self, X):
weighted_sum = np.dot(X, self.weights) + self.bias
return np.where(weighted_sum >= 0, 1, 0) # 如果和>=0则为1,否则为0
# 我们的玩具邮件数据:[垃圾词, 可疑发送者]
X_emails = np.array([
[0, 0], # 不垃圾,不可疑 -> 非垃圾邮件 (0)
[0, 1], # 不垃圾,但可疑 -> 非垃圾邮件 (0)
[1, 0], # 垃圾,但不可疑 -> 非垃圾邮件 (0)
[1, 1] # 垃圾且可疑 -> 垃圾邮件!(1)
])
y_labels = np.array([0, 0, 0, 1]) # "正确"答案
# 让我们训练我们的感知器!
spam_detector = Perceptron(learning_rate=0.1, n_epochs=10)
spam_detector.fit(X_emails, y_labels)
predictions = spam_detector.predict(X_emails)
print("我们的检测器预测:", predictions) # 应该是 [0 0 0 1]
print("实际标签:", y_labels)
print("学习到的权重(每个线索的重要性):", spam_detector.weights)
print("学习到的偏置:", spam_detector.bias)
def plot_decision_boundary(X, y, model):
plt.figure(figsize=(7,5))
plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1],
label="非垃圾邮件", c="skyblue", marker="o", s=100)
plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1],
label="垃圾邮件!", c="salmon", marker="x", s=100)
# 感知器"画"出的分隔垃圾和非垃圾邮件的线
# 方程:w1*x1 + w2*x2 + b = 0 => x2 = -(w1*x1 + b) / w2
# 我们需要确保weights[1]不为零以避免除以零!
if model.weights[1] != 0:
x1_vals = np.array([min(X[:,0])-0.5, max(X[:,0])+0.5]) # 线的范围
x2_vals = -(model.weights[0] * x1_vals + model.bias) / model.weights[1]
plt.plot(x1_vals, x2_vals, "k--", label="决策边界")
else: # 如果weight[1]为零,边界是垂直线 x1 = -bias/weight[0]
if model.weights[0] != 0:
x1_val = -model.bias / model.weights[0]
plt.axvline(x=x1_val, color='k', linestyle='--',
label="决策边界")
else: # 如果两个权重都为零,情况有点奇怪,可能没有边界或全是同一类
print("如果两个权重都为零(或接近零),无法绘制边界!")
plt.xlabel("线索1:垃圾词?(0=否, 1=是)")
plt.ylabel("线索2:可疑发送者?(0=否, 1=是)")
plt.xticks([0,1])
plt.yticks([0,1])
plt.legend()
plt.grid(True, linestyle=':', alpha=0.7)
plt.title("感知器决策:垃圾邮件还是非垃圾邮件?")
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.show()
plot_decision_boundary(X_emails, y_labels, spam_detector)
代码中发生了什么?
Perceptron
类:__init__
:设置学习速度(learning_rate
)和训练轮数(n_epochs
)。fit
:这是训练部分。它做出预测,检查是否正确,如果不正确,就调整其weights
和bias
以在下一次做得更好。它对所有样本重复这个过程。predict
:训练后,这是它对新(或旧)数据做出判断的方式。
- 玩具数据: 我们创建了一个小数据集。它是"线性可分的",意味着你可以画一条直线来分隔垃圾和非垃圾邮件样本(你会在图中看到!)。
- 训练: 我们创建一个
Perceptron
并告诉它fit
我们的数据。 - 输出: 它应该预测
[0 0 0 1]
,意味着它学会了我们的"与"规则!权重和偏置告诉我们它是如何学会这个规则的。 - 绘图: 图表显示我们的数据点和"决策边界" - 感知器用来做决定的线。一边是"非垃圾邮件",另一边是"垃圾邮件"。
这是一个超级简单的例子,但它展示了核心思想!真实的垃圾邮件检测器使用更多的线索(特征)和更多的数据。在现实世界中,我们已经转向使用深度学习和更复杂的模型来对抗垃圾邮件,而不是感知器。
训练感知器(它实际上是如何学习的?)
在这种上下文中,"训练"模型意味着我们有很多邮件,并且我们知道这些邮件是否是垃圾邮件。这意味着我们已经知道答案,我们正在训练模型找到能够得出正确结论的最佳权重。
-
第一次猜测(初始化): 感知器开始时一无所知。所以,它对权重(每个线索的重要性)和偏置做出一个随机的猜测。通常,它只是将所有权重设为零或一些小的随机数。
-
然后感知器从一封邮件开始并做出预测。它将这个预测与已知结果进行比较。
-
预测和已知结果之间的差异称为误差。根据误差,感知器通过将学习率应用于差异来调整权重,如果有误差的话。这种调整希望能在下一轮带来更好的结果。这个学习过程的速率由learning_rate的值控制。较大的值意味着更快的学习速率,但我们可能会因为跳得太快而错过正确的值。另一方面,较小的值意味着我们可能需要学习更多次,过程会更慢。
-
线性可分: 这意味着我们可以画一条直线来分隔垃圾和非垃圾邮件。
感知器的局限性
可怕的XOR问题(和线性可分性)
还记得我们说过如果可以用一条直线来分隔你的组,感知器就能很好地工作吗?这被称为"线性可分"。
考虑**XOR(异或)**问题。XOR意味着"一个或另一个,但不能同时是两者":
- (0,0) -> 0
- (0,1) -> 1
- (1,0) -> 1
- (1,1) -> 0
它是线性不可分的!而AND和OR门是线性可分的。
AND门(就像我们的垃圾邮件例子):
- (0,0) -> 0
- (0,1) -> 0
- (1,0) -> 0
- (1,1) -> 1
我们可以画一条线来分隔(1,1)点和其他点。
结论
尽管感知器很简单,但它在机器学习的历史上占有特殊地位。它是最早尝试创建能够从例子中学习并做出决策的机器之一,就像我们的大脑工作方式一样。虽然它有其局限性 - 特别是它无法解决像XOR这样的非线性可分问题 - 但它为今天我们使用的复杂神经网络奠定了基础。
把感知器看作是神经网络的"Hello World"。它教会我们仍然相关的基本概念:
- 如何用权重组合多个输入
- 如何做出二元决策
- 如何从错误中学习
- 线性可分性的重要性
在现代机器学习中,我们很少再使用单个感知器。相反,我们使用多层感知器(MLP)和深度神经网络,它们可以解决更复杂的问题。这些高级网络本质上是由感知器类单元堆叠而成,具有更复杂的激活函数和学习算法。
所以下次当你使用垃圾邮件过滤器或与任何AI系统交互时,请记住这一切都始于Frank Rosenblatt在1958年提出的这个简单但革命性的想法。感知器可能很基础,但它是现代AI构建的基础。