Инициализация произвольных весов
Flux инициализирует сверточные слои и рекуррентные ячейки с помощью функции glorot_uniform
по умолчанию. Большинство слоев принимают функцию в качестве ключевого слова init
, которое заменяет это значение по умолчанию. Например:
julia> conv = Conv((3, 3), 3 => 2, relu; init=Flux.glorot_normal)
Conv((3, 3), 3 => 2, relu) # 56 параметров
julia> conv.bias
2-element Vector{Float32}:
0.0
0.0
Обратите внимание, что init
создает массив весов, но не вектор отклонения.
Многие функции инициализации принимают ключевые слова, такие как gain
, а также генератор случайных чисел. Чтобы было проще передавать их слоям, существуют методы, которые возвращают функцию:
julia> Dense(4 => 5, tanh; init=Flux.glorot_uniform(gain=2))
Dense(4 => 5, tanh) # 25 параметров
julia> Dense(4 => 5, tanh; init=Flux.randn32(MersenneTwister(1)))
Dense(4 => 5, tanh) # 25 параметров
Функции инициализации
#
Flux.glorot_uniform
— Function
glorot_uniform([rng], size...; gain = 1) -> Array
glorot_uniform([rng]; kw...) -> Function
Возвращает массив Array{Float32}
указанного размера size
, содержащий случайные числа из равномерного распределения в интервале ], где x = gain * sqrt(6 / (fan_in + fan_out))
.
Этот метод описан в работе [1] и также известен как инициализация Ксавье.
Примеры
julia> Flux.glorot_uniform(3, 4) |> summary
"3×4 Matrix{Float32}"
julia> round.(extrema(Flux.glorot_uniform(10, 100)), digits=3)
(-0.232f0, 0.234f0)
julia> round.(extrema(Flux.glorot_uniform(100, 10)), digits=3)
(-0.233f0, 0.233f0)
julia> round.(extrema(Flux.glorot_uniform(100, 100)), digits=3)
(-0.173f0, 0.173f0)
julia> Dense(3 => 2, tanh; init = Flux.glorot_uniform(MersenneTwister(1)))
Dense(3 => 2, tanh) # 8 параметров
julia> ans.bias
2-element Vector{Float32}:
0.0
0.0
Ссылки
[1] Глоро (Glorot), Ксавье (Xavier) и Йошуа Бенжио (Yoshua Bengio). Understanding the difficulty of training deep feedforward neural networks. Материалы тринадцатой международной конференции по вопросам искусственного интеллекта и статистики. 2010 г.
#
Flux.glorot_normal
— Function
glorot_normal([rng], size...; gain = 1) -> Array
glorot_normal([rng]; kw...) -> Function
Возвращает массив Array{Float32}
указанного размера size
, содержащий случайные числа из нормального распределения со среднеквадратичным отклонением gain * sqrt(2 / (fan_in + fan_out))
, с использованием функции nfan
.
Этот метод описан в работе [1] и также известен как инициализация Ксавье.
Примеры
julia> using Statistics
julia> round(std(Flux.glorot_normal(10, 1000)), digits=3)
0.044f0
julia> round(std(Flux.glorot_normal(1000, 10)), digits=3)
0.044f0
julia> round(std(Flux.glorot_normal(1000, 1000)), digits=3)
0.032f0
julia> Dense(10 => 1000, tanh; init = Flux.glorot_normal(gain=100))
Dense(10 => 1000, tanh) # 11_000 параметров
julia> round(std(ans.weight), sigdigits=3)
4.45f0
Ссылки
[1] Глоро (Glorot), Ксавье (Xavier) и Йошуа Бенжио (Yoshua Bengio). Understanding the difficulty of training deep feedforward neural networks. Материалы тринадцатой международной конференции по вопросам искусственного интеллекта и статистики. 2010 г.
#
Flux.kaiming_uniform
— Function
kaiming_uniform([rng], size...; gain = √2) -> Array
kaiming_uniform([rng]; kw...) -> Function
Возвращает массив Array{Float32}
указанного размера size
, содержащий случайные числа из равномерного распределения в интервале [-x, x]
, где x = gain * sqrt(3/fan_in)
, с использованием функции nfan
.
Этот метод описан в работе [1] и также известен как инициализация Хе.
Примеры
julia> round.(extrema(Flux.kaiming_uniform(100, 10)), digits=3)
(-0.774f0, 0.774f0)
julia> round.(extrema(Flux.kaiming_uniform(10, 100)), digits=3)
(-0.245f0, 0.244f0)
julia> round.(extrema(Flux.kaiming_uniform(100, 100)), digits=3)
(-0.245f0, 0.245f0)
Ссылки
[1] Кайминг Хе (Kaiming He) и др. Delving deep into rectifiers: Surpassing human-level performance on imagenet classification. Материалы международной конференции IEEE по вопросам компьютерного зрения. 2015 г.
#
Flux.kaiming_normal
— Function
kaiming_normal([rng], size...; gain = √2) -> Array
kaiming_normal([rng]; kw...) -> Function
Возвращает массив Array{Float32}
указанного размера size
, содержащий случайные числа из нормального распределения со среднеквадратичным отклонением gain / sqrt(fan_in)
, с использованием функции nfan
.
Этот метод описан в работе [1] и также известен как инициализация Хе.
Примеры
julia> using Statistics
julia> round(std(Flux.kaiming_normal(10, 1000)), digits=3)
0.045f0
julia> round(std(Flux.kaiming_normal(1000, 10)), digits=3)
0.447f0
julia> round(std(Flux.kaiming_normal(1000, 1000)), digits=3)
0.045f0
Ссылки
[1] Кайминг Хе (Kaiming He) и др. Delving deep into rectifiers: Surpassing human-level performance on imagenet classification. Материалы международной конференции IEEE по вопросам компьютерного зрения. 2015 г.
#
Flux.truncated_normal
— Function
truncated_normal([rng], size...; mean = 0, std = 1, lo = -2, hi = 2) -> Array
truncated_normal([rng]; kw...) -> Function
Возвращает массив Array{Float32}
указанного размера size
, каждый элемент которого берется из усеченного нормального распределения. Распределение чисел подчиняется условиям filter(x -> lo<=x<=hi, mean .+ std .* randn(100))
.
Значения генерируются путем выборки из Uniform(0, 1) (rand()
) с последующим применением обратной интегральной функции распределения усеченного нормального распределения. Этот метод лучше всего работает при lo ≤ mean ≤ hi
.
Примеры
julia> using Statistics
julia> Flux.truncated_normal(3, 4) |> summary
"3×4 Matrix{Float32}"
julia> round.(extrema(Flux.truncated_normal(10^6)); digits=3)
(-2.0f0, 2.0f0)
julia> round(std(Flux.truncated_normal(10^6; lo = -100, hi = 100)))
1.0f0
#
Flux.orthogonal
— Function
orthogonal([rng], size...; gain = 1) -> Array
orthogonal([rng]; kw...) -> Function
Возвращает массив Array{Float32}
указанного размера size
, представляющий собой (полу-) ортогональную матрицу, как описано в работе [1].
Создать вектор невозможно, то есть значение length(size) == 1
запрещено. Для length(size) > 2
сначала вычисляется ортогональная матрица prod(size[1:(end - 1)])
на size[end]
, которая затем приводится к исходным измерениям.
Примеры
julia> W = Flux.orthogonal(5, 7);
julia> summary(W)
"5×7 Matrix{Float32}"
julia> W * W' ≈ I(5)
true
julia> W2 = Flux.orthogonal(7, 5);
julia> W2 * W2' ≈ I(7)
false
julia> W2' * W2 ≈ I(5)
true
julia> W3 = Flux.orthogonal(3, 3, 2, 4);
julia> transpose(reshape(W3, :, 4)) * reshape(W3, :, 4) ≈ I(4)
true
Ссылки
[1] Сакс (Saxe), Макклелланд (McClelland), Гангули (Ganguli). Exact solutions to the nonlinear dynamics of learning in deep linear neural networks, ICLR 2014 г., https://arxiv.org/abs/1312.6120
#
Flux.sparse_init
— Function
sparse_init([rng], rows, cols; sparsity, std = 0.01) -> Array
sparse_init([rng]; kw...) -> Function
Возвращает матрицу Matrix{Float32}
размера rows, cols
, каждый столбец которой содержит фиксированную долю нулевых элементов, заданных с помощью sparsity
. Ненулевые элементы имеют нормальное распределение с нулевым средним значением и среднеквадратичным отклонением std
.
Этот метод описан в работе [1].
Примеры
julia> count(iszero, Flux.sparse_init(10, 10, sparsity=1/5))
20
julia> sum(0 .== Flux.sparse_init(10, 11, sparsity=0.9), dims=1)
1×11 Matrix{Int64}:
9 9 9 9 9 9 9 9 9 9 9
julia> Dense(3 => 10, tanh; init=Flux.sparse_init(sparsity=0.5))
Dense(3 => 10, tanh) # 40 параметров
julia> count(iszero, ans.weight, dims=1)
1×3 Matrix{Int64}:
5 5 5
Ссылки
[1] Дж. Мартенс (J Martens), Deep learning via Hessian-free optimization. Материалы 27-й международной конференции по вопросам машинного обучения. 2010 г.
#
Flux.identity_init
— Function
identity_init(size...; gain=1, shift=0) -> Array
identity_init(; kw...) -> Function
Возвращает массив Array{Float32}
указанного размера size
, который выдает тождественное отображение при использовании в качестве параметров в большинстве слоев Flux. Для масштабирования тождественности по константе используйте gain
.
Эта функция часто бывает полезна в контексте переноса обучения, когда нужно увеличить емкость модели, начав с того же отображения.
Работает следующим образом:
-
одно измерение: вектор (
Vector
) нулевых значений (zeros
) (полезен для смещения тождественности); -
два измерения: матрица тождественности (полезна для умножения матрицы тождественности);
-
более двух измерений: плотный блочный массив пространственных фильтров средних отводов (полезен для свертки тождественности).
Особенности:
-
Не все слои будут представлять собой тождественное отображение при использовании с этим методом инициализации. К исключениям относятся рекуррентные слои и слои нормализации.
-
Слои должны отвечать условию
input_size == output_size
, чтобы тождественное отображение было возможным. Если это не так, лишние измерения массива заполняются нулями. -
Для сверточных слоев, помимо указанной выше особенности, размеры ядер должны быть нечетными и должно применяться заполнение, чтобы выходные карты признаков имели тот же размер, что и входные. Для этого может применяться, например,
SamePad
.
Для применения циклического сдвига к выходу используйте ключевое слово shift
(целое число или кортеж), что эквивалентно Base.circshift(identity_init(size...), shift)
.
Для согласованности с другими инциализаторами эта функция принимает rng::AbstractRNG
в качестве необязательного первого аргумента. Однако он игнорируется, так как результат не является случайным.
Примеры
julia> Flux.identity_init(3,5)
3×5 Matrix{Float32}:
1.0 0.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0 0.0
0.0 0.0 1.0 0.0 0.0
julia> Dense(5 => 3, relu, init=Flux.identity_init)([1,-2,3,-4,5])
3-element Vector{Float32}:
1.0
0.0
3.0
julia> Flux.identity_init(3,3,2; gain=100)
3×3×2 Array{Float32, 3}:
[:, :, 1] =
0.0 0.0 0.0
100.0 0.0 0.0
0.0 0.0 0.0
[:, :, 2] =
0.0 0.0 0.0
0.0 100.0 0.0
0.0 0.0 0.0
julia> x4 = cat([1 2 3; 4 5 6; 7 8 9]; dims=4);
julia> Conv((2,2), 1 => 1, init=Flux.identity_init(gain=10), pad=SamePad())(x4)
3×3×1×1 Array{Float32, 4}:
[:, :, 1, 1] =
10.0 20.0 30.0
40.0 50.0 60.0
70.0 80.0 90.0
#
Flux.ones32
— Function
ones32(size...) = ones(Float32, size...)
Возвращает массив Array{Float32}
указанного размера size
, заполненный единицами.
#
Flux.zeros32
— Function
zeros32(size...) = zeros(Float32, size...)
Возвращает массив Array{Float32}
указанного размера size
, заполненный нулями.
#
Flux.rand32
— Function
rand32([rng], size...)
Возвращает массив Array{Float32}
указанного размера size
, заполненный случайными значениями (rand
). Если размер не указан, rand32(rng::AbstractRNG)
возвращает функцию.
#
Flux.randn32
— Function
randn32([rng], size...)
Возвращает массив Array{Float32}
указанного размера size
, заполненный случайными значениями (randn
). Если размер не указан, randn32(rng::AbstractRNG)
возвращает функцию.
#
Flux.create_bias
— Function
create_bias(weights, bias, size...)
Возвращает параметр смещения для слоя на основе значения, переданного в ключевом слове конструктора bias=bias
.
-
При значении
bias == true
создается обучаемый массив указанного размера того же типа, что иweights
, инициализированный с нулевыми значениями. -
При значении
bias == false
возвращаетсяfalse
, что механизм автоматического дифференцирования распознает как невозможность дифференцирования. -
При
bias::AbstractArray
используется предоставленный массив, если он имеет правильный размер. Кроме того,eltype
изменяется в соответствии с типом элементовweights
.
Эти функции вызывают:
#
Flux.rng_from_array
— Function
rng_from_array(x)
Создает экземпляр генератора случайных чисел, наиболее подходящего для x
. Текущие значения по умолчанию:
-
x isa CuArray
:CUDA.default_rng()
-
x isa AbstractArray
: `Random.default_rng()
#
Flux.nfan
— Function
nfan(n_out, n_in=1) -> Tuple
nfan(dims...)
nfan(dims::Tuple)
Для слоя, характеризуемого измерениями dims
, возвращает кортеж (fan_in, fan_out)
, где fan_in
— это число входных нейронов, связанных с выходным, а fan_out
— число выходных нейронов, связанных с входным.
Эта функция используется в основном инициализаторами весов, например kaiming_normal
.
Примеры
julia> layer = Dense(10, 20);
julia> Flux.nfan(size(layer.weight))
(10, 20)
julia> layer = Conv((3, 3), 2=>10);
julia> Flux.nfan(size(layer.weight))
(18, 90)
Изменение типа всех параметров
Типом элемента (eltype
) по умолчанию для моделей является Float32
, так как модели часто обучаются или запускаются на графических процессорах. Тип eltype
модели m
можно изменить на Float64
с помощью макроса f64(m)
:
#
Flux.f16
— Function
f16(m)
Преобразует eltype
параметров модели с плавающей запятой во Float16
. Выполняет рекурсию по структурам, помеченным с помощью @functor
.
Во многих ЦП поддержка Float16
ограничена. Julia может выполнять преобразование во Float32
для каждой операции, но это происходит медленно.
Пример
julia> m = Chain(Dense(784, 2048, relu), Dense(2048, 10)) # все Float32
Chain(
Dense(784 => 2048, relu), # 1_607_680 параметров
Dense(2048 => 10), # 20_490 параметров
) # Всего: 4 массива, 1_628_170 параметров, 6,211 МиБ.
julia> m |> f16 # занимает половину памяти
Chain(
Dense(784 => 2048, relu), # 1_607_680 параметров
Dense(2048 => 10), # 20_490 параметров
) # Всего: 4 массива, 1_628_170 параметров, 3,106 МиБ.