全栈工程师开发手册 (作者:栾鹏)
python数据挖掘系列教程
Multiclass classification 多类分类: 意味着一个分类任务需要对多于两个类的数据进行分类。比如,对一系列的橘子,苹果或者梨的图片进行分类。多类分类假设每一个样本有且仅有一个标签:一个水果可以被归类为苹果,也可以 是梨,但不能同时被归类为两类。
Multilabel classification 多标签分类: 给每一个样本分配一系列标签。这可以被认为是预测不相互排斥的数据点的属性,例如与文档类型相关的主题。一个文本可以归类为任意类别,例如可以同时为政治、金融、 教育相关或者不属于以上任何类别。
Multioutput regression 多输出分类: 为每个样本分配一组目标值。这可以认为是预测每一个样本的多个属性,比如说一个具体地点的风的方向和大小。
固有的多类分类器:
1对1的多类分类器:
1对多的多类分类器:
支持多标签分类的分类器:
支持多类-多输出分类的分类器:
在 multilabel learning 中,二元分类任务的合集表示为二进制数组:每一个样本是大小为 (n_samples, n_classes) 的二维数组中的一行二进制值,比如非0元素,表示为对应标签的 子集。 一个数组 np.array([[1, 0, 0], [0, 1, 1], [0, 0, 0]]) 表示第一个样本属于第 0 个标签,第二个样本属于第一个和第二个标签,第三个样本不属于任何标签。
# 多标签分类格式。将多分类转换为二分类的格式,类似于one-hot编码
from sklearn.preprocessing import MultiLabelBinarizer
y = [[2, 3, 4], [2], [0, 1, 3], [0, 1, 2, 3, 4], [0, 1, 2]]
y_new = MultiLabelBinarizer().fit_transform(y)
print('新的输出格式:\n',y_new)
这个方法也被称为 1对多, 在 OneVsRestClassifier 模块中执行。
# =========1对其余的多分类构造方式================
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import LinearSVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf = LinearSVC(random_state=0) # 构建二分类器
clf = OneVsRestClassifier(clf) # 根据二分类器构建多分类器
clf.fit(X, y) # 训练模型
y_pred = clf.predict(X) # 预测样本
print('预测正确的个数:%d,预测错误的个数:%d' %((y==y_pred).sum(),(y!=y_pred).sum()))
OneVsOneClassifier 1对1分类器 将会为每一对类别构造出一个分类器,在预测阶段,收到最多投票的类别将会被挑选出来。 当存在结时(两个类具有同样的票数的时候), 1对1分类器会选择总分类置信度最高的类,其中总分类置信度是由下层的二元分类器 计算出的成对置信等级累加而成。
因为这需要训练出 n_classes * (n_classes - 1) / 2 个分类器, 由于复杂度为 O(n_classes^2),这个方法通常比 one-vs-the-rest 慢。然而,这个方法也有优点,比如说是在没有很好的缩放 n_samples 数据的核方法中。 这是由于每个单独的学习问题只涉及一小部分数据,而 one-vs-the-rest 将会使用 n_classes 次完整的数据。
# =========1对1的多分类构造方式================
from sklearn import datasets
from sklearn.multiclass import OneVsOneClassifier
from sklearn.svm import LinearSVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf = LinearSVC(random_state=0) # 构建二分类器
clf = OneVsOneClassifier(clf) # 根据二分类器构建多分类器
clf.fit(X, y) # 训练模型
y_pred = clf.predict(X) # 预测样本
print('预测正确的个数:%d,预测错误的个数:%d' %((y==y_pred).sum(),(y!=y_pred).sum()))
基于Output-code的方法不同于 one-vs-the-rest 和 one-vs-one。使用这些方法,每一个类将会被映射到欧几里得空间,每一个维度上的值只能为0或者1。另一种解释它的方法是,每一个类被表示为二进制 码(一个 由0 和 1 组成的数组)。保存 location (位置)/ 每一个类的编码的矩阵被称为 code book。编码的大小是前面提到的欧几里得空间的纬度。直观上来说,每一个类应该使用一个唯一的编码,同时,好的 code book 应该能够优化分类的精度。 在实现上,我们使用随机产生的 code book
# =========误差校正输出代码================
from sklearn import datasets
from sklearn.multiclass import OutputCodeClassifier
from sklearn.svm import LinearSVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf = LinearSVC(random_state=0) # 构建二分类器
clf = OutputCodeClassifier(clf,code_size=2, random_state=0) # 根据二分类器构建多分类器
clf.fit(X, y) # 训练模型
y_pred = clf.predict(X) # 预测样本
print('预测正确的个数:%d,预测错误的个数:%d' %((y==y_pred).sum(),(y!=y_pred).sum()))
多输出回归支持 MultiOutputRegressor 可以被添加到任何回归器中。这个策略包括对每个目标拟合一个回归器。因为每一个目标可以被一个回归器精确地表示,通过检查对应的回归器,可以获取关于目标的信息。 因为 MultiOutputRegressor 对于每一个目标可以训练出一个回归器,所以它无法利用目标之间的相关度信息。
# =========多输出回归================
from sklearn.datasets import make_regression
from sklearn.multioutput import MultiOutputRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn import metrics
X, y = make_regression(n_samples=10, n_targets=3, random_state=1) # 产生10个样本,每个样本100个属性,每个样本3个输出值
print('样本特征维度',X.shape)
print('样本输出维度',y.shape)
clf = GradientBoostingRegressor(random_state=0)
clf =MultiOutputRegressor(clf)
clf.fit(X, y)
y_pred = clf.predict(X) # 预测样本
print('均方误差:',metrics.mean_squared_error(y, y_pred)) # 均方误差
Multioutput classification 支持能够被添加到任何带有 MultiOutputClassifier 标志的分类器中. 这种方法为每一个目标训练一个分类器。 这就允许产生多目标变量分类器。这种类的目的是扩展评估器用于评估一系列目标函数 (f1,f2,f3…,fn) ,这些函数在一个单独的预测矩阵上进行训练以此来预测一系列的响应 (y1,y2,y3…,yn)。
# =========多输出分类================
from sklearn.datasets import make_classification
from sklearn.multioutput import MultiOutputClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.utils import shuffle
import numpy as np
X, y1 = make_classification(n_samples=10, n_features=100, n_informative=30, n_classes=3, random_state=1) # 生成分类数据集,10个样本,100个特征,30个有效特征,3种分类
y2 = shuffle(y1, random_state=1) # 分类结果随机排序
y3 = shuffle(y1, random_state=2) # 分类结果随机排序
Y = np.vstack((y1, y2, y3)).T # 多种分类结果组合成
print('多输出多分类器真实输出分类:\n',Y)
n_samples, n_features = X.shape # 10,100
n_outputs = Y.shape[1] # 3个输出
n_classes = 3 # 每种输出有3种分类
forest = RandomForestClassifier(n_estimators=100, random_state=1) # 生成随机森林多分类器
multi_target_forest = MultiOutputClassifier(forest) # 构建多输出多分类器
y_pred = multi_target_forest.fit(X, Y).predict(X)
print('多输出多分类器预测输出分类:\n',y_pred)