Source code for akida_models.kws.model_ds_cnn

#!/usr/bin/env python
# ******************************************************************************
# Copyright 2020 Brainchip Holdings Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ******************************************************************************
"""
DS-CNN model definition for KWS classification.
"""

__all__ = ["ds_cnn_kws", "ds_cnn_kws_pretrained"]

from keras import Model
from keras.layers import (Input, Reshape, Activation, Flatten, Rescaling)

from ..layer_blocks import conv_block, separable_conv_block, dense_block
from ..utils import fetch_file, get_params_by_version
from ..model_io import load_model, get_model_path


[docs]def ds_cnn_kws(input_shape=(49, 10, 1), classes=33, include_top=True, input_scaling=(255, 0)): """Instantiates a MobileNet-like model for the "Keyword Spotting" example. This model is based on the MobileNet architecture, mainly with fewer layers. The weights and activations are quantized such that it can be converted into an Akida model. This architecture is originated from https://arxiv.org/pdf/1711.07128.pdf and was created for the "Keyword Spotting" (KWS) or "Speech Commands" dataset. Note: input preprocessing is included as part of the model (as a Rescaling layer). This model expects inputs to be float tensors of pixels with values in the [0, 255] range. Args: input_shape (tuple, optional): input shape tuple of the model. Defaults to (49, 10, 1). classes (int, optional): optional number of classes to classify words into, only be specified if `include_top` is True. Defaults to 33. include_top (bool, optional): whether to include the classification layer at the top of the model. Defaults to True. input_scaling (tuple, optional): scale factor and offset to apply to inputs. Defaults to (255, 0). Note that following Akida convention, the scale factor is an integer used as a divisor. Returns: keras.Model: a Keras model for MobileNet/KWS """ if include_top and not classes: raise ValueError("If 'include_top' is True, 'classes' must be set.") # Model version management fused, post_relu_gap, relu_activation = get_params_by_version() img_input = Input(shape=input_shape, name="input") if input_scaling is None: x = img_input else: scale, offset = input_scaling x = Rescaling(1. / scale, offset, name="rescaling")(img_input) x = conv_block(x, filters=64, kernel_size=(5, 5), padding='same', strides=(2, 2), use_bias=False, name='conv_0', add_batchnorm=True, relu_activation=relu_activation) x = separable_conv_block(x, filters=64, kernel_size=(3, 3), padding='same', use_bias=False, name='separable_1', add_batchnorm=True, fused=fused, relu_activation=relu_activation) x = separable_conv_block(x, filters=64, kernel_size=(3, 3), padding='same', use_bias=False, name='separable_2', add_batchnorm=True, fused=fused, relu_activation=relu_activation) x = separable_conv_block(x, filters=64, kernel_size=(3, 3), padding='same', use_bias=False, name='separable_3', add_batchnorm=True, fused=fused, relu_activation=relu_activation) x = separable_conv_block(x, filters=64, kernel_size=(3, 3), padding='same', use_bias=False, name='separable_4', pooling='global_avg', add_batchnorm=True, fused=fused, post_relu_gap=post_relu_gap, relu_activation=relu_activation) shape = (1, 1, int(64)) x = Reshape(shape, name='reshape_1')(x) if include_top: x = Flatten(name="flatten")(x) x = dense_block(x, units=classes, name='dense_5', use_bias=True, relu_activation=False) act_function = 'softmax' if classes > 1 else 'sigmoid' x = Activation(act_function, name=f'act_{act_function}')(x) return Model(img_input, x, name='ds_cnn_kws')
[docs]def ds_cnn_kws_pretrained(quantized=True): """ Helper method to retrieve a `ds_cnn_kws` model that was trained on KWS dataset. Args: quantized (bool, optional): a boolean indicating whether the model should be loaded quantized or not. Defaults to True. Returns: keras.Model: a Keras Model instance. """ if quantized: model_name_v1 = 'ds_cnn_kws_iq8_wq4_aq4_laq1.h5' file_hash_v1 = '2ba6220bb9545857c99a327ec14d2d777420c7848cb6a9b17d87e5a01951fe6f' model_name_v2 = 'ds_cnn_kws_edge_i8_w4_a4.h5' file_hash_v2 = '02a6b5c5496e8ef8fb576ee7b2833427ebdd7a70df26cc87db5e416f756042d5' else: model_name_v1 = 'ds_cnn_kws.h5' file_hash_v1 = '95a51677b340ee2420015a8576a8aaf41e84138ac0334cd42080b60499b4f146' model_name_v2 = 'ds_cnn_kws.h5' file_hash_v2 = '54a4071833ef2f0a2da4fd300c2d1534acf211ee7e2838c7f55df5135cf4a8c4' model_path, model_name, file_hash = get_model_path("ds_cnn", model_name_v1, file_hash_v1, model_name_v2, file_hash_v2) model_path = fetch_file(model_path, fname=model_name, file_hash=file_hash, cache_subdir='models') return load_model(model_path)