В машинном обучении, прежде чем приступить к обучению модели, необходимо корректно подготовить данные. Одним из важнейших этапов является разделение исходного набора данных на обучающую и тестовую выборки. Это позволяет оценить обобщающую способность модели на данных, которые она не видела во время обучения. В этой статье мы подробно рассмотрим, как реализовать этот процесс с использованием библиотеки NumPy, фундаментального инструмента для научных вычислений в Python.
Основы разделения данных в машинном обучении
Зачем нужно разделять данные на обучающую и тестовую выборки?
Основная цель разделения данных – получить реалистичную оценку производительности обученной модели. Если обучать и тестировать модель на одних и тех же данных, оценка будет завышенной и не отразит реальную способность модели к обобщению на новые, ранее невиданные данные. Разделение на обучающую и тестовую выборки позволяет имитировать работу модели в реальных условиях.
Основные понятия: обучающая, валидационная и тестовая выборки
-
Обучающая выборка (Training Set): Используется для обучения модели. Модель настраивает свои параметры на основе этих данных.
-
Валидационная выборка (Validation Set): Используется для настройки гиперпараметров модели и выбора наилучшей архитектуры. Используется для предотвращения переобучения модели во время обучения.
-
Тестовая выборка (Test Set): Используется для окончательной оценки производительности обученной модели. Она должна быть репрезентативной для данных, с которыми модель будет работать в реальной среде.
В данной статье основное внимание уделяется разделению на обучающую и тестовую выборки, однако стоит помнить о существовании валидационной выборки, особенно при работе со сложными моделями.
Разделение данных с помощью NumPy
NumPy предоставляет мощные инструменты для манипулирования массивами, что делает его идеальным для разделения данных на выборки. Разберем основные подходы.
Использование numpy.random.shuffle для перемешивания данных
Прежде чем разделить данные, необходимо их перемешать, чтобы избежать систематических смещений. Функция numpy.random.shuffle позволяет перемешать элементы массива случайным образом. Это особенно важно, если данные упорядочены по какому-либо признаку.
import numpy as np
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
np.random.shuffle(data)
print(data)
Создание обучающей и тестовой выборки с использованием индексов
После перемешивания данных можно создать обучающую и тестовую выборки, используя индексы. Определяем размер тестовой выборки как процент от общего размера массива. Затем создаем массивы индексов и используем их для разделения данных.
import numpy as np
def split_train_test(data, test_size=0.2):
"""Разделяет данные на обучающую и тестовую выборки.
Args:
data (numpy.ndarray): Исходный массив данных.
test_size (float): Доля тестовой выборки (от 0 до 1).
Returns:
tuple: (обучающая выборка, тестовая выборка)
"""
np.random.shuffle(data)
test_size = int(len(data) * test_size)
train_size = len(data) - test_size
train_data = data[:train_size]
test_data = data[train_size:]
return train_data, test_data
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
train_data, test_data = split_train_test(data)
print("Обучающая выборка:", train_data)
print("Тестовая выборка:", test_data)
Этот код сначала перемешивает массив data, затем определяет размеры обучающей и тестовой выборок на основе значения test_size. В заключение возвращает два новых массива: train_data и test_data. Функцию можно расширить, чтобы возвращать индексы вместо самих данных, если это необходимо для дальнейшей обработки.
Альтернативные методы и продвинутые техники
Функция train_test_split из scikit-learn: удобная альтернатива NumPy
Хотя NumPy предоставляет базовые инструменты для разделения данных, библиотека scikit-learn предлагает более удобную функцию train_test_split. Она выполняет перемешивание и разделение данных в одной строке кода. В большинстве задач машинного обучения рекомендуется использовать train_test_split из scikit-learn, поскольку она более гибка и предоставляет дополнительные возможности, такие как стратификация.
from sklearn.model_selection import train_test_split
import numpy as np
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([0, 1, 0, 1, 0]) # Метки классов
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
print("X_train:", X_train)
print("X_test:", X_test)
print("y_train:", y_train)
print("y_test:", y_test)
В этом примере X представляет собой матрицу признаков, а y – вектор меток классов. Параметр test_size определяет размер тестовой выборки, а random_state используется для обеспечения воспроизводимости результатов.
Стратифицированное разделение для сбалансированных выборок
Стратифицированное разделение гарантирует, что соотношение классов в обучающей и тестовой выборках будет таким же, как и в исходном наборе данных. Это особенно важно для задач классификации с несбалансированными классами, где один класс значительно преобладает над другим.
train_test_split из scikit-learn поддерживает стратификацию с помощью параметра stratify. Передайте вектор меток классов в этот параметр, и функция обеспечит, чтобы разделение было стратифицированным.
from sklearn.model_selection import train_test_split
import numpy as np
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([0, 0, 1, 1, 1]) # Несбалансированные классы
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=42)
print("y_train:", y_train)
print("y_test:", y_test)
В этом примере stratify=y указывает на необходимость стратифицированного разделения на основе вектора y.
Практические примеры и распространенные ошибки
Пример разделения данных для задачи классификации
Рассмотрим пример разделения данных для задачи классификации изображений. Предположим, у нас есть массив изображений и соответствующий массив меток классов.
import numpy as np
from sklearn.model_selection import train_test_split
# Имитация данных
images = np.random.rand(100, 32, 32, 3) # 100 изображений 32x32 с 3 каналами (RGB)
labels = np.random.randint(0, 10, 100) # 10 классов
# Разделение данных на обучающую и тестовую выборки
images_train, images_test, labels_train, labels_test = train_test_split(
images, labels, test_size=0.2, random_state=42, stratify=labels
)
print("Размер обучающей выборки изображений:", images_train.shape)
print("Размер тестовой выборки изображений:", images_test.shape)
print("Размер обучающей выборки меток:", labels_train.shape)
print("Размер тестовой выборки меток:", labels_test.shape)
Распространенные ошибки при разделении данных и как их избежать
-
Не перемешивать данные перед разделением: Это может привести к смещенным выборкам, особенно если данные упорядочены по какому-либо признаку. Используйте
numpy.random.shuffleилиtrain_test_splitсshuffle=True. -
Не использовать стратификацию для несбалансированных классов: Это может привести к тому, что один из классов будет недостаточно представлен в обучающей или тестовой выборке. Используйте параметр
stratifyвtrain_test_split. -
Использовать тестовую выборку для настройки гиперпараметров: Это приведет к переобучению модели под конкретную тестовую выборку, и оценка производительности будет завышенной. Используйте валидационную выборку для настройки гиперпараметров.
Заключение
Разделение данных на обучающую и тестовую выборки – важный шаг в процессе машинного обучения. NumPy предоставляет базовые инструменты для реализации этой задачи, однако scikit-learn предлагает более удобные и гибкие решения, такие как train_test_split с поддержкой стратификации. Корректное разделение данных позволяет получить реалистичную оценку производительности модели и избежать распространенных ошибок.