model
from typing import Union
from functools import partial
from tensorflow.keras import layers, Model
def _make_divisible(ch, divisor=8, min_ch=None):
"""
This function is taken from the original tf repo.
It ensures that all layers have a channel number that is divisible by 8
It can be seen here:
https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
"""
if min_ch is None:
min_ch = divisor
new_ch = max(min_ch, int(ch + divisor / 2) // divisor * divisor)
# Make sure that round down does not go down by more than 10%.
if new_ch < 0.9 * ch:
new_ch += divisor
return new_ch
def correct_pad(input_size: Union[int, tuple], kernel_size: int):
"""Returns a tuple for zero-padding for 2D convolution with downsampling.
Arguments:
input_size: Input tensor size.
kernel_size: An integer or tuple/list of 2 integers.
Returns:
A tuple.
"""
if isinstance(input_size, int):
input_size = (input_size, input_size)
kernel_size = (kernel_size, kernel_size)
adjust = (1 - input_size[0] % 2, 1 - input_size[1] % 2)
correct = (kernel_size[0] // 2, kernel_size[1] // 2)
return ((correct[0] - adjust[0], correct[0]),
(correct[1] - adjust[1], correct[1]))
class HardSigmoid(layers.Layer):
def __init__(self, **kwargs):
super(HardSigmoid, self).__init__(**kwargs)
self.relu6 = layers.ReLU(6.)
def call(self, inputs, **kwargs):
x = self.relu6(inputs + 3) * (1. / 6)
return x
class HardSwish(layers.Layer):
def __init__(self, **kwargs):
super(HardSwish, self).__init__(**kwargs)
self.hard_sigmoid = HardSigmoid()
def call(self, inputs, **kwargs):
x = self.hard_sigmoid(inputs) * inputs
return x
def _se_block(inputs, filters, prefix, se_ratio=1 / 4.):
# [batch, height, width, channel] -> [batch, channel]
x = layers.GlobalAveragePooling2D(name=prefix + 'squeeze_excite/AvgPool')(inputs)
# Target shape. Tuple of integers, does not include the samples dimension (batch size).
# [batch, channel] -> [batch, 1, 1, channel]
x = layers.Reshape((1, 1, filters))(x)
# fc1
x = layers.Conv2D(filters=_make_divisible(filters * se_ratio),
kernel_size=1,
padding='same',
name=prefix + 'squeeze_excite/Conv')(x)
x = layers.ReLU(name=prefix + 'squeeze_excite/Relu')(x)
# fc2
x = layers.Conv2D(filters=filters,
kernel_size=1,
padding='same',
name=prefix + 'squeeze_excite/Conv_1')(x)
x = HardSigmoid(name=prefix + 'squeeze_excite/HardSigmoid')(x)
x = layers.Multiply(name=prefix + 'squeeze_excite/Mul')([inputs, x])
return x
def _inverted_res_block(x,
input_c: int, # input channel
kernel_size: int, # kennel size
exp_c: int, # expanded channel
out_c: int, # out channel
use_se: bool, # whether using SE
activation: str, # RE or HS
stride: int,

文章提供了两个函数`mobilenet_v3_large`和`mobilenet_v3_small`,用于在TensorFlow中构建MobilenetV3的大、小版本模型。模型结构包含HardSigmoid和HardSwish激活函数,以及squeeze-and-excitation(SE)块。之后的代码片段展示了如何加载数据、预处理、创建数据集并使用该模型进行训练,包括损失函数、优化器、训练和验证步骤。
最低0.47元/天 解锁文章
1561

被折叠的 条评论
为什么被折叠?



