-
-
Notifications
You must be signed in to change notification settings - Fork 66
Unify lower level API for EfficientNet and MobileNet model families #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
251b323
5ce0204
4f487a0
4cdcaef
7827ca6
e048d78
da5d3a7
ab96700
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
function build_irmodel(scalings::NTuple{2, Real}, block_configs::AbstractVector{<:Tuple}; | ||
inplanes::Integer = 32, connection = +, activation = relu, | ||
norm_layer = BatchNorm, divisor::Integer = 8, tail_conv::Bool = true, | ||
expanded_classifier::Bool = false, stochastic_depth_prob = nothing, | ||
headplanes::Integer, dropout_prob = nothing, inchannels::Integer = 3, | ||
nclasses::Integer = 1000, kwargs...) | ||
width_mult, _ = scalings | ||
# building first layer | ||
inplanes = _round_channels(inplanes * width_mult, divisor) | ||
layers = [] | ||
append!(layers, | ||
conv_norm((3, 3), inchannels, inplanes, activation; stride = 2, pad = 1, | ||
norm_layer)) | ||
# building inverted residual blocks | ||
get_layers, block_repeats = mbconv_stage_builder(block_configs, inplanes, scalings; | ||
stochastic_depth_prob, norm_layer, | ||
divisor, kwargs...) | ||
append!(layers, cnn_stages(get_layers, block_repeats, connection)) | ||
# building last layers | ||
outplanes = _round_channels(block_configs[end][3] * width_mult, divisor) | ||
if tail_conv | ||
# special case, supported fully only for MobileNetv3 | ||
if expanded_classifier | ||
midplanes = _round_channels(outplanes * block_configs[end][4], divisor) | ||
append!(layers, | ||
conv_norm((1, 1), outplanes, midplanes, activation; norm_layer)) | ||
classifier = create_classifier(midplanes, headplanes, nclasses, | ||
(hardswish, identity); dropout_prob) | ||
else | ||
append!(layers, | ||
conv_norm((1, 1), outplanes, headplanes, activation; norm_layer)) | ||
classifier = create_classifier(headplanes, nclasses; dropout_prob) | ||
end | ||
else | ||
classifier = create_classifier(outplanes, nclasses; dropout_prob) | ||
end | ||
return Chain(Chain(layers...), classifier) | ||
end | ||
function build_irmodel(width_mult::Real, block_configs::AbstractVector{<:Tuple}; kwargs...) | ||
return build_irmodel((width_mult, 1), block_configs; kwargs...) | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,29 @@ | ||
function dwsepconv_builder(block_configs, inplanes::Integer, stage_idx::Integer, | ||
width_mult::Real; norm_layer = BatchNorm, kwargs...) | ||
""" | ||
irblockbuilder(::typeof(irblockfn), block_configs::AbstractVector{<:Tuple}, | ||
inplanes::Integer, stage_idx::Integer, scalings::NTuple{2, Real}; | ||
stochastic_depth_prob = nothing, norm_layer = BatchNorm, | ||
divisor::Integer = 8, kwargs...) | ||
|
||
Constructs a collection of inverted residual blocks for a given stage. Note that | ||
this function is not intended to be called directly, but rather by the [`mbconv_stage_builder`](@ref) | ||
function. This function must only be extended if the user wishes to extend a custom inverted | ||
residual block type. | ||
theabhirath marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Arguments | ||
|
||
- `irblockfn`: the inverted residual block function to use in the block builder. Metalhead | ||
defines methods for [`dwsep_conv_norm`](@ref), [`mbconv`](@ref) and [`fused_mbconv`](@ref) | ||
as inverted residual blocks. | ||
""" | ||
function irblockbuilder(::typeof(dwsep_conv_norm), block_configs::AbstractVector{<:Tuple}, | ||
theabhirath marked this conversation as resolved.
Show resolved
Hide resolved
|
||
inplanes::Integer, stage_idx::Integer, scalings::NTuple{2, Real}; | ||
stochastic_depth_prob = nothing, norm_layer = BatchNorm, | ||
divisor::Integer = 8, kwargs...) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to have unused keywords? As far as I can tell, right now it is silently ignored, but not including extraneous keywords would throw a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are being used though, to pass stuff like the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I specifically mean stuff like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This particular one needs to be there because it will cause a |
||
width_mult, depth_mult = scalings | ||
block_fn, k, outplanes, stride, nrepeats, activation = block_configs[stage_idx] | ||
outplanes = _round_channels(outplanes * width_mult) | ||
outplanes = _round_channels(outplanes * width_mult, divisor) | ||
if stage_idx != 1 | ||
inplanes = _round_channels(block_configs[stage_idx - 1][3] * width_mult) | ||
inplanes = _round_channels(block_configs[stage_idx - 1][3] * width_mult, divisor) | ||
end | ||
function get_layers(block_idx::Integer) | ||
inplanes = block_idx == 1 ? inplanes : outplanes | ||
|
@@ -12,15 +32,17 @@ function dwsepconv_builder(block_configs, inplanes::Integer, stage_idx::Integer, | |
stride, pad = SamePad(), norm_layer, kwargs...)...) | ||
return (block,) | ||
end | ||
return get_layers, nrepeats | ||
return get_layers, ceil(Int, nrepeats * depth_mult) | ||
end | ||
|
||
function mbconv_builder(block_configs, inplanes::Integer, stage_idx::Integer, | ||
scalings::NTuple{2, Real}; norm_layer = BatchNorm, | ||
divisor::Integer = 8, se_from_explanes::Bool = false, | ||
kwargs...) | ||
function irblockbuilder(::typeof(mbconv), block_configs::AbstractVector{<:Tuple}, | ||
inplanes::Integer, stage_idx::Integer, scalings::NTuple{2, Real}; | ||
stochastic_depth_prob = nothing, norm_layer = BatchNorm, | ||
divisor::Integer = 8, se_from_explanes::Bool = false, kwargs...) | ||
width_mult, depth_mult = scalings | ||
block_fn, k, outplanes, expansion, stride, nrepeats, reduction, activation = block_configs[stage_idx] | ||
block_repeats = [ceil(Int, block_configs[idx][end - 2] * depth_mult) | ||
for idx in eachindex(block_configs)] | ||
block_fn, k, outplanes, expansion, stride, _, reduction, activation = block_configs[stage_idx] | ||
# calculate number of reduced channels for squeeze-excite layer from explanes instead of inplanes | ||
if !isnothing(reduction) | ||
reduction = !se_from_explanes ? reduction * expansion : reduction | ||
|
@@ -29,79 +51,52 @@ function mbconv_builder(block_configs, inplanes::Integer, stage_idx::Integer, | |
inplanes = _round_channels(block_configs[stage_idx - 1][3] * width_mult, divisor) | ||
end | ||
outplanes = _round_channels(outplanes * width_mult, divisor) | ||
sdschedule = linear_scheduler(stochastic_depth_prob; depth = sum(block_repeats)) | ||
function get_layers(block_idx::Integer) | ||
inplanes = block_idx == 1 ? inplanes : outplanes | ||
explanes = _round_channels(inplanes * expansion, divisor) | ||
stride = block_idx == 1 ? stride : 1 | ||
block = block_fn((k, k), inplanes, explanes, outplanes, activation; norm_layer, | ||
stride, reduction, kwargs...) | ||
return stride == 1 && inplanes == outplanes ? (identity, block) : (block,) | ||
use_skip = stride == 1 && inplanes == outplanes | ||
if use_skip | ||
schedule_idx = sum(block_repeats[1:(stage_idx - 1)]) + block_idx | ||
drop_path = StochasticDepth(sdschedule[schedule_idx]) | ||
return (drop_path, block) | ||
else | ||
return (block,) | ||
end | ||
end | ||
return get_layers, ceil(Int, nrepeats * depth_mult) | ||
end | ||
|
||
function mbconv_builder(block_configs, inplanes::Integer, stage_idx::Integer, | ||
width_mult::Real; norm_layer = BatchNorm, kwargs...) | ||
return mbconv_builder(block_configs, inplanes, stage_idx, (width_mult, 1); | ||
norm_layer, kwargs...) | ||
return get_layers, block_repeats[stage_idx] | ||
end | ||
|
||
function fused_mbconv_builder(block_configs, inplanes::Integer, stage_idx::Integer; | ||
norm_layer = BatchNorm, kwargs...) | ||
block_fn, k, outplanes, expansion, stride, nrepeats, activation = block_configs[stage_idx] | ||
function irblockbuilder(::typeof(fused_mbconv), block_configs::AbstractVector{<:Tuple}, | ||
inplanes::Integer, stage_idx::Integer, scalings::NTuple{2, Real}; | ||
stochastic_depth_prob = nothing, norm_layer = BatchNorm, | ||
divisor::Integer = 8, kwargs...) | ||
width_mult, depth_mult = scalings | ||
block_repeats = [ceil(Int, block_configs[idx][end - 1] * depth_mult) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For Mobilenet the config list is
so won't |
||
for idx in eachindex(block_configs)] | ||
block_fn, k, outplanes, expansion, stride, _, activation = block_configs[stage_idx] | ||
inplanes = stage_idx == 1 ? inplanes : block_configs[stage_idx - 1][3] | ||
outplanes = _round_channels(outplanes * width_mult, divisor) | ||
sdschedule = linear_scheduler(stochastic_depth_prob; depth = sum(block_repeats)) | ||
function get_layers(block_idx::Integer) | ||
inplanes = block_idx == 1 ? inplanes : outplanes | ||
explanes = _round_channels(inplanes * expansion, 8) | ||
explanes = _round_channels(inplanes * expansion, divisor) | ||
stride = block_idx == 1 ? stride : 1 | ||
block = block_fn((k, k), inplanes, explanes, outplanes, activation; | ||
norm_layer, stride, kwargs...) | ||
return stride == 1 && inplanes == outplanes ? (identity, block) : (block,) | ||
end | ||
return get_layers, nrepeats | ||
end | ||
|
||
# TODO - these builders need to be more flexible to potentially specify stuff like | ||
# activation functions and reductions that don't change | ||
function _get_builder(::typeof(dwsep_conv_bn), block_configs::AbstractVector{<:Tuple}, | ||
inplanes::Integer, stage_idx::Integer; | ||
scalings::Union{Nothing, NTuple{2, Real}} = nothing, | ||
width_mult::Union{Nothing, Number} = nothing, norm_layer, kwargs...) | ||
@assert isnothing(scalings) "dwsep_conv_bn does not support the `scalings` argument" | ||
return dwsepconv_builder(block_configs, inplanes, stage_idx, width_mult; norm_layer, | ||
kwargs...) | ||
end | ||
|
||
function _get_builder(::typeof(mbconv), block_configs::AbstractVector{<:Tuple}, | ||
inplanes::Integer, stage_idx::Integer; | ||
scalings::Union{Nothing, NTuple{2, Real}} = nothing, | ||
width_mult::Union{Nothing, Number} = nothing, norm_layer, kwargs...) | ||
if isnothing(scalings) | ||
return mbconv_builder(block_configs, inplanes, stage_idx, width_mult; norm_layer, | ||
kwargs...) | ||
elseif isnothing(width_mult) | ||
return mbconv_builder(block_configs, inplanes, stage_idx, scalings; norm_layer, | ||
kwargs...) | ||
else | ||
throw(ArgumentError("Only one of `scalings` and `width_mult` can be specified")) | ||
schedule_idx = sum(block_repeats[1:(stage_idx - 1)]) + block_idx | ||
drop_path = StochasticDepth(sdschedule[schedule_idx]) | ||
return stride == 1 && inplanes == outplanes ? (drop_path, block) : (block,) | ||
end | ||
return get_layers, block_repeats[stage_idx] | ||
end | ||
|
||
function _get_builder(::typeof(fused_mbconv), block_configs::AbstractVector{<:Tuple}, | ||
inplanes::Integer, stage_idx::Integer; | ||
scalings::Union{Nothing, NTuple{2, Real}} = nothing, | ||
width_mult::Union{Nothing, Number} = nothing, norm_layer) | ||
@assert isnothing(width_mult) "fused_mbconv does not support the `width_mult` argument." | ||
@assert isnothing(scalings)||scalings == (1, 1) "fused_mbconv does not support the `scalings` argument" | ||
return fused_mbconv_builder(block_configs, inplanes, stage_idx; norm_layer) | ||
end | ||
|
||
function mbconv_stack_builder(block_configs::AbstractVector{<:Tuple}, inplanes::Integer; | ||
scalings::Union{Nothing, NTuple{2, Real}} = nothing, | ||
width_mult::Union{Nothing, Number} = nothing, | ||
norm_layer = BatchNorm, kwargs...) | ||
bxs = [_get_builder(block_configs[idx][1], block_configs, inplanes, idx; scalings, | ||
width_mult, norm_layer, kwargs...) | ||
for idx in eachindex(block_configs)] | ||
function mbconv_stage_builder(block_configs::AbstractVector{<:Tuple}, inplanes::Integer, | ||
scalings::NTuple{2, Real}; kwargs...) | ||
bxs = [irblockbuilder(block_configs[idx][1], block_configs, inplanes, idx, scalings; | ||
kwargs...) for idx in eachindex(block_configs)] | ||
return (stage_idx, block_idx) -> first.(bxs)[stage_idx](block_idx), last.(bxs) | ||
end |
Uh oh!
There was an error while loading. Please reload this page.