|
import torch |
|
import torchvision |
|
import gradio as gr |
|
import torch.nn as nn |
|
import pennylane as qml |
|
import matplotlib.pyplot as plt |
|
|
|
from pennylane import numpy as np |
|
from torchvision import transforms |
|
|
|
qubits = 4 |
|
batch_size = 8 |
|
depth = 6 |
|
delta = 0.01 |
|
|
|
is_cuda_available = torch.cuda.is_available() |
|
device = torch.device("cuda:0" if is_cuda_available else "cpu") |
|
|
|
if is_cuda_available: |
|
print ("CUDA is available, selected:", device) |
|
else: |
|
print ("CUDA not available, selected:", device) |
|
|
|
dev = qml.device("default.qubit", wires=qubits) |
|
|
|
def H_layer(nqubits): |
|
for idx in range(nqubits): |
|
qml.Hadamard(wires=idx) |
|
|
|
def RY_layer(w): |
|
for idx, element in enumerate(w): |
|
qml.RY(element, wires=idx) |
|
|
|
def entangling_layer(nqubits): |
|
for i in range(0, nqubits - 1, 2): |
|
qml.CNOT(wires=[i, i + 1]) |
|
for i in range(1, nqubits - 1, 2): |
|
qml.CNOT(wires=[i, i + 1]) |
|
|
|
@qml.qnode(dev, interface="torch") |
|
def quantum_net(q_input_features, q_weights_flat): |
|
q_weights = q_weights_flat.reshape(depth, qubits) |
|
H_layer(qubits) |
|
RY_layer(q_input_features) |
|
|
|
for k in range(depth): |
|
entangling_layer(qubits) |
|
RY_layer(q_weights[k]) |
|
|
|
exp_vals = [qml.expval(qml.PauliZ(position)) for position in range(qubits)] |
|
return tuple(exp_vals) |
|
|
|
class QuantumNet(nn.Module): |
|
def __init__(self): |
|
super().__init__() |
|
self.pre_net = nn.Linear(512, qubits) |
|
self.q_params = nn.Parameter(delta * torch.randn(depth * qubits)) |
|
self.post_net = nn.Linear(qubits, 2) |
|
|
|
def forward(self, input_features): |
|
pre_out = self.pre_net(input_features) |
|
q_in = torch.tanh(pre_out) * np.pi / 2.0 |
|
q_out = torch.Tensor(0, qubits) |
|
q_out = q_out.to(device) |
|
for elem in q_in: |
|
q_out_elem = quantum_net(elem, self.q_params).float().unsqueeze(0) |
|
q_out = torch.cat((q_out, q_out_elem)) |
|
return self.post_net(q_out) |
|
|
|
def classify(image): |
|
mhModel = torch.load("QKTCC_simPennylane-26032022174332.pth", map_location=device) |
|
mMModel = torchvision.models.resnet18(pretrained=True) |
|
for param in mMModel.parameters(): |
|
param.requires_grad = False |
|
mMModel.fc = QuantumNet() |
|
mMModel = mMModel.to(device) |
|
qModel = mMModel |
|
qModel.load_state_dict(mhModel) |
|
|
|
from PIL import Image |
|
|
|
data_transforms = transforms.Compose([ |
|
transforms.Resize(256), |
|
transforms.CenterCrop(224), |
|
transforms.ToTensor(), |
|
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), |
|
]) |
|
|
|
PIL_img = image |
|
img = data_transforms(PIL_img) |
|
img_input = img.unsqueeze(0) |
|
|
|
qModel.eval() |
|
with torch.no_grad(): |
|
outputs = qModel(img_input) |
|
base_labels = (("mask", outputs[0, 0]), ("no_mask", outputs[0, 1])) |
|
expvals, preds = torch.max(outputs, 1) |
|
expvals_min, preds_min = torch.min(outputs, 1) |
|
if expvals == base_labels[0][1]: |
|
labels = base_labels[0][0] |
|
else: |
|
labels = base_labels[1][0] |
|
outp = "Classified with output: " + labels + ", Tensor: " + str(expvals) + " (" + str(expvals_min) + ")" |
|
return outp |
|
|
|
out = gr.outputs.Label(label='Result: ',type='auto') |
|
iface = gr.Interface(classify, gr.inputs.Image(type="pil"), outputs=out, |
|
title="Quantum Layered TL RN-18 Face Mask Detector", |
|
description="🤗 This proof-of-concept quantum machine learning model takes a face image input and detects a face that has a mask or no mask: ", theme="default") |
|
|
|
iface.launch(debug=True) |