Ceci est le 4ème message de qiita. (article4)
Dans la continuité de la dernière fois, alors que j'utilisais nnabla, j'ai réussi à me sentir comme "J'aurais aimé avoir ce genre d'informations dans qiita" Résumé de ce que j'ai trouvé dans la référence nnabla et dir ()
(fonction python standard, qui renvoie des variables membres et des fonctions d'arguments) Je vais.
-OS: macOS Catalina (version 10.15.1) ・ Python: 3.5.4 ・ Nnabla: 1.3.0
Cette fois, à partir du modèle entraîné de Nnabla, utilisez MobileNet_v1 comme suit.
article4_add_quantization_for_network.py
import nnabla as nn
import nnabla.functions as F
import nnabla.parametric_functions as PF
from nnabla.models.imagenet import MobileNet
if __name__ == "__main__":
# [load network]
mobilenet = MobileNet()
nnp = mobilenet.nnp
net = nnp.get_network('Runtime', batch_size=1)
y = net.outputs['y\'']
nnabla.models
fournit des modèles entraînés comme un réseau de nnabla. Cette fois, nous utiliserons mobilenet_v1 dedans.mobilenet = MobileNet ()
.nnp = mobilenet.nnp
contiendra mobilenet dans la variable nnp
comme lecture du format de fichier de nnabla" .nnp ".nnp
, il dit ['Validation', 'Validation5', 'Runtime', 'Training']
(nnp.get_network_names ()
Cette fois, nous utiliserons Runtime
comme exemple. C'est la partie de net = nnp.get_network ('Validation', batch_size = 1)
.y'
par y = net.outputs ['y \' ']
. Cela sera utilisé plus tard pour vérifier le fonctionnement. Cela n'a rien à voir avec ce que vous essayez de faire cette fois.Ajoutez une couche de quantification à chaque activation, mise en commun et affiliation (sortie d'identification) de mobilenet_v1 obtenu ci-dessus. Le code réel est ci-dessous.
article4_add_quantization_for_network.py
class AddQuantizeLayer:
def __init__(self, _net):
self.net = _net
def add_quantize_layer_all(self):
# [quantize]
count = 0
for key in self.net.variables:
var = self.net.variables[key]
func = var.parent
if type(func) != type(None):
if func.info.type_name in ['ReLU', 'AveragePooling', 'Affine']:
count = self.add_quantize_layer_one(var, count)
def add_quantize_layer_one(self, _var, _count):
var_out_cur = _var.function_references[0].outputs[0]
# [quantize]
q_out = PF.min_max_quantize(_var, ql_min=0, ql_max=255, x_min_max=True, name='MinMaxQuantize_{}'.format(_count))
# [redefine function]
var_out_new = self.redefine_layer(var_out_cur.parent, q_out)
var_out_cur.rewire_on(var_out_new)
return _count + 1
@staticmethod
def redefine_layer(_func, _input):
if _func.info.type_name == 'DepthwiseConvolution':
return F.depthwise_convolution(_input, *_func.inputs[1:], **_func.info.args)
elif _func.info.type_name == 'Convolution':
return F.convolution(_input, *_func.inputs[1:], **_func.info.args)
elif _func.info.type_name == 'AveragePooling':
return F.average_pooling(_input, **_func.info.args)
elif _func.info.type_name == 'Affine':
return F.affine(_input, *_func.inputs[1:], **_func.info.args)
elif _func.info.type_name == 'Softmax':
return F.softmax(_input, **_func.info.args)
else:
print('[error] redefine_layer()')
print('_func is unexpected layer.')
print('_func.info.type_name = {}'.format(_func.info.type_name))
exit(0)
# [quantize]
AddQuantizeLayer_class = AddQuantizeLayer(net)
AddQuantizeLayer_class.add_quantize_layer_all()
Le contrôle de fonctionnement a été effectué ci-dessous.
article4_add_quantization_for_network.py
def print_func(f):
print('{}'.format(f.name))
print('----- before -----')
y.visit(print_func)
print('')
# [quantize]
AddQuantizeLayer_class = AddQuantizeLayer(net)
AddQuantizeLayer_class.add_quantize_layer_all()
print('----- after -----')
y.visit(print_func)
print('')
Puisque la sortie est longue, certaines parties seront omises, mais elles seront sous la forme suivante. En tant que changement, MinMaxQuantize
(couche de quantification) est ajouté après ReLU
, ʻAveragePooling et ʻAffine
.
----- before -----
ImageAugmentation
MulScalar
AddScalar
Convolution
BatchNormalization
ReLU
DepthwiseConvolution
BatchNormalization
ReLU
Convolution
...(Ce qui suit est omis)...
----- after -----
ImageAugmentation
MulScalar
AddScalar
Convolution
BatchNormalization
ReLU
MinMaxQuantize
DepthwiseConvolution
BatchNormalization
ReLU
MinMaxQuantize
Convolution
...(Ce qui suit est omis)...
. Pour donner un aperçu du processus, nous vérifions ici chaque variable du réseau, et si c'est la variable à laquelle la couche de quantification doit être ajoutée (
ReLU, ʻAveragePooling
, ʻAffine output), ʻAddQuantizeLayer.add_quantize_layer_one
Ajoutez une couche de quantification par.self.net.variables
est le dict
de toutes les variables réseau. ʻAddQuantizeLayer.add_quantize_layer_alll'utilise pour vérifier chaque variable du réseau. Ici,
var.parent obtient la couche qui produit la variable, et
func.info.type_name` obtient le nom de cette couche. utilise
var_out_new = self.redefine_layer (var_out_cur.parent, q_out) pour redéfinir la quantification et les fonctions suivantes. Si vous utilisez
rewire_on, une variable sera écrasée et disparaîtra, c'est donc une contre-mesure. Plus précisément, pour la partie où la connexion de couche est
...-> ReLU-> Convolution-> ..., branchez et connectez avec
...-> ReLU-> MinMax Quantize. Ensuite, vous ne pouvez pas vous connecter comme
...-> MinMaxQuantize-> Convolution-> ...(car
rewire_onnécessite l'écrasement d'une variable). À ce stade, créez le même calque que la
Convolution existante après
MinMaxQuantize, définissez
...-> MinMaxQuantize-> Convolution (new) , puis changez la
Convolution existante en
Convolution (new) . En écrasant avec
, la connexion de` ...-> MinMaxQuantize-> Convolution-> ... ʻest finalement réalisée. (Je voudrais l'expliquer dans la figure.)définit exactement la même couche que celle existante pour gérer le problème ci-dessus.
_input est la variable quantifiée (
nn.Variable),
_func.inputs [1:] est l'autre variable d'entrée (
nn.Variable) (cette fois le coefficient tel que conv),
_func. info.args` est l'autre argument (foulée, remplissage, etc.).En utilisant le contenu publié jusqu'à Dernière fois, j'ai présenté comment ajouter une couche de quantification à un réseau existant. On ne sait pas quoi publier la prochaine fois.