Scikit-learn: Панды вошли, Панды вышли?

Созданный на 22 окт. 2015  ·  59Комментарии  ·  Источник: scikit-learn/scikit-learn

На данный момент можно использовать фреймворк pandas в качестве входных данных для большинства методов подгонки / прогнозирования / преобразования sklearn, но вы получаете массив numpy. Было бы здорово иметь возможность получать данные в том же формате, в котором вы их вставляете.

Это не совсем просто, потому что, если ваш Dataframe содержит столбцы, которые не являются числовыми, тогда промежуточные массивы numpy вызовут сбой sklearn, потому что они будут dtype=object вместо dtype=float . Это можно решить, используя преобразователь Dataframe-> ndarray, который отображает нечисловые данные в числовые данные (например, целые числа, представляющие классы / категории). sklearn-pandas уже делает это, хотя в настоящее время у него нет inverse_transform , но это не должно быть сложно добавить.

Я чувствую, что подобное преобразование было бы _ действительно_ полезно иметь в sklearn - это то, что может пригодиться любому, кто работает с наборами данных с несколькими типами данных. Что нужно сделать, чтобы внедрить что-то подобное в sklearn?

Самый полезный комментарий

Все мои трансформаторы возвращают DataFrame s при получении DataFrame s.
Когда я ввожу DataFrame из 300 столбцов в Pipeline и получаю ndarray из 500 столбцов, я не могу эффективно многому научиться из него, например, с помощью feature_selection , потому что у меня больше нет имен столбцов. Если, скажем, mutual_info_classif говорит мне, что важны только столбцы 30 и 75, я не могу понять, как упростить мой исходный Pipeline для производства.
Таким образом, для моего варианта использования очень важно хранить мои данные в DataFrame .
Спасибо.

Все 59 Комментарий

Scikit-learn был разработан для работы с очень общим форматом ввода. Возможно, мир вокруг scikit-learn сильно изменился с тех пор, что сделало интеграцию Pandas более важной. Он все еще может поставляться сторонними обертками.

Но помимо более широкого вопроса, я думаю, вам следует попытаться привести примеры того, как дружественный к Pandas вывод стандартных оценщиков будет отличаться и повлиять на удобство использования. Примеры, которые я могу придумать:

  • все методы могут копировать индекс из ввода
  • трансформаторы должны выводить столбцы с соответствующими именами
  • multiclass pred_proba может помечать столбцы именами классов

Ага, с головы до ног:

  • индекс может быть действительно полезен, например, для создания переменных с задержкой по времени (например, лаг на 1 день, для ежедневных данных с некоторыми пропущенными днями)
  • Регрессоры sklearn можно прозрачно использовать с категориальными данными (передать смешанный фрейм данных, преобразовать категориальные столбцы с помощью LabelBinarizer, обратное преобразование inverse_transform).
  • sklearn-pandas уже предоставляет удобный интерфейс, который позволяет передавать фрейм данных, использовать только подмножество данных и произвольно преобразовывать отдельные столбцы.

Если это все в преобразовании, то это не влияет на то, как sklearn работает по умолчанию.

Я не думаю, что это может быть красиво реализовано в качестве трансформатора. Это было бы
один или несколько метаэстиматоров или миксинов. Я думаю, что они должны быть изначально
реализовано внешне и продемонстрировано как полезное

22 октября 2015 года в 17:40 naught101 [email protected] написал:

Ага, с головы до ног:

  • индекс может быть действительно полезен, например, для создания с запаздыванием по времени
    переменные (например, отставание на 1 день, ежедневные данные с некоторыми пропущенными днями)
  • Регрессоры sklearn можно прозрачно использовать с категориальными данными
    (передать смешанный фрейм данных, преобразовать категориальные столбцы с помощью LabelBinarizer,
    inverse_transform его обратно).
  • sklearn-pandas уже предоставляет хороший интерфейс, который позволяет вам
    передать фрейм данных и использовать только подмножество данных и произвольно
    преобразовать отдельные столбцы.

Если это все в преобразовании, то это на самом деле не влияет на то, как sklearn
работает по умолчанию.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -150123228
.

Сделать «панд» лучше - это своего рода идея, лежащая в основе трансформатора колонн PR # 3886. Возможно, мне следовало более внимательно изучить то, что sklearn-pandas уже делает. Я не совсем уверен, как лучше всего двигаться вперед.

Еще было бы неплохо сохранить имена столбцов при преобразованиях / выбрать их при выборе функции. Я не нахожу вопроса, где мы это обсуждали прямо сейчас. Может, @jnothman помнит. Я бы очень хотел этого, хотя для сохранения имен столбцов потребуется серьезная операция с проверкой ввода: - /

Связанные # 4196

хотя это потребует серьезной хирургической операции с проверкой входных данных для
сохранить имена столбцов: - /

Не только проверка ввода: каждое преобразование должно описывать, что оно
делает для входных столбцов.

Верно, но это, я думаю, было бы неплохо;)

Один вопрос, может быть, хотим мы этого только в конвейерах или везде? Если мы ограничим его конвейерами, операция проверки ввода будет менее сложной. Но я не уверен, насколько это было бы полезно.

Вы всегда можете создать конвейер, в котором есть только одна вещь, верно? Таким образом, мы _kind of_ обрабатываем все случаи (хотя это хакерский в пределах 1 объекта), ограничивая сначала только конвейер ...

+1. Начать с конвейера звучит неплохо, и на следующем шаге рассмотрим весь трансформатор.

У меня также есть impl с интеграцией pandas и sklearn, который может возвращать информацию о столбцах через inverse_transform (хотя грязный хак ...)

http://pandas-ml.readthedocs.org/en/latest/sklearn.html

• индекс может быть действительно полезен, например, для создания переменных с задержкой по времени
(например, задержка в 1 день для ежедневных данных с некоторыми пропущенными днями)

Я немного глуп, но не говорю о чем-то в образце
направление здесь, а не направление функции?

• регрессоры sklearn могут прозрачно использоваться с категориальными данными (пройти
смешанный фрейм данных, преобразование категориальных столбцов с помощью LabelBinarizer,
inverse_transform его обратно).

• sklearn-pandas уже предоставляет удобный интерфейс, позволяющий передавать
dataframe и использовать только подмножество данных и произвольно преобразовывать
отдельные столбцы.

Хорошо, но это все на уровне одного преобразователя, который принимает Панды,
и выдает матрицу данных, не так ли? Вместо того, чтобы пытаться
модификации на всех объектах scikit-learn (что является рискованным
endeavior), мы могли бы сначала реализовать этот преобразователь (я считаю, что
@amueller думает об этом).

здесь направление образца, а не направление признака?

Ага.

Хорошо, но это все на уровне одного преобразователя, который принимает Pandas и выдает матрицу данных, не так ли?

Ага, это то, о чем я думал с самого начала. Я был бы более чем доволен оболочкой, которая обрабатывала бы X и y как фреймы данных. Я не вижу очевидной причины болтать с внутренностями sklearn.

OK, but that's all at the level of one transformer that takes Pandas in,
and gives a data matrix out, isn't it?

Ага, это то, о чем я думал с самого начала. Я был бы более чем доволен
оболочка, которая обрабатывала X и y как фреймы данных. Я не вижу очевидной причины
прикрутить внутренности sklearn.

Тогда мы на той же странице. Я думаю, что у @amueller есть идеи насчет
это, и мы, возможно, вскоре увидим обсуждение и, возможно, код.

Еще было бы неплохо сохранить имена столбцов при преобразованиях / выбрать их при выборе функции. Я не нахожу вопроса, где мы это обсуждали прямо сейчас.

5172

Примечание: я задавался вопросом, захочется ли только обернуть внешний оценщик в ансамбль, чтобы предоставить эту функциональность пользователю. Я думаю, ответ таков: нет, атомные преобразователи тоже хочется обернуть, чтобы в конвейере можно было использовать преобразователи, поддерживающие фреймы данных (почему бы и нет?). Не реализуя это как миксин, я думаю, вы столкнетесь с проблемами с ненужным префиксом параметров или с клонированием (как в # 5080).

: +1:

Просто хотел выбросить решение, которое использую:

def check_output(X, ensure_index=None, ensure_columns=None):
    """
    Joins X with ensure_index's index or ensure_columns's columns when avaialble
    """
    if ensure_index is not None:
        if ensure_columns is not None:
            if type(ensure_index) is pd.DataFrame and type(ensure_columns) is pd.DataFrame:
                X = pd.DataFrame(X, index=ensure_index.index, columns=ensure_columns.columns)
        else:
            if type(ensure_index) is pd.DataFrame:
                X = pd.DataFrame(X, index=ensure_index.index)
    return X

Затем я создаю оболочки вокруг оценщиков sklearn, которые вызывают эту функцию на выходе преобразования, например,

from sklearn.preprocessing import StandardScaler as _StandardScaler 
class StandardScaler(_StandardScaler):
    def transform(self, X):
        Xt = super(StandardScaler, self).transform(X)
        return check_output(Xt, ensure_index=X, ensure_columns=X)

Классификаторы, которым необходимо использовать индекс входного фрейма данных X, могут просто использовать его индекс (как было указано, полезно для временных рядов).

Преимущество этого подхода состоит в том, что он полностью совместим с существующим дизайном sklearn, а также сохраняет скорость вычислений (математические операции и индексация фреймов данных до 10 раз медленнее, чем массивы numpy, http://penandpants.com/2014/09/05 / performance-of-pandas-series-vs-numpy-array /). К сожалению, добавить к каждому оценщику, который мог бы его использовать, утомительно много работы.

Может быть, только нужно сделать вариант Pipeline с этой магией ...

15 января 2016 года в 02:30 декан Вятте [email protected] написал:

Просто хотел выбросить решение, которое использую:

def check_output (X, sure_index = None, sure_columns = None):
"" "
Присоединяется к X с индексом sure_index или столбцами sure_columns, когда доступно
"" "
если secure_index не равно None:
если sure_columns не равно None:
если тип (sure_index) - pd.DataFrame, а тип (sure_columns) - pd.DataFrame:
X = pd.DataFrame (X, index = secure_index.index, columns = secure_columns.columns)
еще:
если тип (sure_index) - pd.DataFrame:
X = pd.DataFrame (X, индекс = sure_index.index)
вернуть X

Затем я создаю оболочки вокруг оценщиков sklearn, которые вызывают эту функцию.
на выходе преобразования, например,

из sklearn.preprocessing импортировать StandardScaler как _StandardScaler
класс MinMaxScaler (_MinMaxScaler):
def transform (self, X):
Xt = super (MinMaxScaler, self) .transform (X)
вернуть check_output (Xt, sure_index = X, sure_columns = X)

Классификаторы, которым необходимо использовать индекс входного фрейма данных X, могут просто
используйте его индекс (как было указано, полезно для таймсерий).

Преимущество этого подхода в том, что он полностью совместим с
существующий дизайн sklearn с сохранением скорости вычислений
(математические операции и индексация фреймов данных до 10 раз медленнее, чем numpy
массивы). К сожалению, добавить к каждому оценщику очень утомительно.
который мог бы его использовать.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171674105
.

Или просто что-то, что обертывает конвейер / оценщик, нет?

Я действительно не понимаю, почему вы вызываете такую ​​функцию, как "check_ *", когда она делает гораздо больше, чем просто проверку ...

14 января 2016 г., 10:45:44 по центральному поясному времени Джоэл Нотман [email protected] написал:

Может быть, только нужно сделать вариант Pipeline с этой магией ...

15 января 2016 г., в 02:30, Дин Вятте [email protected]
написал:

Просто хотел выбросить решение, которое использую:

def check_output (X, sure_index = None, sure_columns = None):
"" "
Объединяет X с индексом sure_index или столбцами sure_columns
когда доступно
"" "
если secure_index не равно None:
если sure_columns не равно None:
если тип (sure_index) - pd.DataFrame и
тип (sure_columns) - pd.DataFrame:
X = pd.DataFrame (X, index = secure_index.index,
columns = sure_columns.columns)
еще:
если тип (sure_index) - pd.DataFrame:
X = pd.DataFrame (X, индекс = sure_index.index)
вернуть X

Затем я создаю оболочки вокруг оценщиков sklearn, которые называют это
функция
на выходе преобразования, например,

из sklearn.preprocessing импортировать StandardScaler как _StandardScaler
класс MinMaxScaler (_MinMaxScaler):
def transform (self, X):
Xt = super (MinMaxScaler, self) .transform (X)
вернуть check_output (Xt, sure_index = X, sure_columns = X)

Классификаторы, которым необходимо использовать индекс входного фрейма данных X, могут
просто
используйте его индекс (как было указано, полезно для таймсерий).

Преимущество этого подхода в том, что он полностью совместим с
существующий дизайн sklearn при сохранении скорости
вычисление
(математические операции и индексация фреймов данных до 10 раз медленнее, чем
тупой
массивы). К сожалению, добавить к каждому из них довольно утомительно.
оценщик
который мог бы его использовать.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub

https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171674105
.


Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171697542

Отправлено с моего устройства Android с помощью K-9 Mail. Прошу прощения за краткость.

Я не уверен, что Pipeline - правильное место для начала, потому что все наследование имен столбцов зависит от средства оценки, например, средства масштабирования должны наследовать имена столбцов входного фрейма данных, тогда как модели, такие как PCA, не должны. Оценщики выбора функций должны наследовать определенные имена столбцов, но это другая проблема, вероятно, более связанная с # 2007.

Всегда ли при преобразовании сохраняется n_rows всех массивов? Если это так, просто наследование индекса ввода (если он существует) кажется безопасным, но я не уверен, что получение фрейма данных с именами столбцов по умолчанию (например, [0, 1, 2, 3, ...]) является лучше, чем текущее поведение с точки зрения конечного пользователя, но если используется явная оболочка / метаоценка, то, по крайней мере, пользователь будет знать, чего ожидать.

Кроме того, я согласился с тем, что check_ * - плохое имя - я делал немного больше проверки в своей функции и просто вырезал логику фрейма данных, чтобы опубликовать здесь.

Я думаю, что конвейер будет местом для начала, хотя нам нужно будет что-то добавить ко всем оценщикам, которые соответствующим образом отображают имена столбцов.

трансформаторы должны выводить столбцы с соответствующими именами @ naught101

хотя для сохранения имен столбцов потребуется серьезная операция с проверкой ввода: - / @amueller

Не только проверка ввода: каждое преобразование должно описывать, что оно делает с входными столбцами. @GaelVaroquaux

Кто-нибудь задумывался о механике передачи имен от трансформатора к трансформатору и, возможно, как отследить происхождение? Где бы это хранить?

У моего друга, @cbrummitt , есть аналогичная проблема, где каждый столбец его матрицы дизайна представляет собой функциональную форму (например, x ^ 2, x ^ 3, x_1 ^ 3x_2 ^ 2, представленные как симпозиумные выражения), и у него есть трансформаторы. которые действуют аналогично PolynomialFeatures, которые могут принимать функциональные формы и генерировать больше на их основе. Но он использует sympy, чтобы брать старые выражения и генерировать новые, а сохранение выражений в виде строковых меток не сокращает его, и это усложняется, когда вы накладываете преобразования функций на слои. Он мог бы делать все это вне конвейера, но тогда он не получает преимуществ от GridSearch и т. Д.

Я предполагаю, что более общая версия нашего вопроса заключается в том, откуда у вас есть информация, которая будет передаваться от трансформатора к трансформатору, но это НЕ сами данные? Я не могу придумать отличный способ без глобального состояния конвейера, без того, чтобы каждый преобразователь / оценщик знал о предыдущих, или без того, чтобы каждый шаг возвращал несколько вещей или что-то в этом роде.

Затем нам пришла в голову идея изменить конвейер, чтобы отслеживать это, вам нужно будет изменить _fit () и _transform () и, возможно, еще несколько вещей. Кажется, это наш лучший вариант.

Это звучит безумно, но каково ощущение, что мы действительно хотим, чтобы наша матрица данных была симпатичными выражениями, и каждое преобразование генерирует новые выражения? Это грубо, check_array () останавливает это, и это рассердит другие шаги по конвейеру.

текущую идею см. # 6425.

Все, что вам нужно, это отображение для каждого трансформатора (включая конвейер
трансформаторы), от имен входных элементов до имен выходных элементов (или некоторых
структурированное представление преобразований, которое, как я подозреваю, более
инженерии, чем мы собираемся получить). Это то, что предлагает # 6425.

8 октября 2016 г., в 03:42, Андреас Мюллер [email protected]
написал:

см. # 6425 https://github.com/scikit-learn/scikit-learn/issues/6425 для
текущая идея.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -252301608,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAEz65fBsMwqmkDq3DEjMSUC-W-nfn9zks5qxnZxgaJpZM4GThGc
.

Мы рассмотрим это, спасибо!

Может ли кто-нибудь предоставить общую обновленную информацию о состоянии мира в связи с этой проблемой?

Всегда ли поддержка pandas DataFrame будет частью YMMV?
Было бы полезно руководство о том, что считается / не считается безопасным для использования с пандами DataFrame вместо простого ndarray . Возможно, что-то вроде следующего (СДЕЛАННАЯ ПРИМЕРНАЯ ТАБЛИЦА):

модуль / категория | может безопасно использовать pandas DataFrame
- | -
sklearn.pipeline | БЕЗОПАСНО
sklearn.feature_selection | БЕЗОПАСНЫЙ
регрессоры | YMMV
sklearn.feature_extraction | НЕ БЕЗОПАСНО, внедрение не планируется
и т.д | ...

Прямо сейчас я не уверен в другом подходе, кроме «просто попробуйте и посмотрите, не возникнут ли исключения».

Мы протестировали несколько вручную закодированных примеров, которые, кажется, отлично работают, принимая DataFrame pandas, но не можем не думать, что это неизбежно перестанет работать, когда мы решим, что нам нужно сделать, казалось бы, тривиальную замену компонентов конвейера ... в этот момент все рушится, как карточный домик на загадочной трассе стека.

Мой первоначальный мыслительный процесс заключался в создании замещающего объекта конвейера, который может потреблять pandas DataFrame которые автоматически генерируют оболочки для стандартных компонентов scikit-learn для преобразования объектов ввода / вывода DataFrame в numpy ndarray при необходимости. Таким образом, я могу написать свои собственные селекторы / преобразователи, чтобы использовать примитивы pandas DataFrame , но это кажется немного тяжеловесным. Особенно, если мы находимся на пороге «официальной» поддержки для них.

Я следил за несколькими разными PR, но трудно понять, какие из них заброшены и / или которые отражают текущее мышление:
Пример:

6425 (ссылка на октябрь 2016 г. выше в этой ветке)

9012 (очевидное совпадение со sklearn-pandas, но аннотировано как экспериментальное?)

3886 (заменен на # 9012?)

Это в значительной степени зависит от того, что вы имеете в виду под «Может безопасно использовать pandas DataFrame». Если вы имеете в виду DataFrame, содержащий только числа с плавающей запятой, мы гарантируем, что все будет работать. Если где-то есть хоть одна строка, ничего не получится.

Я думаю, что любой оценщик scikit-learn, возвращающий фрейм данных для любой нетривиальной (или, может быть, даже тривиальной) операции, может никогда не произойти (хотя он бы этого хотел).

9012 произойдет и станет стабильным, PR - это первая итерация (или 10-я итерация, если считать неслитые;)

6425, скорее всего, произойдет, хотя это не полностью связано с пандами.

3886 действительно заменен # 9012

Функциональность # 6425 в настоящее время реализована (для некоторых трансформаторов и
расширяемый для других) через singledispatch в
https://codecov.io/gh/TeamHG-Memex/eli5 за то, что он стоит.

21 июня 2017 года в 13:25 Андреас Мюллер [email protected] написал:

9012 https://github.com/scikit-learn/scikit-learn/pull/9012 будет

случится и станет стабильным, PR это первая итерация.

6425 https://github.com/scikit-learn/scikit-learn/issues/6425 - это

Вероятно, это произойдет, хотя это не полностью связано с пандами.

3886 https://github.com/scikit-learn/scikit-learn/pull/3886 действительно

заменен на # 9012
https://github.com/scikit-learn/scikit-learn/pull/9012

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment-309952467 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAEz61lgGBW1AoukPm_87elBjF2NGOUwks5sGI0-gaJpZM4GThGc
.

Да, и когда я говорю: «Если вы имеете в виду DataFrame, содержащий только числа с плавающей запятой, мы гарантируем, что все будет работать». Я имею в виду индексацию столбцов на основе местоположения. Предполагается, что столбцы обучающего и тестового набора совпадают по положению.

Это в значительной степени зависит от того, что вы имеете в виду под «Может безопасно использовать pandas DataFrame». Если вы имеете в виду DataFrame, содержащий только числа с плавающей запятой, мы гарантируем, что все будет работать. Если где-то есть хоть одна строка, ничего не получится.

Думаю, для нас этого достаточно.

Мы используем конвейер настраиваемых компонентов (тонкие оболочки вокруг существующих инструментов, которые не подходят для конвейеров) для преобразования смешанных типов (строк, чисел с плавающей запятой и целых чисел) в числа с плавающей запятой посредством кодирования / масштабирования до достижения таких компонентов scikit-learn, как селекторы или модели.

Все мои трансформаторы возвращают DataFrame s при получении DataFrame s.
Когда я ввожу DataFrame из 300 столбцов в Pipeline и получаю ndarray из 500 столбцов, я не могу эффективно многому научиться из него, например, с помощью feature_selection , потому что у меня больше нет имен столбцов. Если, скажем, mutual_info_classif говорит мне, что важны только столбцы 30 и 75, я не могу понять, как упростить мой исходный Pipeline для производства.
Таким образом, для моего варианта использования очень важно хранить мои данные в DataFrame .
Спасибо.

@ sam-s Полностью согласен. В «краткосрочной» перспективе это будет решено https://github.com/scikit-learn/scikit-learn/pull/13307 и https://github.com/scikit-learn/enhancement_proposals/pull/18.

Вы не получите фреймворка pandas, но получите имя столбца для его создания.

Но не могли бы вы привести более конкретный пример? Потому что, если все преобразователи возвращают DataFrames, все должно работать (или работать проще, чем предложения выше).

Небольшое обновление через https://github.com/pandas-dev/pandas/issues/27211
что ставит под сомнение мои надежды. Похоже, что мы не можем полагаться на то, что существует двусторонний обход с нулевым копированием, поэтому упаковка и развертывание в pandas приведет к значительным затратам.

Небольшое обновление через pandas-dev / pandas # 27211, которое ослабляет мои надежды. Похоже, что мы не можем полагаться на то, что существует двусторонний обход с нулевым копированием, поэтому упаковка и развертывание в pandas приведет к значительным затратам.

да, но я думаю, как только мы рассмотрим эту функцию и образцы свойств (имена строк и «индексы» являются своего рода образцами свойств), большинство связанных сценариев использования, которым сейчас нужны панды, будут рассмотрены, верно?

@adrinjalali Я не

Просто из любопытства, есть ли временные рамки, в которые ожидается улучшение совместимости с Pandas? Меня особенно интересуют Pandas in -> Pandas out for StandardScaler .

У меня есть случай использования, когда мне нужны фреймы данных pandas, сохраняемые на каждом шаге в Pipeline . Например, конвейер с 1) функциями фильтрации шага выбора характеристик на основе данных, 2) шагом преобразования данных, 3) другим шагом выбора характеристик для фильтрации определенных имен столбцов характеристик или исходных индексов, 4) стандартизацией, 5) классификацией.

Шаг 3) Я считаю, что в настоящее время это невозможно в sklearn, даже с вводом массива numpy, потому что исходные индексы функций бессмысленны, когда данные доходят до 3), поскольку в 1) был этап выбора функции. Если бы кадры данных pandas сохранялись в конвейере, это сработало бы, потому что я мог фильтровать по имени столбца в 3).

Я ошибаюсь, думая, что в настоящее время нет способа сделать это даже с вводом массива numpy?

Вы правы, что он не поддерживается, и поддерживать его было бы нетривиально. Что касается вашего варианта использования, мы работаем над передачей имен функций по конвейеру (как вы видите в связанных PR и предложениях выше). Надеюсь, это поможет в вашем случае, когда все будет готово. Я не уверен, поможет ли это, но вы также можете взглянуть на https://github.com/scikit-learn-contrib/sklearn-pandas

Вы правы, что он не поддерживается, и поддерживать его было бы нетривиально. Что касается вашего варианта использования, мы работаем над передачей имен функций по конвейеру (как вы видите в связанных PR и предложениях выше). Надеюсь, это поможет в вашем случае, когда все будет готово.

Спасибо за подтверждение, да, возможность передавать имена функций (или другие свойства функций), чтобы они соответствовали методам, и правильно нарезать их на каждом этапе выбора функции, было бы хорошо для этого варианта использования.

Я не уверен, поможет ли это, но вы также можете взглянуть на https://github.com/scikit-learn-contrib/sklearn-pandas

Раньше я читал их документы и, возможно, я этого не вижу, но большинство (или все) их функции теперь устарели в scikit-learn 0.21 с sklearn.compose.ColumnTransformer ? Также не похоже, что они поддерживают pandas, это похоже на массивы numpy после преобразований.

(Интересно, не сломается ли поддержка Pandas в выборе функций
много...)

Просто кратко проверив код, можно увидеть всевозможные проверки, которые происходят произвольно во многих местах, например, https://github.com/scikit-learn/scikit-learn/blob/939fa3cccefe708db7a81c5248db32a1d600bf8d/sklearn/utils/validation.py# L619

Кроме того, многие операции используют индексирование в виде множества, которые не будут приняты фреймворком данных pandas.

Включение / отключение панд было бы обязательным условием для повседневной обработки данных IMO, но scikit-learn, похоже, спроектирован таким образом, что его сложно реализовать.

Сохранение панд в / из было бы обязательным для повседневной науки о данных IMO, но
scikit-learn, похоже, спроектирован таким образом, чтобы его было трудно
реализовано.

Хорошие числа сложно реализовать на фреймах данных pandas. Они просто
не предназначены для этого, в частности, для многомерных операций (числовые
операции по столбцам).

Машинное обучение - это в основном многомерные числа.

Хорошие числа сложно реализовать на фреймах данных pandas. Они просто не предназначены для этого, в частности, для многомерных операций (числовые операции по столбцам). Машинное обучение - это в основном многомерные числа.

Это решение должно быть оставлено на усмотрение пользователя? По моему опыту использования scikit-learn за последние два года, я думаю, что две основные и важные функции, которые отсутствуют и являются обязательными для многих сценариев использования машинного обучения, - это поддержка передачи метаданных образцов и функций. Полная поддержка фреймов данных pandas - естественный и элегантный способ справиться с некоторыми из этих проблем.

Такие основные функции очень важны для сохранения пользовательской базы и привлечения новых пользователей. В противном случае я вижу, что библиотеки, такие как, например, mlr3, в конечном итоге созревают и отвлекают пользователей от sklearn, потому что я знаю, что они полностью поддерживают (или будут) фреймы данных и метаданные.

Это решение должно быть оставлено на усмотрение пользователя?

Что ж, пользователь не реализует алгоритм.

В противном случае я вижу библиотеки, такие как, например, mlr3, которые в конечном итоге созревают и
привлечение пользователей от sklearn, потому что я знаю, что они делают (или будут)
полностью поддерживают фреймы данных и метаданные.

mlr3 находится в R, фреймы данных сильно отличаются от фреймов данных pandas.
Может быть, это упрощает реализацию.

Я согласен с тем, что лучшая поддержка имен функций и разнородных данных
типы важны. Мы работаем над поиском хороших технических решений
которые не приводят к потере производительности и чрезмерно сложному коду.

Это решение должно быть оставлено на усмотрение пользователя?
Что ж, пользователь не реализует алгоритм.
В противном случае я вижу, что библиотеки, такие как, например, mlr3, в конечном итоге созревают и отвлекают пользователей от sklearn, потому что я знаю, что они полностью поддерживают (или будут) фреймы данных и метаданные.
mlr3 находится в R, фреймы данных сильно отличаются от фреймов данных pandas. Может быть, это упрощает реализацию. Я согласен с тем, что важна лучшая поддержка имен функций и разнородных типов данных. Мы работаем над поиском хороших технических решений, которые не приводят к потере производительности и чрезмерно сложному коду.

Я думаю, что ваш подход, заключающийся в использовании нескольких массивов и, по крайней мере, в поддержке передачи имен функций или, что еще лучше, с использованием метаданных с несколькими функциями, будет работать во многих случаях использования. Вы уже поддерживаете передачу метаданных обучающего образца в **fit_params и я знаю, что есть усилия по улучшению дизайна. Но я упоминал в https://github.com/scikit-learn/enhancement_proposals/pull/16, что есть случаи использования, когда вам также понадобятся метаданные тестового образца, переданные в методы transform и это в настоящее время не поддерживается .

mlr3 находится в R, фреймы данных сильно отличаются от фреймов данных pandas.

Ученые-вычислители, занимающиеся исследованиями в области наук о жизни, обычно очень хорошо знакомы с Python и R и используют их вместе (в том числе и я). Я почти уверен, что значительный процент пользователей scikit-learn - исследователи наук о жизни.

В настоящее время доступные зрелые библиотеки ML в R IMHO даже близко не подходят к scikit-learn с точки зрения предоставления хорошо разработанного API и упрощения утилитарных частей ML (конвейеры, поиск гиперпараметров, оценка и т. Д.), Тогда как в R с этими библиотеками вам придется писать код самостоятельно. Но в MLR3 я вижу в будущем большую конкуренцию scikit-learn, поскольку они проектируют его с нуля правильно.

Хорошие числа сложно реализовать на фреймах данных pandas. Они просто
не предназначены для этого, в частности, для многомерных операций (числовые
операции по столбцам).

Возможно, мне что-то не хватает, но разве нельзя было бы развернуть DataFrame (используя df.values ), выполнить вычисления, а затем вернуться к новому DataFrame?

В основном это то, что я делаю вручную между шагами, и единственное, что предотвращает использование Pipeline .

Может, я чего-то упускаю, но разве нельзя было бы развернуть
DataFrame (используя df.values), выполните вычисления, а затем вернитесь к новому
DataFrame?

В общем, нет: это может не сработать (разнородные столбцы), и это будет
приводят к большому количеству копий в памяти.

В общем нет: это может не сработать (разнородные столбцы)

Я думаю, что Column Transformers и тому подобное могут с этим справиться.

это приведет к созданию большого количества копий памяти.

Я понимаю, что есть трудный выбор дизайна и реализации, и это веский аргумент.

Однако я не понимаю, почему вы утверждаете, что улучшать способ поддержки метаданных столбцов в sklearn - плохая идея.

Разрешение, например, принимать df с функциями, добавлять столбец с помощью предиктора, выполнять больше манипуляций с данными, делать другое прогнозирование, все, что в конвейере, - это то, что было бы полезно, потому что оно (например) позволило бы оптимизировать гиперпараметры. гораздо лучше интегрированным и элегантным способом.

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

Пользователь должен решить не использовать этот рабочий процесс при оптимизации производительности.

Оставляя решение на усмотрение пользователя, необходимо четко объяснить
выбор пользователю. Большинство пользователей не читают документацию, которая
объясните такой выбор. Многие попробовали бы то, что, по их мнению, могло бы работать, а затем
сдаются, когда они находят это медленным, не понимая, что это был их выбор
daraframe, который сделал это так.

Так что здесь нам нужно действовать осторожно. Но нам нужно продолжать решать
это как высокий приоритет.

Я думаю, что лучшим решением было бы поддерживать фреймы данных pandas внутри и снаружи для свойств образца и функции, а также правильно передавать и нарезать их на обучение и тестирование соответствия / преобразования. Это решило бы большинство случаев использования, сохраняя при этом скорость матрицы данных X в виде множества массивов.

Один важный момент, отсутствующий в этих аргументах, заключается в том, что pandas движется к столбчатому представлению данных таким образом, что np.array(pd.DataFrame(numpy_data)) будет иметь две _guaranteed_ копии памяти. Вот почему это не так просто, как просто сохранить фрейм данных и использовать values всякий раз, когда нам нужна скорость.

Один важный момент, отсутствующий в этих аргументах, заключается в том, что pandas движется к столбчатому представлению данных таким образом, что np.array(pd.DataFrame(numpy_data)) будет иметь две _guaranteed_ копии памяти. Вот почему это не так просто, как просто сохранить фрейм данных и использовать values всякий раз, когда нам нужна скорость.

Надеюсь, я был ясен в своем предыдущем посте. Я считаю, что scikit-learn в настоящее время не требуется поддерживать фреймы данных pandas для данных X, храните их как быстрые массивы numpy. Но то, что могло бы решить многие варианты использования, - это полная поддержка фреймворков данных pandas для метаданных, то есть образцов свойств и свойств функций. Это не должно сказываться на производительности даже для копий памяти, поскольку эти две структуры данных будут второстепенными по сравнению с X, и на самом деле для них будет выполняться только подмножество.

Да, эти изменения действительно помогают во многих случаях использования, и мы работаем над ними. Но эта проблема выходит за рамки этого: https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -508807755

@hermidalc , вы предлагаете, чтобы мы позволили X быть массивом numpy и присвоить метаданные другим объектам фрейма данных?

@hermidalc , вы предлагаете, чтобы мы позволили X быть массивом numpy и присвоить метаданные другим объектам фрейма данных?

Да, полная поддержка образцов свойств и свойств функций в виде фреймов данных pandas. Обсуждение свойств образцов и названий функций уже ведется в других PR и проблемах, например здесь # 9566 и # 14315

Я прочитал об этой проблеме и, похоже, здесь есть два основных препятствия:

  1. https://github.com/pandas-dev/pandas/issues/27211
  2. Эти панды не обрабатывают массивы ND.

Думали ли вы вместо этого о добавлении поддержки xarrays? У них нет ограничений панд.

X = np.arange(10).reshape(5, 2)
assert np.asarray(xr.DataArray(X)) is X
assert np.asarray(xr.Dataset({"data": (("samples", "features"), X)}).data).base is X.base

Существует пакет под названием sklearn-xarray : https://phausamann.github.io/sklearn-xarray/content/wrappers.html, который обертывает scikit-оценщики для обработки xarrays в качестве ввода и вывода, но, похоже, он не поддерживается для годы. Однако мне интересно, подходят ли здесь обертки.

xarray активно рассматривается. Его прототип и работа над ним разрабатывается здесь: https://github.com/scikit-learn/scikit-learn/pull/16772. Существует записная книжка по использованию API в PR.

(Я вернусь к нему после того, как мы закончим с выпуском 0.23)

Мне тоже очень интересна эта функция.
Это решило бы бесконечные проблемы. В настоящее время я использую именно это решение.
Я написал оболочку вокруг модуля sklearn.preprocessing , который назвал sklearn_wrapper

Поэтому вместо импорта из sklearn.preprocessing я импортирую из sklearn_wrapper .
Например:

# this
from sklearn.preprocessing import StandardScaler 
# becomes 
from sklearn_wrapper import StandardScaler

Ниже реализация этого модуля. Попробуйте и дайте мне знать, что вы, ребята, думаете

from functools import wraps
from itertools import chain

import pandas as pd
from sklearn import preprocessing, compose, feature_selection, decomposition
from sklearn.compose._column_transformer import _get_transformer_list

modules = (preprocessing, feature_selection, decomposition)


def base_wrapper(Parent):
    class Wrapper(Parent):

        def transform(self, X, **kwargs):
            result = super().transform(X, **kwargs)
            check = self.check_out(X, result)
            return check if check is not None else result

        def fit_transform(self, X, y=None, **kwargs):
            result = super().fit_transform(X, y, **kwargs)
            check = self.check_out(X, result)
            return check if check is not None else result

        def check_out(self, X, result):
            if isinstance(X, pd.DataFrame):
                result = pd.DataFrame(result, index=X.index, columns=X.columns)
                result = result.astype(X.dtypes.to_dict())
            return result

        def __repr__(self):
            name = Parent.__name__
            tmp = super().__repr__().split('(')[1]
            return f'{name}({tmp}'

    Wrapper.__name__ = Parent.__name__
    Wrapper.__qualname__ = Parent.__name__

    return Wrapper


def base_pca_wrapper(Parent):
    Parent = base_wrapper(Parent)

    class Wrapper(Parent):
        @wraps(Parent)
        def __init__(self, *args, **kwargs):
            self._prefix_ = kwargs.pop('prefix', 'PCA')
            super().__init__(*args, **kwargs)

        def check_out(self, X, result):
            if isinstance(X, pd.DataFrame):
                columns = [f'{self._prefix_}_{i}' for i in range(1, (self.n_components or X.shape[1]) + 1)]
                result = pd.DataFrame(result, index=X.index, columns=columns)
            return result

    return Wrapper


class ColumnTransformer(base_wrapper(compose.ColumnTransformer)):

    def check_out(self, X, result):
        if isinstance(X, pd.DataFrame):
            return pd.DataFrame(result, index=X.index, columns=self._columns[0]) if self._remainder[1] == 'drop' \
                else pd.DataFrame(result, index=X.index, columns=X.columns). \
                astype(self.dtypes.iloc[self._remainder[-1]].to_dict())


class SelectKBest(base_wrapper(feature_selection.SelectKBest)):

    def check_out(self, X, result):
        if isinstance(X, pd.DataFrame):
            return pd.DataFrame(result, index=X.index, columns=X.columns[self.get_support()]). \
                astype(X.dtypes[self.get_support()].to_dict())


def make_column_transformer(*transformers, **kwargs):
    n_jobs = kwargs.pop('n_jobs', None)
    remainder = kwargs.pop('remainder', 'drop')
    sparse_threshold = kwargs.pop('sparse_threshold', 0.3)
    verbose = kwargs.pop('verbose', False)
    if kwargs:
        raise TypeError('Unknown keyword arguments: "{}"'
                        .format(list(kwargs.keys())[0]))
    transformer_list = _get_transformer_list(transformers)
    return ColumnTransformer(transformer_list, n_jobs=n_jobs,
                             remainder=remainder,
                             sparse_threshold=sparse_threshold,
                             verbose=verbose)


def __getattr__(name):
    if name not in __all__:
        return

    for module in modules:
        Parent = getattr(module, name, None)
        if Parent is not None:
            break

    if Parent is None:
        return

    if module is decomposition:
        Wrapper = base_pca_wrapper(Parent)
    else:
        Wrapper = base_wrapper(Parent)

    return Wrapper


__all__ = [*[c for c in preprocessing.__all__ if c[0].istitle()],
           *[c for c in decomposition.__all__ if c[0].istitle()],
           'SelectKBest']


def __dir__():
    tmp = dir()
    tmp.extend(__all__)
    return tmp

https://github.com/koaning/scikit-lego/issues/304 предоставил другое решение путем горячей фиксации на sklearn.pipeline.FeatureUnion

Была ли эта страница полезной?
0 / 5 - 0 рейтинги