有人可以告诉如何使用部分拟合在 sklearn 中使用合奏。我不想重新训练我的模型。或者,我们可以通过预先训练的模型进行集成吗?例如,我已经看到投票分类器不支持使用部分拟合进行训练。
5 回答
Mlxtend 库有一个 VotingEnsemble 的实现,它允许您传入预先拟合的模型。例如,如果您有三个预训练模型 clf1、clf2、clf3。以下代码将起作用。
from mlxtend.classifier import EnsembleVoteClassifier
import copy
eclf = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3], weights=[1,1,1], fit_base_estimators=False)
当设置为 false 时,EnsembleVoteClassifier 中的fit_base_estimators参数可确保分类器不会重新拟合。
一般来说,当寻找 sci-kit learn 不提供的更高级的技术特性时,请首先参考 mlxtend。
解决方法:
VotingClassifier 检查是否设置了 estimators_ 以了解它是否适合,并使用 estimators_ 列表中的估算器进行预测。如果你有预训练的分类器,你可以像下面的代码一样直接把它们放在 estimators_ 中。
但是,它也使用 LabelEnconder,因此它假定标签类似于 0、1、2,...,您还需要设置 le_ 和 classes_(见下文)。
from sklearn.ensemble import VotingClassifier
from sklearn.preprocessing import LabelEncoder
clf_list = [clf1, clf2, clf3]
eclf = VotingClassifier(estimators = [('1' ,clf1), ('2', clf2), ('3', clf3)], voting='soft')
eclf.estimators_ = clf_list
eclf.le_ = LabelEncoder().fit(y)
eclf.classes_ = seclf.le_.classes_
# Now it will work without calling fit
eclf.predict(X,y)
不幸的是,目前这在 scikit VotingClassifier 中是不可能的。
但是您可以使用http://sebastianraschka.com/Articles/2014_ensemble_classifier.html(从中实现 VotingClassifer)来尝试实现您自己的投票分类器,该分类器可以采用预先拟合的模型。
我们也可以在这里查看源代码并将其修改为我们的使用:
from sklearn.preprocessing import LabelEncoder
import numpy as np
le_ = LabelEncoder()
# When you do partial_fit, the first fit of any classifier requires
all available labels (output classes),
you should supply all same labels here in y.
le_.fit(y)
# Fill below list with fitted or partial fitted estimators
clf_list = [clf1, clf2, clf3, ... ]
# Fill weights -> array-like, shape = [n_classifiers] or None
weights = [clf1_wgt, clf2_wgt, ... ]
weights = None
#For hard voting:
pred = np.asarray([clf.predict(X) for clf in clf_list]).T
pred = np.apply_along_axis(lambda x:
np.argmax(np.bincount(x, weights=weights)),
axis=1,
arr=pred.astype('int'))
#For soft voting:
pred = np.asarray([clf.predict_proba(X) for clf in clf_list])
pred = np.average(pred, axis=0, weights=weights)
pred = np.argmax(pred, axis=1)
#Finally, reverse transform the labels for correct output:
pred = le_.inverse_transform(np.argmax(pred, axis=1))
实施投票并不难。这是我的实现:
import numpy as np
class VotingClassifier(object):
""" Implements a voting classifier for pre-trained classifiers"""
def __init__(self, estimators):
self.estimators = estimators
def predict(self, X):
# get values
Y = np.zeros([X.shape[0], len(self.estimators)], dtype=int)
for i, clf in enumerate(self.estimators):
Y[:, i] = clf.predict(X)
# apply voting
y = np.zeros(X.shape[0])
for i in range(X.shape[0]):
y[i] = np.argmax(np.bincount(Y[i,:]))
return y
Mlxtend 库有一个实现工程,您仍然需要调用fit
EnsembleVoteClassifier 的函数。似乎该fit
函数并没有真正修改任何参数,而是检查可能的标签值。在下面的示例中,您必须给出一个数组,其中包含原始 y 中出现的所有可能值(在本例中为 1,2)到eclf2.fit
X 无关紧要。
import numpy as np
from mlxtend.classifier import EnsembleVoteClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
import copy
clf1 = LogisticRegression(random_state=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
y = np.array([1, 1, 1, 2, 2, 2])
for clf in (clf1, clf2, clf3):
clf.fit(X, y)
eclf2 = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3],voting="soft",refit=False)
eclf2.fit(None,np.array([1,2]))
print(eclf2.predict(X))