12.1. Поддержка Array API (экспериментальная)#
The Array API спецификация определяет стандартный API для всех библиотек манипуляции массивами с API, подобным NumPy. Scikit-learn включает зафиксированные копии array-api-compat и array-api-extra.
Поддержка Scikit-learn стандарта Array API требует установки переменной окружения
SCIPY_ARRAY_API быть установленным в 1 перед импортом scipy и scikit-learn:
export SCIPY_ARRAY_API=1
Обратите внимание, что эта переменная окружения предназначена для временного использования. Для получения дополнительной информации обратитесь к Документация по Array API.
Некоторые оценщики scikit-learn, которые в основном полагаются на NumPy (в отличие от использования
Cython) для реализации алгоритмической логики своих fit, predict или
transform методы могут быть настроены на прием любых структур входных данных, совместимых с Array API, и автоматически перенаправлять операции в соответствующее пространство имен вместо использования NumPy.
На данном этапе эта поддержка считается экспериментальным и должен быть явно включён
параметром array_api_dispatch конфигурации. Подробности см. ниже.
Примечание
В настоящее время только array-api-strict, cupy, и PyTorch известны своей совместимостью с оценщиками scikit-learn.
Следующее видео предоставляет обзор принципов дизайна стандарта и того, как он способствует взаимодействию между библиотеками массивов:
Scikit-learn на GPU с Array API by Томас Фан на PyData NYC 2023.
12.1.1. Включение поддержки API массивов#
Конфигурация array_api_dispatch=True должно быть установлено в True для поддержки API массивов. Мы рекомендуем установить эту конфигурацию глобально, чтобы обеспечить согласованное поведение и предотвратить случайное смешивание пространств имен массивов. Обратите внимание, что в примерах ниже мы используем контекстный менеджер (config_context) чтобы избежать необходимости сбрасывать его до False в конце каждого фрагмента кода, чтобы не влиять на остальную документацию.
Scikit-learn принимает array-like входные данные для всех metrics
и некоторые оценщики. Когда array_api_dispatch=False, эти входные данные преобразуются
в массивы NumPy с помощью numpy.asarray (или numpy.array).
Хотя это успешно преобразует некоторые входные данные API массивов (например, JAX array), мы обычно рекомендуем установить array_api_dispatch=True при использовании входных данных array API. Это связано с тем, что преобразование NumPy часто может завершиться неудачей, например, тензор torch, размещенный на GPU.
12.1.2. Пример использования#
Пример фрагмента кода ниже демонстрирует, как использовать CuPy запустить
LinearDiscriminantAnalysis на GPU:
>>> from sklearn.datasets import make_classification
>>> from sklearn import config_context
>>> from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
>>> import cupy
>>> X_np, y_np = make_classification(random_state=0)
>>> X_cu = cupy.asarray(X_np)
>>> y_cu = cupy.asarray(y_np)
>>> X_cu.device
>>> with config_context(array_api_dispatch=True):
... lda = LinearDiscriminantAnalysis()
... X_trans = lda.fit_transform(X_cu, y_cu)
>>> X_trans.device
После обучения модели подогнанные атрибуты, которые являются массивами, также будут из того же пространства имен Array API, что и обучающие данные. Например, если для обучения использовалось пространство имен Array API CuPy, то подогнанные атрибуты будут на GPU. Мы предоставляем экспериментальный _estimator_with_converted_arrays утилита, которая
переносит атрибуты оценщика из Array API в ndarray:
>>> from sklearn.utils._array_api import _estimator_with_converted_arrays
>>> cupy_to_ndarray = lambda array : array.get()
>>> lda_np = _estimator_with_converted_arrays(lda, cupy_to_ndarray)
>>> X_trans = lda_np.transform(X_np)
>>> type(X_trans)
12.1.2.1. Поддержка PyTorch#
Тензоры PyTorch также могут быть переданы напрямую:
>>> import torch
>>> X_torch = torch.asarray(X_np, device="cuda", dtype=torch.float32)
>>> y_torch = torch.asarray(y_np, device="cuda", dtype=torch.float32)
>>> with config_context(array_api_dispatch=True):
... lda = LinearDiscriminantAnalysis()
... X_trans = lda.fit_transform(X_torch, y_torch)
>>> type(X_trans)
>>> X_trans.device.type
'cuda'
12.1.3. Поддержка Array API-совместимые входные данные#
Оценщики и другие инструменты в scikit-learn, поддерживающие совместимые с Array API входные данные.
12.1.3.1. Оценщики#
decomposition.PCA(сsvd_solver="full",svd_solver="covariance_eigh", илиsvd_solver="randomized"(svd_solver="randomized"только еслиpower_iteration_normalizer="QR"))linear_model.Ridge(сsolver="svd")linear_model.RidgeCV(сsolver="svd", см. Примечание о поддержке устройств для float64)linear_model.RidgeClassifier(сsolver="svd")linear_model.RidgeClassifierCV(сsolver="svd", см. Примечание о поддержке устройств для float64)discriminant_analysis.LinearDiscriminantAnalysis(сsolver="svd")preprocessing.LabelBinarizer(сsparse_output=False)preprocessing.StandardScaler(см. Примечание о поддержке устройств для float64)mixture.GaussianMixture(сinit_params="random"илиinit_params="random_from_data"иwarm_start=False)
12.1.3.2. Мета-оценщики#
Мета-оценщики, которые принимают входные данные Array API при условии, что базовый оценщик также это делает:
12.1.3.3. Метрики#
sklearn.metrics.cluster.calinski_harabasz_scoresklearn.metrics.mean_poisson_deviance(требуется включение поддержки API массивов для SciPy)sklearn.metrics.pairwise.pairwise_distancesЧтобы сделать задачу интересной, мы генерируем наблюдения целевой переменной y как сумму детерминированного члена, вычисленного функцией f, и случайного шумового члена, следующего центрированномуsklearn.metrics.pairwise.euclidean_distances(см. Примечание о поддержке устройств для float64)sklearn.metrics.pairwise.rbf_kernel(см. Примечание о поддержке устройств для float64)
12.1.3.4. Инструменты#
preprocessing.label_binarize(сsparse_output=False)
Ожидается, что покрытие будет расти со временем. Пожалуйста, следите за выделенным мета-задача на GitHub для отслеживания прогресса.
12.1.4. Обработка типов входных и выходных массивов#
Оценщики и функции оценки способны принимать входные массивы из различных библиотек массивов и/или устройств. Когда передается смешанный набор входных массивов, scikit-learn преобразует массивы по мере необходимости, чтобы сделать их согласованными.
Для оценщиков правило таково “всё следует X “ - смешанные входные данные массивов преобразуются так, чтобы они соответствовали библиотеке массивов и устройству X.
Для функций оценки правило таково: “всё следует y_pred “ - смешанные входные данные массива
преобразуются так, чтобы они соответствовали библиотеке массивов и устройству y_pred.
Когда функция или метод вызывается с совместимыми с Array API входными данными, принято возвращать массивы из той же библиотеки массивов и на том же устройстве, что и входные данные.
12.1.4.1. Оценщики#
Когда оценщик обучается с совместимым с array API X, все другие входные массивы, включая аргументы конструктора (например, y, sample_weight)
будет преобразован для соответствия библиотеке массивов и устройству X, если они еще не установлены.
Это поведение позволяет переключаться с обработки на CPU на обработку
на GPU в любой точке конвейера.
Это позволяет оценщикам принимать смешанные типы входных данных, обеспечивая X для перемещения
на другое устройство в рамках конвейера, без явного перемещения y. Обратите внимание, что конвейеры scikit-learn не позволяют преобразовывать y (чтобы избежать
утечка).
Возьмем, например, конвейер, где X и y оба начинают работу на CPU и проходят
следующие три шага:
TargetEncoder, который преобразует категориальныеXно также требуетy, означающий обаXиyдолжны быть на CPU.FunctionTransformer(func=partial(torch.asarray, device="cuda")), что перемещаетXна GPU, чтобы повысить производительность на следующем шаге.Ridge, производительность которого может быть улучшена при передаче массивов на GPU, так как они могут очень эффективно обрабатывать большие матричные операции.
X изначально содержит категориальные строковые данные (поэтому должен быть на CPU), которые
целевым кодированием преобразуются в числовые значения в TargetEncoder.
X затем явно перемещается на GPU для повышения производительности
Ridge. y не может быть преобразован конвейером
(напомним, что конвейеры scikit-learn не позволяют преобразование y) но как
Ridge способен принимать смешанные типы входных данных,
это не проблема, и конвейер может быть запущен.
Подогнанные атрибуты оценщика, обученного с совместимым API массивов X, будут массивами из той же библиотеки, что и входные данные, и хранятся на том же устройстве. Параметр predict и transform метод впоследствии ожидает
входные данные из той же библиотеки массивов и устройства, что и данные, переданные в fit
метод.
12.1.4.2. Функции оценки#
Когда совместимый с Array API y_pred передается в функцию оценки,
все остальные входные массивы (например, y_true, sample_weight) будет преобразован для соответствия библиотеке массивов и устройству y_pred, если они еще этого не делают.
Это позволяет функциям оценки принимать смешанные типы входных данных, позволяя им быть
использованными в мета-оценщик (или функция, принимающая оценщики), с конвейером, который перемещает входные массивы между устройствами (например, с CPU на GPU).
Например, чтобы иметь возможность использовать конвейер, описанный выше, внутри, например,
cross_validate или
GridSearchCV, внутренне вызываемая функция оценки
должна уметь принимать смешанные типы входных данных.
Тип вывода функций оценки зависит от количества выходных значений. Когда функция оценки возвращает скалярное значение, она вернет скаляр Python (обычно float экземпляра) вместо скалярного значения массива.
Для функций оценки, которые поддерживают многоклассовый или multioutput,
массив из той же библиотеки массивов и устройства, что и y_pred будет возвращен, когда
необходимо вывести несколько значений.
12.1.5. Общие проверки оценщика#
Добавьте array_api_support тег к набору тегов оценщика, чтобы указать, что он поддерживает Array API. Это позволит выполнять специальные проверки в рамках общих тестов для подтверждения, что результаты оценщиков одинаковы при использовании обычного NumPy и входных данных Array API.
Для запуска этих проверок необходимо установить
array-api-strict в вашей тестовой среде. Это позволяет запускать проверки без наличия GPU. Для запуска полного набора проверок также необходимо установить
PyTorch, CuPy и имеют
GPU. Проверки, которые не могут быть выполнены или имеют отсутствующие зависимости, будут
автоматически пропущены. Поэтому важно запускать тесты с
-v флаг, чтобы увидеть, какие проверки пропущены:
pip install array-api-strict # and other libraries as needed
pytest -k "array_api" -v
Запуск тестов scikit-learn против array-api-strict должен помочь выявить
большинство проблем с кодом, связанных с обработкой нескольких входных устройств, с использованием
симулированных не-CPU устройств. Это позволяет быстро итеративно разрабатывать и отлаживать
код, связанный с API массивов.
Однако, чтобы обеспечить полную обработку входных данных PyTorch или CuPy, размещённых на реальных GPU устройствах, необходимо запускать тесты против этих библиотек и оборудования. Это можно достичь, используя Google Colab или используя нашу инфраструктуру CI для pull-запросов (вручную запускаемую сопровождающими по соображениям стоимости).
12.1.5.1. Примечание о поддержке устройства MPS#
В macOS PyTorch может использовать Metal Performance Shaders (MPS) для доступа к аппаратным ускорителям (например, внутреннему GPU-компоненту чипов M1 или M2). Однако поддержка устройства MPS для PyTorch неполная на момент написания. Подробнее см. в следующем issue на GitHub:
Чтобы включить поддержку MPS в PyTorch, установите переменную окружения
PYTORCH_ENABLE_MPS_FALLBACK=1 перед запуском тестов:
PYTORCH_ENABLE_MPS_FALLBACK=1 pytest -k "array_api" -v
На момент написания все тесты scikit-learn должны проходить, однако вычислительная скорость не обязательно лучше, чем на устройстве CPU.
12.1.5.2. Примечание о поддержке устройств для float64#
Некоторые операции в scikit-learn автоматически выполняют операции
над значениями с плавающей точкой с float64 точность для предотвращения переполнений и обеспечения
корректности (например, metrics.pairwise.euclidean_distances,
preprocessing.StandardScaler). Однако,
определенные комбинации пространств имен массивов и устройств, такие как PyTorch on MPS
(см. Примечание о поддержке устройства MPS) не поддерживает float64 тип данных. В этих случаях
scikit-learn вернется к использованию float32 тип данных вместо этого. Это может привести к другому поведению (обычно численно нестабильным результатам) по сравнению с неиспользованием диспетчеризации API массивов или использованием устройства с float64 поддержка.