アプリとサービスのすすめ

アプリやIT系のサービスを中心に書いていきます。たまに副業やビジネス関係の情報なども気ままにつづります

EfficientNet-v2のMBConvライクなレイヤーをtensorflowで自作して精度を検証してみた

EfficientNet-v2が優秀なので、その技術を自分の自作ネットワークに応用して作ってみた。
その結果だけを書いてく備忘録。

目次
1. EfficentNetv2の特徴
2. 今回応用した技術
3. 精度(arcfaceあり)


1. EfficentNetv2の特徴

・MBConvとFused-MBconv(DepthwiseConvの代わりに1×1と3×3のConvを使う)を組み合わせた計算処理の高速化

NASで精度、パラメータ、計算時間を最適にする組み合わせの探索(だから高速で高性能)


・MBconvの中にDepthWiseConv2dを入れることで計算量を削減


・SCSE layerを使ってる

・shortcut=Trueでないブロックごとの最初のレイヤーはstride=2, 他はstride=1

2. 今回応用した技術


・Fused-MBConvの代わりに普通のResblockの亜種をパラメータを同じにして使うことによって、MBConvとFused-MBConvの組み合わせを擬似的に再現して計算速度を上げた。また軽いので層を重ねてもモデルのパラメータが軽量で済む。

・DepthWiseConv2dを全部のLayerの中央に入れて、計算量を削減。

・Conv2dの「kernel_initializer」やstridesなどMBConv特有のパラメータをまねた

・SCSE layerの適用

・Conv2d=> BN=> Activaionはやっぱり定石

深さは従来通り、深さごとにblockのoutputを2倍にしたのでEfficientNet-v2のようにLayerを多用できないけど、MBConvとFused-MBconvをほぼ再現できた感じがする。

[16, 32, 64, 128, 214, 512]で深くした。

NASのパラメータ探索は転用が難しいので使わなかった。


応用したLayer

import tensorflow as tf 
from tensorflow.keras.layers import *
import numpy as np

CONV_KERNEL_INITIALIZER = tf.keras.initializers.VarianceScaling(scale=2.0, mode="fan_out", distribution="truncated_normal")
channel_axis = -1


def fused_like_MBconv(init, nb_filter, k):
    residual = Conv2D(nb_filter * k, (1, 1), strides=(2, 2), padding='same', use_bias=False, kernel_initializer=CONV_KERNEL_INITIALIZER)(init)
    residual = BatchNormalization(axis=-1, momentum=0.9, epsilon=0.001)(residual)
    x = Conv2D(nb_filter * k, (3, 3), padding='same', use_bias=False, kernel_initializer=CONV_KERNEL_INITIALIZER)(init)
    x = BatchNormalization(axis=channel_axis, momentum=0.9, epsilon=0.001)(x)
    x = Activation("swish")(x)
    x = Dropout(0.4)(x)
    x = DepthwiseConv2D(3, padding="same", strides=1, use_bias=False, depthwise_initializer=CONV_KERNEL_INITIALIZER)(x)
    x = BatchNormalization(axis=channel_axis, momentum=0.9, epsilon=0.001)(x)
    x = Activation("swish")(x)
    x = Conv2D(nb_filter * k, (3, 3), padding='same', use_bias=False, kernel_initializer=CONV_KERNEL_INITIALIZER)(x)
    x = BatchNormalization(axis=channel_axis, momentum=0.9, epsilon=0.001)(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = Add()([x, residual])
    return x

def mbconv_block(init, nb_filter, k=1):
    x = Conv2D(nb_filter * k, (1, 1), strides=(1, 1), padding='valid', use_bias=False, kernel_initializer=CONV_KERNEL_INITIALIZER)(init)
    x = BatchNormalization(axis=channel_axis, momentum=0.9, epsilon=0.001)(x)
    x = Activation("swish")(x)
    x = DepthwiseConv2D(3, padding="same", strides=1, use_bias=False, depthwise_initializer=CONV_KERNEL_INITIALIZER)(x)
    x = BatchNormalization(axis=channel_axis, momentum=0.9, epsilon=0.001)(x)
    x = Activation("swish")(x)
    x = scse(x)
    x = Conv2D(nb_filter * k, (1, 1), strides=(1, 1), padding='valid', use_bias=False, kernel_initializer=CONV_KERNEL_INITIALIZER)(x)
    x = BatchNormalization(axis=channel_axis, momentum=0.9, epsilon=0.001)(x)
    x = Dropout(0.2, noise_shape=(None, 1, 1, 1))(x)
    x = Add()([init, x])
    return x

def scse(input_x, se_ratio=4):
    h_axis, w_axis = [1, 2]
    filters = input_x.shape[channel_axis]
    reduction = filters // se_ratio
    # se = GlobalAveragePooling2D()(inputs)
    # se = Reshape((1, 1, filters))(se)
    se = tf.reduce_mean(input_x, [h_axis, w_axis], keepdims=True)
    se = Conv2D(reduction, kernel_size=1, use_bias=True, kernel_initializer=CONV_KERNEL_INITIALIZER)(se)
    # se = PReLU(shared_axes=[1, 2])(se)
    se = Activation("swish")(se)
    se = Conv2D(filters, kernel_size=1, use_bias=True, kernel_initializer=CONV_KERNEL_INITIALIZER)(se)
    se = Activation("sigmoid")(se)
    return Multiply()([input_x, se])
# when to use in Network
x = fused_like_MBconv(x1, nb_filter[i], k)
x = mbconv_block(x, k, nb_filter[i])
x = mbconv_block(x, k, nb_filter[i])


SCSE layerはそのまま、EfficientNet-v2のを使った。

ネットワークはちょっと公開できない。

3.精度(arcfaceあり)

122 labelの画像分類課題で、さらに11種のcolorのメタ情報を画像から分類するSIGNATEのコンペをタスクにして、11 labelの分類問題を解かせてみた。

データリークありや特定のラベルのデータがない上に、職人じゃなければ、普通の人間が画像をみても何が色の基準を表してるのかほぼ判別不可能なハードル高めな分類問題をend2endで解かせてみる。

難易度が高いので、arcfaceを使ってる。なので普通に解くよりも精度はよくなってる。


色の判別表

普通のEfficientNet-V2 (B2でpretrainなし)の精度(arcfaceあり)

  
Total params12,925,406
Trainable params 12,839,598
Non-trainable params 85,808
精度 88.02%


自作Layer付きCNNの判別精度(arcfaceあり)

  
Total params13,009,536
Trainable params 12,985,024
Non-trainable params 24,512
精度 86.21%


NASのパラメータ探索をしてないけど、かなり近い精度まで持ってけた上、他の試作Layerの中で一番精度が良かった。
NASの探索パラメータの、組み合わせは他に転用がしづらいので使わなかった。

blackごとにoutputを2倍にしていく手法は変わらないし、Layerの多重重ね技もできないけど、転用可能な優秀なレイヤーができた。



参考

2021年最強になるか!?最新の画像認識モデルEfficientNetV2を解説

MobileNet(v1,v2,v3)を簡単に解説してみた