CNTK pre-trained model
We tested some CNTK pre-trained models to others, get more detail from this file
√ - Correctness tested
o - Some difference after conversion
space - not tested
Download CNTK pre-trained model
$ mmdownload -f cntk Supported models: ['resnet18', 'resnet50', 'resnet152', 'resnet101', 'inception_v3', 'Fast-RCNN_Pascal', 'alexnet', 'Fast-RCNN_grocery100'] $ mmdownload -f cntk -n resnet50 -o ./ Downloading file [./ResNet50_ImageNet_CNTK.model] from [https://www.cntk.ai/Models/CNTK_Pretrained/ResNet50_ImageNet_CNTK.model] progress: 100264.0 KB downloaded, 100% Selected GPU GeForce GTX 980 Ti as the process wide default device. Cntk Model resnet50 saved as [./ResNet50_ImageNet_CNTK.model].
Above MMdnn@0.1.4, we provide one command to achieve the conversion
$ mmconvert -sf cntk -iw ResNet50_ImageNet_CNTK.model -df cntk -om cntk_resnet50.dnn --inputShape 3,224,224 . . . CNTK model file is saved as [cntk_resnet50.dnn], generated by [f499918b3e7346a78dbaf02559231d53.py] and [f499918b3e7346a78dbaf02559231d53.npy].
Then you get the CNTK original model cntk_resnet50.dnn converted from CNTK. Temporal files are removed automatically.
Step-by-step conversion (for debugging)
Convert architecture from CNTK to IR (CNTK -> IR)
You can use following bash command to convert the network model(architecture and weights) [ResNet50_ImageNet_CNTK.model] to IR architecture file [resnet50_cntk.pb], [resnet50_cntk.json] and IR weights file [resnet50_cntk.npy]
$ mmtoir -f cntk -n ResNet50_ImageNet_CNTK.model -d resnet50_cntk . . . IR network structure is saved as [resnet50_cntk.json]. IR network structure is saved as [resnet50_cntk.pb]. IR weights are saved as [resnet50_cntk.npy].
Convert models from IR to CNTK code snippet (IR -> CNTK)
You can use following bash command to convert the IR architecture file [resnet50_cntk.pb] and weights file [resnet50_cntk.npy] to CNTK Python code file[cntk_resnet50.py]
$ mmtocode -f cntk -n resnet50_cntk.pb -w resnet50_cntk.npy -d cntk_resnet50.py Parse file [resnet50_cntk.pb] with binary format successfully. Target network code snippet is saved as [cntk_resnet50.py].
Generate CNTK model from code snippet file and weight file
You can use following bash command to generate CNTK model file [cntk_resnet50.dnn] from python code [cntk_resnet50.py] and weights file [resnet50_cntk.npy] for further usage.
$ python -m mmdnn.conversion.examples.cntk.imagenet_test -n cntk_resnet50.py -w resnet50_cntk.npy --dump cntk_resnet50.dnn CNTK model file is saved as [cntk_resnet50.dnn], generated by [cntk_resnet50.py] and [resnet50_cntk.npy].
Ubuntu 16.04 with
- CNTK CPU 2.4
Main dataflow in network is NHWC (channel last) format, but CNTK CNN-related operators take NCHW (channel first) format data. So we transpose the data format before and after each CNN-related operators (such as Convolution, Pooling, LRN, BN and so on). The data transpose sacrifices some computing performance. There is some methods to reduce the performance gap.
Like PyTorch and MXNet emitter, change the main dataflow format to NCHW (channel last) and tranpose the weights in IR-Code step.
Remove unnecessary transpose during building the network.
Currently no RNN-related operations support
Retrain the converted CNTK model
If you want to retrain the converted model, you can change all layers from "Channel Last" to "Channel First" in the converted code file and then change the code in **def batch_normalization(input, name, epsilon, kwargs):
from def batch_normalization(input, name, epsilon, **kwargs): mean = cntk.Parameter(init = _weights_dict[name]['mean'], name = name + "_mean") var = cntk.Parameter(init = _weights_dict[name]['var'], name = name + "_var") layer = (input - mean) / cntk.sqrt(var + epsilon) ...... to def batch_normalization(input, name, epsilon, **kwargs): layer = cntk.layers.BatchNormalization( map_rank = 1, name=name )(input) mean = cntk.Parameter(init = _weights_dict[name]['mean'], name = name + "_mean") layer.aggregate_mean = mean var = cntk.Parameter(init = _weights_dict[name]['var'], name = name + "_var") layer.aggregate_variance = var layer.aggregate_count = 4096.0 ......
Thanks to this issue