Skip to content

Qiskit Machine Learning 0.7.0

Compare
Choose a tag to compare
@ElePT ElePT released this 10 Nov 16:24
· 43 commits to main since this release
95894f7

Prelude

Qiskit Machine Learning has been migrated to the qiskit-community Github organization to further emphasize that it is a community-driven project. To reflect this change, and because we are onboarding additional code-owners and maintainers, with this version (0.7) we have decided to remove all deprecated code, regardless of the time of its deprecation. This ensures that the new members of the development team do not have a large bulk of legacy code to maintain. This can mean one of two things for you as the end-user:

  • Nothing, if you already migrated your code and no longer rely on any deprecated features.
  • Otherwise, you should make sure that your workflow doesn’t rely on deprecated classes. If you cannot do that, or want to continue
    using some of the features that were removed, you should pin your version of Qiskit Machine Learning to 0.6.

For more context on the changes around Qiskit Machine Learning and the other application projects as well as the Algorithms library in Qiskit, be sure to read this blog post.

New Features

  • The QNNCircuit class can be passed as circuit to the SamplerQNN and EstimatorQNN. This simplifies the interfaces to build a Sampler or Estimator based neural network implementation from a feature map and an ansatz circuit.
    Using the QNNCircuit comes with the benefit that the feature map and ansatz do not have to be composed explicitly. If a QNNCircuit is passed to the SamplerQNN or EstimatorQNN the input and weight parameters do not have to be provided, because these two properties are taken from the QNNCircuit.
    An example of using QNNCircuit with the SamplerQNN class is as follows:

     from qiskit_machine_learning.circuit.library import QNNCircuit
     from qiskit_machine_learning.neural_networks import SamplerQNN
    
     def parity(x):
         return f"{bin(x)}".count("1") % 2
    
     # Create a parameterized 2 qubit circuit composed of the default ZZFeatureMap feature map
     # and RealAmplitudes ansatz.
     qnn_qc = QNNCircuit(num_qubits = 2)
    
     qnn = SamplerQNN(
         circuit=qnn_qc,
         interpret=parity,
         output_shape=2
     )
    
     qnn.forward(input_data=[1, 2], weights=[1, 2, 3, 4, 5, 6, 7, 8])

    The QNNCircuit is used with the EstimatorQNN class in the same fashion:

    from qiskit_machine_learning.circuit.library import QNNCircuit
    from qiskit_machine_learning.neural_networks import EstimatorQNN
    
    # Create a parameterized 2 qubit circuit composed of the default ZZFeatureMap feature map
    # and RealAmplitudes ansatz.
    qnn_qc = QNNCircuit(num_qubits = 2)
    
    qnn = EstimatorQNN(
        circuit=qnn_qc
    )
    
    qnn.forward(input_data=[1, 2], weights=[1, 2, 3, 4, 5, 6, 7, 8])
  • Added a new QNNCircuit class that composes a Quantum Circuit from a feature map and an ansatz.
    At least one parameter, i.e. number of qubits, feature map, ansatz, has to be provided.
    If only the number of qubits is provided the resulting quantum circuit is a composition of the ZZFeatureMap and the RealAmplitudes ansatz. If the number of qubits is 1 the ZFeatureMap is used per default. If only a feature map is provided, the RealAmplitudes ansatz with the corresponding number of qubits is used. If only an ansatz is provided the ZZFeatureMap with the corresponding number of qubits is used.
    In case number of qubits is provided along with either a feature map, an ansatz or both, a potential mismatch between the three inputs with respect to the number of qubits is resolved by constructing the QNNCircuit with the given number of qubits. If one of the QNNCircuit properties is set after the class construction, the circuit is is adjusted to incorporate the changes. This is, a new valid configuration that considers the latest property update will be derived. This ensures that the classes properties are consistent at all times.

    An example of using this class is as follows:

        from qiskit_machine_learning.circuit.library import QNNCircuit
        qnn_qc = QNNCircuit(2)
        print(qnn_qc)
        # prints:
        #      ┌──────────────────────────┐»
        # q_0: ┤0                         ├»
        #      │  ZZFeatureMap(x[0],x[1]) │»
        # q_1: ┤1                         ├»
        #      └──────────────────────────┘»
        # «     ┌──────────────────────────────────────────────────────────┐
        # «q_0: ┤0                                                         ├
        # «     │  RealAmplitudes(θ[0],θ[1],θ[2],θ[3],θ[4],θ[5],θ[6],θ[7]) │
        # «q_1: ┤1                                                         ├
        # «     └──────────────────────────────────────────────────────────┘
    
        print(qnn_qc.num_qubits)
        # prints: 2
    
        print(qnn_qc.input_parameters)
        # prints: ParameterView([ParameterVectorElement(x[0]), ParameterVectorElement(x[1])])
    
        print(qnn_qc.weight_parameters)
        # prints: ParameterView([ParameterVectorElement(θ[0]), ParameterVectorElement(θ[1]),
        #         ParameterVectorElement(θ[2]), ParameterVectorElement(θ[3]),
        #         ParameterVectorElement(θ[4]), ParameterVectorElement(θ[5]),
        #         ParameterVectorElement(θ[6]), ParameterVectorElement(θ[7])])
  • A new TrainableFidelityStatevectorKernel class has been added that provides a trainable version of FidelityStatevectorKernel. This relationship mirrors that between the existing FidelityQuantumKernel. Thus, TrainableFidelityStatevectorKernel inherits from both FidelityStatevectorKernel and TrainableKernel.
    This class is used with QuantumKernelTrainer in an identical way to TrainableFidelityQuantumKernel, except for the arguments specific to TrainableFidelityStatevectorKernel.

    For an example, see the snippet below:

    from qiskit.quantum_info import Statevector
    from qiskit_machine_learning.kernels import TrainableFidelityStatevectorKernel
    from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer
    
    # Instantiate trainable fidelity statevector kernel.
    quantum_kernel = TrainableFidelityStatevectorKernel(
        feature_map=<your_feature_map>,
        statevector_type=Statevector,
        training_parameters=<your_training_parameters>,
        cache_size=None,
        auto_clear_cache=True,
        shots=None,
        enforce_psd=True,
    )
    
    # Instantiate a quantum kernel trainer (QKT).
    qkt = QuantumKernelTrainer(quantum_kernel=quantum_kernel)
    
    # Train the kernel using QKT directly.
    qkt_results = qkt.fit(<your_X_train>, <your_y_train>)
    optimized_kernel = qkt_results.quantum_kernel
  • The module is migrated to Qiskit Algorithms from the qiskit.algorithms package that is deprecated now.

Upgrade Notes

Bug Fixes

  • Compatibility fix to support Python 3.11.

  • Fixes a bug in FidelityStatevectorKernel where kernel entries could potentially have nonzero complex components due to truncation and rounding errors when enforcing a PSD matrix.

  • Updated RawFeatureVector to support changes in the parameter assignment introduced in Qiskit.

  • Fixed incorrect type conversions in TorchConnector. The bug was causing the connector to convert the output to the same type as the input data. As a result, when an integer tensor was passed, the output would also be converted to an integer tensor, leading to rounding errors.