gmalivenko / onnx2keras

Convert ONNX model graph to Keras model format.
MIT License
193 stars 114 forks source link

Edits needed to make it work for my model #29

Open tsvetiko opened 4 years ago

tsvetiko commented 4 years ago

I needed to do the following changes in order to make it work for tensorflow1.15 / python3.6:

  1. In /home/user/venv/tensorflow1.15/lib/python3.6/site-packages/onnx2keras/operation_layers.py:
import numpy as np

def convert_cast(node, params, layers, node_name, keras_name):
    """
    Convert Cast layer
    :param node: current operation node
    :param params: operation attributes
    :param layers: available keras layers
    :param node_name: internal converter name
    :param keras_name: resulting layer name
    :return: None
    """
    logger = logging.getLogger('onnx2keras:cast')

    if len(node.input) != 1:
        assert AttributeError('More than 1 input for cast layer.')

    if is_numpy(layers[node.input[0]]):

    ...
  1. In /home/user/venv/tensorflow1.15/lib/python3.6/site-packages/onnx2keras/reshape_layers.py:
def convert_slice(node, params, layers, node_name, keras_name):
    """
    Convert slice.
    :param node: current operation node
    :param params: operation attributes
    :param layers: available keras layers
    :param node_name: internal converter name
    :param keras_name: resulting layer name
    :return: None
    """
    logger = logging.getLogger('onnx2keras:slice')

    if len(node.input) != 1:
        raise AttributeError('Number of inputs is not equal 1 for slice layer')

    logger.debug('Convert inputs to Keras/TF layers if needed.')

    if isinstance(layers[node.input[0]], np.ndarray):
        for i in range(len(layers[node.input[0]])):
            layers[node.input[0]][i] = str(layers[node.input[0]][i])

    ...
  1. In /home/user/venv/tensorflow1.15/lib/python3.6/site-packages/onnx2keras/upsampling_layers.py:
import tensorflow as tf

def convert_upsample(node, params, layers, node_name, keras_name):
    """
    Convert upsample.
    :param node: current operation node
    :param params: operation attributes
    :param layers: available keras layers
    :param node_name: internal converter name
    :param keras_name: resulting layer name
    :return: None
    """
    logger = logging.getLogger('onnx2keras:upsample')
    logger.warning('!!! EXPERIMENTAL SUPPORT (upsample) !!!')

    if len(node.input) > 2:
        raise AttributeError('Unsupported number of inputs')

    if params['mode'].decode('utf-8') == 'linear':
        sess = tf.InteractiveSession()
        scales = layers[node.input[1]].eval()
        scale = (int(scales[2]), int(scales[3]))
        sess.close()

        upsampling = keras.layers.UpSampling2D(
            size=scale, name=keras_name, interpolation="bilinear"
        )

        layers[node_name] = upsampling(layers[node.input[0]])
    elif params['mode'].decode('utf-8') == 'nearest':
        scale = np.uint8(params['scales'][-2:])

        upsampling = keras.layers.UpSampling2D(
            size=scale, name=keras_name
        )

        layers[node_name] = upsampling(layers[node.input[0]])
    else:
        logger.error('Cannot convert non-linear/non-nearest upsampling.')
        raise AssertionError('Cannot convert non-linear/non-nearest upsampling')
  1. In /home/user/venv/tensorflow1.15/lib/python3.6/site-packages/onnx2keras/operation_layers.py:
def convert_cast(node, params, layers, node_name, keras_name):
    """
    Convert Cast layer
    :param node: current operation node
    :param params: operation attributes
    :param layers: available keras layers
    :param node_name: internal converter name
    :param keras_name: resulting layer name
    :return: None
    """
    logger = logging.getLogger('onnx2keras:cast')

    if len(node.input) != 1:
        assert AttributeError('More than 1 input for cast layer.')

    if is_numpy(layers[node.input[0]]):
        logger.debug('Cast numpy array')

        cast_map = {
            1: np.float32,
            2: np.uint8,
            3: np.int8,
            5: np.int16,
            6: np.int32,
            7: np.int64,
            9: np.bool,
            10: np.float16,
            11: np.double,
        }

        for i in range(len(layers[node.input[0]])):
            layers[node.input[0]][i] = str(layers[node.input[0]][i])
        layers[node_name] = cast_map[params['to']](layers[node.input[0]])
    else:
        input_0 = ensure_tf_type(layers[node.input[0]], name="%s_const" % keras_name)

        def target_layer(x, dtype=params['to']):
            import tensorflow as tf
            cast_map = {
                1: tf.float32,
                2: tf.uint8,
                3: tf.int8,
                5: tf.int16,
                6: tf.int32,
                7: tf.int64,
                9: tf.bool,
                10: tf.float16,
                11: tf.double,
            }
            if x.dtype=='string':
                return tf.strings.to_number(x, out_type=cast_map[dtype])
            return tf.cast(x, cast_map[dtype])

        lambda_layer = keras.layers.Lambda(target_layer, name=keras_name)
        layers[node_name] = lambda_layer(input_0)
karam-nus commented 4 years ago

Can you please highlight the model design? what exactly was the INP to the upsampling layer in ONNX model? thanks!