sassoftware / python-dlpy

The SAS Deep Learning Python (DLPy) package provides the high-level Python APIs to deep learning methods in SAS Visual Data Mining and Machine Learning. It allows users to build deep learning models using friendly Keras-like APIs.
Apache License 2.0
224 stars 131 forks source link

Export ONNX #331

Open vorodrigues opened 4 years ago

vorodrigues commented 4 years ago

Hi,

When you try to export a model in ONNX format, the deploy method expects the InputLayer parameters height and n_channels not to be None, even though they are meant to be used only with image data.

It would be nice not to have to specify dummy values for them when training RNNs and DNNs for example.

Best regards, Victor

dxq77dxq commented 4 years ago

Hi Victor,

Thanks for bringing this topic up. width, height and n_channels are only needed for CNN models. If the model is RNN (meaning there is at least one Recurrent layer) then these parameters can be None.

Thanks, Maggie

dxq77dxq commented 4 years ago

Hi Victor,

Please let me know if the answer solves the question and we can close the issue.

Thanks, Maggie

vorodrigues commented 4 years ago

Hi Maggie,

Thanks a lot for your answer! I raised this issue because I trained a RNN for a sentiment analysis task and then tried to export it in ONNX format:

model1.deploy(path='/models', output_format='onnx')

And got the following error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-20-6a07ec717e1a> in <module>
----> 1 model1.deploy(path='/models', output_format='onnx')

~/.local/lib/python3.7/site-packages/dlpy/network.py in deploy(self, path, output_format, model_weights, layers, **kwargs)
   1727             self.save_to_table(path=path)
   1728         elif output_format.lower() == 'onnx':
-> 1729             self.save_to_onnx(path, model_weights=model_weights)
   1730         else:
   1731             raise DLPyError('output_format must be "astore", "castable", "table",'

~/.local/lib/python3.7/site-packages/dlpy/network.py in save_to_onnx(self, path, model_weights)
   1664         onnx_model = sas_to_onnx(layers=self.layers,
   1665                                  model_table=model_table,
-> 1666                                  model_weights=model_weights)
   1667         file_name = self.model_name + '.onnx'
   1668         if path is None:

~/.local/lib/python3.7/site-packages/dlpy/model_conversion/write_onnx_model.py in sas_to_onnx(layers, model_table, model_weights)
     69     for layer in layers:
     70         if layer.type == 'input':
---> 71             H = int(layer.config['height'])
     72             W = int(layer.config['width'])
     73             C = int(layer.config['n_channels'])

TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'

I managed to export it by adding a dummy value to the height and n_channels parameters in the input layer:

model1.add(InputLayer(std='STD', height=0, n_channels=1))

I think that sas_to_onnx code might need some fix to avoid that.

Thanks, Victor

eusdougc commented 4 years ago

Hi Victor - we don't officially support exporting an RNN model to ONNX format. With your work-around, aren't you getting an OnnxWriteError exception for your RNN layers? The error message should be something like

is not supported. Doug
vorodrigues commented 4 years ago

Hi Doug,

You are right! I'm sorry, I made many tests to find a workaround and I forgot to mention it worked with a simple DNN - NOT with the original RNN.

Here it is the code I ran:

model1 = Sequential(sas, model_table=name)
model1.add(InputLayer(std='STD', height=0, n_channels=1))
model1.add(Dense(20, act='relu'))
model1.add(Dense(20, act='relu'))
model1.add(OutputLayer(act='softmax', n=2, error='entropy'))

model1.fit(data=bank[bank['_PartInd_']==1], 
           valid_table=bank[bank['_PartInd_']==2],
           inputs=["duration","campaign","pdays","previous","age","emp_var_rate",
                   "cons_price_idx","cons_conf_idx","euribor3m","nr_employed"],
           target='y',
           nominals='y',
           optimizer=Optimizer(AdamSolver(learning_rate=0.001),
                              mini_batch_size=64,
                              max_epochs=20,
                              log_level=2),
           train_from_scratch=True,
           save_best_weights=True)

model1.deploy(path='/home/sasdemo/poc', output_format='onnx')

Anyways, it's nice to know RNNs aren't supported yet.

Many thanks, Victor