Module furiosa.quantizer.frontend.onnx.transformer.deprecated.eliminate_softmax_output

Expand source code
import onnx

from furiosa_sdk_quantizer.interfaces.transformer import Transformer
from furiosa_sdk_quantizer.frontend.onnx.transformer import utils
from furiosa_sdk_quantizer.frontend.onnx.utils.check_model import check_model


class EliminateSoftmaxOutput(Transformer):
    """
    from: Softmax -> graph_output
    to: graph_output
    """

    def transform(self, model: onnx.ModelProto) -> onnx.ModelProto:
        model = self.remove_softmax_new_pattern(model)
        model = self.remove_softmax_old_pattern(model)
        return model

    def remove_softmax_new_pattern(self, model):
        nodes_by_output_name = {node_output: node for node in model.graph.node for node_output in node.output}
        vi_by_output_name = {vi.name: vi for vi in model.graph.value_info}
        outputs_by_output_name = {output.name: output for output in model.graph.output}

        optimized_nodes = []
        removed_nodes = []

        for node in model.graph.node:
            if node in removed_nodes:
                continue

            if node.op_type != 'Transpose':
                optimized_nodes.append(node)
                continue

            if node.output[0] not in outputs_by_output_name.keys():
                optimized_nodes.append(node)
                continue

            prev_node = nodes_by_output_name[node.input[0]]
            if prev_node.op_type != 'Softmax':
                optimized_nodes.append(node)
                continue

            pprev_node = nodes_by_output_name[prev_node.input[0]]
            if pprev_node.op_type != 'Transpose':
                optimized_nodes.append(node)
                continue

            output_node = outputs_by_output_name[node.output[0]]
            removed_nodes.extend([node, prev_node, pprev_node])
            model.graph.output.remove(output_node)

            # Graph must have at least one graph output
            if not len(model.graph.output):
                ppprev_node = nodes_by_output_name[pprev_node.input[0]]
                model.graph.output.append(vi_by_output_name[ppprev_node.output[0]])

        # remove duplicate node(s) in optimized nodes
        seen = []
        for op_node in optimized_nodes:
            if op_node in seen:
                continue
            seen.append(op_node)
        optimized_nodes = seen

        new_nodes = list(filter(lambda node: node not in removed_nodes, optimized_nodes))
        model = utils.rebuild_model(model, new_nodes)
        check_model(model)

        return model

    def remove_softmax_old_pattern(self, model):
        nodes_by_output_name = {node.output[0]: node for node in model.graph.node}
        vi_by_output_name = {vi.name: vi for vi in model.graph.value_info}
        outputs_by_output_name = {output.name: output for output in model.graph.output}

        optimized_nodes = []
        removed_nodes = []

        for node in model.graph.node:
            if node.op_type != 'Softmax':
                optimized_nodes.append(node)
                continue

            # Softmax must be graph output
            if node.output[0] not in outputs_by_output_name.keys():
                optimized_nodes.append(node)
                continue

            output_node = outputs_by_output_name[node.output[0]]
            removed_nodes.append(node)
            model.graph.output.remove(output_node)

            # Graph must have at least one graph output
            if not len(model.graph.output):
                prev_node = nodes_by_output_name[node.input[0]]
                model.graph.output.append(vi_by_output_name[prev_node.output[0]])

        # remove duplicate node(s) in optimized nodes
        seen = []
        for op_node in optimized_nodes:
            if op_node in seen:
                continue
            seen.append(op_node)
        optimized_nodes = seen

        new_nodes = list(filter(lambda node: node not in removed_nodes, optimized_nodes))
        model = utils.rebuild_model(model, new_nodes)
        check_model(model)

        return model

Classes

class EliminateSoftmaxOutput (*args, **kwds)

from: Softmax -> graph_output to: graph_output

Expand source code
class EliminateSoftmaxOutput(Transformer):
    """
    from: Softmax -> graph_output
    to: graph_output
    """

    def transform(self, model: onnx.ModelProto) -> onnx.ModelProto:
        model = self.remove_softmax_new_pattern(model)
        model = self.remove_softmax_old_pattern(model)
        return model

    def remove_softmax_new_pattern(self, model):
        nodes_by_output_name = {node_output: node for node in model.graph.node for node_output in node.output}
        vi_by_output_name = {vi.name: vi for vi in model.graph.value_info}
        outputs_by_output_name = {output.name: output for output in model.graph.output}

        optimized_nodes = []
        removed_nodes = []

        for node in model.graph.node:
            if node in removed_nodes:
                continue

            if node.op_type != 'Transpose':
                optimized_nodes.append(node)
                continue

            if node.output[0] not in outputs_by_output_name.keys():
                optimized_nodes.append(node)
                continue

            prev_node = nodes_by_output_name[node.input[0]]
            if prev_node.op_type != 'Softmax':
                optimized_nodes.append(node)
                continue

            pprev_node = nodes_by_output_name[prev_node.input[0]]
            if pprev_node.op_type != 'Transpose':
                optimized_nodes.append(node)
                continue

            output_node = outputs_by_output_name[node.output[0]]
            removed_nodes.extend([node, prev_node, pprev_node])
            model.graph.output.remove(output_node)

            # Graph must have at least one graph output
            if not len(model.graph.output):
                ppprev_node = nodes_by_output_name[pprev_node.input[0]]
                model.graph.output.append(vi_by_output_name[ppprev_node.output[0]])

        # remove duplicate node(s) in optimized nodes
        seen = []
        for op_node in optimized_nodes:
            if op_node in seen:
                continue
            seen.append(op_node)
        optimized_nodes = seen

        new_nodes = list(filter(lambda node: node not in removed_nodes, optimized_nodes))
        model = utils.rebuild_model(model, new_nodes)
        check_model(model)

        return model

    def remove_softmax_old_pattern(self, model):
        nodes_by_output_name = {node.output[0]: node for node in model.graph.node}
        vi_by_output_name = {vi.name: vi for vi in model.graph.value_info}
        outputs_by_output_name = {output.name: output for output in model.graph.output}

        optimized_nodes = []
        removed_nodes = []

        for node in model.graph.node:
            if node.op_type != 'Softmax':
                optimized_nodes.append(node)
                continue

            # Softmax must be graph output
            if node.output[0] not in outputs_by_output_name.keys():
                optimized_nodes.append(node)
                continue

            output_node = outputs_by_output_name[node.output[0]]
            removed_nodes.append(node)
            model.graph.output.remove(output_node)

            # Graph must have at least one graph output
            if not len(model.graph.output):
                prev_node = nodes_by_output_name[node.input[0]]
                model.graph.output.append(vi_by_output_name[prev_node.output[0]])

        # remove duplicate node(s) in optimized nodes
        seen = []
        for op_node in optimized_nodes:
            if op_node in seen:
                continue
            seen.append(op_node)
        optimized_nodes = seen

        new_nodes = list(filter(lambda node: node not in removed_nodes, optimized_nodes))
        model = utils.rebuild_model(model, new_nodes)
        check_model(model)

        return model

Ancestors

  • furiosa_sdk_quantizer.interfaces.transformer.Transformer
  • typing.Generic

Methods

def remove_softmax_new_pattern(self, model)
Expand source code
def remove_softmax_new_pattern(self, model):
    nodes_by_output_name = {node_output: node for node in model.graph.node for node_output in node.output}
    vi_by_output_name = {vi.name: vi for vi in model.graph.value_info}
    outputs_by_output_name = {output.name: output for output in model.graph.output}

    optimized_nodes = []
    removed_nodes = []

    for node in model.graph.node:
        if node in removed_nodes:
            continue

        if node.op_type != 'Transpose':
            optimized_nodes.append(node)
            continue

        if node.output[0] not in outputs_by_output_name.keys():
            optimized_nodes.append(node)
            continue

        prev_node = nodes_by_output_name[node.input[0]]
        if prev_node.op_type != 'Softmax':
            optimized_nodes.append(node)
            continue

        pprev_node = nodes_by_output_name[prev_node.input[0]]
        if pprev_node.op_type != 'Transpose':
            optimized_nodes.append(node)
            continue

        output_node = outputs_by_output_name[node.output[0]]
        removed_nodes.extend([node, prev_node, pprev_node])
        model.graph.output.remove(output_node)

        # Graph must have at least one graph output
        if not len(model.graph.output):
            ppprev_node = nodes_by_output_name[pprev_node.input[0]]
            model.graph.output.append(vi_by_output_name[ppprev_node.output[0]])

    # remove duplicate node(s) in optimized nodes
    seen = []
    for op_node in optimized_nodes:
        if op_node in seen:
            continue
        seen.append(op_node)
    optimized_nodes = seen

    new_nodes = list(filter(lambda node: node not in removed_nodes, optimized_nodes))
    model = utils.rebuild_model(model, new_nodes)
    check_model(model)

    return model
def remove_softmax_old_pattern(self, model)
Expand source code
def remove_softmax_old_pattern(self, model):
    nodes_by_output_name = {node.output[0]: node for node in model.graph.node}
    vi_by_output_name = {vi.name: vi for vi in model.graph.value_info}
    outputs_by_output_name = {output.name: output for output in model.graph.output}

    optimized_nodes = []
    removed_nodes = []

    for node in model.graph.node:
        if node.op_type != 'Softmax':
            optimized_nodes.append(node)
            continue

        # Softmax must be graph output
        if node.output[0] not in outputs_by_output_name.keys():
            optimized_nodes.append(node)
            continue

        output_node = outputs_by_output_name[node.output[0]]
        removed_nodes.append(node)
        model.graph.output.remove(output_node)

        # Graph must have at least one graph output
        if not len(model.graph.output):
            prev_node = nodes_by_output_name[node.input[0]]
            model.graph.output.append(vi_by_output_name[prev_node.output[0]])

    # remove duplicate node(s) in optimized nodes
    seen = []
    for op_node in optimized_nodes:
        if op_node in seen:
            continue
        seen.append(op_node)
    optimized_nodes = seen

    new_nodes = list(filter(lambda node: node not in removed_nodes, optimized_nodes))
    model = utils.rebuild_model(model, new_nodes)
    check_model(model)

    return model
def transform(self, model: onnx.onnx_ml_pb2.ModelProto) ‑> onnx.onnx_ml_pb2.ModelProto
Expand source code
def transform(self, model: onnx.ModelProto) -> onnx.ModelProto:
    model = self.remove_softmax_new_pattern(model)
    model = self.remove_softmax_old_pattern(model)
    return model