一、应用场景

在使用机器学习建模中,往往会遇到这样的一种场景,给定一批数据,建立的模型不论你怎么调参,验证集在该模型上的表现能力较差,且每次得到的结果也不稳定,出现这样的原因在于你的数据本身可能存在一定问题(预处理),第二就是超参数没调整好,这时就可以考虑采用提升学习算法,提升方法的基本思想是:对于一个复杂的任务来说,将多个专家(模型)的判断适当的综合所得出的判断,要比一个专家单独判断好,实际上就是“三个臭皮匠顶一个诸葛亮”的道理。

二、Adaboost 介绍

AdaBoost算法属于一种迭代算法,它的核心思想是针对同一训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强大的最终分类器(强分类器)。其算法本身是通过改变数据分布来实现的,它根据每次训练集中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。与随机森林相似。

AdaBoost是属于boosting中的一种算法。bagging和boosting是两种集成方法,在bagging中是通过随机取样的方法从原数据中得到与原数据规模一样的数据集来获取弱分类器;boosting更进一步,它在数据集上顺序应用了多个不同分类器,如前面说的利用上一个弱分类器的准确率和权重来调整数据,获得下一个分类器。

所以AdaBoost的原理也比较简单,就是通过一些手段获得多个弱分类器,将它们集成起来构成强分类器,综合所有分类器的预测得出最终的结果。这里的弱分类器可以使用任意的分类器如:K-NN分类器、朴素贝叶斯分类器、决策树分类器、logistic回归分类器等等,作为弱分类器,简单分类器的效果更好。在下面的代码中使用的就是单层决策树作为弱分类器。

三、AdaBoost 算法描述

输入:训练集 G ( x ) = s i g n ( f ( x ) = s i g n ( m = 1 N α m G m ( x ) )

四、Python代码(不用sklearn包)

该部分代码是结合上一篇博客内容,是AdaBoost算法在神经网络上的结果具体代码如下

# -- coding: utf-8 --
import pandas as pd
from keras.models import Sequential
from keras.layers import Dense, Dropout
import matplotlib.pyplot as plt
import numpy as np
class AdaBoostClass(object):
    def __init__(self, train_data, train_label, test_data, test_label,
                 inputn, hidden1=10, hidden2=20, hidden3=10, M=3):
        :param train_data: 训练数据
        :param train_label: 训练数据标签
        :param test_data: 测试集
        :param test_label: 测试集标签
        :param hidden: 隐藏层节点个数
        :param inputn: 输入数据维数
        :param M: 模型集成个数
        self.train_data = train_data
        self.train_label = train_label
        self.test_data = test_data
        self.test_label = test_label
        self.hidden1 = hidden1
        self.hidden2 = hidden2
        self.hidden3 = hidden3
        self.M = M
        self.inputn = inputn
        self.p, self.q = x_train.shape
        self.p1, self.q1 = x_test.shape
    # @staticmethod
    def neural_network(self):
        神经网络训练
        :return: 分类概率,误差
        model = Sequential()
        model.add(Dense(self.hidden1, input_dim=n, activation='sigmoid'))
        # model.add(Dropout(0.2))
        model.add(Dense(self.hidden2, activation='sigmoid'))
        model.add(Dense(self.hidden3, activation='relu'))
        model.add(Dense(1, activation='sigmoid'))
        model.compile(loss='binary_crossentropy',
                      optimizer='rmsprop',
                      metrics=['accuracy'])
        history = model.fit(self.train_data, self.train_label,
                            validation_split=0.25,
                            validation_data=(self.test_data, self.test_label),
                            epochs=100,
                            batch_size=120)
        score = model.evaluate(self.test_data, self.test_label)
        print('loss:%.3f,Accuracy:%.3f' % (score[0], score[1]))
        pre_train = model.predict_proba(x_train)
        pre_test = model.predict_proba(x_test)
        return pre_train.flatten(), pre_test.flatten(), 1 - score[1]
    def AdaBoost(self):
        pre_train = np.ones([self.M, self.p])
        pre_test = np.ones([self.M, self.p1])
        at = np.zeros(self.M)
        # 初始化权重 w
        omiga = np.ones([self.M+1, self.inputn])/self.inputn
        Error = np.zeros(self.M)
        eer = np.zeros([self.M, self.p])
        et = []
        for i in range(0, self.M):
            # 获取弱分类器误差以及label
            pre_train1, pre_test1, e = self.neural_network()
            # print('pre_class.shape is', pre_class.shape,pre_class.dtype)
            # print('test_label .shape is', self.test_label.shape, self.test_label.dtype)
            pk = self.train_label - pre_train1
            eer[i, :] = pk
            et.append(e)
            pre_train[i, :] = pre_train1
            pre_test[i, :] = pre_test1
            # 更新 omiga
            Error[i] = 0
            for j in range(0, self.q):
                if np.abs(eer[i, j]) > 0.1:
                    Error[i] = Error[i] + omiga[i, j]
                    omiga[i+1, j] = omiga[i, j] * 1.1
                else:
                    omiga[i+1, j] = omiga[i, j]
            at[i] = 0.5 * np.log((1 - Error[i])/Error[i])
            # at[i] = 0.5 / np.exp(Error[i])
            omiga[i+1, :] = omiga[i+1, :] / np.sum(omiga[i+1, :])
        at = np.mat(at / np.sum(at))
        pre_train = np.mat(pre_train)
        output_train = at * pre_train
        output_test = at * pre_test
        return  output_test
data = pd.read_excel('D:/PyWork/booktnb.xlsx')
x_1 = data.ix[1:3000]
x_0 = data.ix[7000:10000]
x_train = pd.concat([x_0, x_1])
x_train = x_train.reset_index(drop=True)
x_train = x_train.sample(frac=1.0)
y_train = x_train['labels']
x_train.drop(['X', 'labels'], axis=1, inplace=True)
t_1 = data.ix[3001:4200]
t_0 = data.ix[10001:12000]
x_test = pd.concat([t_1, t_0])
y_test = x_test['labels']
x_test.drop(['X', 'labels'], axis=1, inplace=True)
m, n = x_train.shape
# 归一化
x_train.apply(lambda x: (x - np.min(x)) / (np.max(x) - np.min(x)))
x_test.apply(lambda x: (x - np.min(x)) / (np.max(x) - np.min(x)))
clf = AdaBoostClass(x_train, y_train, x_test, y_test, 10, 10, 20, 10, 10)
k_test = clf.AdaBoost()
k2 = np.array(k_test)
label_test = list(map(lambda x: 1 if x > 0.5 else 0, k2[0, :]))
# acc = 1 - np.sum(np.abs(label - y_test))/len(y_test)
test_acc = 1 - np.sum(np.abs(label_test - y_test))/len(y_test)
print('测试集准确率:', test_acc)

下图是运行结果,从结果可知,比单个神经网络结果要好
在这里插入图片描述

五、利用sklearn.ensemble.AdaBoostClassifier代码

sklearn.ensemble.AdaBoostClassifier 中,默认的方法是决策树,几个重要参数的说明:
base_estimator:基分类器,默认是决策树,在该分类器基础上进行boosting,理论上可以是任意一个分类器,但是如果是其他分类器时需要指明样本权重。

n_estimators:基分类器提升(循环)次数,默认是50次,这个值过大,模型容易过拟合;值过小,模型容易欠拟合。

learning_rate:学习率,表示梯度收敛速度,默认为1,如果过大,容易错过最优值,如果过小,则收敛速度会很慢;该值需要和n_estimators进行一个权衡,当分类器迭代次数较少时,学习率可以小一些,当迭代次数较多时,学习率可以适当放大。
python 代码

from sklearn.ensemble import AdaBoostClassifier
from sklearn.datasets import make_classification
import pandas as pd
import numpy as np
data = pd.read_excel('D:/PyWork/booktnb.xlsx')
# 数据划分
x_1 = data.ix[1:3000]
x_0 = data.ix[7000:10000]
x_train = pd.concat([x_0, x_1])
x_train = x_train.reset_index(drop=True)
x_train = x_train.sample(frac=1.0)
y_train = x_train['labels']
x_train.drop(['X', 'labels'], axis=1, inplace=True)
t_1 = data.ix[3001:4200]
t_0 = data.ix[10001:12000]
x_test = pd.concat([t_1, t_0])
y_test = x_test['labels']
x_test.drop(['X', 'labels'], axis=1, inplace=True)
m, n = x_train.shape
# 归一化
x_train.apply(lambda x: (x - np.min(x)) / (np.max(x) - np.min(x)))
x_test.apply(lambda x: (x - np.min(x)) / (np.max(x) - np.min(x)))
X, y = make_classification(n_samples=1000, n_features=4,
                           n_informative=2, n_redundant=0,
                           random_state=0, shuffle=False)
clf = AdaBoostClassifier(n_estimators=10, random_state=0)
clf.fit(x_train, y_train)
pk = clf.feature_importances_
# clf.predict([[0, 0, 0, 0]])
acc = clf.score(x_test, y_test)
print('测试集准确率', acc)

下图是使用sklearn包的准确率
在这里插入图片描述

一、AdaBoost算法描述输入:训练集T=(x1,y1),(x2,y2),...,(xn,yn)T=(x_{1},y_{1}),(x_{2},y_{2}),...,(x_{n},y_{n})T=(x1​,y1​),(x2​,y2​),...,(xn​,yn​),y=−1,1y={-1,1}y=−1,1输出:最终分类器G(x)G(x)G(x)(1)初始化权值分布D1=(w11,w12,..... path1 = r'C:\Users\郑思铭\Desktop\py\hw_3\ex3data1.mat' data1 = scio.loadmat(path1) x = data1['X'] y = data1['y'] #数据可视化 m = x.shape[0] random = np.random.permutation(range(m)) temp = random[0:100] select = x[temp, :] displaydata(select) 数据可视化