Трюк с хешированием
Обновлено: 21.11.2024
Разработка функций играет важную роль при решении задач науки о данных. Здесь мы изучим хэширование функций или трюк с хешированием, который представляет собой метод преобразования произвольных функций в разреженный двоичный вектор.
Уилл МакГиннис.
В предыдущем посте о категориальном кодировании мы рассмотрели различные методы преобразования категориальных переменных в числовые признаки. В этом посте мы рассмотрим еще один метод: хеширование признаков.
Хеширование объектов или трюк с хешированием – это метод преобразования произвольных объектов в разреженный двоичный вектор. Это может быть чрезвычайно эффективно, если иметь автономную хэш-функцию, для работы которой не требуется предварительно созданный словарь возможных категорий.
Простая реализация, которая позволяет пользователю выбрать желаемую размерность вывода, состоит в том, чтобы просто хэшировать входное значение в число, затем разделить его на желаемую размерность вывода и взять остаток, R. Таким образом, вы можете закодировать функцию как вектор нулей с единицей в индексе R.
В псевдокоде из статьи в Википедии:
функция hashing_vectorizer(features : массив строк, N : integer):
x := новый вектор[N]
для f в характеристиках:
h := hash(f) < br />x[h mod N] += 1
возврат x
def hash_fn(x):
tmp = [0for_inrange(N)]
для val в x.values:
tmp[hash(val)% N] += 1
вернуть pd.Series(tmp, index=cols)
cols = ['col_%d'% d для d в диапазоне (N)]
X = X.apply(hash_fn, axis=1)
Насколько это работает? Что ж, в прошлый раз мы запустили все кодировщики, используя одну и ту же модель, и сравнили результаты. Некоторые кодировки каждый раз немного отличаются (в зависимости от того, как проходит начальное порядковое преобразование), поэтому мы запускаем модели 100 раз и создаем блок-диаграмму их оценок. Использование набора грибных данных:
В этом сюжете можно увидеть пару интересных вещей. Во-первых, бинарное кодирование, которое было представлено в предыдущем посте, хотя в среднем работает хорошо, имеет довольно высокую дисперсию от запуска к запуску, что не идеально. Кроме того, вы можете наблюдать постепенное повышение производительности по мере увеличения количества компонентов, используемых для кодировщика хеширования, но оно достигает предела при 16, потому что категорий просто недостаточно, чтобы использовать более 16 компонентов для этого набора данных.
В следующем посте я представлю преобразователи, совместимые с scikit-learn, для каждого из них, несколько примеров их использования и некоторые эмпирические правила для построения хороших моделей на высокоразмерных категориальных данных без перегрузки вашей памяти.< /p>
Проверьте обновленный репозиторий, чтобы попробовать свои собственные кодировщики, использовать мои или попробовать это на своих данных:
У меня есть большой набор категориальных данных и ИНС с прямой связью, которые я использую для целей классификации. Я запрограммировал модель машинного обучения с помощью Excel VBA (единственный язык программирования, к которому у меня есть доступ в настоящее время).
В моем наборе данных есть 150 категорий, которые мне нужно обработать. Я пытался использовать Binary Encoding и One-Hot Encoding, однако из-за количества категорий, которые мне нужно обработать, эти векторы часто слишком велики для обработки VBA, и в итоге я получаю ошибку памяти.
Я хотел бы попробовать трюк с хешированием и посмотреть, работает ли он лучше. Однако я не понимаю, как это сделать в Excel.
Я просмотрел следующие ссылки, чтобы попытаться понять это:
Я до сих пор не совсем понимаю. Вот что я сделал до сих пор. Я использовал следующий пример кода для создания хеш-последовательности для моей категориальной даты: Генерировать короткую хеш-строку на основе VBA
Используя приведенный выше код, я смог создать числовые хеш-последовательности без коллизий. Однако что мне теперь делать? Нужно ли теперь преобразовывать хэш-последовательность в двоичный вектор? Вот где я теряюсь.
Я привел небольшой пример своих данных. Может ли кто-нибудь показать мне шаг за шагом, как работает трюк с хешированием (желательно для Excel)?
1 Ответ 1
Трюк с хешированием предотвращает ~фальшивые слова, занимающие дополнительную память. В обычной модели Bag-Of-Words (BOW) у вас есть 1 измерение на слово в словаре. Это означает, что слово с ошибкой и обычное слово могут занимать отдельные измерения — если слово с ошибкой вообще присутствует в модели. Если слово с ошибкой отсутствует в модели (в зависимости от вашей модели), вы можете полностью ее проигнорировать. Это суммируется со временем. И говоря о слове с ошибкой, я просто использую пример любого слова, которого нет в словаре, который вы используете для создания векторов для обучения вашей модели. Это означает, что любая модель, обученная таким образом, не может адаптироваться к новой лексике без повторного обучения.
Метод хэширования позволяет включать слова, не входящие в словарь, с некоторой потенциальной потерей точности.Это также гарантирует, что вы можете связать свою память. По сути, метод хеширования начинается с определения хеш-функции, которая принимает некоторый ввод (обычно слово) и сопоставляет его с выходным значением в пределах уже определенного диапазона. Вы бы выбрали свою хэш-функцию для вывода где-то между, скажем, 0-2 ^ 16. Таким образом, вы знаете, что ваши выходные векторы всегда будут ограничены размером 2 ^ 16 (на самом деле произвольное значение), поэтому вы можете предотвратить проблемы с памятью. Кроме того, хеш-функции имеют «коллизии» — это означает, что хэш (а) может быть равен хэш (b) — очень редко с соответствующим диапазоном вывода, но это возможно. Это означает, что вы теряете некоторую точность, но, поскольку хэш-функция теоретически может принимать любую входную строку, она может работать со словами из словаря, чтобы получить новый вектор того же размера, что и исходные векторы, используемые для обучения модели. Поскольку ваш новый вектор данных имеет тот же размер, что и те, которые использовались для обучения модели ранее, вы можете использовать его для уточнения своей модели, а не для обучения новой модели.
Практические пошаговые руководства по машинному обучению, исследованию данных и поиску идей.
Ресурсы
Пакеты, используемые в этом пошаговом руководстве
Хеширование признаков — это умный способ моделирования наборов данных, содержащих большое количество факторных и символьных данных. Он использует меньше памяти и требует небольшой предварительной обработки. В этом пошаговом руководстве мы моделируем большой набор медицинских данных, сначала используя фиктивные переменные, а затем хэшируя функции.
Что важно? Ну, обычно так:
- Обработка всех факторов, текста и неупорядоченных категорийных данных. При этом создается новый столбец для каждого уникального значения и помечается двоичное значение независимо от того, содержит ли наблюдение это конкретное значение. Для больших наборов данных это может значительно увеличить пространство измерений (добавление большего количества столбцов).
- Отбрасывание уровней. Например, можно взять верхние x% самых популярных уровней и нейтрализовать остальные, сгруппировать уровни по темам, используя расстояние между строками, или просто игнорировать факторы, слишком большие для памяти компьютера.
- Используйте разреженную матрицу. Это может уменьшить размер этих фиктивных наборов данных за счет удаления нулей.
Но более полное решение, особенно при наличии десятков тысяч уникальных значений, — это «трюк с хешированием».
Вуш Ву создал пакет FeatureHashing, доступный в CRAN. Согласно представлению пакета на CRAN:
"Хеширование объектов, также называемое хэш-трюком, представляет собой метод преобразования объектов в вектор. Без поиска индексов в ассоциативном массиве он применяет хеш-функцию к объектам и использует их хэш-значения в качестве индексов. напрямую. Метод хеширования функций в этом пакете был предложен Вайнбергером и др. (2009). Алгоритм хеширования — это murmurhash3 из пакета дайджеста. Дополнительную информацию см. в README.md».р>
Хеширование признаков имеет множество преимуществ при моделировании и машинном обучении. Он работает с адресами, а не с фактическими данными, что позволяет ему обрабатывать данные только тогда, когда это необходимо. Итак, первая найденная функция — это действительно столбец данных, содержащий только один уровень (одно значение), когда он встречает другое значение, то становится функцией с 2 уровнями и так далее. Он также не требует предварительной обработки факторных данных; вы просто кормите его своим фактором в сыром виде. Этот подход требует гораздо меньше памяти, чем полностью отсканированный и обработанный набор данных. Много теории для тех, кто хочет более глубокого понимания.
Некоторые из его недостатков включают замедление работы моделей и определенное запутывание данных.
Давайте программировать!
Мы будем использовать большой набор медицинских данных о повторных госпитализациях пациентов с диабетом – набор данных Diabetes 130 – больницы США за 1999–2008 годы. Повторная госпитализация имеет большое значение для больниц в США, поскольку программы Medicare/Medicaid тщательно изучают эти счета и в некоторых случаях возмещают только процент от них. Мы будем использовать код для автоматизации загрузки и распаковки данных непосредственно из репозитория машинного обучения Калифорнийского университета в Ирвине.
Давайте быстро взглянем на данные, а затем очистим их.
101766 обс. из 50 переменных
Интересны 3 поля: diag_1 , diag_2 , diag_3 . Эти 3 функции являются числовым представлением диагнозов пациентов. У каждого пациента может быть записано до 3 диагнозов. Если мы суммируем все уникальные уровни для всех 3 наборов, мы получим много уровней. Помните, что даже несмотря на то, что это числовые представления диагнозов, они все же являются диагнозами и не могут быть смоделированы как числовые данные, поскольку расстояние между двумя диагнозами ничего не значит. Все это нужно поместить в отдельный столбец.
Сумма всех уникальных диагнозов составляет 2256.Это означает, что для того, чтобы разбить каждый диагноз на отдельный столбец, нам нужны дополнительные 2256 новых столбцов поверх исходных 50.
Хорошо, давайте закончим очистку данных. Мы собираемся отказаться от функций, не связанных с прогнозированием, заменить вопросительные знаки на NA и установить для переменной результата двоичное значение.
Теперь давайте подготовим данные двумя способами: обычный подход с использованием фиктивных переменных для наших факторов и другой подход с использованием хэширования признаков.
Использование фиктивных переменных
Здесь мы используем функцию dummyVars каретки, чтобы создать наш фиктивный столбец (подробнее об этой замечательной функции см. в моем пошаговом руководстве). Имейте в виду, что для этого вам потребуется как минимум 2 гигабайта свободной оперативной памяти в вашей системе!
После всей этой подготовительной работы мы получаем довольно широкое пространство данных с 2462 функциями/столбцами:
Мы будем использовать cv.glmnet для моделирования наших данных, так как он поддерживает разреженные матрицы (это также отлично работает с XGBoost).
Давайте посмотрим на AUC (площадь под кривой), чтобы сравнить этот подход с подходом, основанным на хешировании признаков:
Использование хеширования признаков
Функция hashed.model.matrix принимает значение hash.size. Это критическая часть. В зависимости от размера ваших данных вам может потребоваться настроить это значение. Я установил здесь значение 2^12, но если вы попробуете большее значение, оно будет обрабатывать больше переменных (т. е. уникальных значений). С другой стороны, если вы попробуете меньшее значение, вы рискуете столкнуться с конфликтами памяти и потерей данных. Это то, с чем вам нужно поэкспериментировать.
Давайте посмотрим, как оценивается эта версия:
Практически такой же результат, как при самостоятельной подготовке данных, но с вдвое меньшим объемом работы и гораздо меньшим объемом памяти.
Мануэль Амунатеги – Подпишитесь на меня в Твиттере: @amunategui
У меня есть большой набор категориальных данных и ИНС с прямой связью, которые я использую для целей классификации. Я запрограммировал модель машинного обучения с помощью Excel VBA (единственный язык программирования, к которому у меня есть доступ в настоящее время).
В моем наборе данных есть 150 категорий, которые мне нужно обработать. Я пытался использовать Binary Encoding и One-Hot Encoding, однако из-за количества категорий, которые мне нужно обработать, эти векторы часто слишком велики для обработки VBA, и в итоге я получаю ошибку памяти.
Я хотел бы попробовать трюк с хешированием и посмотреть, работает ли он лучше. Однако я не понимаю, как это сделать в Excel.
Я просмотрел следующие ссылки, чтобы попытаться понять это:
Я до сих пор не совсем понимаю. Вот что я сделал до сих пор. Я использовал следующий пример кода для создания хеш-последовательности для моей категориальной даты: Генерировать короткую хеш-строку на основе VBA
Используя приведенный выше код, я смог создать числовые хеш-последовательности без коллизий. Однако что мне теперь делать? Нужно ли теперь преобразовывать хэш-последовательность в двоичный вектор? Вот где я теряюсь.
Я привел небольшой пример своих данных. Может ли кто-нибудь показать мне шаг за шагом, как работает трюк с хешированием (желательно для Excel)?
1 Ответ 1
Трюк с хешированием предотвращает ~фальшивые слова, занимающие дополнительную память. В обычной модели Bag-Of-Words (BOW) у вас есть 1 измерение на слово в словаре. Это означает, что слово с ошибкой и обычное слово могут занимать отдельные измерения — если слово с ошибкой вообще присутствует в модели. Если слово с ошибкой отсутствует в модели (в зависимости от вашей модели), вы можете полностью ее проигнорировать. Это суммируется со временем. И говоря о слове с ошибкой, я просто использую пример любого слова, которого нет в словаре, который вы используете для создания векторов для обучения вашей модели. Это означает, что любая модель, обученная таким образом, не может адаптироваться к новой лексике без повторного обучения.
Метод хэширования позволяет включать слова, не входящие в словарь, с некоторой потенциальной потерей точности. Это также гарантирует, что вы можете связать свою память. По сути, метод хеширования начинается с определения хеш-функции, которая принимает некоторый ввод (обычно слово) и сопоставляет его с выходным значением в пределах уже определенного диапазона. Вы бы выбрали свою хэш-функцию для вывода где-то между, скажем, 0-2 ^ 16. Таким образом, вы знаете, что ваши выходные векторы всегда будут ограничены размером 2 ^ 16 (на самом деле произвольное значение), поэтому вы можете предотвратить проблемы с памятью. Кроме того, хеш-функции имеют «коллизии» — это означает, что хэш (а) может быть равен хэш (b) — очень редко с соответствующим диапазоном вывода, но это возможно. Это означает, что вы теряете некоторую точность, но, поскольку хэш-функция теоретически может принимать любую входную строку, она может работать со словами из словаря, чтобы получить новый вектор того же размера, что и исходные векторы, используемые для обучения модели. Поскольку ваш новый вектор данных имеет тот же размер, что и те, которые использовались для обучения модели ранее, вы можете использовать его для уточнения своей модели, а не для обучения новой модели.
Читайте также: