scikit-learn / GridSearchCV - наименее населенный класс в y имеет только 2 члена, что меньше, чем n_splits = 5 - PullRequest
0 голосов
/ 12 февраля 2020

Я пытаюсь использовать GridSearchCV для настройки гиперпараметра на RandomForrestClassifier. Для этого я подготовил набор данных (в csv), который выглядит следующим образом: (с> 8k строк):

| Consignor Code | Consignee Code | Origin | Destination | Carrier Code | 
|----------------|----------------|--------|-------------|--------------| 
| 23763          | 6404216422     | DKCPH  | CNPVG       | 6402746370   | 
| 87132          | 6404111479     | DKCPH  | USDEN       | 6402746424   | 
| 99553          | 65199597       | DKCPH  | MYKUL       | 6402746393   | 
| 99553          | 6407326944     | DKBLL  | AEDXB       | 6402746368   | 
| 99553          | 6407326944     | DKCPH  | AEDXB       | 6402746368   | 
...

Теперь, чтобы выполнить настройку гиперпараметра, я делаю это:

from sklearn.model_selection import GridSearchCV

# Import the dataset (A CSV file)
dataset = pd.read_csv('shipments_non_empty.csv',
                      header=0, skip_blank_lines=True)

# Drop the columns we don't need
dataset.drop(columns=['Consignor Code', 'Origin','Carrier Code'], inplace=True)

#Convert the 'Consignee Code' to a string.
dataset['Consignee Code'] = dataset['Consignee Code'].astype('int64')

#Set the target for the model
target = dataset.pop('Destination')

# Convert all our data to numeric values, so we can use the .fit function.
# For that, we use LabelEncoder

le_target = preprocessing.LabelEncoder()
target = le_target.fit_transform(list(target))

le_consignee = preprocessing.LabelEncoder()
dataset['Consignee Code'] = le_consignee.fit_transform(
    list(dataset['Consignee Code']))

# Prepare the dataset.
X_train, X_test, y_train, y_test = train_test_split(
    dataset, target, test_size=0.3, random_state=None)


n_estimators = [100, 300, 500, 800, 1200]
max_depth = [5, 8, 15, 25, 30]
min_samples_split = [2, 5, 10, 15, 100]
min_samples_leaf = [1, 2, 5, 10]
param_grid = dict(n_estimators=n_estimators, max_depth=max_depth,
                  min_samples_split=min_samples_split,
                  min_samples_leaf=min_samples_leaf)


rf = RandomForestClassifier()
grid_search = GridSearchCV(estimator=rf, param_grid=param_grid)
best_model = grid_search.fit(X_train, y_train)

print(round(best_model.score(X_test, y_test), 2))
print(best_model.best_params_)

Теперь приведенный выше код дает мне следующую ошибку:

Наименее заполненный класс в y имеет только 1 член, что меньше, чем n_splits = 5

То, что я пробовал до сих пор

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

Итак, я решил, что могу удалить все записи с менее чем 5 классами - сразу после импорта набора данных:

#Group column "Consignee Code" and remove if less than 5 records
dataset["CLASS_COUNT"] = dataset.groupby("Consignee Code").transform("count")
dataset.query('CLASS_COUNT > 5', inplace=True)
dataset.drop(columns=['CLASS_COUNT'], inplace=True)

#Group column "Destination" and remove if less than 5 records
dataset["CLASS_COUNT"] = dataset.groupby("Destination").transform("count")
dataset.query('CLASS_COUNT > 5', inplace=True)
dataset.drop(columns=['CLASS_COUNT'], inplace=True)

Однако, это все равно дает мне ту же ошибку (только с другое число, чем раньше):

Наименее заполненный класс в y имеет только 3 члена, что меньше, чем n_splits = 5

...