pplonski / keras2cpp

This is a bunch of code to port Keras neural network model into pure C++.
MIT License
679 stars 153 forks source link

TypeError: string indices must be integers #18

Closed xdtl closed 7 years ago

xdtl commented 7 years ago

Thank you for your work! I got the following error by running: python dump_to_simple_cpp.py -a net.json -w net.h5 -o dumped.nnet

Writing to dumped.nnet Traceback (most recent call last): File "dump_to_simple_cpp.py", line 33, in fout.write('layer ' + str(ind) + ' ' + l['class_name'] + '\n') TypeError: string indices must be integers

The error occurred when ind=0. I checked my 'arch["config"]', which is a very long dict and I only show a small part of it here:

{'layers': [{'class_name': 'InputLayer', 'config': {'batch_input_shape': [None, 1, 160, 128], 'input_dtype': 'float32', 'sparse': False, 'name': 'input_1'}, 'inbound_nodes': [], 'name': 'input_1'}, {'class_name': 'Convolution2D', 'config': {'activity_regularizer': None, 'trainable': True, 'dim_ordering': 'th', 'bias': True, 'nb_row': 3, 'b_constraint': None, 'name': 'convolution2d_1', 'W_constraint': None, 'nb_col': 3, 'subsample': [1, 1], 'init': 'glorot_uniform', 'nb_filter': 32, 'border_mode': 'same', 'b_regularizer': None, 'W_regularizer': None, 'activation': 'relu'}, 'inbound_nodes': [[['input_1', 0, 0]]], 'name': 'convolution2d_1'}, {'class_name': 'Convolution2D', 'config': {'activity_regularizer': None, 'trainable': True, 'dim_ordering': 'th', 'bias': True, 'nb_row': 3, 'b_constraint': None, 'name': 'convolution2d_2', 'W_constraint': None, 'nb_col': 3, 'subsample': [1, 1], 'init': 'glorot_uniform', 'nb_filter': 32, 'border_mode': 'same', 'b_regularizer': None, 'W_regularizer': None, 'activation': 'relu'}, 'inbound_nodes': [[['convolution2d_1', 0, 0]]], 'name': 'convolution2d_2'}, ...

It seems the term 'l['class_name']' caused the problem. But I have no clue how to fix it. Could you please give me some suggestions? Thanks!

pplonski commented 7 years ago

Sorry, it is hard to say ... what Keras verison are you using? Do you use theano as backend?

xdtl commented 7 years ago

Thanks for your reply! I don't know which Keras version it is, because I used Amazon AWS to run my code instead of building my own machine. It did show it is using theano backend.

At first, I got 'arch["config"]' like this: {u'layers': [{u'class_name': u'InputLayer', u'inbound_nodes': [], u'config': {u'batch_input_shape': [None, 1, 160, 128], u'sparse': False, u'input_dtype': u'float32', u'name': u'input_1'}, u'name': u'input_1'}, {u'class_name': u'Convolution2D', u'inbound_nodes': [[[u'input_1', 0, 0]]], u'config': {u'W_constraint': None, u'b_constraint': None, u'name': u'convolution2d_1', u'activity_regularizer': None, u'trainable': True, u'dim_ordering': u'th', u'nb_col': 3, u'subsample': [1, 1], u'init': u'glorot_uniform', u'bias': True, u'nb_filter': 32, u'b_regularizer': None, u'W_regularizer': None, u'nb_row': 3, u'activation': u'relu', u'border_mode': u'same'}, u'name': u'convolution2d_1'}, {u'class_name': u'Convolution2D', u'inbound_nodes': [[[u'convolution2d_1', 0, 0]]], ...

There are a lot of 'u'. I searched online and found it was Unicode object. I followed the suggestions to replace your original code "arch = json.loads(arch)" with "arch = yaml.safe_load(arch)" or "arch = simplejson.loads(arch)". Those 'u' disappeared, but the error is still there...

pplonski commented 7 years ago

Try to change line 30:

for ind, l in enumerate(arch["config"]):

to

for ind, l in enumerate(arch["layers"]):

This should help, but for sure it will require more custom changes and I can help with this - sorry! You should change this code by yourself for your needs.

xdtl commented 7 years ago

Thanks very much! This is very helpful. It seems the layout of arch varies from case to case. I tried: for ind, l in enumerate(arch["config"]["layers"]): and got dumped.nnet. But test_run_cnn.cc generated another error: "Layer is empty, maybe it is not defined? Cannot define network." The problem lies in keras_model.cc, keras::KerasModel::load_weights: layer_type =="InputLayer", which doesn't meet any of those if...else... conditions.

I fully understand I am responsible to change it for my own needs. But any directions or suggestions are highly appreciated.