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

Прямое унитарное кодирование с OneHotArrays.jl

Категориальные переменные (такие как true, false или cat, dog) часто кодируются в форме «один из k» или прямой унитарной форме. OneHotArrays.jl предоставляет функцию onehot, упрощающую эту задачу.

julia> using OneHotArrays

julia> onehot(:b, [:a, :b, :c])
3-element OneHotVector(::UInt32) with eltype Bool:
 ⋅
 1
 ⋅

julia> onehot(:c, [:a, :b, :c])
3-element OneHotVector(::UInt32) with eltype Bool:
 ⋅
 ⋅
 1

Существует также функция onecold, которая является обратной для функции onehot. Вместо логических значений ей можно также передать массив чисел. В этом случае она выполняет операцию наподобие argmax, возвращая метку, наиболее соответствующую по весу.

julia> onecold(ans, [:a, :b, :c])
:c

julia> onecold([true, false, false], [:a, :b, :c])
:a

julia> onecold([0.3, 0.2, 0.5], [:a, :b, :c])
:c

В случае со сразу несколькими выборками onehotbatch создает пакет (матрицу) прямых унитарных векторов, а onecold обрабатывает матрицы как пакеты.

julia> using OneHotArrays

julia> onehotbatch([:b, :a, :b], [:a, :b, :c])
3×3 OneHotMatrix(::Vector{UInt32}) with eltype Bool:
 ⋅  1  ⋅
 1  ⋅  1
 ⋅  ⋅  ⋅

julia> onecold(ans, [:a, :b, :c])
3-element Vector{Symbol}:
 :b
 :a
 :b

Обратите внимание, что эти операции возвращают OneHotVector и OneHotMatrix, а не Array. Векторы OneHotVector похожи на обычные векторы, но позволяют избежать лишних затрат, которые возникают при использовании целочисленных индексов напрямую. Например, при умножении матрицы на прямой унитарный вектор на внутреннем уровне просто создается срез соответствующей строки матрицы.

Список функций

onehot(x, labels, [default])

Возвращает вектор OneHotVector, который примерно соответствует разреженному представлению x .== labels.

Вместо сохранения, например, Vector{Bool}, в нем сохраняется индекс первого вхождения x в labels. Если x отсутствует в метках, то либо возвращается onehot(default, labels), либо выдается ошибка, если значение по умолчанию не задано.

См. также описание функции onehotbatch, которая применяется сразу ко многим x, и функции onecold, которая является обратной для обеих этих функций, а также общей функцией для argmax.

Примеры

julia> β = onehot(:b, (:a, :b, :c))
3-element OneHotVector(::UInt32) with eltype Bool:
 ⋅
 1
 ⋅

julia> αβγ = (onehot(0, 0:2), β, onehot(:z, [:a, :b, :c], :c))  # использует значение по умолчанию
(Bool[1, 0, 0], Bool[0, 1, 0], Bool[0, 0, 1])

julia> hcat(αβγ...)  # сохраняет разреженность
3×3 OneHotMatrix(::Vector{UInt32}) with eltype Bool:
 1  ⋅  ⋅
 ⋅  1  ⋅
 ⋅  ⋅  1
onecold(y::AbstractArray, labels = 1:size(y,1))

Операция, которая является примерно обратной для onehot или onehotbatch: Находит индекс самого большого элемента в y или каждого столбца в y и ищет его в labels.

Если метки labels не заданы, по умолчанию ими являются целые числа 1:size(y,1) — это та же операция, что и argmax(y, dims=1), но иногда тип возвращаемого значения иной.

Примеры

julia> onecold([false, true, false])
2

julia> onecold([0.3, 0.2, 0.5], (:a, :b, :c))
:c

julia> onecold([ 1  0  0  1  0  1  0  1  0  0  1
                 0  1  0  0  0  0  0  0  1  0  0
                 0  0  0  0  1  0  0  0  0  0  0
                 0  0  0  0  0  0  1  0  0  0  0
                 0  0  1  0  0  0  0  0  0  1  0 ], 'a':'e') |> String
"abeacadabea"
onehotbatch(xs, labels, [default])

Возвращает матрицу OneHotMatrix, в которой k-й столбец — onehot(xs[k], labels). Это разреженная матрица, в которой хранится лишь вектор Vector{UInt32} с индексами ненулевых элементов.

Если один из входных элементов в xs не найден в labels, то столбец имеет вид onehot(default, labels) при заданном значении default; в противном случае выдается ошибка.

Если в xs больше измерений (N = ndims(xs) > 1), то результатом будет массив AbstractArray{Bool, N+1}, который является прямым унитарным по первому измерению, то есть result[:, k...] == onehot(xs[k...], labels).

Обратите внимание, что xs может быть любым итерируемым объектом, например строкой, и что использование кортежа для labels зачастую ускоряет создание, по крайней мере если классов менее 32.

Примеры

julia> oh = onehotbatch("abracadabra", 'a':'e', 'e')
5×11 OneHotMatrix(::Vector{UInt32}) with eltype Bool:
 1  ⋅  ⋅  1  ⋅  1  ⋅  1  ⋅  ⋅  1
 ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅
 ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅
 ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅

julia> reshape(1:15, 3, 5) * oh  # данное умножение матриц будет выполняться эффективно
3×11 Matrix{Int64}:
 1  4  13  1  7  1  10  1  4  13  1
 2  5  14  2  8  2  11  2  5  14  2
 3  6  15  3  9  3  12  3  6  15  3
OneHotArray{T, N, M, I} <: AbstractArray{Bool, M}
OneHotArray(indices, L)

Прямой унитарный M-мерный массив с L метками (то есть size(A, 1) == L и sum(A, dims=1) == 1), хранящийся как компактный N == M-1-мерный массив индексов.

Обычно создается с помощью onehot и onehotbatch. Параметр I — это тип базового объекта для хранения, а T — тип его элементов.

OneHotVector{T} = OneHotArray{T, 0, 1, T}
OneHotVector(indices, L)

Прямой унитарный вектор с L метками (то есть length(A) == L и count(A) == 1), обычно создаваемый с помощью onehot. Хранится эффективно как один индекс типа T, обычно UInt32.

OneHotMatrix{T, I} = OneHotArray{T, 1, 2, I}
OneHotMatrix(indices, L)

Прямая унитарная матрица (с L метками), обычно создаваемая с помощью onehotbatch. Хранится эффективно как вектор индексов типа I и типом элементов T.