书籍信息
Hands-On Machine Learning with Scikit-Learn and Tensorflow
出版社: O’Reilly Media, Inc, USA
平装: 566页
语种: 英语
ISBN: 1491962291
条形码: 9781491962299
商品尺寸: 18 x 2.9 x 23.3 cm
ASIN: 1491962291
系列博文为书籍中文翻译
代码以及数据下载:https://github.com/ageron/handson-ml
假设我们训练了许多分类器(例如逻辑回归,SVM,随机森林),每个分类器有大约80%的准确率。创造更优分类器的简单方法是将这些分类器的预测结果进行组合,将多数分类器输出的结果作为最终的预测结果,这就是hard voting classifier的基本思想。
令人吃惊的是,这样的分类器通常能够获得更好的效果。事实上,即使每个分类器都是弱分类器(略优于随机猜测),这些分类器组合而成的分类器仍然可能是效果优秀的强分类器,前提是分类器的数量足够而且具有充分的多样性。
下面的例子阐释其中的原因。假如我们有枚硬币,抛掷时有51%的概率正面向上,49%的概率背面向上。根据数学推导,抛掷1000次后正面向上的次数多于背面向上的次数的概率是75%,抛掷10000次后这样的概率是97%。这是因为大数定理:如果我们持续抛掷硬币,正面向上次数的比例越来越接近51%。
import numpy.random as rnd
rnd.seed(42)
heads_proba = 0.51
coin_tosses = (rnd.rand(10000, 10) < heads_proba).astype(np.int32)
cumulative_heads_ratio = np.cumsum(coin_tosses, axis=0) / np.arange(1, 10001).reshape(-1, 1)
plt.figure(figsize=(8,3.5))
plt.plot(cumulative_heads_ratio)
plt.plot([0, 10000], [0.51, 0.51], "k--", linewidth=2, label="51%")
plt.plot([0, 10000], [0.5, 0.5], "k-", label="50%")
plt.xlabel("Number of coin tosses")
plt.ylabel("Heads ratio")
plt.legend(loc="lower right")
plt.axis([0, 10000, 0.42, 0.58])
plt.show()
注释:随着抛掷次数的增加,正面向上次数的比例越来越接近51%,同时正面向上次数的比例稳定大于50%。
类似的,如果我们根据上面的方法使用1000个只有51%准确率的弱分类器构建强分类器,我们理论上会得到75%的准确率。但是前提是这些分类器是独立的,彼此的错误是不相关的,考虑到我们使用的是相同的训练数据,这样的前提是不现实的。实际上,因为这些分类器会犯同样的错误,而我们只是将多数分类器输出的结果作为最终的预测结果,所以模型的准确率会受到影响。
注释:
选择不同的算法能够增加模型犯不同错误的概率,从而提升集成学习的效果。
以下通过构造的数据集利用逻辑回归,随机森林和SVM训练voting classifier。
from sklearn.cross_validation import train_test_split
from sklearn.datasets import make_moons
X, y = make_moons(n_samples=500, noise=0.30, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
log_clf = LogisticRegression(random_state=42)
rnd_clf = RandomForestClassifier(random_state=42)
svm_clf = SVC(probability=True, random_state=42)
hard_voting_clf = VotingClassifier(
estimators=[('lr', log_clf), ('rf', rnd_clf), ('svc', svm_clf)],
voting='hard'
)
soft_voting_clf = VotingClassifier(
estimators=[('lr', log_clf), ('rf', rnd_clf), ('svc', svm_clf)],
voting='soft'
)
hard_voting_clf.fit(X_train, y_train)
soft_voting_clf.fit(X_train, y_train)
from sklearn.metrics import accuracy_score
for clf in (log_clf, rnd_clf, svm_clf):
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
print clf.__class__.__name__, accuracy_score(y_test, y_pred)
hard_voting_clf.fit(X_train, y_train)
y_pred = hard_voting_clf.predict(X_test)
print "hard voting classifier", accuracy_score(y_test, y_pred)
soft_voting_clf.fit(X_train, y_train)
y_pred = soft_voting_clf.predict(X_test)
print "soft voting classifier", accuracy_score(y_test, y_pred)
# output
# LogisticRegression 0.864
# RandomForestClassifier 0.872
# SVC 0.888
# hard voting classifier 0.896
# soft voting classifier 0.912
如果所有的分类器都能够预测类别的概率(拥有predict_proba方法),那么我们可以将平均概率最高的结果作为最终的预测结果,这就是soft voting classifier的基本思想。通常,它比hard voting classifier效果好,因为它给把握高的结果更高的权重。我们可以通过VotingClassifier的voting参数实现以上方法。注意默认情况下SVM不能够预测类别的概率,需要设置参数probability,这样的设置会降低训练速度。可以发现,hard voting classifier达到89.6%的准确率,soft voting classifier达到91.2%的准确率,均高于单独的分类器。