#-*- coding:utf-8 -*-
import numpy as np
from sklearn.ensemble import GradientBoostingClassifier,GradientBoostingRegressor
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_wine,load_boston
from sklearn import tree


def read_data():
    boston = load_boston()
    Xtrain, Xtest, Ytrain, Ytest = train_test_split(boston.data, boston.target, test_size=0.3)
    return Xtrain, Xtest, Ytrain, Ytest

def init(Ytrain):
    return np.average(Ytrain)


def fit(Xtrain, Ytrain):
    print("init", Ytrain[:10])
    fx = []
    trees = []

    fx0 = np.ones(Ytrain.shape[0])*init(Ytrain)
    fx.append(fx0)

    print("0", fx0[:10])

    gx = Ytrain

    for i in range(55):
        # 求残差
        gx = gx - fx0
        print("第", i, '轮 残差', gx[:10])
        clf = tree.DecisionTreeRegressor(criterion="mse", max_features=5, max_depth=10, random_state=10)
        clf.fit(Xtrain, gx)
        trees.append(clf)

        fx0 = clf.predict(Xtrain)*0.7
        print("第", i, '轮 结果', fx0[:10])
        fx.append(fx0)


    gx = np.zeros(Ytrain.shape[0])
    for i in range(len(fx)):
        gx = gx + fx[i]

    print(gx[:10])

    sum = 0
    for i in range(Ytrain.shape[0]):
        sum = sum + (gx[i] - Ytrain[i])**2

    print("train mse", sum/Ytrain.shape[0])
    return trees, fx[0][0]


def score(Xtest, Ytest, trees, fx0):
    gx = np.ones(Ytest.shape[0]) * fx0

    for i in range(len(trees)):
        gx = gx + trees[i].predict(Xtest)
    print(gx[:10])
    print(Ytest[:10])

    sum = 0
    for i in range(Ytest.shape[0]):
        sum = sum + (gx[i] - Ytest[i])**2

    print("test mse", sum/Ytest.shape[0])

    gx = trees[0].predict(Xtest)
    sum = 0
    for i in range(Ytest.shape[0]):
        sum = sum + (gx[i] - Ytest[i]) ** 2
    print("test mse0", sum / Ytest.shape[0])


if __name__ == '__main__':
    Xtrain, Xtest, Ytrain, Ytest = read_data()
    trees, fx0 = fit(Xtrain, Ytrain)
    score(Xtest, Ytest, trees, fx0)

    gbm2 = GradientBoostingRegressor(n_estimators=55, max_depth=10, learning_rate=0.7,
                                     max_features='sqrt', random_state=10)
    gbm2.fit(Xtrain, Ytrain)  # 分数越高越好
    print("gbdt1", gbm2.score(Xtest, Ytest))

    gx = gbm2.predict(Xtest)
    sum = 0
    for i in range(Ytest.shape[0]):
        sum = sum + (gx[i] - Ytest[i]) ** 2
    print(gx[:10])
    print(Ytest[:10])
    print("gbdt mse", sum / Ytest.shape[0])

