Классификатор XGBoost и оптимизация с помощью класса hyperopt и функции стоимости - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть XGBoostClassifier о повреждениях, которые классифицируются как простые случаи и сложные случаи, и я хочу оптимизировать его с точки зрения затрат, но прежде чем разделить на категории разных размеров.Поскольку классификатор неправильно классифицирует некоторые случаи, я хочу, чтобы hyperopt оптимизировал эти категории размеров.Поэтому, если ущерб более дорогостоящий, ему будет сложнее классифицировать его как простой случай.По некоторым причинам hyperopt не работает лучше после каждой категории размеров.

rstate = np.random.RandomState(7)
CM = []
paramst = {'colsample_bytree': 0.9697677752045393, 'gamma': 2,
           'learning_rate': 0.08597574025592336, 'max_depth': 14,
           'n_estimators': 29, 'subsample': 0.900027377690923}

model = XGBClassifier(**paramst, random_state = 7)
model.fit(X_train, y_train)

probab = model.predict_proba(X_valid)
prob = np.array(probab[:,0])

y_pred_pre = model.predict(X_valid)

cost = X_valid['cost']
cost = np.array(cost)

ClassK = [100,200,300,400,500,600,700,800,900,901]
PercentK = 0.1

def treshold(params):    
    def classification(x, y):
        class1 = [None]*len(y)
        for idx, i in enumerate(y):
            l = True
            if (x[idx] < ClassK[0]):
                if (params['100'] > i):
                    l = False
            elif (x[idx] < ClassK[1]) and (x[idx] > ClassK[0]):
                if (params['200'] > i):
                    l = False
            elif (x[idx] < ClassK[2]) and (x[idx] > ClassK[1]):
                if (params['300'] > i):
                    l = False
            elif (x[idx] < ClassK[3]) and (x[idx] > ClassK[2]):
                if (params['400'] > i):
                    l = False
            elif (x[idx] < ClassK[4]) and (x[idx] > ClassK[3]):
                if (params['500'] > i):
                    l = False
            elif (x[idx] < ClassK[5]) and (x[idx] > ClassK[4]):
                if (params['600'] > i):
                    l = False
            elif (x[idx] < ClassK[6]) and (x[idx] > ClassK[5]):
                if (params['700'] > i):
                    l = False
            elif (x[idx] < ClassK[7]) and (x[idx] > ClassK[6]):
                if (params['800'] > i):
                    l = False
            elif (x[idx] < ClassK[8]) and (x[idx] > ClassK[7]):
                if (params['900'] > i):
                    l = False
            elif (x[idx] >= ClassK[9]):
                if (params['901'] > i):
                    l = False
            class1[idx] = l
        return class1

    cl = classification(x=cost, y= prob)

    def cmsumfunction(cl):       
        CM = []
        for i in range(len(y_valid)):
            if not y_valid[i] and not cl[i]:
                CM.append(0)
            elif not y_valid[i] and cl[i]:
                CM.append(1)
            elif y_valid[i] and not cl[i]:
                CM.append(2)
            elif y_valid[i] and cl[i]:
                CM.append(3)

        X_valid.loc[:,'CM'] = CM

        cmsum = X_valid.groupby('CM')['cost'].sum()
        X_valid.drop('CM', axis = 1, errors = 'ignore', inplace = True)
        return cmsum, CM

    def costfunc(cl):
        cmsum, CM = cmsumfunction(cl)
        a = 0
        try: 
            a = cmsum[1]*PercentK
        except:
            print('Error')
        b = CM.count(3)*10+CM.count(1)*10
        return a-b

    return {'loss': costfunc(cl), 'status': 'ok', 'class': cl, 'Parameter': params}

def optimize (random_state = 7):
    resultlist = []
    trialslist = []
    for i in space:
            space_copy = space1.copy()
            space_copy[i] = space[i]
            global trials
            trials = Trials()
            best = fmin(treshold, space_copy, algo=tpe.suggest, max_evals = 100, trials = trials)
    resultlist.append(best)
    trialslist.append(trials)
    return(resultlist, trialslist)

result_hyper = []
result, thresholds = optimize()
result_hyper.append(result)

Вывод:

100%|█████████████████████████████████████████████████| 100/100 [00:12<00:00,  7.24it/s, best loss: 117349.50499999977]
100%|██████████████████████████████████████████████████| 100/100 [00:14<00:00,  7.85it/s, best loss: 112980.0749999994]
100%|██████████████████████████████████████████████████| 100/100 [00:12<00:00,  8.36it/s, best loss: 98664.08699999997]
100%|██████████████████████████████████████████████████| 100/100 [00:13<00:00,  7.32it/s, best loss: 96265.73999999941]
100%|█████████████████████████████████████████████████| 100/100 [00:13<00:00,  7.36it/s, best loss: 101592.99399999916]
100%|██████████████████████████████████████████████████| 100/100 [00:13<00:00,  6.67it/s, best loss: 105445.9679999993]
100%|█████████████████████████████████████████████████| 100/100 [00:16<00:00,  6.03it/s, best loss: 105469.19599999941]
100%|█████████████████████████████████████████████████| 100/100 [00:15<00:00,  6.87it/s, best loss: 109068.51899999939]
100%|██████████████████████████████████████████████████| 100/100 [00:13<00:00,  7.63it/s, best loss: 110204.6389999995]
100%|██████████████████████████████████████████████████| 100/100 [00:12<00:00,  7.75it/s, best loss: 99880.33999999936]

result_hyper Результат в этом:

[[{'100': 0.02},
  {'200': 0.98},
  {'300': 1.0},
  {'400': 0.97},
  {'500': 0.98},
  {'600': 0.97},
  {'700': 0.96},
  {'800': 0.99},
  {'900': 0.98},
  {'901': 0.99}]]

Я быложидая найти лучшее решение для самой высокой отрицательной стоимости (прибыли).Например, если я устанавливаю a = 1 и меняю класс от 100 до 0,8, я получаю отрицательные результаты.Прежде чем я сам начну его оптимизировать, есть ли какое-то решение, почему Hyperopt не дает хорошего результата?Спасибо за любую помощь, ребята.

...