Должны ли результаты "Gradient Boosting" быть разными, если поменять местами признаки

Есть набор данных для классификации в "Gradient Boosting". Если я меняю их местами получается разный результат. Так должно быть? Если результаты должны быть действительно разными, значит есть смысл попробовать разные последовательности? Разместил файл с данными здесь данные. Последнее значение справа это метки классов(бинарная классификация)

    import numpy as np
    import pandas as pd
    from sklearn.ensemble import GradientBoostingClassifier
    from sklearn.metrics import classification_report
    
    df1 = pd.read_csv('dataclass.csv',
                      header=None)

    
    split = 5700
    
    y = df1.iloc[:, 11].values# метки классов
    y  = y.astype('int')
    len_ = len(y)
    
    q = np.ones((len_, 11), dtype=float)
    q[0:len_, 0] = df1.iloc[:, 7].values
    q[0:len_, 1] = df1.iloc[:, 8].values
    q[0:len_, 2] = df1.iloc[:, 9].values
    q[0:len_, 3] = df1.iloc[:, 10].values
    q[0:len_, 4] = df1.iloc[:, 0].values
    q[0:len_, 5] = df1.iloc[:, 5].values
    q[0:len_, 6] = df1.iloc[:, 4].values
    q[0:len_, 7] = df1.iloc[:, 3].values
    q[0:len_, 8] = df1.iloc[:, 2].values
    q[0:len_, 9] = df1.iloc[:, 1].values
    q[0:len_, 10] = df1.iloc[:, 6].values
    q = np.round(q, 5)
    
    X_train = q[:split]
    clf = GradientBoostingClassifier(max_depth=3, max_features="sqrt", n_estimators=30,
                                         learning_rate=0.01,random_state=0)
    
    clf.fit(X_train, y[:split])
    yALL = clf.predict(q)
    peport = classification_report(y, yALL)
    print(peport)

    y_test = clf.predict(q[split:])
    confmat = confusion_matrix(y[split:], y_test)

   print(confmat)

Если запускаю на обучение, то получаются следующие метрики:

                  precision    recall  f1-score   support
    
               0       0.61      0.05      0.09      3867
               1       0.51      0.97      0.67      3983
    
        accuracy                           0.52      7850
       macro avg       0.56      0.51      0.38      7850
    weighted avg       0.56      0.52      0.39      7850

[[187 875]
 [172 916]]

Делаю следующую очередность признаков:

q[0:len_, 0] = df1.iloc[:, 0].values
q[0:len_, 1] = df1.iloc[:, 1].values
q[0:len_, 2] = df1.iloc[:, 2].values
q[0:len_, 3] = df1.iloc[:, 3].values
q[0:len_, 4] = df1.iloc[:, 4].values
q[0:len_, 5] = df1.iloc[:, 5].values
q[0:len_, 6] = df1.iloc[:, 6].values
q[0:len_, 7] = df1.iloc[:, 7].values
q[0:len_, 8] = df1.iloc[:, 8].values
q[0:len_, 9] = df1.iloc[:, 9].values
q[0:len_, 10] = df1.iloc[:, 10].values

результат получается несколько иной:

                  precision    recall  f1-score   support
    
               0       0.63      0.04      0.08      3867
               1       0.51      0.98      0.67      3983
    
        accuracy                           0.52      7850
       macro avg       0.57      0.51      0.38      7850
    weighted avg       0.57      0.52      0.38      7850

[[250 812]
 [222 866]]

Ответы (1 шт):

Автор решения: CrazyElf

Посмотрел немного ваши данные. Могу сделать следующие выводы и замечания.

  • вы зря предсказываете на всех данных, надо только на тесте предсказывать по-хорошему, дальше я делаю наблюдения по предсказаниям только на тесте, хотя и предсказание на всех данных даёт в принципе те же результаты
  • качество предсказаний вашей модели близко к случайному 0.5 с некоторой погрешностью
  • с заданным вами параметром max_depth=1 модель в 99% случаев предсказывает результат 1, хотя во входных данных примерно поровну зачений 0 и 1
  • если увеличить глубину деревьев до max_depth=10, то модель начинает больше 0 предсказывать (где-то 1/3 0 на 2/3 1), но в целом качество модели всё-равно получается близко к случайному 0.5
  • если поиграться параметром random_state, то вы увидите даже бОльший разброс качества, чем при перемешивании колонок, таким образом, наблюдающаяся разница целиком объясняется тем, что модель берёт случайные наборы колонок, какие именно и в каком порядке - зависит как от random_state, так и от физического расположения колонок, в общем, можно считать, что перемешивая колонки, вы просто меняете random_state, вот и всё объяснение разницы в метриках

Изменённый код для более понятного разбиения на трейн/тест и проверки на тесте:

X_train, X_test = q[:split],q[split:]
y_train, y_test = y[:split],y[split:]
clf = GradientBoostingClassifier(max_depth=1, max_features="sqrt", n_estimators=30,
                                     learning_rate=0.01,random_state=4)

clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
peport = classification_report(y_test, y_pred)
print(peport)
→ Ссылка