我试图在以下文章中实现第8页所列的电路:https://arxiv.org/pdf/1905.10876.pdf使用Tensorflow量子(TFQ)。我以前已经这样做的一个子集的电路使用Qiskit,并以准确的结果,可以在第14页上找到以下论文:https://arxiv.org/pdf/2003.09887.pdf。在TFQ中,我的准确性很低。我认为这是因为在TFQ中,我只在第一个量子位上使用了一个可观测的Pauli Z算子,而电路似乎并没有将所有的知识“传递给第一个量子位”。我把这个放在引号里,因为我确信有更好的方法来描述这一点。另一方面,在Qiskit中,16个状态(4^2)被映射到两个状态。
我的问题:我怎样才能恢复我的精确性?
潜在答案( a):将所有信息“传输”到单个量子位(可能是ancilla qubit )的方法,并对该量子位进行读出。
( b)在所有量子位上放置一个可观察到的Pauli Z(总共4),将16种状态中的一半映射到标签0,另一半映射到标签1。我在下面的代码中尝试了这一点。
(我试图回答b):
我有一个用Tensorflow实现的Tensorflow量子(TFQ)电路。这个电路有多个可观测值,我试图在我的损失函数中把它集合起来。我更喜欢使用尽可能多的标准组件,但需要将我的量子态映射到标签以确定损失。我想我所要达到的并不是TFQ所独有的。我定义我的模型的方式如下:
def circuit():
data_qubits = cirq.GridQubit.rect(4, 1)
circuit = cirq.Circuit()
...
return circuit, [cirq.Z(data_qubits[0]), cirq.Z(data_qubits[1]), cirq.Z(data_qubits[2]), cirq.Z(data_qubits[3])]
model_circuit, model_readout = circuit()
model = tf.keras.Sequential([
tf.keras.layers.Input(shape=(), dtype=tf.string),
# The PQC layer returns the expected value of the readout gate, range [-1,1].
tfq.layers.PQC(model_circuit, model_readout),
])
# compile model
model.compile(
loss = loss_mse,
optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
metrics=[])在loss_mse (均方误差)中,我得到了y_pred的(32,4)张量。一行看起来就像
[-0.2, 0.33, 0.6, 0.3]这必须首先从-1,1映射到一个0,1的二进制版本,这样看起来如下:
[0, 1, 1, 1]现在,需要进行一个表查找,它告诉这个组合是0还是1。最后,常规的(y_true-y_pred)^2可以由该行执行,然后在所有行上执行np.sum。我试图实现这一点:
def get_label(measurement):
if measurement == [0,0,0,0]: return 0
...
elif measurement == [1,1,1,1]: return 0
else: return -1
def py_call(y_true, y_pred):
# cast tensor to numpy
y_pred_np = np.asarray(y_pred)
loss = np.zeros((len(y_pred))) # could be a single variable with += within the loop
# evalaute all 32 samples
for pred in range(len(y_pred_np)):
# map, binarize and lookup
y_labelled = get_label([0 if y<0 else 1 for y in y_pred_np[pred]])
# regular loss comparison
loss[pred] = (y_labelled - y_true[pred])**2
# reduce
loss = np.sum(loss)/len(y_true)
return loss
@tf.function
def loss_mse(y_true, y_pred):
external_list = []
loss = tf.py_function(py_call, inp=[y_true, y_pred], Tout=[tf.float64])
return loss然而,该系统似乎仍然期待一个(32,4)张量。我本以为我可以提供一个单一的损失值(浮动)。我的问题是:如何将y_true的多个值映射到单个数字,以便与tensorflow损失函数中的单个y_pred值进行比较?
发布于 2020-07-10 01:44:04
看起来这里发生了几件事。回答你的问题
如何将y_true的多个值映射到单个数字,以便与tensorflow损失函数中的单个y_pred值进行比较?
您可能需要的是某种tf.reduce_*函数,如tf.reduce_mean或tf.reduce_sum。这个函数将允许您在给定的张量轴上应用这个缩减运算,使您能够将形状张量(32,4)转换为形状张量(32 )或形状张量(4,)。下面是一个简短的片段:
@tf.function
def my_loss(y_true, y_pred):
# y_true is shape (32, 4)
# y_pred is shape (32, 4)
# Scale from [-1, 1] to [0, 1]
y_true += 1
y_true /= 2
y_pred += 1
y_pred /= 2
# These are now both (32,) with the reduction of taking the mean applied along
# the second axis.
reduced_true = tf.reduce_mean(y_true, axis=1)
reduced_pred = tf.reduce_mean(y_pred, axis=1)
# Now a scalar loss.
loss = tf.reduce_mean((reduce_true - reduced_pred) ** 2)
return loss现在,上面的内容并不完全是您想要的,因为对于我来说,至少对于像[0,1,1,1] -> 0和[0,0,0,0] -> 1这样的东西,您所想到的确切的还原规则并不是非常清楚。
我还要提到的另一件事是,如果您只想得到cirq中这些Pauli运算符的和,在列表[cirq.Z(data_qubits[0]), cirq.Z(data_qubits[1]), cirq.Z(data_qubits[2]), cirq.Z(data_qubits[3])]中有一个逐项的项,而您所关心的只是这些期望的最后和,那么您可以很容易地做到:
my_operator = sum([cirq.Z(data_qubits[0]), cirq.Z(data_qubits[1]),
cirq.Z(data_qubits[2]), cirq.Z(data_qubits[3])])
print(my_op)它应该提供如下内容:cirq.PauliSum(cirq.LinearDict({frozenset({(cirq.GridQubit(0, 0), cirq.Z)}): (1+0j), frozenset({(cirq.GridQubit(0, 1), cirq.Z)}): (1+0j), frozenset({(cirq.GridQubit(0, 2), cirq.Z)}): (1+0j), frozenset({(cirq.GridQubit(0, 3), cirq.Z)}): (1+0j)}))
它也可以作为PQC层中的读出操作。最后,如果建议阅读下面的一些片段和示例:https://www.tensorflow.org/quantum/api_docs/python/tfq/layers/PQC
在这里:
https://www.tensorflow.org/quantum/api_docs/python/tfq/layers/Expectation
它很好地描述了函数的输入和输出签名,以及您可以期望它们的形状。
https://stackoverflow.com/questions/62794947
复制相似问题