deepinsight / insightface

State-of-the-art 2D and 3D Face Analysis Project
https://insightface.ai
22.86k stars 5.35k forks source link

what tool did you use to convert mxnet to caffe ? #67

Closed GarrickLin closed 6 years ago

GarrickLin commented 6 years ago

I guess you are using MXNet2Caffe and it hard coded batchnorm eps as 0.001 but eps=2e-05 in mxnet. I will test it.

nttstar commented 6 years ago

@GarrickLin Thank you. I didn't find out it. Please tell me the result once you finish it~

GarrickLin commented 6 years ago

After replacing eps from 0.001 to 2e-05 in prototxt file, LFW result improved at 99.50%. There is still remaining some difference.

nttstar commented 6 years ago

Can you share the converting scripts here?

GarrickLin commented 6 years ago

model.prototxt.txt

nttstar commented 6 years ago

@GarrickLin I mean the modified MXNet2Caffe program, can you share it? At least the input layers, PRelu layers must be adjusted to match our pretrained model.

GarrickLin commented 6 years ago

GarrickLin/MXNet2Caffe/blob/master/prototxt_basic.py

Or you can just replace all 0.001 to 2e-05 in model.prototxt.

nttstar commented 6 years ago

@GarrickLin Thank you very much. Then other caffe guys can use it.

GarrickLin commented 6 years ago

Can you achieve the same result as mxnet model after modifying eps ?

nttstar commented 6 years ago

@GarrickLin I do not have time to test using Caffe model... I think someone else may want to.

GarrickLin commented 6 years ago

GarrickLin/MXNet2Caffe/blob/master/mxnet2caffe.py

I have fix the prelu support, and now the results are exactly the same.

nttstar commented 6 years ago

@GarrickLin Very promising, thank you! Which model did you test? Resnet50?

nttstar commented 6 years ago

@GarrickLin Can I copy your code to this repo?

GarrickLin commented 6 years ago

Yes you can

GarrickLin commented 6 years ago

I have just tested with LResNet34E-IR

anguoyang commented 6 years ago

hi@GarrickLin @nttstar, thank you all for your great help. I have tried your tool to convert LResNet50, it generated only the input layer for caffe:

name: "mxnet-mdoel" layer { name: "data" type: "Input" top: "data" input_param { shape: { dim: 1 dim: 3 dim: 64 dim: 64 } } }

nttstar commented 6 years ago

@GarrickLin Can you help?

ysc703 commented 6 years ago

@GarrickLin @nttstar I got the same file like anguoyang, and the message is as follow: 0, op:null , name:data -> data 1, op:_copy , name:id -> id use shared weight -> data {'bottom': ['data'], u'inputs': [[0, 0, 0]], u'name': u'id', u'op': u'copy', 'params': ['data'], 'share': True, 'top': u'id'} Warning! Unknown mxnet op:_copy_

Can you give more details about how to convert the insightface model from mxnet to caffe? Thank a lot!

YoWhatever commented 6 years ago

@ysc703 Same problem! @GarrickLin could you help?

GarrickLin commented 6 years ago

I am really busy nowadays. I'll take care of this as soon as I have time.

myfighterforever commented 6 years ago

@YoWhatever @ysc703 @anguoyang I have met the same problem. Did you fix it?

GarrickLin commented 6 years ago

LResNet50.prototxt.txt what you need to do is just skip those layers

ysc703 commented 6 years ago

@GarrickLin Thanks for the the proto file and the recommendation. It worked after I added some codes in json2prototxt.py and prototxt_basic.py as fellow: In json2prototxt.py _if str(node_i['op']) == '_copy' or str(node_i['op']) == '_minus_scalar' or \ str(node_i['op']) == '_mul_scalar' or str(nodei['op']) == 'Dropout': continue In prototxt_basic.py _if info[attrstr]['act_type'] == 'prelu': ... txtfile.write(' type: "PReLU"\n')

Although the bottom names of conv0 layer and pre_fc1 layer need to be modified, it is really nice. Thanks a lot!

aitaoquanyi commented 6 years ago

@ysc703 can you share your modify code? thanks!

ewrfcas commented 6 years ago

maybe this: in "json2prototxt.py": if str(node_i['op']) == '_copy' or str(node_i['op']) == '_minus_scalar' or str(node_i['op']) == 'mul_scalar' or str(node_i['op']) == '_mul_scalar' or str(node_i['op']) == 'Dropout' or (str(node_i['op']) == 'null' and str(node_i['name']) != 'data'): continue

in "prototxt_basic.py": def LeakyReLU(txt_file, info): if info[attrstr]['act_type'] == 'prelu': txt_file.write('layer {\n') txt_file.write(' bottom: "%s"\n' % info['bottom'][0]) txt_file.write(' top: "%s"\n' % info['top']) txt_file.write(' name: "%s"\n' % info['top']) txt_file.write(' type: "PReLU"\n') txt_file.write('}\n') txt_file.write('\n') else: raise Exception("unsupported Activation")

I am not sure about whether "elu_param { alpha: 0.25 }" is required for PReLU. The bottom names of conv0 and pre_fc1 should be change to "data" and "bn1", because some layers are removed.

class8hawk commented 6 years ago

@ewrfcas thanks

GarrickLin commented 6 years ago

MXNet2Caffe is updated now

GarrickLin commented 6 years ago

@ewrfcas yes you should manually modify the prototxt file

nwdxbx commented 6 years ago

@nttstar @GarrickLin when I use your MXNet2Caffe code to convert mxnet LMobileNetE to caffe . It appear: Check failed: status == CUDNN_STATUS_SUCCESS (4 vs. 0) CUDNN_STATUS_INTERNAL_ERROR. But when I convert mxnet model-r50-am-lfw to caffe,it's good. Did you fix it?

GarrickLin commented 6 years ago

@xubenxiang Sorry, I didn't try LMobileNetE.

nwdxbx commented 6 years ago

@GarrickLin when you free,can you try it. Thanks

anguoyang commented 6 years ago

@xubenxiang I recommend you to use mxnet instead, as the conversion tools are always with bugs.

GarrickLin commented 6 years ago

@xubenxiang where is the model file ?

nwdxbx commented 6 years ago

@GarrickLin I'm sorry. I don't know how can give you the model file. I planed use github,the github's file size limit of 100.00MB,but my param file is 115.8M. External network is restricted too.

GarrickLin commented 6 years ago

@xubenxiang LMobileNetE has depthwise convolution which is not well optimized in caffe. Make sure you really need this model in caffe, or you can get faster performance in mxnet.

nwdxbx commented 6 years ago

@GarrickLin Thank you very much.I'll give up LMobileNetE

WeicongChen commented 6 years ago

This line is wrong @GarrickLin https://github.com/GarrickLin/MXNet2Caffe/blob/d77bc61c99e3fbc03e79bcccfac31aa0827de2fe/prototxt_basic.py#L34 When no_bias is true, bias_term should be false.

GarrickLin commented 6 years ago

@juicecwc thank you, will you submit a PR ?

WeicongChen commented 6 years ago

ok.

nwdxbx commented 6 years ago

@GarrickLin Have you test the caffe model? I test the pretrained caffe-r34-amf model,but the accruacy is very low. Probe score matrix size: 3530 3530 distractor score matrix size: 3530 1000000 Done loading. Time to compute some stats! Finding top distractors! Done sorting distractor scores Making gallery! Done Making Gallery! Allocating ranks (1000080) Rank 1: 0.232038 I don't kown where is wrong?can you give me some advice?

GarrickLin commented 6 years ago

@xubenxiang I didn't run a LFW or megaface benchmark. But I have tested with the output of caffe and mxnet models, the results are exactly the same for the first 5~6 decimal places. You can try following tips:

  1. try to test the output of both model with the same image input
  2. make sure you did a preprocessing before sending an image tensor to caffe model, since mxnet doing the normlization during inference, this might be a little bit difference
  3. make sure your input data layout is NCHW, which is the same as mxnet but different with traditional caffe model
nwdxbx commented 6 years ago

@GarrickLin I got feature code is here: def do_flip(data): for idx in xrange(data.shape[0]): data[idx,:,:] = np.fliplr(data[idx,:,:])

class Resnet_caffe(object): def init(self,deploy_net=deploy_net,caffe_model=caffe_model): caffe.set_device(0) caffe.set_mode_gpu() self.net = caffe.Net(deploy_net,caffe_model,caffe.TEST)

def get_feature(self,img):
    img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
    img = cv2.resize(img,(112,112))
    #img = img/127.5 -1
    img = np.transpose(img,(2,0,1))

    embedding = None
    for flipid in [0,1]:
        _img = np.copy(img)
        if flipid==1:
            do_flip(_img)
        #self.net.blobs['data'].data[0,...] = _img  #np.expand_dims(_img,axis=0)
        self.net.blobs['data'].data[...] = np.expand_dims(_img,axis=0)
        out = self.net.forward()
        _embedding = self.net.blobs['fc1'].data[0].flatten()
        if embedding is None:
            embedding = _embedding
        else:
            embedding +=_embedding
    _norm = np.linalg.norm(embedding)
    embedding /= _norm

    return embedding

do you find some wrong?

GarrickLin commented 6 years ago

you comment this line

#img = img/127.5 -1

which should be uncomment, and fix a bug

img = (img-127.5) / 128.
nwdxbx commented 6 years ago

@GarrickLin 2. since mxnet doing the normlization during inference, this might be a little bit difference but I see in author's code ,I did't find this operator img = img/127.5 -128.This is you say mxnet doing the normlization during inference?

GarrickLin commented 6 years ago

mxnet doing this during inference

img = (img-127.5) / 128.

but caffe not

nwdxbx commented 6 years ago

@GarrickLin I see. Thank you very much.

marcosly commented 6 years ago

@GarrickLin Have you succeed to convert the mobilenetv1 from mxnet to caffe model? The result seems different. Thx

jeehyun100 commented 6 years ago

Hello. I have tried verification.py using your caffe model. Accuracy is 50%. I think I made big mistake in my caffe prediction code. So Can I get source for caffe inferrence you made?

KaleidoZhouYN commented 6 years ago

@marcosly did you find the reason? I found it dosen't work on mobilefacenet model.

marcosly commented 6 years ago

@KaleidoZhouYN it seems that the attr setting doesn't fix well.Some modification need to be done in MXNet2Caffe manually.It could be a large work.So I suggest to train it in caffe framwork