PennyLane WireError求助:量子网络处理4D张量时设备无对应线路
问题分析与修复建议
报错pennylane.wires.WireError: Cannot run circuit(s) on default.qubit as they contain wires not found on the device的核心原因及修复点如下:
核心问题
- 量子设备wire数量未匹配:默认
default.qubit设备未指定足够的wire数,而你设置了n_qubits=32,电路尝试使用32及以上编号的wire但设备不支持。 - BatchNorm层类型误用:输入是4维张量
(32,32,128,2),经过Linear(2,32)后输出形状为(32,32,128,32),但BatchNorm2d是针对通道在第2维度(dim=1)的张量,此处通道在最后一维,类型不匹配。 - 输入维度与量子层不兼容:4维张量直接传入
TorchLayer会导致量子层无法正确解析每个样本的输入角度,需要调整维度适配量子电路的输入要求。 - 标签形状不匹配:输入总样本数为
32*32*128=131072,但标签形状未对应,会导致交叉熵损失计算报错。
修复步骤与完整代码
1. 定义带指定wire数的量子设备与qnode
显式创建支持32个wire的量子设备,并定义匹配输入输出的量子电路。
2. 修正BatchNorm层与维度处理
将BatchNorm2d替换为BatchNorm1d(指定通道维度为最后一维),并在forward中调整张量维度,确保量子层输入为(总样本数, n_qubits)的形状。
3. 匹配标签形状
生成与输入总样本数一致的标签张量。
完整修复代码:
import torch import torch.nn as nn import torch.nn.init as init import pennylane as qml import numpy as np # 全局参数定义 feat_dim = 2 n_qubits = 32 q_depth = 2 # 补充原代码未定义的q_depth参数 batch_size_total = 32 * 32 * 128 # 输入总样本数 # 1. 创建带指定wire数的量子设备与qnode dev = qml.device("default.qubit", wires=n_qubits) @qml.qnode(dev) def qnode(inputs, weights): # 角度嵌入:将每个输入对应到一个qubit的旋转角度 qml.AngleEmbedding(inputs, wires=range(n_qubits), rotation='Y') # 纠缠层:构建深度为q_depth的纠缠电路 qml.BasicEntanglerLayers(weights, wires=range(n_qubits)) # 返回每个qubit的Z期望测量值,共n_qubits个输出 return [qml.expval(qml.PauliZ(w)) for w in range(n_qubits)] # 2. 修正量子网络类 class Quantumnet(nn.Module): def __init__(self, feat_dim): super().__init__() self.pre_net = nn.Linear(feat_dim, n_qubits) # 使用BatchNorm1d,指定通道维度为最后一维 self.bn = nn.BatchNorm1d(n_qubits, dim=-1) # 初始化TorchLayer,参数形状匹配q_depth和n_qubits self.vqc = qml.qnn.TorchLayer(qnode, {"weights": (q_depth, n_qubits)}) self.post_net = nn.Linear(n_qubits, 2) self.ce = nn.CrossEntropyLoss() self.initialize_params() def initialize_params(self): for m in self.modules(): if isinstance(m, nn.Linear): init.xavier_normal_(m.weight.data) if m.bias is not None: m.bias.data.fill_(0) elif isinstance(m, nn.BatchNorm1d): m.running_mean.data.fill_(0) m.running_var.data.fill_(1) def forward(self, input_features, labels=None): # 保存原始形状,用于后续恢复 original_shape = input_features.shape # 将4维张量展平为(总样本数, feat_dim),适配Linear层 flat_input = input_features.flatten(0, -2) pre_out = self.pre_net(flat_input) pre_out = self.bn(pre_out) q_in = torch.tanh(pre_out) * np.pi / 2.0 # 量子层输出形状为(总样本数, n_qubits) q_out = self.vqc(q_in) post_out = self.post_net(q_out) # 计算损失,标签需与post_out的第一维度匹配 loss = self.ce(post_out, labels) if labels is not None else None # 恢复输出形状为(32,32,128,2),并计算差值 post_out = post_out.view(original_shape[0], original_shape[1], original_shape[2], 2) quantum_output = (post_out[:, :, :, 1] - post_out[:, :, :, 0]) return loss, quantum_output # 3. 初始化模型与输入数据 model = Quantumnet(feat_dim) input_features = torch.randn(32, 32, 128, feat_dim) # 生成匹配总样本数的标签 labels = torch.randint(2, (batch_size_total,), dtype=torch.long) # 测试模型 output = model(input_features, labels=labels) loss, quantum_output = output print('Quantum Output Tensor Shape:', quantum_output.shape) # 应为(32,32,128)
额外说明
- 原代码中
q_depth未定义,修复时补充了该参数,你可根据需求调整量子电路深度。 - 量子电路的结构(
AngleEmbedding、BasicEntanglerLayers)可根据任务需求替换为其他电路模板。 - 若需要保留4维张量的维度处理,也可通过转置操作将通道移至dim=1,再使用
BatchNorm2d,但展平后处理更简洁。
内容的提问来源于stack exchange,提问作者baba tnvn
相关产品推荐
相关产品推荐

