Add an inner product layer to the model.

        Parameters
        ----------
        name: str
            The name of this layer
        W: numpy.array or bytes()
            Weight matrix of shape (output_channels, input_channels)
            If W is of type bytes(), i.e. quantized, other quantization related arguments must be provided as well (see below).
        b: numpy.array
            Bias vector of shape (output_channels, ).
        input_channels: int
            Number of input channels.
        output_channels: int
            Number of output channels.
        has_bias: boolean
            Whether the bias vector of this layer is ignored in the spec.

            - If True, the bias vector of this layer is not ignored.
            - If False, the bias vector is ignored.

        input_name: str
            The input blob name of this layer.
        output_name: str
            The output blob name of this layer.

        Quantization arguments expected in kwargs, when W is of type bytes():

            quantization_type : str
                When weights are quantized (i.e. W is of type bytes()), this should be either "linear" or "lut".

            nbits: int
                Should be between 1 and 8 (inclusive). Number of bits per weight value. Only applicable when
                weights are quantized.

            quant_scale: numpy.array(dtype=numpy.float32)
                scale vector to be used with linear quantization. Must be of length either 1 or output_channels.

            quant_bias: numpy.array(dtype=numpy.float32)
                bias vector to be used with linear quantization. Must be of length either 1 or output_channels.

            quant_lut: numpy.array(dtype=numpy.float32)
                the LUT (look up table) to be used with LUT quantization. Must be of length 2^nbits.

        See Also
        --------
        add_embedding, add_convolution

def add_inner_product(self, name, W, b, input_channels, output_channels, has_bias,
                          input_name, output_name, **kwargs):
        """
        Add an inner product layer to the model.

        Parameters
        ----------
        name: str
            The name of this layer
        W: numpy.array or bytes()
            Weight matrix of shape (output_channels, input_channels)
            If W is of type bytes(), i.e. quantized, other quantization related arguments must be provided as well (see below).
        b: numpy.array
            Bias vector of shape (output_channels, ).
        input_channels: int
            Number of input channels.
        output_channels: int
            Number of output channels.
        has_bias: boolean
            Whether the bias vector of this layer is ignored in the spec.

            - If True, the bias vector of this layer is not ignored.
            - If False, the bias vector is ignored.

        input_name: str
            The input blob name of this layer.
        output_name: str
            The output blob name of this layer.

        Quantization arguments expected in kwargs, when W is of type bytes():

            quantization_type : str
                When weights are quantized (i.e. W is of type bytes()), this should be either "linear" or "lut".

            nbits: int
                Should be between 1 and 8 (inclusive). Number of bits per weight value. Only applicable when
                weights are quantized.

            quant_scale: numpy.array(dtype=numpy.float32)
                scale vector to be used with linear quantization. Must be of length either 1 or output_channels.

            quant_bias: numpy.array(dtype=numpy.float32)
                bias vector to be used with linear quantization. Must be of length either 1 or output_channels.

            quant_lut: numpy.array(dtype=numpy.float32)
                the LUT (look up table) to be used with LUT quantization. Must be of length 2^nbits.

        See Also
        --------
        add_embedding, add_convolution
        """

        spec = self.spec
        nn_spec = self.nn_spec

        # Add a new layer
        spec_layer = nn_spec.layers.add()
        spec_layer.name = name
        spec_layer.input.append(input_name)
        spec_layer.output.append(output_name)
        spec_layer_params = spec_layer.innerProduct

        # Fill in the parameters
        spec_layer_params.inputChannels = input_channels
        spec_layer_params.outputChannels = output_channels
        spec_layer_params.hasBias = has_bias

        weights = spec_layer_params.weights

        if len(kwargs) == 0:
            weights.floatValue.extend(map(float, W.flatten()))
        else:
            _verify_quantization_arguments(weight=W, output_channels=output_channels, **kwargs)
            _fill_quantized_weights(weights_message=weights, W=W, **kwargs)

        if has_bias:
            bias = spec_layer_params.bias
            bias.floatValue.extend(map(float, b.flatten()))