Как остановить машину с повышением градиента от переоснащения?

#python #machine-learning #scikit-learn

#python #машинное обучение #scikit-learn

Вопрос:

Я сравниваю несколько моделей (машину с повышением градиента, случайный лес, логистическую регрессию, SVM, многослойный персептрон и нейронную сеть keras) по проблеме мультиклассификации. Я использовал вложенную перекрестную проверку и поиск по сетке в своих моделях, проверяя их на своих фактических данных, а также на рандомизированных данных для проверки на переоснащение. Однако для машины с повышением градиента, которую я нахожу, независимо от того, как я изменяю свои данные или параметры модели, это дает мне 100% точность случайных данных каждый раз. Есть ли что-то в моем коде, что может быть причиной этого?

Вот мой код:

 dataset= pd.read_csv('data.csv')
data = dataset.drop(["gene"],1)
df = data.iloc[:,0:26]
df = df.fillna(0)
X = MinMaxScaler().fit_transform(df)

le = preprocessing.LabelEncoder()
encoded_value = le.fit_transform(["certain", "likely", "possible", "unlikely"])
Y = le.fit_transform(data["category"])

sm = SMOTE(random_state=100)
X_res, y_res = sm.fit_resample(X, Y)

seed = 7
logreg = LogisticRegression(penalty='l1', solver='liblinear',multi_class='auto')
LR_par= {'penalty':['l1'], 'C': [0.5, 1, 5, 10], 'max_iter':[100, 200, 500, 1000]}

rfc =RandomForestClassifier(n_estimators=500)
param_grid = {"max_depth": [3],
             "max_features": ["auto"],
              "min_samples_split": [2],
              "min_samples_leaf": [1],
              "bootstrap": [False],
              "criterion": ["entropy", "gini"]}


mlp = MLPClassifier(random_state=seed)
parameter_space = {'hidden_layer_sizes': [(50,50,50)],
     'activation': ['relu'],
     'solver': ['adam'],
     'max_iter': [10000],
     'alpha': [0.0001],
     'learning_rate': ['constant']}

gbm = GradientBoostingClassifier()
param = {"loss":["deviance"],
    "learning_rate": [0.001],
    "min_samples_split": [2],
    "min_samples_leaf": [1],
    "max_depth":[3],
    "max_features":["auto"],
    "criterion": ["friedman_mse"],
    "n_estimators":[50]
    }

svm = SVC(gamma="scale")
tuned_parameters = {'kernel':('linear', 'rbf'), 'C':(1,0.25,0.5,0.75)}

inner_cv = KFold(n_splits=10, shuffle=True, random_state=seed)

outer_cv = KFold(n_splits=10, shuffle=True, random_state=seed)


def baseline_model():

    model = Sequential()
    model.add(Dense(100, input_dim=X_res.shape[1], activation='relu')) #dense layers perform: output = activation(dot(input, kernel)   bias).
    model.add(Dropout(0.5))
    model.add(Dense(50, activation='relu')) #8 is the dim/ the number of hidden units (units are the kernel)
    model.add(Dense(4, activation='softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

models = []

models.append(('GBM', GridSearchCV(gbm, param, cv=inner_cv,iid=False, n_jobs=1)))
models.append(('RFC', GridSearchCV(rfc, param_grid, cv=inner_cv,iid=False, n_jobs=1)))
models.append(('LR', GridSearchCV(logreg, LR_par, cv=inner_cv, iid=False, n_jobs=1)))
models.append(('SVM', GridSearchCV(svm, tuned_parameters, cv=inner_cv, iid=False, n_jobs=1)))
models.append(('MLP', GridSearchCV(mlp, parameter_space, cv=inner_cv,iid=False, n_jobs=1)))
models.append(('Keras', KerasClassifier(build_fn=baseline_model, epochs=100, batch_size=50, verbose=0)))

results = []
names = []
scoring = 'accuracy'
X_train, X_test, Y_train, Y_test = train_test_split(X_res, y_res, test_size=0.2, random_state=0)


for name, model in models:
    nested_cv_results = model_selection.cross_val_score(model, X_res, y_res, cv=outer_cv, scoring=scoring)
    results.append(nested_cv_results)
    names.append(name)
    msg = "Nested CV Accuracy %s: %f ( /- %f )" % (name, nested_cv_results.mean()*100, nested_cv_results.std()*100)
    print(msg)
    model.fit(X_train, Y_train)
    print('Test set accuracy: {:.2f}'.format(model.score(X_test, Y_test)*100),  '%')
  

Вывод:

 Nested CV Accuracy GBM: 90.952381 ( /- 2.776644 )
Test set accuracy: 90.48 %
Nested CV Accuracy RFC: 79.285714 ( /- 5.112122 )
Test set accuracy: 75.00 %
Nested CV Accuracy LR: 91.904762 ( /- 4.416009 )
Test set accuracy: 92.86 %
Nested CV Accuracy SVM: 94.285714 ( /- 3.563483 )
Test set accuracy: 96.43 %
Nested CV Accuracy MLP: 91.428571 ( /- 4.012452 )
Test set accuracy: 92.86 %
  

Код случайных данных:

 ran = np.random.randint(4, size=161)
random = np.random.normal(500, 100, size=(161,161))
rand = np.column_stack((random, ran))
print(rand.shape)
X1 = rand[:161]
Y1 = rand[:,-1]
print("Random data counts of label '1': {}".format(sum(ran==1)))
print("Random data counts of label '0': {}".format(sum(ran==0)))
print("Random data counts of label '2': {}".format(sum(ran==2)))
print("Random data counts of label '3': {}".format(sum(ran==3)))

for name, model in models:
    cv_results = model_selection.cross_val_score(model, X1, Y1,  cv=outer_cv, scoring=scoring)
    names.append(name)
    msg = "Random data CV %s: %f ( /- %f)" % (name, cv_results.mean()*100, cv_results.std()*100)
    print(msg)
  

Случайный вывод данных:

 Random data CV GBM: 100.000000 ( /- 0.000000)
Random data CV RFC: 62.941176 ( /- 15.306485)
Random data CV LR: 23.566176 ( /- 6.546699)
Random data CV SVM: 22.352941 ( /- 6.331220)
Random data CV MLP: 23.639706 ( /- 7.371392)
Random data CV Keras: 22.352941 ( /- 8.896451)
  

Этот классификатор повышения градиента (GBM) работает на 100%, независимо от того, уменьшаю ли я количество функций, изменяю параметры в поиске по сетке (я ввожу несколько параметров, однако это может длиться часами для меня безрезультатно, поэтому я пока оставил эту проблему), а также то же самое, если япопробуйте данные двоичной классификации.

Случайный лес (RFC) также выше на 62%, я что-то делаю не так?

Данные, которые я использую, представляют собой преимущественно двоичные объекты, в качестве примера, который выглядит так (и предсказывает столбец категории):

 gene   Tissue    Druggable Eigenvalue CADDvalue Catalogpresence   Category
ACE      1           1         1          0           1            Certain
ABO      1           0         0          0           0            Likely
TP53     1           1         0          0           0            Possible
  

Любые рекомендации будут оценены.

Комментарии:

1. Может быть, интересный связанный с этим вопрос: stats.stackexchange.com/questions/372676 /…

2. Привет, спасибо, что поделились этим, я рассмотрю это подробнее, поскольку я новичок, но на первый взгляд я прав, думая, что это подразумевает, что моя модель может каким-то образом работать с неограниченной глубиной?

3. Вас может заинтересовать следующее: подходит ли переобучение с повышением градиента , где я сосредоточился на влиянии изменения количества оценок в алгоритме повышения градиента.

Ответ №1:

В общем, есть несколько параметров, с которыми вы можете поиграть, чтобы уменьшить переобучение. Проще всего концептуально понять, это увеличить min_samples_split и min_samples_leaf . Установка для них более высоких значений не позволит модели запомнить, как правильно идентифицировать отдельный фрагмент данных или очень маленькие группы данных. Для большого набора данных (~ 1 млн строк) я бы поместил эти значения примерно на 50, если не выше. Вы можете выполнить поиск по сетке, чтобы найти значения, которые хорошо подходят для ваших конкретных данных.

Вы также можете использовать подвыборку для уменьшения переобучения, а также max_features. Эти параметры в основном не позволяют вашей модели просматривать некоторые данные, что мешает ей запоминать их.

Комментарии:

1. Большое вам спасибо, этот ответ очень ясен и показал мне его в перспективе. Повторная попытка повышения градиента и случайного леса с увеличенными разделениями и листьями снизила точность до 20%, аналогично другим моделям. Спасибо!