code: def test_gemm_conversion(self):
      node_def = make_node(
          "Gemm", ["A", "B", "C"], ["Y"], alpha=2.0, beta=3.0
      )
      node_def_broadcast = make_node(
          "Gemm",
          ["A", "B", "C"],
          ["Y"],
          alpha=2.0,
          beta=3.0,
          broadcast=1,
      )
      node_def_transpose_b = make_node(
          "Gemm", ["A", "B", "C"], ["Y"], alpha=2.0, beta=3.0, transB=1
      )
  
      node_def_transpose_b_broadcast = make_node(
          "Gemm",
          ["A", "B", "C"],
          ["Y"],
          alpha=2.0,
          beta=3.0,
          transB=1,
          broadcast=1,
      )
  
      backend = C.Caffe2Backend()
  
      # without broadcast and without shape info, gemm will be
      # converted to matmul + add
      _, op_strs = backend.convert_node(node_def.SerializeToString())
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "MatMul", "Add"])
  
      # opset7
      # If C is a 1d tensor, gemm will be converted to FC/FCTransposed
      _, op_strs = backend.convert_node(
          node_def_transpose_b.SerializeToString(),
          [
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (3,)
              ).SerializeToString()
          ],
          7,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "FC"])
  
      _, op_strs = backend.convert_node(
          node_def.SerializeToString(),
          [
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (3,)
              ).SerializeToString()
          ],
          7,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "FCTransposed"])
  
      # opset6 without broadcast(C should match A*B's dim)
      # The gemm will be converted to matmul + add, since the FC requires c
      # to be 1d tensor.
      _, op_strs = backend.convert_node(
          node_def.SerializeToString(),
          [
              make_tensor_value_info(
                  "A", onnx.TensorProto.FLOAT, (3, 2)
              ).SerializeToString(),
              make_tensor_value_info(
                  "B", onnx.TensorProto.FLOAT, (2, 3)
              ).SerializeToString(),
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (3, 3)
              ).SerializeToString(),
          ],
          6,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "MatMul", "Add"])
  
      # opset6 with broadcast
      # If C is a 1d tensor, gemm will be converted to FC/FCTransposed
      _, op_strs = backend.convert_node(
          node_def_transpose_b_broadcast.SerializeToString(),
          [
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (3,)
              ).SerializeToString()
          ],
          6,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "FC"])
  
      _, op_strs = backend.convert_node(
          node_def_broadcast.SerializeToString(),
          [
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (3,)
              ).SerializeToString()
          ],
          6,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "FCTransposed"])
  
      # opset7
      # If C is a scalar and B's last dim is 1, gemm will be converted to FC/FCTransposed
      _, op_strs = backend.convert_node(
          node_def_transpose_b.SerializeToString(),
          [
              make_tensor_value_info(
                  "B", onnx.TensorProto.FLOAT, (1, 2)
              ).SerializeToString(),
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (1,)
              ).SerializeToString(),
          ],
          7,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "FC"])
  
      _, op_strs = backend.convert_node(
          node_def.SerializeToString(),
          [
              make_tensor_value_info(
                  "B", onnx.TensorProto.FLOAT, (2, 1)
              ).SerializeToString(),
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (1,)
              ).SerializeToString(),
          ],
          7,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "FCTransposed"])
      # If C is a scalar and B's last dim is not 1, gemm will be converted
      # to matmul + add.
      _, op_strs = backend.convert_node(
          node_def_transpose_b.SerializeToString(),
          [
              make_tensor_value_info(
                  "B", onnx.TensorProto.FLOAT, (2, 2)
              ).SerializeToString(),
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (1,)
              ).SerializeToString(),
          ],
          7,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "MatMul", "Add"])
      # If C is a scalar and B's shape info is not available,
      # gemm will be converted to matmul + add.
      _, op_strs = backend.convert_node(
          node_def_transpose_b.SerializeToString(),
          [
              make_tensor_value_info(
                  "C", onnx.TensorProto.FLOAT, (1,)
              ).SerializeToString()
          ],
          7,
      )
      op_names = []
      for s in op_strs:
          op = caffe2_pb2.OperatorDef()
          op.ParseFromString(s)
          op_names.append(op.type)
      self.assertEqual(op_names, ["Scale", "Scale", "MatMul", "Add"])
  
imports: import os
  import unittest
  from caffe2.python import core
  from caffe2.proto import caffe2_pb2
  import onnx
  from onnx.helper import make_node, make_graph, make_tensor, make_tensor_value_info, make_model
  from caffe2.python.onnx.helper import c2_native_run_net, c2_native_run_op
  from onnx import mapping
  import caffe2.python.onnx.frontend
  import caffe2.python.onnx.backend
  import numpy
  from caffe2.python.models.download import ModelDownloader
  from caffe2.python.onnx.tests.test_utils import TestCase
  import caffe2.python._import_c_extension
label_desc: Use image node_id 12 for calling the TestCaffe2Basic obj's underlying member method code with example usage: obj.test_gemm_conversion() without return types