反向函数以获取原始输入值
我有一个叫做 get_angles
的函数,它可以从 input_features
生成一些角度。这些函数返回的特征被用来训练一个变分量子电路。
def get_angles(x):
beta0 = 2 * np.arcsin(np.sqrt(x[1] ** 2) / np.sqrt(x[0] ** 2 + x[1] ** 2 + 1e-12))
beta1 = 2 * np.arcsin(np.sqrt(x[2] ** 2) / np.sqrt(x[2] ** 2 + x[2] ** 2 + 1e-12))
beta2 = 2 * np.arcsin(np.linalg.norm(x[2:]) / np.linalg.norm(x))
return np.array([beta2, -beta1 / 2, beta1 / 2, -beta0 / 2, beta0 / 2])
也就是说:
input_features = [10, 20, 30, 40, 50]`
# Transform the features
features = np.array(get_angles(input_features))
现在,我想把这个过程反过来,拿到最后的 features
值,然后把它们转换回最开始在 get_angles
函数中使用的 input_features
值。有没有办法可以反向操作上面定义的 get_angles
函数呢?
提前谢谢你。
我希望通过运行最终的 features
来得到 input_features
,所以我尝试了多个不同版本的 get_reverse_angles
函数,比如下面这个,但都没有成功。
def get_reverse_angles(angles):
# Extract the angles
beta2, neg_beta1, pos_beta1, neg_beta0, pos_beta0 = angles
# Solve for x using trigonometric equations
x0 = np.sqrt(2)
x1 = np.sin(beta2 / 2) * np.sqrt(2)
x2 = np.sin(pos_beta1 / 2) * np.sqrt(2)
x3 = np.sin(pos_beta0 / 2) * np.sqrt(2)
x4 = np.sin(neg_beta0 / 2) * np.sqrt(2)
# Compute x0 using the first equation
x0 = np.sqrt(x1 ** 2 + x2 ** 2 + x3 ** 2 + x4 ** 2)
# Return the values of the reversed operation
return np.array([x0, x1 * x0, x2 * x0, x3 * x0, x4 * x0])
这个 get_reverse_angles
函数返回了 [ 1.79350156 2.41835701 0.97063605 1.33346136 -1.33346136],而我期待的结果是 [10 20 30 40 50] 的 input_features
。
1 个回答
这个回答是根据@camaya的额外评论重新写的:
- 重载的get_angles_or_features函数看起来很有希望,几乎可以解决问题,只需要处理更大的输入特征,也就是
input_features = [22393, 22962, 22689, 21849, 20979]
。 - 考虑到input_features中只有一个样本,包含5个元素的5个数字,尝试一下可能值得。输入数据总是包含5个元素,并且是随机排序的。
那么我们有什么呢?
输入数据
input_features = [22393, 22962, 22689, 21849, 20979]
- 一组无序的整数。在
get_angles
函数中声明了三个变量:表格“输入数据恢复的阶段” 步骤 变量 参与计算的元素 1 beta0 input[1] & input[0] 可以用features[4]恢复 2 beta1 input[2] 不能用features[2]恢复,变化太多 3 beta2 input[:] 如果保存input[2],可以用(input[3], input[4])或(input[4], input[3])恢复features[0] (
input[:] == input_features ; def get_angles(x): return features[:]
)
步骤 1
import numpy as np
from datetime import datetime
from typing import Union, List
def get_angles_or_features(
input: Union[List[int], np.ndarray[float]]
) -> Union[np.ndarray, List, None]:
""""""
input_type = type(input).__name__
# Check type input
if not (input_type == 'ndarray' or input_type == 'list'):
print("Input Error")
return None
# Processing get angles
elif input_type == 'list':
beta0 = (
2 * np.arcsin((np.sqrt(input[1] ** 2))
/ np.sqrt(input[0] ** 2 + input[1] ** 2 + 1e-12)
)
)
beta1 = (
2 * np.arcsin(np.sqrt(input[2] ** 2)
/ np.sqrt(input[2] ** 2 + input[2] ** 2 + 1e-12)
)
)
beta2 = (
2 * np.arcsin(np.linalg.norm(input[2:]) / np.linalg.norm(input))
)
return np.array([beta2, -beta1 / 2, beta1 / 2, -beta0 / 2, beta0 / 2])
# Restoring data input_features
elif input_type == 'ndarray':
beta0 = input[4]
x0, x1, x2, x3, x4 = None, None, None, None, None
start1 = datetime.now()
for x0 in range(1, 100000):
for x1 in range(1, 100000):
if (check := beta0 == (
np.arcsin(np.sqrt(x1 ** 2)
/ np.sqrt(x0 ** 2 + x1 ** 2 + 1e-12)))):
break
if check:
print("We spent on the selection "
f"of the first two elements: {datetime.now() - start1}")
break
return [x0, x1, x2, x3, x4]
# input_features = [10, 20, 30, 40, 50]
input_features = [35, 50, 65, 80, 90]
# input_features = [22393, 22962, 22689, 21849, 20979]
# input_features = [5, 4, 3, 2, 1]
# input_features = [99960, 99970, 99980, 99990, 99999]
# input_features = [3, 2, 1, 5, 4]
# Transform the features
features = np.array(get_angles_or_features(input_features))
print(f"input_features >>> {input_features}")
print(f"features >>> {features}")
# Restoring the original data input_features
restored_features = get_angles_or_features(features)
print(f"restored_features >>> {restored_features}")
输出到控制台:
input_features >>> [35, 50, 65, 80, 90]
features >>> [ 2.3025178 -0.78539816 0.78539816 -0.96007036 0.96007036]
We spent on the selection of the first two elements: 0:00:25.827939
restored_features >>> [35, 50, None, None, None]
我们可以确保得到前两个元素,但为此我们使用了两个嵌套的for循环,这段代码在最坏情况下的时间复杂度是O(n^2)。
步骤 2
在第二步中无法确定第三个元素,只能减少第三步的迭代次数。
import numpy as np
from datetime import datetime
from typing import Union, List
def get_angles_or_features(
input: Union[List[int], np.ndarray[float]]
) -> Union[np.ndarray, List, None]:
""""""
input_type = type(input).__name__
# Check type input
if not (input_type == 'ndarray' or input_type == 'list'):
print("Input Error")
return None
# Processing get angles
elif input_type == 'list':
beta0 = (
2 * np.arcsin((np.sqrt(input[1] ** 2))
/ np.sqrt(input[0] ** 2 + input[1] ** 2 + 1e-12)
)
)
beta1 = (
2 * np.arcsin(np.sqrt(input[2] ** 2)
/ np.sqrt(input[2] ** 2 + input[2] ** 2 + 1e-12)
)
)
beta2 = (
2 * np.arcsin(np.linalg.norm(input[2:]) / np.linalg.norm(input))
)
return np.array([beta2, -beta1 / 2, beta1 / 2, -beta0 / 2, beta0 / 2])
# Restoring data input_features
elif input_type == 'ndarray':
beta0, beta1 = input[4], input[2]
x0, x1, x2, x3, x4 = None, None, None, None, None
# Step 1
start1 = datetime.now()
for x0 in range(1, 100000):
for x1 in range(1, 100000):
if (check := beta0 == (
np.arcsin(np.sqrt(x1 ** 2)
/ np.sqrt(x0 ** 2 + x1 ** 2 + 1e-12)))):
break
if check:
print("We spent on the selection "
f"of the first two elements: {datetime.now() - start1}"
)
break
# Step 2
start2 = datetime.now()
_x2 = tuple(x for x in range(1, 100000)
if beta1 == np.arcsin(np.sqrt(x ** 2)
/ np.sqrt(x ** 2 + x ** 2 + 1e-12)
)
)
end2 = datetime.now()
print("Reduced future iterations from 100000 "
f"to {(_len := len(_x2))} and wasted time: {end2 - start2}"
)
return [x0, x1, (type(_x2), f"len: {_len}"), x3, x4]
# input_features = [10, 20, 30, 40, 50]
input_features = [35, 50, 65, 80, 90]
# input_features = [22393, 22962, 22689, 21849, 20979]
# input_features = [5, 4, 3, 2, 1]
# input_features = [99960, 99970, 99980, 99990, 99999]
# input_features = [3, 2, 1, 5, 4]
# Transform the features
features = np.array(get_angles_or_features(input_features))
print(f"input_features >>> {input_features}")
print(f"features >>> {features}")
# Restoring the original data input_features
restored_features = get_angles_or_features(features)
print(f"restored_features >>> {restored_features}")
输出到控制台:
input_features >>> [35, 50, 65, 80, 90]
features >>> [ 2.3025178 -0.78539816 0.78539816 -0.96007036 0.96007036]
We spent on the selection of the first two elements: 0:00:26.472476
Reduced future iterations from 100000 to 43309 and wasted time: 0:00:00.814264
restored_features >>> [35, 50, (<class 'tuple'>, 'len: 43309'), None, None]
然而,43309次的第一次for循环迭代太耗费资源了...
这是因为只有一个元素input_features被用来计算beta1——这增加了反向变化的复杂性。
beta1 = 2 * np.arcsin(np.sqrt(x[2] ** 2) / np.sqrt(x[2] ** 2 + x[2] ** 2 + 1e-12))
如果可以接受为features添加一个元素以保持向后兼容,
那么变化性可以得到平衡。
步骤 3
from typing import Union, Tuple, List
from datetime import datetime
import numpy as np
def get_angles_or_features(
input: Union[List[int], np.ndarray[float]]
) -> Union[Tuple, None]:
""""""
input_type = type(input).__name__
# Check type input
if not (input_type == 'tuple' or input_type == 'list'):
print("Input Error")
return None
# Processing get angles
if input_type == 'list':
beta0 = (
2 * np.arcsin((np.sqrt(input[1] ** 2))
/ np.sqrt(input[0] ** 2 + input[1] ** 2 + 1e-12)))
beta1 = (
2 * np.arcsin(np.sqrt(input[2] ** 2)
/ np.sqrt(input[2] ** 2 + input[2] ** 2 + 1e-12)))
beta2 = (
2 * np.arcsin(np.linalg.norm(input[2:]) / np.linalg.norm(input)))
return (np.array([beta2, -beta1 / 2, beta1 / 2,
-beta0 / 2, beta0 / 2]), input[2])
# Conversion angles
elif input_type == 'tuple':
beta0, beta2 = input[0][4], input[0][0] / 2
x2 = int(input[-1])
start, end = (x2 - 3500 if x2 - 3500 >= 0 else 0,
x2 + 3501 if x2 + 3501 <= 43000 else 43000)
# Defining x0 & x1
_x0_x1 = tuple(
(x0, x1)
for x0 in range(start, end)
for x1 in range(start, end)
if (0.46 < x2 / (x0 + x1) < 0.51
and (beta0 == np.arcsin(np.sqrt(x1 ** 2)
/ np.sqrt(x0 ** 2 + x1 ** 2 + 1e-12)))
)
)[0]
x0, x1 = _x0_x1
# Defining x3 & x4
regeneraite_features = (
[x0, x1, x2, x3, x4]
for x3 in range(start, end)
for x4 in range(start, end)
if (0.5 < x2 / (x3 + x4) < 0.54
and (beta2 == np.arcsin(
np.linalg.norm([x2, x3, x4])
/ np.linalg.norm([x0, x1, x2, x3, x4])))
)
)
return tuple(regeneraite_features)
all_input_features = [
[20979, 20583, 19433, 18988, 18687],
[22689, 21849, 20979, 20583, 19433],
[22962, 22689, 21849, 20979, 20583],
[22393, 22962, 22689, 21849, 20979],
[21849, 20979, 20583, 19433, 18988]
]
if __name__ == "__main__":
for input_features in all_input_features:
# Transform the features
features = get_angles_or_features(input_features)
print(f"\ninput_features >>> {input_features}")
print(f"features >>> {features}")
start_time = datetime.now()
restored_features = get_angles_or_features(features)
# print(f"restored_features >>> {features}")
print(f"restored_features >>> {restored_features}")
print(f"Duration of the recovery process: {datetime.now() - start_time}")
输出到控制台:
input_features >>> [20979, 20583, 19433, 18988, 18687]
features >>> (array([ 1.6856525 , -0.78539816, 0.78539816, -0.77587052, 0.77587052]), 19433)
restored_features >>> ([20979, 20583, 19433, 18687, 18988], [20979, 20583, 19433, 18988, 18687])
Duration of the recovery process: 0:08:55.662949
input_features >>> [22689, 21849, 20979, 20583, 19433]
features >>> (array([ 1.68262106, -0.78539816, 0.78539816, -0.7665401 , 0.7665401 ]), 20979)
restored_features >>> ([22689, 21849, 20979, 19433, 20583], [22689, 21849, 20979, 20583, 19433])
Duration of the recovery process: 0:09:29.221780
input_features >>> [22962, 22689, 21849, 20979, 20583]
features >>> (array([ 1.69663709, -0.78539816, 0.78539816, -0.77941808, 0.77941808]), 21849)
restored_features >>> ([22962, 22689, 21849, 19089, 22347], [22962, 22689, 21849, 20583, 20979], [22962, 22689, 21849, 20979, 20583], [22962, 22689, 21849, 22347, 19089])
Duration of the recovery process: 0:09:36.666942
input_features >>> [22393, 22962, 22689, 21849, 20979]
features >>> (array([ 1.73553479, -0.78539816, 0.78539816, -0.79794298, 0.79794298]), 22689)
restored_features >>> ([22393, 22962, 22689, 20979, 21849], [22393, 22962, 22689, 21849, 20979])
Duration of the recovery process: 0:10:10.256594
input_features >>> [21849, 20979, 20583, 19433, 18988]
features >>> (array([ 1.68858074, -0.78539816, 0.78539816, -0.76508714, 0.76508714]), 20583)
restored_features >>> ([21849, 20979, 20583, 18988, 19433], [21849, 20979, 20583, 19433, 18988])
Duration of the recovery process: 0:09:07.385657
很好。 当你保存了input[2]
时,你有机会得到一个可以接受的结果,
但它仍然不是绝对完美的。
此外,恢复过程的持续时间仍然很长。
总结
我们必须经过这三个步骤来表明这种方法的有效性不足。
在处理将来需要的数据时,保持访问这些数据的机会。
至少这样...
from typing import List, Union, Tuple, Dict
import numpy as np
def get_angles(x: List[int]
) -> Union[Tuple[np.ndarray, tuple], Dict[tuple, list]]:
""""""
beta0 = 2 * np.arcsin(np.sqrt(x[1] ** 2) / np.sqrt(x[0] ** 2 + x[1] ** 2 + 1e-12))
beta1 = 2 * np.arcsin(np.sqrt(x[2] ** 2) / np.sqrt(x[2] ** 2 + x[2] ** 2 + 1e-12))
beta2 = 2 * np.arcsin(np.linalg.norm(x[2:]) / np.linalg.norm(x))
return (np.array([beta2, -beta1 / 2, beta1 / 2, -beta0 / 2, beta0 / 2]),
(x[0], x[1], x[2], x[3], x[4])
)
# or this way...
return {(x[0], x[1], x[2], x[3], x[4]):
[beta2, -beta1 / 2, beta1 / 2, -beta0 / 2, beta0 / 2]
}
你可以更进一步...
from typing import List
import numpy as np
@freeze_arguments
def get_angles(x: List[int]) -> np.ndarray:
""""""
beta0 = 2 * np.arcsin(np.sqrt(x[1] ** 2) / np.sqrt(x[0] ** 2 + x[1] ** 2 + 1e-12))
beta1 = 2 * np.arcsin(np.sqrt(x[2] ** 2) / np.sqrt(x[2] ** 2 + x[2] ** 2 + 1e-12))
beta2 = 2 * np.arcsin(np.linalg.norm(x[2:]) / np.linalg.norm(x))
return np.array([beta2, -beta1 / 2, beta1 / 2, -beta0 / 2, beta0 / 2])