Документация Engee

DataFrames

В качестве обучающего набора можно использовать dataframe, но сначала его нужно преобразовать в массив. Для указания способа преобразования используется DataFrameMapper. Например, PCA можно применить к некоторым числовым столбцам dataframe, а кодирование с одним активным состоянием — к категориальным столбцам.

Сопоставление преобразования

Рассмотрим следующий набор данных.

julia> using ScikitLearn

julia> using DataFrames: DataFrame, missing

julia> @sk_import preprocessing: (LabelBinarizer, StandardScaler)
PyObject <class 'sklearn.preprocessing._data.StandardScaler'>

julia> data = DataFrame(pet=["cat", "dog", "dog", "fish", "cat", "dog", "cat", "fish"],
                 children=[4., 6, 3, 3, 2, 3, 5, 4],
                 salary=[90, 24, 44, 27, 32, 59, 36, 27])
8×3 DataFrame
│ Row │ pet    │ children │ salary │
│     │ String │ Float64  │ Int64  │
├─────┼────────┼──────────┼────────┤
│ 1   │ cat    │ 4.0      │ 90     │
│ 2   │ dog    │ 6.0      │ 24     │
│ 3   │ dog    │ 3.0      │ 44     │
│ 4   │ fish   │ 3.0      │ 27     │
│ 5   │ cat    │ 2.0      │ 32     │
│ 6   │ dog    │ 3.0      │ 59     │
│ 7   │ cat    │ 5.0      │ 36     │
│ 8   │ fish   │ 4.0      │ 27     │

Сопоставление столбцов с преобразованиями

Модуль сопоставления содержит список пар. Первый элемент — это имя столбца из DataFrame или список, содержащий один или несколько столбцов (пример с несколькими столбцами мы рассмотрим позже). Второй — это объект, выполняющий преобразование, которое будет применено к этому столбцу:

Примечание. ScikitLearn.DataFrameMapper будет доступен только после импорта DataFrames.

julia> mapper = DataFrameMapper([(:pet, LabelBinarizer()),
                          ([:children], StandardScaler())]);

Разница между указанием селектора столбцов как :column (в виде одного символа) и [:column] (в виде списка с одним элементом) заключается в форме массива, который передается преобразователю. В первом случае будет передан одномерный массив, а во втором — двумерный массив с одним столбцом, т. е. вектор-столбец.

Тестирование преобразования

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

julia> round.(fit_transform!(mapper, copy(data)), digits=2)
8×4 Array{Float64,2}:
 1.0  0.0  0.0   0.21
 0.0  1.0  0.0   1.88
 0.0  1.0  0.0  -0.63
 0.0  0.0  1.0  -0.63
 1.0  0.0  0.0  -1.46
 0.0  1.0  0.0  -0.63
 1.0  0.0  0.0   1.04
 0.0  0.0  1.0   0.21

Обратите внимание, что первые три столбца — это результаты выполнения LabelBinarizer (соответствующие cat, dog и fish соответственно), а четвертый столбец — это стандартизированное значение количества детей. В общем случае столбцы упорядочиваются согласно порядку, заданному при создании DataFrameMapper.

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

julia> sample = DataFrame(pet = ["cat"], children = [5.])
1×2 DataFrame
│ Row │ pet    │ children │
│     │ String │ Float64  │
├─────┼────────┼──────────┤
│ 1   │ cat    │ 5.0      │

julia> round.(transform(mapper, sample), digits=2)
1×4 Array{Float64,2}:
 1.0  0.0  0.0  1.04

Преобразование нескольких столбцов

Для преобразований может потребоваться несколько столбцов. В этих случаях имена столбцов можно указать в виде списка:

julia> @sk_import decomposition: PCA
PyObject <class 'sklearn.decomposition._pca.PCA'>

julia> mapper2 = DataFrameMapper([([:children, :salary], PCA(1))]);

Теперь выполнение fit_transform! запустит PCA для столбцов children и salary и возвратит первый главный компонент:

julia> round.(fit_transform!(mapper2, copy(data)), digits=1)
8×1 Array{Float64,2}:
  47.6
 -18.4
   1.6
 -15.4
 -10.4
  16.6
  -6.4
 -15.4

Несколько преобразователей для того же столбца

К одному и тому же столбцу можно применить несколько преобразователей, указав их в списке:

julia> @sk_import impute: SimpleImputer
PyObject <class 'sklearn.impute._base.SimpleImputer'>

julia> mapper3 = DataFrameMapper([([:age], [SimpleImputer(),
                                     StandardScaler()])]; missing2NaN=true);

julia> data_3 = DataFrame(age= [1, missing, 3]);

julia> fit_transform!(mapper3, data_3)
3×1 Array{Float64,2}:
 -1.224744871391589
  0.0
  1.224744871391589

Столбцы, которым не требуется преобразование

Сохраняются только столбцы, перечисленные в DataFrameMapper. Чтобы сохранить столбец, но не применять к нему никаких преобразований, используйте nothing в качестве преобразователя:

julia> mapper3 = DataFrameMapper([(:pet, LabelBinarizer()), (:children, nothing)]);

julia> round.(fit_transform!(mapper3, copy(data)))
8×4 Array{Float64,2}:
 1.0  0.0  0.0  4.0
 0.0  1.0  0.0  6.0
 0.0  1.0  0.0  3.0
 0.0  0.0  1.0  3.0
 1.0  0.0  0.0  2.0
 0.0  1.0  0.0  3.0
 1.0  0.0  0.0  5.0
 0.0  0.0  1.0  4.0

Перекрестная проверка

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

julia> @sk_import linear_model: LinearRegression
PyObject <class 'sklearn.linear_model._base.LinearRegression'>

julia> using ScikitLearn.CrossValidation: cross_val_score

julia> pipe = Pipelines.Pipeline([(:featurize, mapper), (:lm, LinearRegression())]);

julia> round.(cross_val_score(pipe, data, data[!,:salary]), digits=2)
3-element Array{Float64,1}:
  -1.09
  -5.3
 -15.38