#python #scikit-learn #object-detection #cross-validation
#python #scikit-learn #обнаружение объектов #перекрестная проверка
Вопрос:
Обновлено
Я загрузил фиктивный набор данных, ссылка здесь. The df.head()
:
Всего в нем 4 класса и df.object.value_counts()
:
human 23
car 13
cat 5
dog 3
Я хочу правильно выполнить K-Fold
разделение проверки по набору данных обнаружения объектов нескольких классов.
Первоначальный подход
Чтобы добиться правильного разделения проверки в k раз, я принял object counts
bounding box
во внимание и количество. Я понимаю, K-fold
стратегии разделения в основном зависят от набора данных (метаинформации). Но на данный момент с этим набором данных я попробовал что-то вроде следующего:
skf = StratifiedKFold(n_splits=3, shuffle=True, random_state=101)
df_folds = main_df[['image_id']].copy()
df_folds.loc[:, 'bbox_count'] = 1
df_folds = df_folds.groupby('image_id').count()
df_folds.loc[:, 'object_count'] = main_df.groupby('image_id')['object'].nunique()
df_folds.loc[:, 'stratify_group'] = np.char.add(
df_folds['object_count'].values.astype(str),
df_folds['bbox_count'].apply(lambda x: f'_{x // 15}').values.astype(str)
)
df_folds.loc[:, 'fold'] = 0
for fold_number, (train_index, val_index) in enumerate(skf.split(X=df_folds.index, y=df_folds['stratify_group'])):
df_folds.loc[df_folds.iloc[val_index].index, 'fold'] = fold_number
После разделения я проверил, работает ли он. И пока все в порядке.
Все сгибы содержат стратифицированные k-fold
выборки len(df_folds[df_folds['fold'] == fold_number].index)
и не пересекаются друг с другом, set(A).intersection(B)
где A
и B
— значение индекса ( image_id
) двух сгибов. Но проблема, похоже,:
Fold 0 has total: 18 2 3 = 23 bbox
Fold 1 has total: 2 11 = 13 bbox
Fold 2 has total: 5 3 = 8 bbox
Проблема
Однако я не мог убедиться, подходит ли это для такого типа задач в целом. Мне нужен совет. Подходит ли приведенный выше подход? или какая-либо проблема? или есть какой-то лучший подход! Любые предложения будут оценены. Спасибо.
Ответ №1:
При создании разделения перекрестной проверки мы заботимся о создании складок, которые имеют хорошее распределение различных «случаев», встречающихся в данных.
В вашем случае вы решили основывать свои сгибы на количестве автомобилей и количестве ограничивающих прямоугольников, что является хорошим, но ограниченным выбором. Итак, если вы можете определить конкретные случаи, используя свои данные / метаданные, вы можете попытаться создать более разумные сгибы, используя их.
Наиболее очевидный выбор — сбалансировать типы объектов (классы) в ваших сгибах, но вы могли бы пойти дальше.
Вот основная идея, допустим, у вас есть изображения с автомобилями, встречающимися в основном во Франции, и другие с автомобилями, встречающимися в основном в США, ее можно использовать для создания хороших фолдов со сбалансированным количеством французских и американских автомобилей в каждом фолде. То же самое можно сделать с погодными условиями и т. Д. Таким образом, каждый fold будет содержать репрезентативные данные для изучения, чтобы ваша сеть не была предвзятой для вашей задачи. В результате ваша модель будет более устойчивой к таким потенциальным реальным изменениям в данных.
Итак, можете ли вы добавить некоторые метаданные в свою стратегию перекрестной проверки, чтобы создать лучшее резюме? Если это не так, можете ли вы получить информацию о потенциальных угловых случаях, используя столбцы x, y, w, h вашего набора данных?
Затем вы должны попытаться сбалансировать сгибы с точки зрения выборок, чтобы ваши оценки оценивались при том же размере выборки, что уменьшит дисперсию и обеспечит лучшую оценку в конце.
Комментарии:
1. Спасибо за ваш совет. Среди всех приведенных ответов этот достаточно близок к временной шкале вознаграждения. Но я бы отметил как правильный ответ, если у него тоже есть минимальная демонстрация кода.
Ответ №2:
Вы можете использовать StratifiedKFold() или StratifiedShuffleSplit() напрямую для разделения вашего набора данных с использованием стратифицированной выборки на основе некоторого категориального столбца.
Фиктивные данные:
import pandas as pd
import numpy as np
np.random.seed(43)
df = pd.DataFrame({'ID': (1,1,2,2,3,3),
'Object': ('bus', 'car', 'bus', 'bus', 'bus', 'car'),
'X' : np.random.randint(0, 10, 6),
'Y' : np.random.randn(6)
})
df
Использование StratifiedKFold()
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=2)
for train_index, test_index in skf.split(df, df["Object"]):
strat_train_set_1 = df.loc[test_index]
strat_test_set_1 = df.loc[test_index]
print('train_set :', strat_train_set_1, 'n' , 'test_set :', strat_test_set_1)
Аналогично, если вы решите использовать StratifiedShuffleSplit() , вы можете иметь
from sklearn.model_selection import StratifiedShuffleSplit
sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
# n_splits = Number of re-shuffling amp; splitting iterations.
for train_index, test_index in sss.split(df, df["Object"]):
# split(X, y[, groups]) Generates indices to split data into training and test set.
strat_train_set = df.loc[train_index]
strat_test_set = df.loc[test_index]
print('train_set :', strat_train_set, 'n' , 'test_set :', strat_test_set)
Комментарии:
1. Спасибо за ваш комментарий. Однако, я думаю, вы неправильно поняли мой запрос. Меня не волнует использование
StratifiedKFold()
илиStratifiedShuffleSplit()
. Моя задача — разработать правильную стратегию проверки для обнаружения объектов нескольких классов. И для этого мой подход заключался в том, чтобы учитыватьobject
тип и количествоbbox
. Однако, если вы видите в моем запросе, я уже используюStratifiedKFold()
.
Ответ №3:
Я бы сделал это просто, используя KFold
метод scikit-learn of python
from numpy import array
from sklearn.model_selection import KFold
data = array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6])
kfold = KFold(3, True, 1)
for train, test in kfold.split(data):
print('train: %s, test: %s' % (data[train], data[test]))
и, пожалуйста, посмотрите, может ли это быть полезным
Комментарии:
1. Можете ли вы объяснить, почему вы просто выбрали «KFold», не задумываясь о последствиях?
2. @M.Innat Какие последствия?