OneRClassifier: 一规则 (OneR) 分类方法
One Rule (OneR) 分类方法的实现。
from mlxtend.classifier import OneRClassifier
概述
"OneR" 代表 One Rule (由 Robert Holte [1] 提出),它是一种经典的监督学习算法。请注意,该算法的预测性能并非突出;因此,它更推荐用于教学目的以及在实际应用中作为性能的下限基准。
"OneRule" 这个名称可能有点误导,因为它技术上是关于“一个特征”,而不是“一个规则”。也就是说,OneR 返回一个特征,为此特征定义了一个或多个决策规则。本质上,作为一个简单的分类器,它只找到一个特征(以及该特征的一个或多个特征值)来对数据实例进行分类。
基本过程如下
- 对于数据集中的所有特征(列)中的每个特征
- 对于给定特征的每个特征值
- 获取具有该特征值的训练样本。
- 获取与上一步中确定的训练样本相对应的类别标签(及类别标签计数)。
- 将频率(计数)最高的类别标签视为多数类。
- 将错误数量记录为具有给定特征值但不是多数类的训练样本数量。
- 通过汇总该特征所有可能特征值的错误来计算该特征的错误。
- 对于给定特征的每个特征值
- 返回最佳特征,最佳特征被定义为错误最低的特征。
请注意,OneR 算法假定特征值是分类的(或离散化的)。在 Interpretable Machine Learning 在线章节“4.5.1 Learn Rules from a Single Feature (OneR)” (https://christophm.github.io/interpretable-ml-book/rules.html, [2]) 中可以找到很好的解释和 OneR 分类器。
参考文献
[1] Holte, Robert C. "Very simple classification rules perform well on most commonly used datasets." Machine learning 11.1 (1993): 63-90.
[2] Interpretable Machine Learning (2018) by Christoph Molnar: https://christophm.github.io/interpretable-ml-book/rules.html
示例 1 -- 在离散化鸢尾花数据集上演示 OneR
如上文概述所述,OneR 算法要求特征是分类的或离散化的。MLxtend 中的 OneRClassifier
实现不会修改数据集中的特征,确保特征是分类的是用户的责任。
在下面的示例中,我们将离散化鸢尾花数据集。特别地,我们将数据集转换为四分位数。换句话说,每个特征值都被替换为一个分类值。对于萼片宽度(鸢尾花数据集的第一列),这将是
- (0, 5.1] => 0
- (5.1, 5.8] => 1
- (5.8, 6.4] => 2
- (6,4, 7.9] => 3
以下是原始鸢尾花数据的前 15 行(花朵)
from mlxtend.data import iris_data
X, y = iris_data()
X[:15]
array([[5.1, 3.5, 1.4, 0.2],
[4.9, 3. , 1.4, 0.2],
[4.7, 3.2, 1.3, 0.2],
[4.6, 3.1, 1.5, 0.2],
[5. , 3.6, 1.4, 0.2],
[5.4, 3.9, 1.7, 0.4],
[4.6, 3.4, 1.4, 0.3],
[5. , 3.4, 1.5, 0.2],
[4.4, 2.9, 1.4, 0.2],
[4.9, 3.1, 1.5, 0.1],
[5.4, 3.7, 1.5, 0.2],
[4.8, 3.4, 1.6, 0.2],
[4.8, 3. , 1.4, 0.1],
[4.3, 3. , 1.1, 0.1],
[5.8, 4. , 1.2, 0.2]])
以下是离散化后的数据集。每个特征被划分为 4 个四分位数。
import numpy as np
def get_feature_quartiles(X):
X_discretized = X.copy()
for col in range(X.shape[1]):
for q, class_label in zip([1.0, 0.75, 0.5, 0.25], [3, 2, 1, 0]):
threshold = np.quantile(X[:, col], q=q)
X_discretized[X[:, col] <= threshold, col] = class_label
return X_discretized.astype(np.int)
Xd = get_feature_quartiles(X)
Xd[:15]
array([[0, 3, 0, 0],
[0, 1, 0, 0],
[0, 2, 0, 0],
[0, 2, 0, 0],
[0, 3, 0, 0],
[1, 3, 1, 1],
[0, 3, 0, 0],
[0, 3, 0, 0],
[0, 1, 0, 0],
[0, 2, 0, 0],
[1, 3, 0, 0],
[0, 3, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[1, 3, 0, 0]])
给定一个带有分类特征的数据集,我们可以像使用 scikit-learn 的分类估计器一样使用 OneR 分类器。首先,我们将数据集划分为训练数据和测试数据
from sklearn.model_selection import train_test_split
Xd_train, Xd_test, y_train, y_test = train_test_split(Xd, y, random_state=0, stratify=y)
接下来,我们可以使用 fit
方法在训练集上训练一个 OneRClassifier
模型
from mlxtend.classifier import OneRClassifier
oner = OneRClassifier()
oner.fit(Xd_train, y_train);
模型拟合后,可以通过 feature_idx_
属性访问所选特征的列索引
oner.feature_idx_
2
模型拟合后,还有一个 prediction_dict_
可用。它列出了所选特征的总错误(即在 feature_idx_
下列出的特征)。它还提供了分类规则
oner.prediction_dict_
{'total error': 16, 'rules (value: class)': {0: 0, 1: 1, 2: 1, 3: 2}}
例如,'rules (value: class)': {0: 0, 1: 1, 2: 1, 3: 2}
意味着所选特征(花瓣长度)有 3 条规则: - 如果值为 0,则分类为 0 (Iris-setosa) - 如果值为 1,则分类为 1 (Iris-versicolor) - 如果值为 2,则分类为 1 (Iris-versicolor) - 如果值为 3,则分类为 2 (Iris-virginica)
模型拟合后,我们可以使用 oner
对象进行预测
oner.predict(Xd_train)
array([1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 2, 2, 1,
0, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 0, 0, 1, 2, 1, 1, 2, 2, 1, 0, 1,
1, 1, 2, 0, 1, 2, 1, 2, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 2, 0, 1, 1,
0, 1, 2, 1, 2, 0, 1, 2, 1, 1, 2, 0, 1, 0, 0, 1, 1, 2, 0, 0, 0, 1,
0, 1, 2, 2, 2, 0, 1, 0, 2, 0, 1, 1, 1, 1, 0, 2, 2, 0, 1, 1, 0, 2,
1, 2])
y_pred = oner.predict(Xd_train)
train_acc = np.mean(y_pred == y_train)
print(f'Training accuracy {train_acc*100:.2f}%')
Training accuracy 85.71%
y_pred = oner.predict(Xd_test)
test_acc = np.mean(y_pred == y_test)
print(f'Test accuracy {test_acc*100:.2f}%')
Test accuracy 84.21%
除了手动计算预测准确率(如上所示),我们还可以使用 score
方法
test_acc = oner.score(Xd_test, y_test)
print(f'Test accuracy {test_acc*100:.2f}%')
Test accuracy 84.21%
API
OneRClassifier(resolve_ties='first')
OneR (一规则) 分类器。
参数
-
resolve_ties
: str (默认值: 'first')当两个或多个特征具有相同的错误时,如何解决平局的选项。选项包括 - 'first' (默认值): 选择列表中的第一个特征,即列索引较低的特征。 - 'chi-squared': 对每个特征与目标进行卡方检验,并选择 p 值最低的特征。
属性
-
self.classes_labels_
: array-like, shape = [n_labels]包含训练集中找到的唯一类别标签的数组。
-
self.feature_idx_
: int基于训练集中列的规则特征的索引。
-
self.p_value_
: float给定特征的 p 值。仅在使用
fit
方法且 OneR 属性resolve_ties = 'chi-squared'
被设置后可用。 -
self.prediction_dict_
: dict包含特征 (self.feature_idx_) 规则和总错误信息的字典。例如,
{'total error': 37, 'rules (value: class)': {0: 0, 1: 2}}
意味着总错误为 37,规则是“如果特征值 == 0 则分类为 0”和“如果特征值 == 1 则分类为 2”。(否则分类为类别 1。)有关用法示例,请参阅 https://mlxtend.cn/mlxtend/user_guide/classifier/OneRClassifier/
方法
fit(X, y)
从训练数据中学习规则。
参数
-
X
: {array-like, sparse matrix}, shape = [n_samples, n_features]训练向量,其中 n_samples 是样本数,n_features 是特征数。
-
y
: array-like, shape = [n_samples]目标值。
返回
self
: object
get_params(deep=True)
获取此估计器的参数。
参数
-
deep
: bool, default=True如果为 True,将返回此估计器及其包含的作为估计器的子对象的参数。
返回
-
params
: mapping of string to any参数名称映射到其值。
predict(X)
预测 X 的类别标签。
参数
-
X
: {array-like, sparse matrix}, shape = [n_samples, n_features]训练向量,其中 n_samples 是样本数,n_features 是特征数。
返回
-
maj
: array-like, shape = [n_samples]预测的类别标签。
score(X, y, sample_weight=None)
返回给定测试数据和标签的平均准确率。
在多标签分类中,这是子集准确率,这是一个严格的指标,因为它要求每个样本的每个标签集都被正确预测。
参数
-
X
: array-like of shape (n_samples, n_features)测试样本。
-
y
: array-like of shape (n_samples,) or (n_samples, n_outputs)X 的真实标签。
-
sample_weight
: array-like of shape (n_samples,), default=None样本权重。
返回
-
score
: floatself.predict(X) 相对于 y 的平均准确率。
set_params(params)
设置此估计器的参数。
该方法适用于简单估计器和嵌套对象(例如管道)。后者的参数形式为 <component>__<parameter>
,以便可以更新嵌套对象的每个组件。
参数
-
**params
: dict估计器参数。
返回
-
self
: object估计器实例。
ython