我正在尝试将单层感知器分类器的 Python 实现放在一起。我发现 Sebastian Raschka 的《Python 机器学习》一书中的示例非常有用,但我对他的实现的一小部分有疑问。这是代码:
import numpy as np
class Perceptron(object):
"""Perceptron classifier.
Parameters
------------
eta : float
Learning rate (between 0.0 and 1.0)
n_iter : int
Passes over the training dataset.
Attributes
-----------
w_ : 1d-array
Weights after fitting.
errors_ : list
Number of misclassifications in every epoch.
"""
def __init__(self, eta=0.01, n_iter=10):
self.eta = eta
self.n_iter = n_iter
def fit(self, X, y):
"""Fit training data.
Parameters
----------
X : {array-like}, shape = [n_samples, n_features]
Training vectors, where n_samples
is the number of samples and
n_features is the number of features.
y : array-like, shape = [n_samples]
Target values.
Returns
-------
self : object
"""
self.w_ = np.zeros(1 + X.shape[1])
self.errors_ = []
for _ in range(self.n_iter):
errors = 0
for xi, target in zip(X, y):
update = self.eta * (target - self.predict(xi))
self.w_[1:] += update * xi
self.w_[0] += update
errors += int(update != 0.0)
self.errors_.append(errors)
return self
def net_input(self, X):
"""Calculate net input"""
return np.dot(X, self.w_[1:]) + self.w_[0]
def predict(self, X):
"""Return class label after unit step"""
return np.where(self.net_input(X) >= 0.0, 1, -1)
我无法理解的部分是为什么我们定义
net_input()
和
predict()
来采用数组
X
而不仅仅是一个向量。一切顺利,因为我们只将向量
xi
传递给
predict()
函数中的
fit()
(因此也只将向量传递给
net_input()
),但是将函数定义为背后的逻辑是什么取一个数组?如果我正确理解该模型,我们一次只取一个样本,计算权重向量和与样本相关的特征向量的点积,并且我们永远不需要将整个数组传递给
net_input()
或|| |。
predict()
.
你对感知器算法的理解是正确的,而且你观察到在这个特定的实现中,
net_input()
和
predict()
函数一次只应用于一个样本,这也是正确的。但是,将这些函数设计为可以处理数组而不是单个向量,有几个原因:
-
效率: 向量化。通过将
X
设计为一个数组,该代码可以利用 NumPy 的向量化操作。这意味着不是循环遍历每个样本,而是可以使用一个矩阵操作来同时计算所有样本的点积。这对于大型数据集来说效率要高得多。 -
代码简洁性: 使用数组作为输入,
fit()
函数中的训练循环可以写得更紧凑。zip(X, y)
表达式创建了样本和标签的对,而predict()
函数可以应用于整个X
数组,而无需额外的循环。这使代码更易于阅读和理解。 -
灵活性: 将数组作为输入,可以在训练后更容易地对新的样本集进行预测。你可以将一个包含多个样本的数组传递给
predict()
函数,它将返回一个包含每个样本预测的数组。
虽然感知器算法一次处理一个样本,但从设计角度来看,让
net_input()
和
predict()
函数接受数组输入更有益。这利用了 NumPy 的向量化功能来提高效率、使代码更简洁,并提供更大的灵活性来处理样本集。
总而言之,即使当前实现一次只对一个样本使用
predict()
,但将
net_input()
和
predict()
函数概括为处理数组是基于效率、代码简洁性和灵活性的深思熟虑的设计选择。