Scikit-learn: Переосмысливаете API Категорического Энкодера?

Созданный на 23 янв. 2018  ·  63Комментарии  ·  Источник: scikit-learn/scikit-learn

Основываясь на некоторых обсуждениях, которые у нас здесь проводятся, и на открытых проблемах, у нас есть некоторые сомнения, что CategoricalEncoder (https://github.com/scikit-learn/scikit-learn/pull/9151) был хорошим выбор имени (и, поскольку он еще не выпущен, у нас есть место для изменения).

Итак, краткое изложение того, как это сейчас:

  • Имя класса CategoricalEncoder говорит, какой тип данных он принимает (категориальные данные).
  • Аргумент ключевого слова encoding указывает, как кодировать эти данные.

В настоящее время у нас уже есть encoding='onehot'|'onehot-dense'|'ordinal' .

Но что делать в следующих случаях:

  • Мы хотим добавить больше вариантов кодирования (например, двоичное кодирование, среднее целевое кодирование, унарное кодирование и т. Д.). Продолжаем ли мы добавлять их как новые значения для encoding kwarg в один большой класс CategoricalEncoder ?
  • Мы хотим добавить опцию, специфичную для одной из кодировок (например, для кодирования «onehot», чтобы удалить первый (избыточный) столбец, или для «порядкового» кодирования основывать порядок категорий по частоте, ...). Проблема здесь в том, что затем нам нужно добавить дополнительные аргументы ключевого слова в CategoricalEncoder , которые активны или не активны, в зависимости от того, что вы передали для encoding kwarg, что не является лучшим дизайном API.

Для этой последней проблемы у нас уже было это с опцией sparse=True/False , которая была актуальна только для 'onehot', а не для 'ordinal', и которую мы решили с помощью как 'onehot', так и 'onehot-density' параметры кодирования, а не ключевое слово sparse . Но и такой подход не масштабируется.

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


Какие варианты впереди:

1) Сохраните все, что у нас есть сейчас, в master, и не возражайте, добавив некоторые новые параметры в отдельный класс (важный вопрос, на который сейчас трудно ответить, - сколько новых функций мы захотим добавить в будущем) .
2) Переключите схему именования и получите кучу «категориальных кодировщиков», в названии которых указано, как они кодируются (OnehotEncoder, OrdinalEncoder, а позже, возможно, BinaryEncoder, UnaryEncoder, ...)

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


Одна проблема со вторым подходом (и одна из причин, по которой мы изначально выбрали CategoricalEncoder , даже до того, как мы добавили несколько вариантов кодирования), заключается в том, что уже существует OnehotEncoder , который имеет другой API, чем CategoricalEncoder . И на самом деле нет подходящего другого названия, которое мы могли бы использовать для кодировщика, который выполняет одноразовое кодирование.
Однако я думаю, что с помощью некоторых временных уродливых хаков мы могли бы повторно использовать имя, если мы согласны отказаться от текущих атрибутов (и я думаю, что мы согласны с тем, что это не самые полезные атрибуты). Идея состоит в том, что если вы поместите класс со строковыми данными, вы получите новое поведение, а если вы поместите класс с целочисленными данными, вы получите предупреждение об устаревании, указывающее, что поведение по умолчанию изменится (и указывающее, какое ключевое слово указать, чтобы получить избавиться от предупреждения).

cc @jnothman @amueller @GaelVaroquaux @rth

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

Идея возврата к категориальному энкодеру меня очень огорчает, но я думаю, что
Вы правы, что будущие пользователи будут меньше озадачены вариантом 2. Моя основная
обеспокоенность заключается в том, что мы пытались реализовать это как изменение OHE для
давно и ни разу не полетела. Возможно, было бы хорошо попробовать
модификации строки документации OneHotEncoder в соответствии с предложенным
изменения, так что мы можем видеть, выглядит ли это вменяемым.

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

Спасибо за резюме @jorisvandenbossche. Я думаю, что я за вариант 2: повторно использовать OneHotEncoder class, исключить странные атрибуты и добавить параметр конструктора для выбора поведения с будущим предупреждением, в котором говорится, что поведение по умолчанию изменится, но позволяет легко отключить это предупреждение, просто передав значение для этой опции.

Идея возврата к категориальному энкодеру меня очень огорчает, но я думаю, что
Вы правы, что будущие пользователи будут меньше озадачены вариантом 2. Моя основная
обеспокоенность заключается в том, что мы пытались реализовать это как изменение OHE для
давно и ни разу не полетела. Возможно, было бы хорошо попробовать
модификации строки документации OneHotEncoder в соответствии с предложенным
изменения, так что мы можем видеть, выглядит ли это вменяемым.

+1 к тому, что сказал Джоэл

⁣ Отправлено с моего телефона. Прошу простить за опечатки и краткость.

23 января 2018 г., 12:28, в 12:28 Джоэл Нотман [email protected] написал:

Идея возврата к категориальному энкодеру меня очень огорчает, но я
считать
Вы правы, что будущие пользователи будут менее озадачены вариантом 2. Мой
главный
беспокойство заключается в том, что мы пытались реализовать это как изменение OHE для
а
давно и ни разу не полетела. Возможно, было бы хорошо попробовать
модификации строки документации OneHotEncoder в соответствии с предложенным
изменения, так что мы можем видеть, выглядит ли это вменяемым.

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

Идея возврата к категориальному энкодеру меня очень огорчает

Чтобы было ясно, это не будет откат, это будет рефакторинг / переименование, сохраняющее всю функциональность!
Но мне также нравится название «Категориальный кодировщик», что действительно было бы печально.

Тем не менее, я быстро попытаюсь внести изменения, чтобы понять, насколько возможно интегрировать это в OnehotEncoder.

Хорошо, я открыл PR с подтверждением концепции: https://github.com/scikit-learn/scikit-learn/pull/10523.
Он еще не завершен (предупреждения об устаревании и новые атрибуты еще не рассчитываются в старом поведении).

Основной вопрос API - это формат входных данных.
Напомним, что в настоящее время мы обрабатываем категориальные данные двумя разными способами :

1) Как актуальные, еще не закодированные (целые или строковые) категориальные данные (как это делается в CategoricalEncoder ) -> вывести категории из уникальных значений в обучающих данных
2) Как целое число, уже закодированные данные (как это делается в текущем OneHotEncoder ) -> вывести категории из максимального значения в обучающих данных

Вопрос в том, стоит ли поддерживать оба случая? Таким образом, в потенциально объединенном OneHotEncoder сохраняем ли мы возможность делать и то, и другое, или мы полностью отказываемся от поддержки, а затем удаляем возможность обработки порядкового ввода?

Если вам нужна возможность обрабатывать и то, и другое, мы можем добавить логическое ключевое слово, чтобы указать тип входных данных (сейчас я использую encoded_input=False/True , но другие идеи: ordinal_input , ...)

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

Учитывая, что мы хотим обрабатывать и то, и другое, обзор того, как будет работать OneHotEncoder:

  • на данный момент encoded_input=None , и мы делаем вывод по умолчанию на основе данных
  • если данные, подобные int (ранее обрабатываемые OneHotEncoder), encoded_input внутренне имеют значение True и появляется предупреждение об устаревании. Если пользователь хочет сохранить текущее поведение, он может вручную указать его как OneHotEncoder(encoded_input=True) чтобы отключить предупреждение.
  • если ввод не похож на int, мы устанавливаем для encoded_input внутренне значение False и без предупреждения используем новое поведение (= текущее поведение категориального кодировщика)
  • в будущем мы изменим значение по умолчанию encoded_input с None на False (по умолчанию новое поведение, также для данных типа int)

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

@jnothman Я полагаю, вы признаете, что на практике может быть разница? (результат зависит от имеющихся у вас данных)

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

Я думаю, что мне лично никогда не понадобится этот метод, основанный на максимальном значении, но OneHotEncoder был таким уже много лет (по уважительной причине или нет?).

Фактически отказ от категоризации на основе максимального значения, безусловно, упростит реализацию (после устаревания).
И если мы выберем этот маршрут, я согласен, что вариант должен быть скорее legacy_mode=True/False а не encoded_input / ordinal_input

Напомните мне, какова реальная разница в выводе, когда n_values ​​= 'auto',
пожалуйста? Я думал, что active_features_ делает их в основном
идентично, но я, наверное, что-то забываю.

Ага, это проясняет наше недоразумение :-)
Я неправильно понял, как на самом деле работает текущий OneHotEncoder. Предположим, у вас есть одна функция со значениями [2, 3, 5, 2]. Я думал, что текущий OneHotEncoder будет иметь категории [0, 1, 2, 3, 4, 5] (в то время как текущий CategoryEncoder будет иметь категории [2, 3, 5]). Но вы правы в том, что active_features_ также только [2, 3, 5], что, по сути, делает их одинаковыми со значением по умолчанию n_values='auto' .

Таким образом, это только тот случай, когда вы передаете целое число в n_values (например, n_values=6 для категорий = [0, 1, 2, 3, 4, 5] в приведенном выше случае), чтобы указать количество категорий, которые фактически будут изменены API (устарело / удалено).
И это будет легко заменено пользователем на categories=range(6)

Извините за путаницу.
В этом свете, я думаю, нам даже не нужна опция legacy_mode . Мы можем просто внутренне перевести n_values=6 в categories=range(6) и выдать для этого предупреждение (но необходимо проверить это с помощью реальных тестов).

Другое отличие - обработка невидимых категорий. При текущем поведении OneHotEncoder, если невидимые значения находятся в диапазоне (0, max), он не вызовет ошибку, даже если handle_unknow='error' (по умолчанию). Но также это можно решить отдельно, подняв предупреждение о том, что пользователь должен вручную установить handle_unknown='ignore' чтобы сохранить существующее поведение.

Единственная особенность, которую мы потеряем, - это различие между неизвестными категориями, которые находятся в диапазоне (0, max) (текущим OneHotEncoder не считается `` неизвестным ''), и теми, которые больше этого (> max, они в настоящее время уже считаются как неизвестно OneHotEncoder).

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

нет, это то, что мы пробовали раньше, и это слишком привередливо.

Вы можете уточнить, к какому аспекту относится это «нет»?
К тому, что думаю legacy_mode не нужен?

да, к идее, что вы можете просто сделать что-то в обратном направлении
совместимы и чего мы хотим в будущем

да, к идее, что вы можете просто сделать что-то, что одновременно обратно совместимо, и то, что мы хотим в будущем

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

Итак, чтобы быть конкретным: значение по умолчанию n_values может быть устаревшим и должно быть заменено спецификацией categories . handle_unknow в случае целочисленных данных должен быть явно установлен пользователем, чтобы выбрать либо полное игнорирование, либо полное устранение ошибок вместо текущего сочетания (в противном случае появляется предупреждение об устаревании).

поэтому, если я использую .fit ([[5]]). transform ([[4]]), для которого значения n_values,
категории и handle_umknown вызовут ли это ошибку?

25 января 2018 г., 9:32, «Йорис Ван ден Босше» [email protected]
написал:

да, к идее, что вы можете просто сделать что-то в обратном направлении
совместимы и чего мы хотим в будущем

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

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

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

можем ли мы просто сделать так, чтобы во время устаревания категории должны были быть установлены
явно, а в противном случае действует устаревший режим с предупреждениями? В том, что
что вы предлагаете?

можем ли мы просто сделать так, чтобы во время устаревания категории должны были быть установлены явно, а в противном случае действовал устаревший режим с предупреждениями? Вы это предлагаете?

Да, может все еще отсутствовать корпус, но я думаю, что это возможно (проверю, написав код на следующей неделе).

Различные «унаследованные» кейсы:

  • n_values ​​= 'auto' (по умолчанию)

    • handle_unknown = 'ignore' -> нормально, без изменений в поведении

    • handle_unknown = 'error' -> Проблема, значения в диапазоне по-прежнему игнорируются, значения выше диапазона ошибка



      • Возможное решение:





        • подходит, если диапазон последовательный => нормально, никаких изменений в поведении (для всех людей, которые теперь объединили с ним LabelEncoder, что, я думаю, является типичным вариантом использования)



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






  • n_values ​​= значение

    • это может быть преобразовано в категории = [диапазон (значение)] для внутреннего использования и вызывать предупреждение об устаревании, что пользователь должен сделать это сам в будущем.

    • в этом случае handle_unknown='error' / 'ignore' работает должным образом

Предупреждение об устаревании в случае n_values='auto' будет повышаться только в fit а не при построении (что не совсем идеально), но мы знаем только, что пользователь передает его. числовые данные, а не строковые данные.

мы обычно не поднимаем предупреждения до тех пор, пока не подойдем, так что не беспокойтесь о
что.

эта стратегия звучит в основном хорошо.

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

Один вопрос: если по умолчанию используются категории и параметры n_values, сделайте
мы публикуем категории_? Если n_values ​​задано явно, публикуем ли мы
категории_?

29 января 2018 г. в 10:00, «Йорис Ван ден Босше» [email protected]
написал:

можем ли мы просто сделать так, чтобы во время устаревания категории должны были быть установлены
явно, а в противном случае действует устаревший режим с предупреждениями? В том, что
что вы предлагаете?

Да, может все еще отсутствует корпус, но я думаю, что это возможно (будет
проверьте фактическое кодирование на следующей неделе).

Различные «унаследованные» кейсы:

  • n_values ​​= 'auto' (по умолчанию)

    • handle_unknown = 'ignore' -> нормально, без изменений в поведении

    • handle_unknown = 'error' -> Проблема, значения в диапазоне все еще остаются

      игнорируется, значения выше диапазона ошибка



      • Возможное решение:





        • подходит, если диапазон последовательный => нормально, без изменений



          поведение (для всех людей, которые теперь объединили с ним LabelEncoder,



          типичный вариант использования я думаю)



        • если это не так: выведите предупреждение об устаревании, которое



          они должны явно установить категории, чтобы сохранить это поведение (и



          внутренне использовать устаревший режим)





      • n_values ​​= значение



    • это может быть преобразовано в категории = [диапазон (значение)] внутри,

      и вывести предупреждение об устаревании, что пользователь должен сделать это сам в

      будущее

    • в этом случае handle_unknown = 'error' / 'ignore' работает должным образом

Предупреждение об устаревании в случае n_values ​​= 'auto' будет появляться только в
подходят, а не по конструкции (что не совсем идеально), но это только
в соответствии с тем, что мы знаем, что пользователь передает ему числовые данные, а не строку
данные.

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

Вы в основном хотите, чтобы это было: устаревший режим активен, если категории не установлены и если все данные целые?

Да, действительно (на практике будет примерно так же)

Один вопрос: если по умолчанию используются категории и параметры n_values, публиковать ли мы категории_? Если n_values ​​задано явно, публиковать ли мы категории_?

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


Поэтому я попытался поместить приведенную выше логику в код (добавлю некоторые обновления в PR), и у меня есть еще один вопрос для случая целочисленных данных, когда n_values или categories не установлены ( типичный случай для legacy_mode). Проблема заключается в том, что если предполагаемые категории представляют собой просто последовательный диапазон (0, 1, 2, 3, ... макс.), Нет никакой разницы между новым и старым (устаревшим) поведением, и мы этого не делаем. обязательно нужно поднять предупреждение об устаревании.
Некоторые возможности сделать в этом конкретном случае:

1) Обнаружьте этот случай (что предполагаемые категории являются последовательным диапазоном) и в этом случае не поднимайте предупреждение.
- Это можно обнаружить (с небольшой дополнительной сложностью кода), поскольку мы в любом случае уже готовы
- Я думаю, что это будет обычным случаем при использовании OneHotEncoder с целочисленными данными и случаем, когда пользователю действительно не нужно беспокоиться о нашем рефакторинге, поэтому было бы неплохо не беспокоить его / ее предупреждением
2) Всегда создавайте предупреждение и указывайте в предупреждающем сообщении, что делать, если вы находитесь в таком случае (в дополнение к объяснению, что делать, если у вас нет последовательного диапазона):
- Если они знают, что у них есть только последовательные диапазоны в качестве категорий, они хотят игнорировать предупреждение, поэтому мы можем добавить к предупреждающему сообщению объяснение, как это сделать (добавьте образец кода с предупреждениями о фильтрах, которые они могут скопировать и вставить)
- Потенциальным преимуществом этого является то, что мы также можем добавить к предупреждающему сообщению, что если они использовали LabelEncoder для создания целых чисел, теперь они могут напрямую использовать OneHotEncoder (я думаю, что в настоящее время это типичный шаблон использования). Таким образом, предупреждение также исчезнет
3) Всегда выдавать предупреждение, но указывать ключевое слово, чтобы отключить его (например, legacy_mode=False ).
- Если мы посчитаем совет использовать инструкцию filterwarnings (см. Пункт 2 выше) слишком громоздким, мы также можем добавить ключевое слово для получения того же результата.
- Недостатком этого является введение ключевого слова, которое больше не понадобится в нескольких выпусках, когда будут удалены устаревшие версии.

Я лично поддерживаю вариант 1 или 2. Использование LabelEncoder до OneHotEncoder кажется типичным шаблоном (из быстрого поиска на github), и в этом случае у вас всегда есть последовательные диапазоны, и никогда не будет изменений в поведении с новая реализация, поэтому не стоит за нее предупреждать. С другой стороны, если мы предупреждаем, мы можем указать им на тот факт, что, если они использовали LabelEncoder, им больше не нужно это делать. Было бы неплохо дать этот совет прямо.
Вопрос в том, как часто пользователи имеют такие последовательные целые числа в качестве категорий без использования LabelEncoder в качестве предыдущего шага.

Хм, я забыл об одном случае, когда у вас есть целочисленные категории, которые не являются последовательными (скажем, [1,3,5]), но вам нужно новое поведение, а не устаревшее (так что в этом случае вы не можете просто игнорировать предупреждение , так как это будет обрабатывать невидимые значения по-разному на этапе преобразования, то есть значения между диапазоном (например, 2) не вызовут ошибку).
Если мы не предоставляем ключевое слово legacy_mode=False , единственный способ получить новое поведение - вручную передать categories=[1,3,5] , что может быть небольшим неудобством. Это может быть причиной отдать предпочтение варианту 3 и отказаться от моего возражения против введения временного ключевого слова legacy_mode=False (но также не совсем уверен, что оно того стоит, поскольку это будет единственный случай *, когда такое ключевое слово действительно нужный)

* это единственный случай = целочисленные данные с предполагаемыми категориями, которые не являются последовательным диапазоном, и где вы не можете / не хотите устанавливать категории вручную или установить для handle_unknown значение игнорирования.

Простите за длинный текст, но он довольно сложный :)

Мы говорим только о случае, когда n_values ​​не установлено, верно?

Меня устраивает 1., и дороже бы не было, т.к. авто
уже нужно изучить набор этикеток. Я мог бы также согласиться, потому что
простота, вариант 3. это просто "OneHotEncoder, работающий в устаревшей
режим. Установите category = 'auto' для немного другого поведения без
предупреждение."

Мы говорим только о случае, когда n_values ​​не установлено, верно?

Да (другой случай легко переводится в эквивалентное ему значение categories , с красивым предупреждением об устаревании и без различий в новом и устаревшем поведении)

вариант 3., который был просто «OneHotEncoder, работающий в устаревшем режиме. Установите Categories = 'auto' для немного другого поведения без предупреждения».

Ах, это звучит как хорошая идея! (независимо от того, обнаруживается ли регистр последовательных категорий или нет). Таким образом, мы установили в коде значение по умолчанию categories на None (без изменения семантики его значения по умолчанию), поэтому мы знаем, установил ли пользователь его явно, и таким образом это хороший способ указать legacy_mode=False без дополнительного ключевого слова.

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

Что это за свежий ад: - /

ИЛИ мы могли бы назвать новый DummyEncoder ;) (хотя это немного противоречит DummyClassifier)

@amueller Не читайте все вышеперечисленное!
Я как раз собирался сделать красивое резюме для новых читателей номера. Вышеупомянутое обсуждение слишком сложно (также потому, что я все еще не полностью понимал текущее сложное поведение OneHotEncoder ... :-))

ИЛИ мы могли бы назвать новую DummyEncoder;)

Я думаю, что @GaelVaroquaux был против этого, потому что "one-hot", как известно, является этим в других областях (и мы уже используем Dummy для других вещей в scikit-learn ...)

Переделывать это для единообразия именования имхо не стоит. Мы нигде не единообразны в именовании. Не могли бы вы резюмировать дискуссии, которые к этому привели?

Я думаю, что «пустышка» - это то, что используют статистики, и это то, что используют панды.

Верхний пост по-прежнему точен и заслуживает прочтения, и в нем резюмируются причины отказа от использования КатегорическогоEncoder (что не означает, что нам нужно использовать OneHotEncoder вместо, например, DummyEncoder, это отдельный вопрос)

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

вопросы, которые открыты

Вы можете это объяснить?

"переделывать это для единообразия не стоит"

Последовательно, указываете ли вы на схему именования «что он принимает» и «что он делает»? Если так, то это была лишь незначительная причина. Для меня это в основном вопрос масштабируемости при добавлении дополнительных функций в один класс.

вопросы, которые открыты

У нас возникла проблема с обработкой отсутствующих значений (https://github.com/scikit-learn/scikit-learn/issues/10465), и для этого вам может потребоваться другое поведение для порядкового и однократного кодирования (или нет все варианты действительны для обоих, ..). У нас также уже есть существующий handle_unknown который актуален только для однократного кодирования, а не для порядкового номера. И был https://github.com/scikit-learn/scikit-learn/issues/10518 о взвешивании функций для кодирования onehot, но также не относился к порядковому номеру (эта проблема в конце концов не была проблемой, как вы можете сделать взвешивание с аргументом Transformer_weights ColumnTransformer). И у нас также есть запрос функции, чтобы добавить что-то вроде drop_first для one-hot, что снова не имеет отношения к порядковому кодированию.

Я не понимаю, как предлагаемые изменения так сильно помогут с пропущенными значениями. А несовместимые варианты - это то, что часто случается в scikit-learn. Не идеально, но имхо тоже не страшно.

Я не понимаю, как предлагаемые изменения так сильно помогут с пропущенными значениями.

Это не помогает как таковое , но делает менее сложным наличие определенных параметров, специально адаптированных к различным типам кодирования.

А несовместимые варианты - это то, что часто случается в scikit-learn. Не идеально, но имхо тоже не страшно.

В настоящее время, конечно, все в порядке, несовместимых опций не так много (но также отчасти потому, что я переместил sparse=True/False в опцию encoding ). Но вопрос в том, до какой степени мы хотим расширить функциональность кодирования в scikit-learn в будущем. Который, конечно , сложный вопрос сейчас ответить.
У нас уже есть PR для «унарного кодирования». Разве это не должно быть добавлено в КатегорическийEncoder вместо добавления нового класса UnaryEncoder? А что, если кто-то захочет добавить «двоичную кодировку»? Или «(средний) целевой кодировщик»?

"Средний целевой кодировщик" - CountTransformer , для этого есть PR;)

У вас есть для этого ссылка? Поиск "CountTransformer" не дал результатов

Извините, CountFeaturizer # 9614

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

Почему это не означает целевую кодировку? Но да, давайте не будем здесь слишком отвлекаться;)

Итак, краткое изложение актуальных вопросов, на которые нам нужно ответить (в указанном порядке!):

  1. Сохраняем ли мы текущие CategoricalEncoder ? Если нет, идея состоит в том, чтобы разделить его на разные классы, по одному классу для каждого типа кодирования (в настоящее время кодирование «onehot» и «порядковое»).

  2. Если мы разделимся на несколько классов, мы могли бы (в идеале?) Использовать OneHotEncoder для кодировки onehot, но этот класс уже существует. Итак, интегрируем ли мы новую кодировку onehot (которая поддерживает строки и имеет другие параметры) в существующий класс OneHotEncoder? Или мы выбираем другое имя? (например, DummyEncoder)

  3. Если мы решим интегрироваться в существующий OneHotEncoder, согласны ли мы со следующими последствиями: мы отказываемся от ряда ключевых слов / атрибутов OneHotEncoder, и конкретный вариант использования (автоматическое игнорирование невидимых значений в диапазоне видимых значений) будет невозможен больше после периода прекращения поддержки.

Большая часть обсуждения выше касалась вопроса 3 (сложные детали того, как интегрировать КатегориальныйEncoder (encoding = 'onehot') в OneHotEncoder). Но давайте сначала договоримся о решении первых двух вопросов.

другим фактором для меня является то, что все думают, что текущий автоматический режим в
OneHotEncoder странный. его реализация, конвертирующая coo в csr, также
странный. он заслуживает редизайна. и говоря людям «если вы хотите, чтобы один горячий
кодировать строки, вместо этого перейти к КатегорическомуEncoder "неудобно, потому что OHE
уже предназначен для категорий ...

хрм Думаю, мы сохранили OneHotEncoder, потому что он более эффективен, когда его можно использовать ... В идеале мы бы избавились от всего странного поведения. Я как бы хотел осудить его, но тогда мы не ...

Я как бы хотел осудить его, но тогда мы не ...

В моем POC PR (https://github.com/scikit-learn/scikit-learn/pull/10523) я отказался от почти всего OneHotEncoder, кроме его имени ...

Это не намного эффективнее. И если у LabelEncoder были быстрые пути для ints
в диапазоне [0, n_values-1], если это оправдано, этого было бы достаточно.

@amueller ,

Я попробую посмотреть на это на весенних каникулах через две недели, хорошо? не уверен, успею ли я до этого: - /

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

Рассмотрим фрейм данных df = pd.DataFrame([{'apple': 1, 'pear':'a', 'carrot': 1}, {'apple':'a', 'pear':2, 'carrot':3}, {'apple': 2, 'pear':3, 'carrot':1}, {'apple': 3, 'pear':'b', 'carrot': 1}, {'apple': 4, 'pear':4, 'carrot': 1}]) который равен:

  apple  carrot pear
0     1       1    a
1     a       3    2
2     2       1    3
3     3       1    b
4     4       1    4

DictVectorizer дает именно то, что мне нужно в этом случае.

    from sklearn.feature_extraction import DictVectorizer
    enc = DictVectorizer(sparse = False)
    enc.fit_transform(df.to_dict(orient='r'))

Это дает:

array([[ 1.,  0.,  1.,  0.,  1.,  0.],
       [ 0.,  1.,  3.,  2.,  0.,  0.],
       [ 2.,  0.,  1.,  3.,  0.,  0.],
       [ 3.,  0.,  1.,  0.,  0.,  1.],
       [ 4.,  0.,  1.,  4.,  0.,  0.]])

Мы можем увидеть имена функций столбцов с:

    enc.feature_names_
    ['apple', 'apple=a', 'carrot', 'pear', 'pear=a', 'pear=b']

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

Я не думаю, что мы собираемся разбираться в таком смешанном случае

Это позор. Один простой подслучай - это числовой столбец, в котором отсутствуют некоторые значения. Простое решение - преобразовать NaN в пустые строки, а затем использовать DictVectorizer, как в моем примере выше. Это эффективно создает новую функцию, когда значение отсутствует, но в противном случае числовые значения остаются неизменными. Я нашел эту технику очень полезной.

Сможет ли новый категориальный кодировщик делать что-то подобное?

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

Это звучит неплохо.

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

Допустим, у вас есть целочисленная функция, которая принимает большой диапазон значений. Однако вы подозреваете, что для некоторых небольших значений точное значение имеет значение. Вы подозреваете, что для больших значений это не так. Проще всего преобразовать все небольшие значения в строки, запустить DictVectorizer, как указано выше, а затем выполнить выбор функций или просто использовать свой любимый классификатор напрямую.

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

25 февраля 2018 года в 18:10 lesshaste [email protected] написал:

Это звучит неплохо.

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

Скажем, у вас есть целочисленная функция, которая принимает большой диапазон
ценности. Однако вы подозреваете, что для некоторых небольших значений точное значение
важно. Вы подозреваете, что для больших значений это не так. Просто
нужно преобразовать все маленькие значения в строки, запустить DictVectorizer
как указано выше, а затем выполните выбор функции или просто используйте свой любимый
классификатор напрямую.

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

@jnothman Да, в некотором смысле, кроме одной изюминки. Скажем, я подозреваю, что некоторые значения от 1 до 1024 имеют смысл. То есть 22 указывает на что-то конкретное, что сильно отличается от 21 или 23. Ведение журналов здесь не поможет. Но я хочу оставить все значения выше 1024 как числовые, поскольку я не думаю, что эти конкретные значения много значат.

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

25 февраля 2018 года в 20:37 lesshaste [email protected] написал:

@jnothman https://github.com/jnothman Да, в некотором смысле, кроме
крутить. Скажем, я подозреваю, что некоторые значения от 1 до 1024 имеют смысл.
То есть 22 указывает на что-то конкретное, что сильно отличается от 21 или

  1. Журналы здесь не помогут. Но я хочу оставить все ценности
    1024 настолько числовое, насколько я не думаю, что эти конкретные значения много значат.

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

@jnothman Чтобы быть немного яснее, я не знаю, что 22 имеет значение. Я просто подозреваю, что некоторые ценности есть, но я не знаю, какие и сколько их. Я обнаружил, что метод «преобразовать в строку», а затем метод DictVectorizer очень полезен для определения того, что это такое.

@lesshaste По вопросу о NaN как отдельной категории см. https://github.com/scikit-learn/scikit-learn/issues/10465
Если вы хотите дополнительно обсудить конкретную нелинейную дискретизацию или смешанное числовое / строковое кодирование, не стесняйтесь открывать новый выпуск. Но я хотел бы, чтобы этот вопрос был сосредоточен на исходной проблеме, то есть на именовании и организации в разных классах CategoryEncoder / OneHotEncoder.

Я попробую посмотреть на это на весенних каникулах через две недели, хорошо? не уверен, успею ли я до этого: - /

@amueller , все в порядке. В ближайшие две недели у меня не будет времени заниматься пиаром, который все равно заблокирован. После этого у меня тоже должно быть время поработать над этим.

@amueller у тебя было время взглянуть на это?

@amueller , вы

Извините за отсутствие. Вроде нормально, но не могли бы вы дать мне две недели, чтобы я действительно мог сделать обзор? Спасибо!

@amueller без проблем, для меня то же самое :-)
Но теперь я планирую еще раз взглянуть на это. Так что, если бы вы могли взглянуть на это, это будет приветствоваться. Мне нужно поработать над PR (https://github.com/scikit-learn/scikit-learn/pull/10523), поэтому пока не просматривайте это подробно (вы можете взглянуть на него, чтобы получить представление того, что мы предлагаем, однако).
Я думаю, что главный вопрос, на который я хочу получить ответ, прежде чем я потрачу на него много времени, заключается в том, согласны ли вы с разделением CategoryEncoder на несколько классов, и в этом случае, если вы в порядке с повторным использованием OneHotEncoder (что означает отказавшись от некоторых из его текущих (странных) функций). Эти вопросы кратко изложены в https://github.com/scikit-learn/scikit-learn/issues/10521#issuecomment -363851328 и https://github.com/scikit-learn/scikit-learn/issues/10521#issuecomment. -364802471.

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

Я обновил PR https://github.com/scikit-learn/scikit-learn/pull/10523 , готов к рассмотрению

Я осторожно скажу, что вернулся;)

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

PS https://github.com/scikit-learn-contrib/categorical-encoding ?

В пакете category_encoders все кодировщики имеют аргумент cols , аналогичный categorical_features в старом OneHotEncoder (хотя он не принимает точно такие же значения). См., Например, http://contrib.scikit-learn.org/categorical-encoding/onehot.html
Это связано с текущим обсуждением, которое мы ведем в https://github.com/scikit-learn/scikit-learn/pull/10523 об отказе от поддержки categorical_features или нет.

В остальном я думаю, что на самом деле нет конфликтующих ключевых слов (у них есть некоторые другие, специфичные для фреймов данных, которые мы не будем добавлять в sklearn на данном этапе). Именование для OneHotEncoder и OrdinalEncoder по крайней мере соответствует пакету category_encoders .

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