Встроенные типы слоев
Если вы начали изучать это руководство с самого начала, то вам уже встречался базовый слой Dense и вы уже видели, как объединять слои с помощью Chain. Эти базовые слои служат основой почти для всех нейронных сетей.
На примере слоя Dense хорошо виден ряд особенностей.
-
Он содержит функцию активации, которая транслируется через выход. Поскольку данная трансляция может совмещаться с другими операциями, такой подход более эффективен по сравнению с отдельным применением функции активации.
-
Он имеет именованный аргумент
init, который принимает функцию, действующую какrand. То есть вызовinit(2,3,4)должен создавать массив соответствующего размера. Во Flux есть множество таких встроенных функций. Все они создают массив в памяти ЦП, который затем при желании можно перенести с помощью функцииgpu. -
Вектор смещений всегда инициализируется с помощью
Flux.zeros32. Именованный аргументbias=falseотключает это поведение, то есть смещения всегда будут оставаться равными нулю. -
Он аннотируется с помощью
@functor, то есть функцииparamsбудет доступно содержимое, а функцияgpuбудет перемещать массивы в память GPU.
В свою очередь, объект Chain сам по себе не содержит параметров, но связывает другие слои. В разделе о слоях потока данных представлены другие слои наподобие этого.
Полносвязные слои
#
Flux.Dense — Type
Dense(in => out, σ=identity; bias=true, init=glorot_uniform)
Dense(W::AbstractMatrix, [bias, σ])
Создает традиционный полносвязный слой, прямой проход которого задается следующим образом:
y = σ.(W * x .+ bias)
Входной параметр x должен представлять собой вектор длиной in или пакет векторов, представленный в виде матрицы in × N либо массива с size(x,1) == in. Результат y будет вектором длиной out или пакетом с size(y) == (out, size(x)[2:end]...)
Именованный аргумент bias=false отключает обучаемое смещение для слоя. Весовая матрица инициализируется следующим образом: W = init(out, in). При этом вызывается функция, переданная в именованном аргументе init. По умолчанию это функция glorot_uniform. Весовую матрицу и (или) вектор смещений (длиной out) также можно предоставить явным образом.
Примеры
julia> d = Dense(5 => 2)
Dense(5 => 2) # 12 параметров
julia> d(rand32(5, 64)) |> size
(2, 64)
julia> d(rand32(5, 6, 4, 64)) |> size # обрабатывается как три пакетных измерения
(2, 6, 4, 64)
julia> d1 = Dense(ones(2, 5), false, tanh) # используется предоставленная весовая матрица
Dense(5 => 2, tanh; bias=false) # 10 параметров
julia> d1(ones(5))
2-element Vector{Float64}:
0.9999092042625951
0.9999092042625951
julia> Flux.params(d1) # обучаемое смещение отсутствует
Params([[1.0 1.0 … 1.0 1.0; 1.0 1.0 … 1.0 1.0]])
#
Flux.Bilinear — Type
Bilinear((in1, in2) => out, σ=identity; bias=true, init=glorot_uniform)
Bilinear(W::AbstractArray, [bias, σ])
Создает слой с полной связью между двумя входами и выходом, который в остальном аналогичен Dense. Если x и y — векторы, результат представляет собой еще один вектор z, для всех i ∈ 1:out в котором верно следующее:
z[i] = σ(x' * W[i,:,:] * y + bias[i])
Если x и y — матрицы, каждый столбец в результате z = B(x, y) имеет такую форму, причем B — это билинейный слой.
Если второй вход y не задан, он принимается равным x, то есть B(x) == B(x, x).
Два входа можно также предоставить в виде кортежа, Bx, y == B(x, y), который принимается в качестве входных данных Chain.
Если два входа имеют одинаковый размер (in1 == in2), вызов можно записать так: Bilinear(in => out, σ).
Инициализация происходит так же, как для слоя Dense, с W = init(out, in1, in2). Вектор смещений по умолчанию имеет вид zeros(Float32, out); аргумент bias=false отключает обучаемое смещение. Каждый из этих параметров можно задать явным образом.
Примеры
julia> x, y = randn(Float32, 5, 32), randn(Float32, 5, 32);
julia> B = Flux.Bilinear((5, 5) => 7)
Bilinear(5 => 7) # 182 параметра
julia> B(x) |> size # взаимодействия на основе одного входа
(7, 32)
julia> B(x,y) == B((x,y)) # два входа, могут быть заданы в виде кортежа
true
julia> sc = SkipConnection(
Chain(Dense(5 => 20, tanh), Dense(20 => 9, tanh)),
Flux.Bilinear((9, 5) => 3, bias=false),
); # используется в качестве рекомбинатора, второй вход пропущен
julia> sc(x) |> size
(3, 32)
julia> Flux.Bilinear(rand(4,8,16), false, tanh) # выходом является первое измерение веса
Bilinear((8, 16) => 4, tanh; bias=false) # 512 параметров
#
Flux.Scale — Type
Scale(size::Integer..., σ=identity; bias=true, init=ones32)
Scale(scale::AbstractArray, [bias, σ])
Создает поэлементный слой, прямой проход которого задается следующим образом:
y = σ.(scale .* x .+ bias)
При этом используется операция .* вместо умножения матриц * в Dense. Обучаемый масштаб и смещение инициализируются посредством init(size...) и zeros32(size...); по умолчанию init=ones32. Вы можете указать функцию init, отключить обучаемое смещение с помощью bias=false или предоставить массивы явным образом.
Используется LayerNorm с affine=true.
Примеры
julia> a = Flux.Scale(2)
Scale(2) # 4 параметра
julia> Flux.params(a)
Params([Float32[1.0, 1.0], Float32[0.0, 0.0]])
julia> a([1 2 3])
2×3 Matrix{Float32}:
1.0 2.0 3.0
1.0 2.0 3.0
julia> b = Flux.Scale([1 2 3 4], false, abs2)
Scale(1, 4, abs2; bias=false) # 4 параметра
julia> b([1, 10])
2×4 Matrix{Int64}:
1 4 9 16
100 400 900 1600
julia> Flux.params(b)
Params([[1 2 3 4]])
Слой Scale, возможно, и не является полносвязным, но его можно представить как Dense(Diagonal(s.weights), s.bias), а тип Diagonal из LinearAlgebra — это матрица, в которой содержится множество нулей.
|
Совместимость: Flux ≤ 0.12
В старых версиях Flux допускались только вызовы |
Сверточные модели
Эти слои служат для построения сверточных нейронных сетей (CNN).
Все они принимают изображения в так называемом порядке WHCN: пакет из 32 цветных изображений, каждое размером 50 x 50 пикселей, будет иметь размер size(x) == (50, 50, 3, 32). У одного изображения в оттенках серого размер будет size(x) == (28, 28, 1, 1).
Помимо изображений, то есть двумерных данных, они также работают с одномерными данными. Например, стереофоническая запись с 1000 точек дискретизации может иметь размер size(x) == (1000, 2, 1). Эти слои также работают с трехмерными данными, ndims(x) == 5, где последние два измерения опять же соответствуют каналу и пакету.
Работа с шагами и заполнением хорошо проиллюстрирована в статье Дюмулена (Dumoulin) и Визина (Visin).
#
Flux.Conv — Type
Conv(filter, in => out, σ = identity;
stride = 1, pad = 0, dilation = 1, groups = 1, [bias, init])
Стандартный сверточный слой. filter — это кортеж целых чисел, определяющий размер сверточного ядра, а in и out задают количество входных и выходных каналов.
Данные изображения должны храниться в порядке WHCN (ширина, высота, каналы, пакет). То есть изображение размером 100×100 в модели RGB будет представлять собой массив 100×100×3×1, а пакет из 50 таких изображений — массив 100×100×3×50. При этом количество пространственных измерений N = 2, поэтому ядро должно иметь размер, например, (5,5), то есть кортеж из двух целых чисел.
Для сверток по N измерениям признаков этот слой требует на входе массива с ndims(x) == N+2, где size(x, N+1) == in — это количество входных каналов, а size(x, ndims(x)) — это (как и всегда) количество наблюдений в пакете. В таком случае:
-
filterдолжно быть кортежем изNцелых чисел. -
Значениями именованных аргументов
strideиdilationдолжны быть одновременно либо целые числа, либо кортежи изNцелых чисел. -
Именованный аргумент
padопределяет количество элементов, добавляемых к границам массива данных. Его значением может быть:-
одно целое число для равномерного заполнения со всех сторон;
-
кортеж из
Nцелых чисел для одинакового заполнения в начале и конце каждого пространственного измерения; -
кортеж из
2*Nцелых чисел для асимметричного заполнения; -
одинарное значение
SamePad()для расчета заполнения таким образом, чтобыsize(output,d) == size(x,d) / stride(possibly rounded) for each spatial dimension.
-
-
Именованный аргумент
groupsдолжен иметь значение типаInt. Он задает количество групп, на которые делится свертка.
Именованные аргументы для управления инициализацией слоя:
-
init- функция для генерирования начальных весов. Значение по умолчанию —glorot_uniform. -
bias- начальный вектор смещений по умолчанию содержит одни нули. Можно полностью отключить обучаемое смещение, присвоив этому аргументу значениеfalse, либо передать другой вектор, напримерbias = randn(Float32, out).
См. также описание ConvTranspose, DepthwiseConv и CrossCor.
Примеры
julia> xs = rand32(100, 100, 3, 50); # пакет из 50 изображений в модели RGB
julia> layer = Conv((5,5), 3 => 7, relu; bias = false)
Conv((5, 5), 3 => 7, relu, bias=false) # 525 параметров
julia> layer(xs) |> size
(96, 96, 7, 50)
julia> Conv((5,5), 3 => 7; stride = 2)(xs) |> size
(48, 48, 7, 50)
julia> Conv((5,5), 3 => 7; stride = 2, pad = SamePad())(xs) |> size
(50, 50, 7, 50)
julia> Conv((1,1), 3 => 7; pad = (20,10,0,0))(xs) |> size
(130, 100, 7, 50)
julia> Conv((5,5), 3 => 7; stride = 2, dilation = 4)(xs) |> size
(42, 42, 7, 50)
#
Flux.Conv — Method
Conv(weight::AbstractArray, [bias, activation; stride, pad, dilation])
Создает сверточный слой с указанными весом и смещением. Принимает те же именованные аргументы и имеет те же значения по умолчанию, что и Conv(k::NTuple{N,Integer}, ch::Pair{<:Integer,<:Integer}, σ; ...).
julia> weight = rand(3, 4, 5);
julia> bias = zeros(5);
julia> layer = Conv(weight, bias, sigmoid) # ожидает 1 пространственное измерение
Conv((3,), 4 => 5, σ) # 65 параметров
julia> layer(randn(100, 4, 64)) |> size
(98, 5, 64)
julia> Flux.params(layer) |> length
2
#
Flux.ConvTranspose — Type
ConvTranspose(filter, in => out, σ=identity; stride=1, pad=0, dilation=1, [bias, init])
Стандартный транспонированный сверточный слой. filter — это кортеж целых чисел, определяющий размер сверточного ядра, а in и out задают количество входных и выходных каналов.
Обратите внимание: чтобы попытаться обеспечить соблюдение условия size(output,d) == size(x,d) * stride в данном случае, можно задать pad=SamePad().
Параметры контролируются дополнительными именованными аргументами со значениями по умолчанию init=glorot_uniform и bias=true.
Более подробное описание именованных аргументов см. в описании Conv.
Примеры
julia> xs = rand32(100, 100, 3, 50); # пакет из 50 изображений в модели RGB
julia> layer = ConvTranspose((5,5), 3 => 7, relu)
ConvTranspose((5, 5), 3 => 7, relu) # 532 parameters
julia> layer(xs) |> size
(104, 104, 7, 50)
julia> ConvTranspose((5,5), 3 => 7, stride=2)(xs) |> size
(203, 203, 7, 50)
julia> ConvTranspose((5,5), 3 => 7, stride=3, pad=SamePad())(xs) |> size
(300, 300, 7, 50)
#
Flux.ConvTranspose — Method
ConvTranspose(weight::AbstractArray, [bias, activation; stride, pad, dilation, groups])
Создает слой ConvTranspose с указанными весом и смещением. Принимает те же именованные аргументы и имеет те же значения по умолчанию, что и ConvTranspose(k::NTuple{N,Integer}, ch::Pair{<:Integer,<:Integer}, σ; ...).
Примеры
julia> weight = rand(3, 4, 5);
julia> bias = zeros(4);
julia> layer = ConvTranspose(weight, bias, sigmoid)
ConvTranspose((3,), 5 => 4, σ) # 64 parameters
julia> layer(randn(100, 5, 64)) |> size # транспонированная свертка увеличивает размер измерения (повышающая дискретизация)
(102, 4, 64)
julia> Flux.params(layer) |> length
2
#
Flux.CrossCor — Type
CrossCor(filter, in => out, σ=identity; stride=1, pad=0, dilation=1, [bias, init])
Стандартный взаимнокорреляционный слой. filter — это кортеж целых чисел, определяющий размер сверточного ядра, а in и out задают количество входных и выходных каналов.
Параметры контролируются дополнительными именованными аргументами со значениями по умолчанию init=glorot_uniform и bias=true.
Более подробное описание именованных аргументов см. в описании Conv.
Примеры
julia> xs = rand(Float32, 100, 100, 3, 50); # пакет из 50 изображений в модели RGB
julia> layer = CrossCor((5,5), 3 => 6, relu; bias=false)
CrossCor((5, 5), 3 => 6, relu, bias=false) # 450 параметров
julia> layer(xs) |> size
(96, 96, 6, 50)
julia> CrossCor((5,5), 3 => 7, stride=3, pad=(2,0))(xs) |> size
(34, 32, 7, 50)
#
Flux.CrossCor — Method
CrossCor(weight::AbstractArray, [bias, activation; stride, pad, dilation])
Создает слой CrossCor с указанными весом и смещением. Принимает те же именованные аргументы и имеет те же значения по умолчанию, что и CrossCor(k::NTuple{N,Integer}, ch::Pair{<:Integer,<:Integer}, σ; ...).
Примеры
julia> weight = rand(3, 4, 5);
julia> bias = zeros(5);
julia> layer = CrossCor(weight, bias, relu)
CrossCor((3,), 4 => 5, relu) # 65 параметров
julia> layer(randn(100, 4, 64)) |> size
(98, 5, 64)
#
Flux.DepthwiseConv — Function
DepthwiseConv(filter, in => out, σ=identity; stride=1, pad=0, dilation=1, [bias, init])
DepthwiseConv(weight::AbstractArray, [bias, activation; stride, pad, dilation])
Возвращает поканальный сверточный слой, то есть слой Conv с количеством групп, равным количеству входных каналов.
Описание аргументов см. в описании Conv.
Примеры
julia> xs = rand(Float32, 100, 100, 3, 50); # пакет из 50 изображений в модели RGB
julia> layer = DepthwiseConv((5,5), 3 => 6, relu; bias=false)
Conv((5, 5), 3 => 6, relu, groups=3, bias=false) # 150 параметров
julia> layer(xs) |> size
(96, 96, 6, 50)
julia> DepthwiseConv((5, 5), 3 => 9, stride=2, pad=2)(xs) |> size
(50, 50, 9, 50)
#
Flux.SamePad — Type
SamePad()
При передаче в качестве параметра в сверточные (и подобные им) слои приводит к выбору такого заполнения, что размеры входа и выхода будут согласованы (для первых N измерений, ядра или окна) при stride==1. При stride≠1 размер выхода равен ceil(input_size/stride).
Примеры
julia> xs = rand32(100, 100, 3, 50); # пакет изображений
julia> layer = Conv((2,2), 3 => 7, pad=SamePad())
Conv((2, 2), 3 => 7, pad=(1, 0, 1, 0)) # 91 параметр
julia> layer(xs) |> size # обратите внимание, что при таком заполнении измерения остаются такими же
(100, 100, 7, 50)
julia> layer2 = Conv((2,2), 3 => 7)
Conv((2, 2), 3 => 7) # 91 параметр
julia> layer2(xs) |> size # выходное измерение изменяется, так как заполнение не было аналогичным
(99, 99, 7, 50)
julia> layer3 = Conv((5, 5), 3 => 7, stride=2, pad=SamePad())
Conv((5, 5), 3 => 7, pad=2, stride=2) # 532 parameters
julia> layer3(xs) |> size # размер выхода = `ceil(input_size/stride)` = 50
(50, 50, 7, 50)
#
Flux.flatten — Function
flatten(x)
Действует аналогично функции MLUtils.flatten, которая является предпочтительной, так как данный метод существует только в целях обратной совместимости.
MultiHeadAttention
Базовые блоки, необходимые для реализации архитектур преобразователей. См. также описание функциональных аналогов в разделе, посвященном примитиву Attention из NNlib.
Подвыборка
Данные слои часто используются после сверточного слоя и сокращают размер его выходных данных. У них нет обучаемых параметров.
#
Flux.AdaptiveMaxPool — Type
AdaptiveMaxPool(out::NTuple)
Адаптивный пулинговый слой со взятием максимума. Необходимый размер окна вычисляется так, что для выхода size(y)[1:N] == out.
На входе ожидается массив с ndims(x) == N+2, то есть с измерениями каналов и пакетов после N измерений признаков, где N = length(out).
См. также описание MaxPool и AdaptiveMeanPool.
Примеры
julia> xs = rand(Float32, 100, 100, 3, 50); # пакет из 50 изображений в модели RGB
julia> AdaptiveMaxPool((25, 25))(xs) |> size
(25, 25, 3, 50)
julia> MaxPool((4,4))(xs) ≈ AdaptiveMaxPool((25, 25))(xs)
true
#
Flux.MaxPool — Type
MaxPool(window::NTuple; pad=0, stride=window)
Пулинговый слой со взятием максимума, в котором все пиксели в блоке размером window заменяются единицей.
На входе ожидается массив с ndims(x) == N+2, то есть с измерениями каналов и пакетов после N измерений признаков, где N = length(window).
По умолчанию размер окна — это также шаг в каждом измерении. Именованный аргумент pad принимает те же значения, что и для слоя Conv, включая SamePad().
См. также описание Conv, MeanPool, AdaptiveMaxPool и GlobalMaxPool.
Примеры
julia> xs = rand(Float32, 100, 100, 3, 50); # пакет из 50 изображений в модели RGB
julia> m = Chain(Conv((5, 5), 3 => 7, pad=SamePad()), MaxPool((5, 5), pad=SamePad()))
Chain(
Conv((5, 5), 3 => 7, pad=2), # 532 parameters
MaxPool((5, 5), pad=2),
)
julia> m[1](xs) |> size
(100, 100, 7, 50)
julia> m(xs) |> size
(20, 20, 7, 50)
julia> layer = MaxPool((5,), pad=2, stride=(3,)) # одномерное окно
MaxPool((5,), pad=2, stride=3)
julia> layer(rand(Float32, 100, 7, 50)) |> size
(34, 7, 50)
#
Flux.GlobalMaxPool — Type
GlobalMaxPool()
Глобальный пулинговый слой со взятием максимума.
Преобразует входные данные в форме (w,h,c,b) в форму (1,1,c,b), выполняя подвыборку со взятием максимума применительно к полным картам признаков в форме (w,h).
См. также описание MaxPool и GlobalMeanPool.
julia> xs = rand(Float32, 100, 100, 3, 50);
julia> m = Chain(Conv((3,3), 3 => 7), GlobalMaxPool());
julia> m(xs) |> size
(1, 1, 7, 50)
julia> GlobalMaxPool()(rand(3,5,7)) |> size # сохраняет 2 измерения
(1, 5, 7)
#
Flux.AdaptiveMeanPool — Type
AdaptiveMeanPool(out::NTuple)
Адаптивный пулинговый слой со взятием среднего значения. Необходимый размер окна вычисляется так, что для выхода size(y)[1:N] == out.
На входе ожидается массив с ndims(x) == N+2, то есть с измерениями каналов и пакетов после N измерений признаков, где N = length(out).
См. также описание MaxPool и AdaptiveMaxPool.
Примеры
julia> xs = rand(Float32, 100, 100, 3, 50); # пакет из 50 изображений в модели RGB
julia> AdaptiveMeanPool((25, 25))(xs) |> size
(25, 25, 3, 50)
julia> MeanPool((4,4))(xs) ≈ AdaptiveMeanPool((25, 25))(xs)
true
#
Flux.MeanPool — Type
MeanPool(window::NTuple; pad=0, stride=window)
Пулинговый слой со взятием среднего значения, в котором все пиксели в блоке размера window усредняются.
На входе ожидается массив с ndims(x) == N+2, то есть с измерениями каналов и пакетов после N измерений признаков, где N = length(window).
По умолчанию размер окна — это также шаг в каждом измерении. Именованный аргумент pad принимает те же значения, что и для слоя Conv, включая SamePad().
См. также описание функций Conv, MaxPool и AdaptiveMeanPool.
Примеры
julia> xs = rand(Float32, 100, 100, 3, 50);
julia> m = Chain(Conv((5,5), 3 => 7), MeanPool((5,5), pad=SamePad()))
Chain(
Conv((5, 5), 3 => 7), # 532 parameters
MeanPool((5, 5), pad=2),
)
julia> m[1](xs) |> size
(96, 96, 7, 50)
julia> m(xs) |> size
(20, 20, 7, 50)
#
Flux.GlobalMeanPool — Type
GlobalMeanPool()
Глобальный пулинговый слой со взятием среднего значения.
Преобразует входные данные в форме (w,h,c,b) в форму (1,1,c,b), выполняя подвыборку со взятием среднего значения применительно к полным картам признаков в форме (w,h).
julia> xs = rand(Float32, 100, 100, 3, 50);
julia> m = Chain(Conv((3,3), 3 => 7), GlobalMeanPool());
julia> m(xs) |> size
(1, 1, 7, 50)
Повышающая дискретизация
Такие слои, действующие противоположно слоям подвыборки, увеличивают размер массива. У них нет обучаемых параметров.
#
Flux.Upsample — Type
Upsample(mode = :nearest; [scale, size])
Upsample(scale, mode = :nearest)
Слой повышающей дискретизации. Необходимо задать один из двух именованных аргументов:
Если scale — число, оно применяется ко всем измерениям входных данных, кроме двух последних (измерений каналов и пакетов). Значением также может быть кортеж для управления измерениями по отдельности. Именованный аргумент size также может принимать кортеж для указания начальных измерений результата напрямую.
В настоящее время поддерживаются следующие режимы (mode) повышающей дискретизации и соответствующие методы NNlib:
-
:nearest->NNlib.upsample_nearest -
:bilinear->NNlib.upsample_bilinear -
:trilinear->NNlib.upsample_trilinear
Примеры
julia> m = Upsample(scale = (2, 3))
Upsample(:nearest, scale = (2, 3))
julia> m(ones(2, 2, 1, 1)) |> size
(4, 6, 1, 1)
julia> m = Upsample(:bilinear, size = (4, 5))
Upsample(:bilinear, size = (4, 5))
julia> m(ones(2, 2, 1, 1)) |> size
(4, 5, 1, 1)
#
Flux.PixelShuffle — Type
PixelShuffle(r::Int)
Слой перемешивания пикселей с коэффициентом увеличения масштаба r. Обычно применяется для генерирования изображений в более высоком разрешении при увеличении их масштаба.
См. описание NNlib.pixel_shuffle.
Примеры
julia> p = PixelShuffle(2);
julia> xs = [2row + col + channel/10 for row in 1:2, col in 1:2, channel in 1:4, n in 1:1]
2×2×4×1 Array{Float64, 4}:
[:, :, 1, 1] =
3.1 4.1
5.1 6.1
[:, :, 2, 1] =
3.2 4.2
5.2 6.2
[:, :, 3, 1] =
3.3 4.3
5.3 6.3
[:, :, 4, 1] =
3.4 4.4
5.4 6.4
julia> p(xs)
4×4×1×1 Array{Float64, 4}:
[:, :, 1, 1] =
3.1 3.3 4.1 4.3
3.2 3.4 4.2 4.4
5.1 5.3 6.1 6.3
5.2 5.4 6.2 6.4
julia> xs = [3row + col + channel/10 for row in 1:2, col in 1:3, channel in 1:4, n in 1:1]
2×3×4×1 Array{Float64, 4}:
[:, :, 1, 1] =
4.1 5.1 6.1
7.1 8.1 9.1
[:, :, 2, 1] =
4.2 5.2 6.2
7.2 8.2 9.2
[:, :, 3, 1] =
4.3 5.3 6.3
7.3 8.3 9.3
[:, :, 4, 1] =
4.4 5.4 6.4
7.4 8.4 9.4
julia> p(xs)
4×6×1×1 Array{Float64, 4}:
[:, :, 1, 1] =
4.1 4.3 5.1 5.3 6.1 6.3
4.2 4.4 5.2 5.4 6.2 6.4
7.1 7.3 8.1 8.3 9.1 9.3
7.2 7.4 8.2 8.4 9.2 9.4
Векторные представления
Эти слои принимают индекс (или несколько индексов) и возвращают вектор (или несколько векторов). Одними из возможных векторных представлений являются обучаемые параметры.
#
Flux.Embedding — Type
Embedding(in => out; init=randn32)
Таблица поиска, в которой хранятся векторные представления измерения out для словаря размером in в виде обучаемой матрицы.
Этот слой часто применяется для хранения векторных представлений слов и их извлечения по индексам. Входными данными для этого слоя могут быть индекс словаря в 1:in, массив индексов или соответствующая кодировка onehot encoding.
Для индексов x результат имеет размер (out, size(x)...), благодаря чему допустимо несколько измерений пакетов. Для прямой унитарной кодировки ohx результат имеет размер (out, size(ohx)[2:end]...).
Примеры
julia> emb = Embedding(26 => 4, init=Flux.identity_init(gain=22))
Embedding(26 => 4) # 104 параметра
julia> emb(2) # один столбец примерных весов (в данном случае не случайных)
4-element Vector{Float32}:
0.0
22.0
0.0
0.0
julia> emb([3, 1, 20, 14, 4, 15, 7]) # индексы словаря в диапазоне 1:26
4×7 Matrix{Float32}:
0.0 22.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0
22.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 22.0 0.0 0.0
julia> ans == emb(Flux.onehotbatch("cat&dog", 'a':'z', 'n'))
true
julia> emb(rand(1:26, (10, 1, 12))) |> size # три измерения пакетов
(4, 10, 1, 12)
#
Flux.EmbeddingBag — Type
EmbeddingBag(in => out, reduction=mean; init=Flux.randn32)
Таблица поиска, в которой хранятся векторные представления измерения out для словаря размером in. Отличается от Embedding тем, что вместо применения к одному индексу словаря всегда применяется к вектору индексов, который называется мультимножеством. Отдельные векторные представления сводятся к единице с помощью mean или какой-либо иной функции.
Вместо применения к одному мультимножеству, например x::Vector{Int}, этот слой также может работать с несколькими:
-
При применении к вектору мультимножеств создается матрица, столбцы которой представляют собой приведенные векторы. В более общем случае при применении к
x::Array{Vector{Int}}результат имеет размер(out, size(x)...). -
Любой массив целых чисел более высокого ранга рассматривается как коллекция мультимножеств, каждое из которых располагается по первому измерению. Таким образом, при
e::EmbeddingBagиx::Array{Int,N}результатом будетmapslices(e, x; dims=1). Этот метод эффективнее, но требует, чтобы все мультимножества были одинаковой длины. -
Вектор мультимножеств можно также получить путем разделения вектора индексов в заданных точках. В таком случае слой принимает два входных объекта, каждый из которых представляет собой вектор целых чисел. Подробные сведения см. ниже.
Мультимножество можно эквивалентно представить как OneHotMatrix. Их коллекция или один массив OneHotArray более высокого ранга также создают стек векторных представлений. Подробные сведения см. ниже.
Примеры
julia> vocab_size = 26; # внедрение в 3 измерения с неслучайными векторами:
julia> eb = EmbeddingBag(vocab_size => 3, init=Flux.identity_init(gain=100))
EmbeddingBag(26 => 3) # 78 параметров
julia> eb([2]) # одно мультимножество из 1 элемента
3-element Vector{Float32}:
0.0
100.0
0.0
julia> eb([3,3,1]) # одно мультимножество из 3 элементов, одно усредненное векторное представление
3-element Vector{Float32}:
33.333332
0.0
66.666664
julia> eb([[3,1,3], [2,1]]) # два мультимножества
3×2 Matrix{Float32}:
33.3333 50.0
0.0 50.0
66.6667 0.0
julia> eb([1 1 1 1; 1 2 3 4]) # 4 мультимножества по 2 элемента, eachcol([1 1 1 1; 1 2 3 4])
3×4 Matrix{Float32}:
100.0 50.0 50.0 50.0
0.0 50.0 0.0 0.0
0.0 0.0 50.0 0.0
julia> eb(rand(1:26, 10, 5, 5)) |> size # 25 мультимножество по 10 элементов
(3, 5, 5)
Другим способом задания «множества мультимножеств из множества элементов» является передача вектора data (в диапазоне 1:in) и вектора at, указывающего, в каких точках его следует разделить на мультимножества. Первое мультимножество начинается с data[at[1]], второе — с data[at[2]] и т. д., без перекрытий и оставшихся элементов (поэтому требуется at[1]==1).
julia> data = [11, 1, 12, 2, 13, 3, 14];
julia> Flux._splitat(data, [1, 4]) |> println # внутренняя функция, выполняет data[1:3], data[4:end]
[[11, 1, 12], [2, 13, 3, 14]]
julia> eb(data, [1, 4]) # два мультимножества из 3 и 4 элементов
3×2 Matrix{Float32}:
33.3333 0.0
0.0 25.0
0.0 25.0
Наконец, каждое мультимножество можно также представить как OneHotMatrix.
julia> eb(Flux.onehotbatch("bba", 'a':'z')) # то же, что и [2,2,1], одно мультимножество из 3 элементов
3-element Vector{Float32}:
33.333332
66.666664
0.0
julia> eb([Flux.onehotbatch("bba", 'a':'z'), Flux.onehotbatch("cc", 'a':'z')]) # два мультимножества
3×2 Matrix{Float32}:
33.3333 0.0
66.6667 0.0
0.0 100.0
Слои потока данных или контейнеры
Базовый объект Chain(F, G, H) применяет содержащиеся в нем слои по порядку, что равносильно H ∘ G ∘ F. Во Flux есть и другие слои, которые также содержат слои, но соединенные более сложным образом: SkipConnection обеспечивает остаточную связь ResNet.
#
Flux.Chain — Type
Chain(layers...)
Chain(name = layer, ...)
Объединяет несколько слоев или функций для поочередного вызова применительно к указанным входным данным. Поддерживает индексирование и создание срезов (m[2], m[1:end-1]), а если заданы имена, то m[:name] == m[1] и т. д.
Примеры
julia> m = Chain(x -> x^2, x -> x+1);
julia> m(5) == 26
true
julia> m = Chain(Dense(10 => 5, tanh), Dense(5 => 2));
julia> x = rand32(10, 32);
julia> m(x) == m[2](m[1](x))
true
julia> m2 = Chain(enc = Chain(Flux.flatten, Dense(10 => 5, tanh)),
dec = Dense(5 => 2));
julia> m2(x) == (m2[:dec] ∘ m2[:enc])(x)
true
Для больших моделей есть специальный нестабильный по типу путь, позволяющий ускорить компиляцию. Для его использования можно предоставить вектор слоев Chain([layer1, layer2, ...]). Однако будьте осторожны: эта функция пока имеет экспериментальный характер.
#
Flux.activations — Function
activations(c::Chain, input)
Действует аналогично вызову Chain, но сохраняет результат каждого слоя в выходных данных.
Примеры
julia> using Flux: activations
julia> c = Chain(x -> x + 1, x -> x * 2, x -> x ^ 3);
julia> activations(c, 1)
(2, 4, 64)
#
Flux.Maxout — Type
Maxout(layers...)
Maxout(f, n_alts)
Содержит несколько внутренних слоев, каждый из которых принимает одни и те же входные данные. Результатом является поэлементный максимум выходов внутренних слоев.
Можно не определять слои по отдельности, а предоставить создающую их функцию без аргументов и количество создаваемых слоев.
Результат применения функции Maxout к линейным плотным слоям соответствует теореме об универсальной аппроксимации. См. работу Гудфеллоу (Goodfellow), Варда-Фарли (Warde-Farley), Мирзы (Mirza), Курвиля (Courville) и Бенжио (Bengio) — Maxout Networks https://arxiv.org/abs/1302.4389.
См. также сведения о приведении с помощью других операторов в описании Parallel.
Примеры
julia> m = Maxout(x -> abs2.(x), x -> x .* 3);
julia> m([-2 -1 0 1 2])
1×5 Matrix{Int64}:
4 1 0 3 6
julia> m3 = Maxout(() -> Dense(5 => 7, tanh), 3)
Maxout(
Dense(5 => 7, tanh), # 42 параметра
Dense(5 => 7, tanh), # 42 параметра
Dense(5 => 7, tanh), # 42 параметра
) # Всего: 6 массивов, 126 параметров, 888 байтов.
julia> Flux.outputsize(m3, (5, 11))
(7, 11)
#
Flux.SkipConnection — Type
SkipConnection(layer, connection)
Создает связь с пропуском, которая состоит из слоя или объекта Chain с последовательностью слоев и связи напрямую между входом и выходом блока, посредством предоставленного пользователем вызова с двумя аргументами. Первый аргумент вызова распространяется через слой layer, а второй представляет неизменяемый, «пропускаемый» вход.
Простейший тип связи ResNet — SkipConnection(layer, +). Вот более сложный пример:
julia> m = Conv((3,3), 4 => 7, pad=(1,1));
julia> x = ones(Float32, 5, 5, 4, 10);
julia> size(m(x)) == (5, 5, 7, 10)
true
julia> sm = SkipConnection(m, (mx, x) -> cat(mx, x, dims=3));
julia> size(sm(x)) == (5, 5, 11, 10)
true
#
Flux.Parallel — Type
Parallel(connection, layers...)
Parallel(connection; name = layer, ...)
Создает слой, который передает входной массив по каждому пути в layers перед приведением выхода с помощью connection.
Вызов с одним входом x эквивалентен connection([l(x) for l in layers]...). При вызове с несколькими входами в каждый слой передается один из них, то есть Parallel(+, f, g)(x, y) = f(x) + g(y).
Как и в случае с Chain, подслоям можно присвоить имена с помощью конструктора с именованными аргументами. Обращаться к ним можно по индексам: m[1] == m[:name] — это первый слой.
См. также описание типа SkipConnection, который аналогичен identity, но имеет один аргумент Parallel, и типа Maxout, который выполняет приведение путем трансляции max.
Примеры
julia> model = Chain(Dense(3 => 5),
Parallel(vcat, Dense(5 => 4), Chain(Dense(5 => 7), Dense(7 => 4))),
Dense(8 => 17));
julia> model(rand32(3)) |> size
(17,)
julia> model2 = Parallel(+; α = Dense(10, 2, tanh), β = Dense(5, 2))
Parallel(
+,
α = Dense(10 => 2, tanh), # 22 параметра
β = Dense(5 => 2), # 12 параметров
) # Всего: 4 массива, 34 параметра, 392 байта.
julia> model2(rand32(10), rand32(5)) |> size
(2,)
julia> model2[:α](rand32(10)) |> size
(2,)
julia> model2[:β] == model2[2]
true
#
Flux.PairwiseFusion — Type
PairwiseFusion(connection, layers...)
Аргументы
-
connection: функция, принимающая два входа и объединяющая их в один выход -
layers: слои, выходы которых следует объединить
Входные данные
Поведение этого слоя зависит от типа входных данных.
-
Если вход
x— это кортеж длиной N, соответствующей количеству слоевlayers(либо если на входе передан объектxsиз Nx),
каждый слой принимает новый вход x[i], объединенный с предыдущим выходом y[i-1] с помощью connection. Таким образом, выражение (y1, y2, y3) = PairwiseFusion(connection, layer1, layer2, layer3)x1, x2, x3 можно представить такой схемой:
x1 → layer1 → y1 ↘
connection → layer2 → y2 ↘
x2 ↗ connection → layer3 → y3
x3 ↗
-
или записать в следующем виде:
y1 = layer1(x1) y2 = layer2(connection(y1, x2)) y3 = layer3(connection(y2, x3))
-
Если вход только один, каждый слой принимает один и тот же вход
x, объединенный с предыдущим выходом. Таким образом, выражениеy = PairwiseFusion(connection, layers...)(x)соответствует следующему коду:
y[1] == layers[1](x)
for i in 2:length(layers)
y[i] == connection(layers[i](y[i-1]), x)
end
Возвращаемые значения
Кортеж длиной N с результатом каждого слияния (в примере выше это будет (y1, y2, …, yN)).
Рекуррентные модели
Во многом похожи на описанные выше базовые слои, но могут применяться для обработки данных последовательностей (а также других структурированных данных).
#
Flux.RNN — Function
RNN(in => out, σ = tanh)
Самый базовый рекуррентный слой; по сути действует как слой Dense, но на каждом временном шаге выход подается обратно на вход.
Аргументы in и out описывают размер векторов признаков, передаваемых в качестве входа и выхода. Таким образом, функция принимает вектор длиной in или пакет векторов, представленный в виде матрицы in x B, и выдает вектор длиной out или пакет векторов размером out x B.
Данный конструктор представляет собой синтаксический сахар для Recur(RNNCell(a...)), то есть вызовы RNN производятся с сохранением состояния. Обратите внимание, что форма состояния может изменяться в зависимости от входов, поэтому при изменении размера пакета между вызовами вывода желательно сбрасывать модель с помощью reset!. См. примеры ниже.
Примеры
julia> r = RNN(3 => 5)
Recur(
RNNCell(3 => 5, tanh), # 50 параметров
) # Всего: 4 обучаемых массива, 50 параметров,
# плюс 1 необучаемый, 5 параметров, суммарный размер 432 байта.
julia> r(rand(Float32, 3)) |> size
(5,)
julia> Flux.reset!(r);
julia> r(rand(Float32, 3, 10)) |> size # размер пакета 10
(5, 10)
|
Если не вызвать
|
Примечание.
RNNCell можно создать напрямую, задав нелинейную функцию, внутренние матрицы Wi и Wh, вектор смещений b и обучаемое исходное состояние state0. Матрицы Wi и Wh могут быть разных типов, но если Wh имеет форму dxd, матрица Wi должна иметь форму dxN.
julia> using LinearAlgebra
julia> r = Flux.Recur(Flux.RNNCell(tanh, rand(5, 4), Tridiagonal(rand(5, 5)), rand(5), rand(5, 1)))
julia> r(rand(4, 10)) |> size # размер пакета 10
(5, 10)
#
Flux.LSTM — Function
LSTM(in => out)
Рекуррентный слой сети с долговременной и кратковременной памятью . Похож на RNN, но, как правило, требует большего объема памяти по сравнению с последовательностями.
Аргументы in и out описывают размер векторов признаков, передаваемых в качестве входа и выхода. Таким образом, функция принимает вектор длиной in или пакет векторов, представленный в виде матрицы in x B, и выдает вектор длиной out или пакет векторов размером out x B.
Данный конструктор представляет собой синтаксический сахар для Recur(LSTMCell(a...)), то есть вызовы LSTM производятся с сохранением состояния. Обратите внимание, что форма состояния может изменяться в зависимости от входов, поэтому при изменении размера пакета между вызовами вывода желательно сбрасывать модель с помощью reset!. См. примеры ниже.
В этой статье дается хороший обзор внутренних принципов работы.
Примеры
julia> l = LSTM(3 => 5)
Recur(
LSTMCell(3 => 5), # 190 параметров
) # Всего: 5 обучаемых массивов, 190 параметров,
# плюс 2 необучаемых, 10 параметров, суммарный размер 1,062 КиБ.
julia> l(rand(Float32, 3)) |> size
(5,)
julia> Flux.reset!(l);
julia> l(rand(Float32, 3, 10)) |> size # размер пакета 10
(5, 10)
|
Если не вызвать |
Примечание.
LSTMCell можно создать напрямую, задав нелинейную функцию, внутренние матрицы Wi и Wh, вектор смещений b и обучаемое исходное состояние state0. Матрицы Wi и Wh могут быть разных типов. См. пример в описании RNN.
#
Flux.GRU — Function
GRU(in => out)
Слой управляемого рекуррентного блока. Похож на RNN, но, как правило, требует большего объема памяти по сравнению с последовательностями. Реализует вариант, предложенный в версии 1 работы по ссылке.
Целочисленные аргументы in и out описывают размер векторов признаков, передаваемых в качестве входа и выхода. Таким образом, функция принимает вектор длиной in или пакет векторов, представленный в виде матрицы in x B, и выдает вектор длиной out или пакет векторов размером out x B.
Данный конструктор представляет собой синтаксический сахар для Recur(GRUCell(a...)), то есть вызовы GRU производятся с сохранением состояния. Обратите внимание, что форма состояния может изменяться в зависимости от входов, поэтому при изменении размера пакета между вызовами вывода желательно сбрасывать модель с помощью reset!. См. примеры ниже.
В этой статье дается хороший обзор внутренних принципов работы.
Примеры
julia> g = GRU(3 => 5)
Recur(
GRUCell(3 => 5), # 140 параметров
) # Всего: 4 обучаемых массива, 140 параметров,
# плюс 1 необучаемый, 5 параметров, суммарный размер 792 байта.
julia> g(rand(Float32, 3)) |> size
(5,)
julia> Flux.reset!(g);
julia> g(rand(Float32, 3, 10)) |> size # размер пакета 10
(5, 10)
|
Если не вызвать |
Примечание.
GRUCell можно создать напрямую, задав нелинейную функцию, внутренние матрицы Wi и Wh, вектор смещений b и обучаемое исходное состояние state0. Матрицы Wi и Wh могут быть разных типов. См. пример в описании RNN.
#
Flux.GRUv3 — Function
GRUv3(in => out)
Слой управляемого рекуррентного блока. Похож на RNN, но, как правило, требует большего объема памяти по сравнению с последовательностями. Реализует вариант, предложенный в версии 3 работы по ссылке.
Аргументы in и out описывают размер векторов признаков, передаваемых в качестве входа и выхода. Таким образом, функция принимает вектор длиной in или пакет векторов, представленный в виде матрицы in x B, и выдает вектор длиной out или пакет векторов размером out x B.
Данный конструктор представляет собой синтаксический сахар для Recur(GRUv3Cell(a...)), то есть вызовы GRUv3 производятся с сохранением состояния. Обратите внимание, что форма состояния может изменяться в зависимости от входов, поэтому при изменении размера пакета между вызовами вывода желательно сбрасывать модель с помощью reset!. См. примеры ниже.
В этой статье дается хороший обзор внутренних принципов работы.
Примеры
julia> g = GRUv3(3 => 5)
Recur(
GRUv3Cell(3 => 5), # 140 параметров
) # Всего: 5 обучаемых массивов, 140 параметров,
# плюс 1 необучаемый, 5 параметров, суммарный размер 848 байтов.
julia> g(rand(Float32, 3)) |> size
(5,)
julia> Flux.reset!(g);
julia> g(rand(Float32, 3, 10)) |> size # размер пакета 10
(5, 10)
|
Если не вызвать |
Примечание.
GRUv3Cell можно создать напрямую, задав нелинейную функцию, внутренние матрицы Wi, Wh и Wh_h, вектор смещений b и обучаемое исходное состояние state0. Матрицы Wi, Wh и Wh_h могут быть разных типов. См. пример в описании RNN.
#
Flux.Recur — Type
Recur(cell)
Recur принимает рекуррентную ячейку и делает ее ячейкой с сохранением состояния, управляя скрытым состоянием в фоновом режиме. Аргумент cell должен представлять собой модель в следующей форме:
h, y = cell(h, x...)
Например, вот рекуррентная сеть, сохраняющая промежуточную сумму входов:
Примеры
julia> accum(h, x) = (h + x, x)
accum (generic function with 1 method)
julia> rnn = Flux.Recur(accum, 0)
Recur(accum)
julia> rnn(2)
2
julia> rnn(3)
3
julia> rnn.state
5
Также поддерживается свертка трехмерного массива с измерениями (features, batch, time):
julia> accum(h, x) = (h .+ x, x)
accum (generic function with 1 method)
julia> rnn = Flux.Recur(accum, zeros(Int, 1, 1))
Recur(accum)
julia> rnn([2])
1-element Vector{Int64}:
2
julia> rnn([3])
1-element Vector{Int64}:
3
julia> rnn.state
1×1 Matrix{Int64}:
5
julia> out = rnn(reshape(1:10, 1, 1, :)); # применяется к последовательности (признаки, пакет, время)
julia> out |> size
(1, 1, 10)
julia> vec(out)
10-element Vector{Int64}:
1
2
3
4
5
6
7
8
9
10
julia> rnn.state
1×1 Matrix{Int64}:
60
#
Flux.reset! — Function
reset!(rnn)
Сбрасывает скрытое состояние рекуррентного слоя в исходное значение.
Для слоя rnn типа Recur это будет примерно соответствовать следующему выражению:
rnn.state = hidden(rnn.cell)
Примеры
julia> r = Flux.RNNCell(relu, ones(1,1), zeros(1,1), ones(1,1), zeros(1,1)); # вместо этого следует использовать структуру оболочки RNN
julia> y = Flux.Recur(r, ones(1,1));
julia> y.state
1×1 Matrix{Float64}:
1.0
julia> y(ones(1,1)) # relu(1*1 + 1)
1×1 Matrix{Float64}:
2.0
julia> y.state
1×1 Matrix{Float64}:
2.0
julia> Flux.reset!(y)
1×1 Matrix{Float64}:
0.0
julia> y.state
1×1 Matrix{Float64}:
0.0
Нормализация и регуляризация
Эти слои не влияют на структуру сети, но могут ускорять обучение или предотвращать чрезмерное обучение. Некоторые из них содержат обучаемые параметры, а другие — нет.
#
Flux.BatchNorm — Type
BatchNorm(channels::Integer, λ=identity;
initβ=zeros32, initγ=ones32,
affine=true, track_stats=true, active=nothing,
eps=1f-5, momentum= 0.1f0)
Слой пакетной нормализации. Аргумент channels должен содержать размер измерения канала в данных (см. ниже).
Для массива с N измерениями следует вызвать N-1-е измерение канала. Для пакета векторов признаков это просто измерение данных; для изображений WHCN это обычное измерение канала.
BatchNorm вычисляет среднее значение и дисперсию для каждого входного среза D_1×...×D_{N-2}×1×D_N и соответствующим образом нормализует входные данные.
При affine=true также применяет сдвиг и коэффициент масштаба к входным данным посредством обучаемых параметров поканального смещения β и масштаба γ.
После нормализации применяется поэлементная активация λ.
При track_stats=true на этапе обучения накапливается статистика по средним значениям и дисперсии, которая будет использоваться для повторной нормализации входных данных на этапе проверки.
Во время вывода используйте testmode!.
Примеры
julia> using Statistics
julia> xs = rand(3, 3, 3, 2); # пакет из 2 изображений по 3 канала в каждом
julia> m = BatchNorm(3);
julia> Flux.trainmode!(m);
julia> isapprox(std(m(xs)), 1, atol=0.1) && std(xs) != std(m(xs))
true
#
Flux.Dropout — Type
Dropout(p; [dims, rng, active])
Слой, реализующий предотвращение переобучения с заданной вероятностью. Используется в целях регуляризации, то есть для предотвращения чрезмерного обучения.
При обучении каждый вход устанавливается в значение 0 (с вероятностью p) либо масштабируется в отношении 1 / (1 - p)с помощью функции NNlib.dropout. При проверке не действует.
По умолчанию режим активируется автоматически, но им также можно управлять вручную с помощью Flux.testmode! или путем передачи именованного аргумента active=true для режима обучения.
По умолчанию каждый вход обрабатывается независимо. При задании именованного аргумента dims вместо этого случайный выбор делается только по данному измерению. Например, при вызове Dropout(p; dims = 3) случайным образом обнуляются целые каналы на входе WHCN (это также называется двумерным исключением).
Именованный аргумент rng позволяет указать пользовательский генератор случайных чисел. (Поддерживается только при выполнении на ЦП.)
Примеры
julia> m = Chain(Dense(ones(3,2)), Dropout(0.4))
Chain(
Dense(2 => 3), # 9 параметров
Dropout(0.4),
)
julia> m(ones(2, 7)) # тестовый режим, не оказывает эффекта
3×7 Matrix{Float64}:
2.0 2.0 2.0 2.0 2.0 2.0 2.0
2.0 2.0 2.0 2.0 2.0 2.0 2.0
2.0 2.0 2.0 2.0 2.0 2.0 2.0
julia> Flux.trainmode!(m) # равносильно использованию в градиенте
Chain(
Dense(2 => 3), # 9 параметров
Dropout(0.4, active=true),
)
julia> m(ones(2, 7))
3×7 Matrix{Float64}:
0.0 0.0 3.33333 0.0 0.0 0.0 0.0
3.33333 0.0 3.33333 0.0 3.33333 0.0 3.33333
3.33333 3.33333 0.0 3.33333 0.0 0.0 3.33333
julia> y = m(ones(2, 10_000));
julia> using Statistics
julia> mean(y) # примерно равно 2,0, как и в режиме проверки
1.9989999999999961
julia> mean(iszero, y) # примерно равно 0,4
0.4003
#
Flux.AlphaDropout — Type
AlphaDropout(p; [rng, active])
Слой исключения. Используется в самонормализующихся нейронных сетях. Слой AlphaDropout гарантирует сохранение среднего значения и дисперсии активаций.
Если testmode! имеет значение true, со входом ничего не происходит.
Примеры
julia> using Statistics
julia> x = randn32(1000,1);
julia> m = Chain(Dense(1000 => 1000, selu), AlphaDropout(0.2));
julia> Flux.trainmode!(m);
julia> y = m(x);
julia> isapprox(std(x), std(y), atol=0.2)
true
#
Flux.LayerNorm — Type
LayerNorm(size..., λ=identity; affine=true, eps=1f-5)
Слой нормализации, предназначенный для использования с рекуррентными скрытыми состояниями. Значением аргумента size должно быть целое число или их кортеж.
При прямом проходе слой нормализует среднее значение и среднеквадратичное отклонение входа, а затем применяет поэлементную активацию λ. Вход нормализуется по первым length(size) измерениям для кортежа size или по первому измерению для целочисленного значения size. Размер первых измерений входа должен быть равен size.
При affine=true также применяются обучаемый сдвиг и коэффициент масштаба с помощью слоя Scale.
См. также описание BatchNorm, InstanceNorm, GroupNorm и normalise.
Примеры
julia> using Statistics
julia> xs = rand(3, 3, 3, 2); # пакет из 2 изображений по 3 канала в каждом
julia> m = LayerNorm(3);
julia> y = m(xs);
julia> isapprox(std(y, dims=1:3), ones(1, 1, 1, 2), atol=0.1) && std(y, dims=1:3) != std(xs, dims=1:3)
true
#
Flux.InstanceNorm — Type
InstanceNorm(channels::Integer, λ=identity;
initβ=zeros32, initγ=ones32,
affine=false, track_stats=false,
eps=1f-5, momentum=0.1f0)
Слой индивидуальной нормализации. Аргумент channels должен содержать размер измерения канала в данных (см. ниже).
Для массива с N > 2 измерениями следует вызвать N-1-е измерение канала. Для изображений WHCN это обычное измерение канала.
InstanceNorm вычисляет среднее значение и дисперсию для каждого входного среза D_1×...×D_{N-2}×1×1 и соответствующим образом нормализует входные данные.
При affine=true также применяет сдвиг и коэффициент масштаба к входным данным посредством обучаемых параметров поканального смещения β и масштаба γ.
При track_stats=true на этапе обучения накапливается статистика по средним значениям и дисперсии, которая будет использоваться для повторной нормализации входных данных на этапе проверки.
Внимание! Для параметров affine и track_stats значением по умолчанию было true в предыдущих версиях Flux (до версии 0.12).
Примеры
julia> using Statistics
julia> xs = rand(3, 3, 3, 2); # пакет из 2 изображений по 3 канала в каждом
julia> m = InstanceNorm(3);
julia> y = m(xs);
julia> isapprox(std(y, dims=1:2), ones(1, 1, 3, 2), atol=0.2) && std(y, dims=1:2) != std(xs, dims=1:2)
true
#
Flux.GroupNorm — Type
GroupNorm(channels::Int, G::Int, λ = identity;
initβ = zeros32,
initγ = ones32,
affine = true,
eps = 1f-5,
momentum = 0.1f0)
Слой групповой нормализации.
chs — это количество каналов в измерении каналов входа. Для массива с N измерениями измерение каналов имеет индекс N-1.
G — это количество групп, по которым вычисляется статистика. Количество каналов должно быть целым числом, кратным количеству групп.
Аргумент channels должен содержать размер измерения канала в данных (см. ниже).
Для массива с N > 2 измерениями следует вызвать N-1-е измерение канала. Для изображений WHCN это обычное измерение канала.
При affine=true также применяет сдвиг и коэффициент масштаба к входным данным посредством обучаемых параметров поканального смещения β и масштаба γ.
Примеры
julia> using Statistics
julia> xs = rand(3, 3, 4, 2); # пакет из 2 изображений по 4 канала в каждом
julia> m = GroupNorm(4, 2);
julia> y = m(xs);
julia> isapprox(std(y[:, :, 1:2, 1]), 1, atol=0.1) && std(xs[:, :, 1:2, 1]) != std(y[:, :, 1:2, 1])
true
julia> isapprox(std(y[:, :, 3:4, 2]), 1, atol=0.1) && std(xs[:, :, 3:4, 2]) != std(y[:, :, 3:4, 2])
true
#
Flux.normalise — Function
normalise(x; dims=ndims(x), eps=1e-5)
Нормализует x к среднему значению 0 и среднеквадратичному отклонению 1 по измерениям, указанным в dims. По умолчанию dims — это последнее измерение. eps — это небольшой член, который добавляется в знаменатель для численной устойчивости.
Примеры
julia> using Statistics
julia> x = [90, 100, 110, 130, 70];
julia> mean(x), std(x; corrected=false)
(100.0, 20.0)
julia> y = Flux.normalise(x)
5-element Vector{Float64}:
-0.49999975000012503
0.0
0.49999975000012503
1.499999250000375
-1.499999250000375
julia> isapprox(std(y; corrected=false), 1, atol=1e-5)
true
julia> x = rand(10:100, 10, 10);
julia> y = Flux.normalise(x, dims=1);
julia> isapprox(std(y; dims=1, corrected=false), ones(1, 10), atol=1e-5)
true
Проверка и обучение
Некоторые нормализационные слои ведут себя по-разному в режиме обучения и вывода (проверки). По умолчанию Flux автоматически определяет, вычисляется ли слой в рамках обучения или вывода.
|
Автоматическое определение режима обучения или проверки лучше всего работает с Zygote, пакетом по умолчанию для автоматического дифференцирования. С другими пакетами, такими как Tracker, Yota или ForwardDiff, оно может не работать. |
С помощью функций Flux.trainmode! и Flux.testmode! можно вручную указать требуемое поведение. При вызове для модели они переводят все ее слои в заданный режим.
#
Flux.testmode! — Method
testmode!(model, [mode]) -> model
Переводит слой или все слои модели в режим проверки. При этом перестают действовать Dropout и некоторые другие слои регуляризации.
Если модель была переведена в режим проверки вручную, ее необходимо также вручную перевести обратно в режим обучения на этапе обучения с помощью trainmode!.
Кроме того, имеется необязательный второй аргумент, который принимает символ :auto для перевода всех слоев обратно в автоматический режим по умолчанию.
Пример
julia> d = Dropout(0.3)
Dropout(0.3)
julia> testmode!(d) # исключение теперь всегда отключено
Dropout(0.3, active=false)
julia> trainmode!(d) # исключение теперь всегда включено
Dropout(0.3, active=true)
julia> testmode!(d, :auto) # восстановление режима по умолчанию
Dropout(0.3)
#
Flux.testmode! — Method
testmode!(model, inactive)
Этот метод с двумя аргументами предназначен преимущественно для внутреннего использования. Он выполняет рекурсию по model, пока метод, например testmode!(d::Dropout, inactive), не изменит активность слоя. Пользовательские слои могут поддерживать переключение вручную между testmode! и trainmode! путем определения такого метода.
Возможные значения inactive:
-
trueдля тестирования, то естьactive=false; -
falseдля обучения; равносильно xref:./layers.adoc#Flux.trainmode!(m); -
:autoилиnothingдля автоматического обнаружения обучения библиотекой Flux.
compat Этот метод может быть упразднен при внесении следующего критического изменения для отделения доступной пользователю функции testmode! от внутренней рекурсии.
#
Flux.trainmode! — Function
trainmode!(model) -> model
Переводит слой или все слои модели в режим обучения. Функция, обратная функции testmode!. Дополнительные сведения см. в ее описании.
trainmode!(m, active)
|
Этот метод с двумя аргументами устарел. |
Возможные значения active:
-
trueдля обучения; -
falseдля тестирования; равносильноtestmode!(m); -
:autoилиnothingдля автоматического обнаружения обучения библиотекой Flux.