(builder, node, graph, err)
convert to CoreML SoftMax ND Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#3547
convert to CoreML SoftMax ND Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#3547
convert to CoreML SoftMax ND Layer : https : // github . com / apple / coremltools / blob / 655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492 / mlmodel / format / NeuralNetwork . proto#3547
def _convert_softmax(builder, node, graph, err):
    '''
    convert to CoreML SoftMax ND Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#3547
    '''
    def add_softmax(output_name, rank=-1, axis=-3):
        softmax_axis = 3
        axes = list(range(5-rank))
        if axis < 0:
            axis = rank + axis
        axis += len(axes)
        softmax_output_name = output_name+'_expanded'
        
        expanded_node = node.name + '_' + node.inputs[0] + '_expanded'
        builder.add_expand_dims(
            name=node.name+'_expand_dims',
            input_name=node.inputs[0],
            output_name=expanded_node,
            axes=axes
        )
        input_name = expanded_node
        rank = 5

        if axis != -3 and axis != rank - softmax_axis:
            transpose_axes = list(range(rank))
            transpose_axes[-3], transpose_axes[axis] = transpose_axes[axis], transpose_axes[-3]

            builder.add_transpose(
                name=node.name + '_transpose',
                axes=transpose_axes,
                input_name=input_name,
                output_name=input_name+'_transposed'
            )
            input_name += '_transposed'
            softmax_output_name += '_transposed'
        
        builder.add_softmax(
            name=node.name,
            input_name=input_name,
            output_name=softmax_output_name
        )

        if axis != -3 and axis != rank - softmax_axis:
            transpose_axes = list(range(rank))
            transpose_axes[-3], transpose_axes[axis] = transpose_axes[axis], transpose_axes[-3]

            builder.add_transpose(
                name=node.name+'_transpose_back',
                axes=transpose_axes,
                input_name=softmax_output_name,
                output_name=softmax_output_name + '_transposed_back'
            )
            softmax_output_name += '_transposed_back'
        
        builder.add_squeeze(
            name=node.name+'_squeeze_dims',
            input_name=softmax_output_name,
            output_name=output_name,
            axes=axes
        )

    axis = node.attrs.get('axis', 1)
    rank = builder._get_rank(node.inputs[0])
    if rank == -1:
        return _convert_softmax_nd(builder, node, graph, err)

    if node.op_type == 'LogSoftmax':
        add_softmax(node.outputs[0] + '_softmax', rank=rank, axis=axis)
        builder.add_unary(
            name=node.name+'_log',
            input_name=node.outputs[0] + '_softmax',
            output_name=node.outputs[0],
            mode='log'
        )
    else:
        add_softmax(node.outputs[0], rank=rank, axis=axis)
def _convert_softmax ( builder , node , graph , err ) : def add_softmax ( output_name , rank = - 1 , axis = - 3 ) : softmax_axis = 3 axes = list ( range ( 5 - rank ) ) if axis < 0 : axis = rank + axis axis += len ( axes ) softmax_output_name = output_name + '_expanded' expanded_node = node . name + '_' + node . inputs [ 0 ] + '_expanded' builder . add_expand_dims ( name = node . name + '_expand_dims' , input_name = node . inputs [ 0 ] , output_name = expanded_node , axes = axes ) input_name = expanded_node rank = 5 if axis != - 3 and axis != rank - softmax_axis : transpose_axes = list ( range ( rank ) ) transpose_axes [ - 3 ] , transpose_axes [ axis ] = transpose_axes [ axis ] , transpose_axes [ - 3 ] builder . add_transpose ( name = node . name + '_transpose' , axes = transpose_axes , input_name = input_name , output_name = input_name + '_transposed' ) input_name += '_transposed' softmax_output_name += '_transposed' builder . add_softmax ( name = node . name , input_name = input_name , output_name = softmax_output_name ) if axis != - 3 and axis != rank - softmax_axis : transpose_axes = list ( range ( rank ) ) transpose_axes [ - 3 ] , transpose_axes [ axis ] = transpose_axes [ axis ] , transpose_axes [ - 3 ] builder . add_transpose ( name = node . name + '_transpose_back' , axes = transpose_axes , input_name = softmax_output_name , output_name = softmax_output_name + '_transposed_back' ) softmax_output_name += '_transposed_back' builder . add_squeeze ( name = node . name + '_squeeze_dims' , input_name = softmax_output_name , output_name = output_name , axes = axes ) axis = node . attrs . get ( 'axis' , 1 ) rank = builder . _get_rank ( node . inputs [ 0 ] ) if rank == - 1 : return _convert_softmax_nd ( builder , node , graph , err ) if node . op_type == 'LogSoftmax' : add_softmax ( node . outputs [ 0 ] + '_softmax' , rank = rank , axis = axis ) builder . add_unary ( name = node . name + '_log' , input_name = node . outputs [ 0 ] + '_softmax' , output_name = node . outputs [ 0 ] , mode = 'log' ) else : add_softmax ( node . outputs [ 0 ] , rank = rank , axis = axis )