Обращение к категориальным функциям с помощью одного горячего кодирования и векторного ассемблера против векторного индексатора - PullRequest
0 голосов
/ 16 января 2019

Скажем, у меня есть категорические особенности в кадре данных. Чтобы выполнить ML на кадре данных, я делаю одно горячее кодирование для категориальных столбцов, используя OneHotEncoderEstimator(), а затем использую VectorAssembler(), чтобы собрать все функции в один столбец. При чтении Spark docs я видел использование VectorIndexer() для индексации категориальных объектов в векторном столбце объектов. Если я уже выполнил одно горячее кодирование для категориальных столбцов до формулировки векторного столбца объектов, есть ли смысл применять VectorIndexer() к нему.

1 Ответ

0 голосов
/ 19 января 2019

OneHotEncoder(Estimator) и VectorIndexer - совершенно разные звери и не подлежат обмену. OneHotEncoder(Estimator) используется главным образом, когда в последующем процессе используется линейная модель ( также может использоваться с наивным байесовским алгоритмом ).

Давайте рассмотрим простое Dataset

val df = Seq(1.0, 2.0, 3.0).toDF

и Pipeline

import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.feature._

val m1 = new Pipeline().setStages(Array(
  new OneHotEncoderEstimator()
   .setInputCols(Array("value")).setOutputCols(Array("features"))
)).fit(df)

Если такая модель применяется к нашим данным, она будет с горячим кодированием (в зависимости от конфигурации OneHotEncoderEstimator поддерживает как горячее, так и фиктивное кодирование) - другими словами, каждый уровень , исключая ссылку, будет представлен отдельным двоичным столбцом:

m1.transform(df).schema("features").metadata
 org.apache.spark.sql.types.Metadata = {"ml_attr":{"attrs":{"binary":[{"idx":0,"name":"0"},{"idx":1,"name":"1"},{"idx":2,"name":"2"}]},"num_attrs":3}}

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

Напротив, VectorIndexer только анализирует данные и соответственно корректирует метаданные

val m2 = new Pipeline().setStages(Array(
  new VectorAssembler().setInputCols(Array("value")).setOutputCol("raw"),
  new VectorIndexer().setInputCol("raw").setOutputCol("features")
)).fit(df)

m2.transform(df).schema("features").metadata
org.apache.spark.sql.types.Metadata = {"ml_attr":{"attrs":{"nominal":[{"ord":false,"vals":["1.0","2.0","3.0"],"idx":0,"name":"value"}]},"num_attrs":1}}

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

Такие функции не подходят для линейных моделей , но являются допустимыми входными данными для деревьев решений и ансамблей деревьев.

Подводя итог - на практике OneHotEncoder(Esitmator) и VectorIndexer являются взаимоисключающими, и выбор, какой из них следует использовать, зависит от последующего процесса.

...