[ad_1]
Quantum Machine Studying (QML) represents an enchanting convergence of quantum computing and machine studying applied sciences. With quantum computing’s potential in arithmetic and knowledge processing with advanced construction, QML may revolutionize areas like drug discovery, finance, and past. This weblog delves into the revolutionary realms of quantum neural networks (QNNs) and quantum kernel strategies, showcasing their distinctive capabilities by sensible Python examples. The weblog is not going to element the mathematical ideas. For extra data don’t hesitate to learn my newest guide Machine Studying Concept and Functions: Fingers-on Use Circumstances with Python on Classical and Quantum Machines, Wiley, 2024.
Quantum kernel strategies, introduce a quantum-enhanced method of processing knowledge. By mapping classical knowledge into quantum function area, these strategies make the most of the superposition and entanglement properties of quantum mechanics to carry out classifications or regression duties. Using quantum kernel estimator and quantum variational classifier examples illustrates the sensible utility of those ideas. QNNs, leveraging quantum states for computation, supply a novel method to neural community structure. The Qiskit framework facilitates the implementation of each quantum kernel strategies and QNNs, enabling the exploration of quantum algorithms’ effectivity in studying and sample recognition.
Incorporating Python code examples, this weblog goals to offer complete code examples of QML for readers to discover its promising functions, and the challenges it faces. Via these examples, readers can begin practising and acquire an appreciation for the transformative potential of quantum computing in machine studying and the thrilling prospects that lie forward.
We are going to use the open-source SDK Qiskit (https://qiskit.org) which permits working with quantum computer systems. Qiskit helps Python model 3.6 or later.
In the environment, we will set up Qiskit with pip:
pip set up qiskit
We are able to additionally set up qiskit-machine-learning utilizing pip:
pip set up qiskit-machine-learning
Documentation might be discovered on GitHub: https://github.com/Qiskit/qiskit-machine-learning/.
To run our code, we will use both simulators or actual {hardware} even when I strongly advocate using {hardware} or push the boundaries of simulators to enhance analysis on this subject. Whereas learning the Qiskit documentation, you’ll encounter references to the Qiskit Runtime primitives, which function implementations of the Sampler and Estimator interfaces discovered within the qiskit.primitives module. These interfaces facilitate the seamless interchangeability of primitive implementations with minimal code modifications. The preliminary launch of Qiskit Runtime contains two important primitives:
- Sampler: This primitive generates quasi-probabilities primarily based on enter circuits.
- Estimator: This primitive calculates expectation values derived from enter circuits and observables.
For extra complete insights, detailed data is obtainable within the following useful resource: https://qiskit.org/ecosystem/ibm-runtime/tutorials/how-to-getting-started-with-sampler.html.
Venturing into quantum approaches for supervised machine studying poses a novel analysis path. Classical machine studying extensively makes use of kernel strategies, amongst which the assist vector machine (SVM) for classification stands out for its widespread utility.
SVMs, recognized for his or her position in binary classification, have more and more been utilized to multiclass issues. The essence of binary SVM includes devising a hyperplane to linearly separate n-dimensional knowledge factors into two teams, aiming for an optimum margin that distinctively classifies the information into its respective classes. This hyperplane, efficient in both the unique function area or a reworked higher-dimensional kernel area, is chosen for its capability to maximise the separation between lessons, which includes an optimization drawback to maximise the margin, outlined as the space from the closest knowledge level to the hyperplane on both facet. This results in the formulation of a maximum-margin classifier. The important knowledge factors on the boundary are termed assist vectors, and the margin represents a zone sometimes devoid of information factors. An optimum hyperplane too proximate to the information factors, indicating a slender margin, undermines the mannequin’s predictive robustness and generalization functionality.
To navigate multiclass SVM challenges, strategies just like the all-pair technique, which conducts a binary classification for every pair of lessons, have been launched. Past simple linear classification, nonlinear classifications might be achieved by the kernel trick. This method employs a kernel perform to raise inputs right into a extra expansive, higher-dimensional function area, facilitating the separation of information that’s not linearly separable within the enter area. The kernel perform basically performs an interior product in a doubtlessly huge Euclidian area, often called the function area. The purpose of nonlinear SVM is to attain this separation by mapping knowledge to a better dimension utilizing an appropriate mapping. Deciding on an acceptable function map turns into essential for knowledge that can not be addressed by linear strategies alone. That is the place quantum can leap into it. Quantum kernel strategies, mixing classical kernel methods with quantum improvements, carve out new avenues in machine studying. Early quantum kernel approaches have targeted on encoding knowledge factors into interior merchandise or amplitudes in Hilbert area by quantum function maps. The complexity of the quantum circuit implementing the function map scales linearly or polylogarithmically with the dataset measurement.
On this first instance, we’ll use the ZZFeatureMap with linear entanglement, we’ll repeat the information encoding step two instances, and we’ll use function discount with principal element evaluation. You may after all use different function discount, knowledge rescaling or function choice strategies to enhance the accuracy of your fashions. We are going to use the breast most cancers dataset that you could find right here: https://github.com/xaviervasques/hephaistos/blob/important/knowledge/datasets/breastcancer.csv
Let’s describe the steps of the Python script beneath. This Python script demonstrates an utility of integrating quantum computing strategies with conventional machine studying to categorise breast most cancers knowledge. It represents a hybrid method, the place quantum-enhanced options are used inside a classical machine studying workflow. The purpose is to foretell breast most cancers analysis (benign or malignant) primarily based on a set of options extracted from the breast mass traits.
The way in which of doing quantum kernel machine studying is similar to what we do classically as knowledge scientists. We import the mandatory libraries (Pandas, NumPy, scikit-learn) and Qiskit for quantum computing and kernel estimation, we load the information, preprocess the information and separate the information into options (X) and goal labels (y). A selected step is the quantum function mapping. The script units up a quantum function map utilizing the ZZFeatureMap from Qiskit, configured with specified parameters for function dimension, repetitions, and entanglement kind. Quantum function maps are important for translating classical knowledge into quantum states, enabling the appliance of quantum computing ideas for knowledge evaluation. Then, the quantum kernel setup consists in configuring a quantum kernel with a fidelity-based method. It serves as a brand new technique to compute the similarity between knowledge factors within the function area outlined by quantum states and doubtlessly capturing advanced patterns. The final step comes again to a traditional machine studying pipeline with knowledge rescaling with commonplace scaler, dimension discount utilizing principal element evaluation and using assist vector classifier (SVC) which makes use of the quantum kernel for classification. We consider the mannequin utilizing 5-fold cross-validation.
Let’s code.
# Import essential libraries for knowledge manipulation, machine studying, and quantum computing
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder# Load the dataset utilizing pandas, specifying the file location and delimiter
breastcancer = './breastcancer.csv'
df = pd.read_csv(breastcancer, delimiter=';')
# Take away the 'id' column as it isn't helpful for prediction, to simplify the dataset
df = df.drop(["id"], axis=1)
# Separate the dataset into options (X) and goal label (y)
y = df['diagnosis'] # Goal label: analysis
X = df.drop('analysis', axis=1) # Options: all different columns
# Convert the analysis string labels into numeric values for use by machine studying fashions
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
# Quantum computing sections begin right here
# Set parameters for the quantum function map
feature_dimension = 2 # Variety of options used within the quantum function map
reps = 2 # Variety of repetitions of the function map circuit
entanglement = 'linear' # Kind of entanglement within the quantum circuit
# Import quantum function mapping utilities from Qiskit
from qiskit.circuit.library import ZZFeatureMap
qfm = ZZFeatureMap(feature_dimension=feature_dimension, reps=reps, entanglement=entanglement)
# Arrange an area simulator for quantum computation
from qiskit.primitives import Sampler
sampler = Sampler()
# Configure quantum kernel utilizing ZZFeatureMap and a fidelity-based quantum kernel
from qiskit.algorithms.state_fidelities import ComputeUncompute
from qiskit_machine_learning.kernels import FidelityQuantumKernel
constancy = ComputeUncompute(sampler=sampler)
quantum_zz = FidelityQuantumKernel(constancy=constancy, feature_map=qfm)
# Create a machine studying pipeline integrating commonplace scaler, PCA for dimensionality discount,
# and a Assist Vector Classifier utilizing the quantum kernel
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.svm import SVC
pipeline = make_pipeline(StandardScaler(), PCA(n_components=2), SVC(kernel=quantum_zz.consider))
# Consider the mannequin utilizing cross-validation to evaluate its efficiency
from sklearn.model_selection import cross_val_score
cv = cross_val_score(pipeline, X, y, cv=5, n_jobs=1) # n_jobs=1 specifies that the computation will use 1 CPU
mean_score = np.imply(cv) # Calculate the imply of the cross-validation scores
# Print the imply cross-validation rating to judge the mannequin's efficiency
print(mean_score)
We are going to get hold of a imply rating validation rating of 0.63.
This code is executed with the native simulator. To run on actual {hardware}, substitute the next traces:
# Arrange an area simulator for quantum computation
from qiskit.primitives import Sampler
sampler = Sampler()
by
# Import essential lessons from qiskit_ibm_runtime for accessing IBM Quantum companies
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler# Initialize the QiskitRuntimeService along with your IBM Quantum credentials
# 'channel', 'token', and 'occasion' are placeholders in your precise IBM Quantum account particulars
service = QiskitRuntimeService(channel='YOUR CHANNEL', token='YOUR TOKEN FROM IBM QUANTUM', occasion='YOUR INSTANCE')
# Specify the backend you want to use. This could possibly be a simulator or an precise quantum laptop accessible by IBM Quantum
# 'quantum_backend' needs to be changed with the identify of the quantum backend you want to use
backend = service.backend('quantum_backend')
# Import the Choices class to customise the execution of quantum applications
from qiskit_ibm_runtime import Choices
choices = Choices() # Create an occasion of Choices
# Set the resilience stage. Stage 1 sometimes implies some stage of error mitigation or resilience towards errors
choices.resilience_level = 1
# Set the variety of photographs, which is the variety of instances the quantum circuit shall be executed to collect statistics
# Extra photographs can result in extra correct outcomes however take longer to execute
choices.execution.photographs = 1024
# Set the optimization stage for compiling the quantum circuit
# Greater optimization ranges try to cut back the circuit's complexity, which might enhance execution however could take longer to compile
choices.optimization_level = 3
# Initialize the Sampler, which is used to run quantum circuits and procure samples from their measurement outcomes
# The Sampler is configured with the required backend and choices
sampler = Sampler(session=backend, choices=choices)
This half will discover the tactic of Quantum Kernel Alignment (QKA) for the aim of binary classification. QKA iteratively adjusts a quantum kernel that’s parameterized to suit a dataset, aiming for the biggest doable margin in Assist Vector Machines (SVM). For additional particulars on QKA, reference is made to the preprint titled “Covariant quantum kernels for knowledge with group construction.” The Python script beneath is a complete instance of integrating conventional machine studying strategies with quantum computing for the prediction accuracy in classifying breast most cancers analysis. It employs a dataset of breast most cancers traits to foretell the analysis (benign or malignant).
The machine studying pipeline is much like the one used within the quantum kernel with ZZFeatureMaps part. The distinction is that we’ll constructs a customized quantum circuit, integrating a rotational layer with a ZZFeatureMap, to arrange the quantum state representations of the information. The quantum kernel estimation step makes use of Qiskit primitives and algorithms for optimizing the quantum kernel’s parameters utilizing a quantum kernel educated (QKT) and an optimizer.
Let’s code.
# Import essential libraries for knowledge manipulation, machine studying, and quantum computing
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder# Load the dataset utilizing pandas, specifying the file location and delimiter
breastcancer = './breastcancer.csv'
df = pd.read_csv(breastcancer, delimiter=';')
# Take away the 'id' column as it isn't helpful for prediction, to simplify the dataset
df = df.drop(["id"], axis=1)
# Cut back the dataframe measurement by sampling 1/3 of the information
df = df.pattern(frac=1/3, random_state=1) # random_state for reproducibility
# Separate the dataset into options (X) and goal label (y)
y = df['diagnosis'] # Goal label: analysis
X = df.drop('analysis', axis=1) # Options: all different columns
# Convert the analysis string labels into numeric values for use by machine studying fashions
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
# Quantum computing sections begin right here
# Set parameters for the quantum function map
feature_dimension = 2 # Variety of options used within the quantum function map
reps = 2 # Variety of repetitions of the function map circuit
entanglement = 'linear' # Kind of entanglement within the quantum circuit
# Outline a customized rotational layer for the quantum function map
from qiskit import QuantumCircuit
from qiskit.circuit import ParameterVector
training_params = ParameterVector("θ", 1)
fm0 = QuantumCircuit(feature_dimension)
for qubit in vary(feature_dimension):
fm0.ry(training_params[0], qubit)
# Use ZZFeatureMap to characterize enter knowledge
from qiskit.circuit.library import ZZFeatureMap
fm1 = ZZFeatureMap(feature_dimension=feature_dimension, reps=reps, entanglement=entanglement)
# Compose the customized rotational layer with the ZZFeatureMap to create the function map
fm = fm0.compose(fm1)
# Initialize the Sampler, a Qiskit primitive for sampling from quantum circuits
from qiskit.primitives import Sampler
sampler = Sampler()
# Arrange the ComputeUncompute constancy object for quantum kernel estimation
from qiskit.algorithms.state_fidelities import ComputeUncompute
from qiskit_machine_learning.kernels import TrainableFidelityQuantumKernel
constancy = ComputeUncompute(sampler=sampler)
# Instantiate the quantum kernel with the function map and coaching parameters
quant_kernel = TrainableFidelityQuantumKernel(constancy=constancy, feature_map=fm, training_parameters=training_params)
# Callback class for monitoring optimization progress
class QKTCallback:
# Callback wrapper class
def __init__(self):
self._data = [[] for i in vary(5)]
def callback(self, x0, x1=None, x2=None, x3=None, x4=None):
#Seize callback knowledge for evaluation
for i, x in enumerate([x0, x1, x2, x3, x4]):
self._data[i].append(x)
def get_callback_data(self):
#Get captured callback knowledge
return self._data
def clear_callback_data(self):
#Clear captured callback knowledge
self._data = [[] for i in vary(5)]
# Setup and instantiate the optimizer for the quantum kernel
from qiskit.algorithms.optimizers import SPSA
cb_qkt = QKTCallback()
spsa_opt = SPSA(maxiter=10, callback=cb_qkt.callback, learning_rate=0.01, perturbation=0.05)
# Quantum Kernel Coach (QKT) for optimizing the kernel parameters
from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer
qkt = QuantumKernelTrainer(
quantum_kernel=quant_kernel, loss="svc_loss", optimizer=spsa_opt, initial_point=[np.pi / 2]
)
# Cut back dimensionality of the information utilizing PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_ = pca.fit_transform(X)
# Practice the quantum kernel with the decreased dataset
qka_results = qkt.match(X_, y)
optimized_kernel = qka_results.quantum_kernel
# Use the quantum-enhanced kernel in a Quantum Assist Vector Classifier (QSVC)
from qiskit_machine_learning.algorithms import QSVC
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
qsvc = QSVC(quantum_kernel=optimized_kernel)
pipeline = make_pipeline(StandardScaler(), PCA(n_components=2), qsvc)
# Consider the efficiency of the mannequin utilizing cross-validation
from sklearn.model_selection import cross_val_score
cv = cross_val_score(pipeline, X, y, cv=5, n_jobs=1)
mean_score = np.imply(cv)
# Print the imply cross-validation rating
print(mean_score)
We are going to get hold of the next output: 0.6526315789473685
As you actually noticed, there’s time variations in execution between QKT and utilizing a quantum kernel with a predefined function map like ZZFeatureMap even when we decreased the dataframe measurement by sampling 1/3 of the information and setting the utmost iteration for SPSA to 10. QKT includes not solely using a quantum kernel but in addition the optimization of parameters inside the quantum function map or the kernel itself to enhance mannequin efficiency. This optimization course of requires iterative changes to the parameters, the place every iteration includes operating quantum computations to judge the efficiency of the present parameter set. This iterative nature considerably will increase computational time. When utilizing a predefined quantum kernel just like the ZZFeatureMap, the function mapping is fastened, and there’s no iterative optimization of quantum parameters concerned. The quantum computations are carried out to judge the kernel between knowledge factors, however with out the added overhead of adjusting and optimizing quantum circuit parameters. This method is extra simple and requires fewer quantum computations, making it quicker. Every step of the optimization course of in QKT requires evaluating the mannequin’s efficiency with the present quantum kernel, which is determined by the quantum function map parameters at that step. This implies a number of evaluations of the kernel matrix, every of which requires a considerable variety of quantum computations.
This Python script beneath incorporates quantum neural networks (QNNs) right into a machine studying pipeline. Within the script, we have to configure the quantum function map and ansatz (a quantum circuit construction), assemble a quantum circuit by appending the function map and ansatz to a base quantum circuit (this setup is essential for creating quantum neural networks that course of enter knowledge quantum mechanically) and create a QNN utilizing the quantum circuit designed for binary classification. Earlier than coming again to the traditional machine studying pipeline with knowledge rescaling, knowledge discount and mannequin analysis, we make use of a quantum classifier which integrates the QNN with a classical optimization algorithm (COBYLA) for coaching. A callback perform is outlined to visualise the optimization course of, monitoring the target perform worth throughout iterations.
Let’s code.
# Importing important libraries for dealing with knowledge, machine studying, and integrating quantum computing
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
import matplotlib.pyplot as plt # For knowledge visualization# Load and put together the dataset
breastcancer = './breastcancer.csv'
df = pd.read_csv(breastcancer, delimiter=';') # Load dataset from CSV file
df = df.drop(["id"], axis=1) # Take away the 'id' column as it isn't essential for evaluation
# Splitting the information into options (X) and the goal variable (y)
y = df['diagnosis'] # Goal variable: analysis end result
X = df.drop('analysis', axis=1) # Characteristic matrix: all knowledge besides the analysis
# Encoding string labels in 'y' into numerical type for machine studying fashions
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y) # Remodel labels to numeric
# Quantum function map and circuit configuration
feature_dimension = 2 # Dimensionality for the function map (matches PCA discount later)
reps = 2 # Variety of repetitions of the ansatz circuit for depth
entanglement = 'linear' # Kind of qubit entanglement within the circuit
# Initialize an array to retailer evaluations of the target perform throughout optimization
objective_func_vals = []
# Outline a callback perform for visualization of the optimization course of
def callback_graph(weights, obj_func_eval):
"""Updates and saves a plot of the target perform worth after every iteration."""
objective_func_vals.append(obj_func_eval)
plt.title("Goal perform worth towards iteration")
plt.xlabel("Iteration")
plt.ylabel("Goal perform worth")
plt.plot(vary(len(objective_func_vals)), objective_func_vals)
plt.savefig('Objective_function_value_against_iteration.png') # Save plot to file
# Instance perform circuitously utilized in the primary workflow, demonstrating a utility perform
def parity(x):
"""Instance perform to calculate parity of an integer."""
return "{:b}".format(x).rely("1") % 2
# Initializing the quantum sampler from Qiskit
from qiskit.primitives import Sampler
sampler = Sampler() # Used for sampling from quantum circuits
# Setting up the quantum function map and ansatz for the quantum circuit
from qiskit.circuit.library import ZZFeatureMap, RealAmplitudes
feature_map = ZZFeatureMap(feature_dimension)
ansatz = RealAmplitudes(feature_dimension, reps=reps) # Quantum circuit ansatz
# Composing the quantum circuit with the function map and ansatz
from qiskit import QuantumCircuit
qc = QuantumCircuit(feature_dimension)
qc.append(feature_map, vary(feature_dimension)) # Apply function map to circuit
qc.append(ansatz, vary(feature_dimension)) # Apply ansatz to circuit
qc.decompose().draw() # Draw and decompose circuit for visualization
# Making a Quantum Neural Community (QNN) utilizing the configured quantum circuit
from qiskit_machine_learning.neural_networks import SamplerQNN
sampler_qnn = SamplerQNN(
circuit=qc,
input_params=feature_map.parameters,
weight_params=ansatz.parameters,
output_shape=2, # For binary classification
sampler=sampler
)
# Configuring the quantum classifier with the COBYLA optimizer
from qiskit.algorithms.optimizers import COBYLA
from qiskit_machine_learning.algorithms.classifiers import NeuralNetworkClassifier
sampler_classifier = NeuralNetworkClassifier(
neural_network=sampler_qnn, optimizer=COBYLA(maxiter=100), callback=callback_graph)
# Organising Okay-Fold Cross Validation to evaluate mannequin efficiency
from sklearn.model_selection import KFold
k_fold = KFold(n_splits=5) # 5-fold cross-validation
rating = np.zeros(5) # Array to retailer scores for every fold
i = 0 # Index counter for scores array
for indices_train, indices_test in k_fold.cut up(X):
X_train, X_test = X.iloc[indices_train], X.iloc[indices_test]
y_train, y_test = y[indices_train], y[indices_test]
# Making use of PCA to cut back the dimensionality of the dataset to match the quantum function map
from sklearn.decomposition import PCA
pca = PCA(n_components=2) # Cut back to 2 dimensions for the quantum circuit
X_train = pca.fit_transform(X_train) # Remodel coaching set
X_test = pca.fit_transform(X_test) # Remodel check set
# Coaching the quantum classifier with the coaching set
sampler_classifier.match(X_train, y_train)
# Evaluating the classifier's efficiency on the check set
rating[i] = sampler_classifier.rating(X_test, y_test) # Retailer rating for this fold
i += 1 # Increment index for subsequent rating
# Calculating and displaying the outcomes of cross-validation
import math
print("Cross-validation scores:", rating)
cross_mean = np.imply(rating) # Imply of cross-validation scores
cross_var = np.var(rating) # Variance of scores
cross_std = math.sqrt(cross_var) # Commonplace deviation of scores
print("Imply cross-validation rating:", cross_mean)
print("Commonplace deviation of cross-validation scores:", cross_std)
We get hold of the next outcomes:
Cross-validation scores: [0.34210526 0.4122807 0.42982456 0.21929825 0.50442478]
Imply cross-validation rating: 0.3815867101381773
Commonplace deviation of cross-validation scores: 0.09618163326986424
As we will see, on this particular dataset, QNN doesn’t present an excellent classification rating.
This concept of this weblog is to make it straightforward to start out utilizing quantum machine studying. Quantum Machine Studying is an rising subject on the intersection of quantum computing and machine studying that holds the potential to revolutionize how we course of and analyze huge datasets by leveraging the inherent benefits of quantum mechanics. As we confirmed in our paper Software of quantum machine studying utilizing quantum kernel algorithms on multiclass neuron M-type classification printed in Nature Scientific Report, a vital side of optimizing QML fashions, together with Quantum Neural Networks (QNNs), includes pre-processing strategies comparable to function rescaling, function extraction, and have choice.
These strategies will not be solely important in classical machine studying but in addition current vital advantages when utilized inside the quantum computing framework, enhancing the efficiency and effectivity of quantum machine studying algorithms. Within the quantum realm, function extraction strategies like Principal Element Evaluation (PCA) might be quantum-enhanced to cut back the dimensionality of the information whereas retaining most of its vital data. This discount is important for QML fashions because of the restricted variety of qubits accessible on present quantum {hardware}.
Quantum function extraction can effectively map high-dimensional knowledge right into a lower-dimensional quantum area, enabling quantum fashions to course of advanced datasets with fewer sources. Deciding on probably the most related options can also be a method for optimizing quantum circuit complexity and useful resource allocation. In quantum machine studying, function choice helps in figuring out and using probably the most informative options, lowering the necessity for intensive quantum sources.
This course of not solely simplifies the quantum fashions but in addition enhances their efficiency by focusing the computational efforts on the options that contribute probably the most to the predictive accuracy of the mannequin.
Sources
Vasques, X., Paik, H. & Cif, L. Software of quantum machine studying utilizing quantum kernel algorithms on multiclass neuron M-type classification. Sci Rep 13, 11541 (2023). https://doi.org/10.1038/s41598-023-38558-z
This dataset used is licensed beneath a Inventive Commons Attribution 4.0 Worldwide (CC BY 4.0) license.
[ad_2]