如何在 tensorflow-probability 中限制 differential_evolution_minimize 的输入维度?

How to bound input dimension for differential_evolution_minimize in tensorflow-probability?

与差分进化 (DE) 的 scipy's implementation 不同,没有直接的方法为我的输入定义边界 在 tensorflow-probability

因为我函数的输入是定义图像中像素的 5 元组 (x,y,R,G,B),这些值需要是整数并限制在我的图像维度以及优化期间 0 到 255 的 RGB 值。

描绘大局: 我想最小化图像分类器的置信度,它本身是强化学习代理的一部分,需要根据对环境的观察来决定采取什么行动。该代理已经过全面训练,但现在我想通过在其观察中扰动单个像素并监控其性能来抛出一些石头。

我想使用差分进化算法找到最能降低代理对其行为的信心的像素。

目前我有一个动作预测函数,它将扰动像素作为参数,通过分类器运行扰动观察,returns 代理在没有扰动:

代码块 I

#random perturbation pixel as an example of my input:
pixel = tf.constant([36,48,255,255,255]) # (x,y,R,G,B)

def predict_action(pixel):
   perturbed_obs = perturb_obs(pixel, observation)
   confidence = classifier(perturbed_obs)
   return confidence

现在我想将此函数提供给具有初始填充的优化器:

代码块 II

popsize=80

init_pop = generate_population(popsize)
# returns Tensor("scan/while/Squeeze:0", shape=(80, 5), dtype=int64)
# i.e. 80 random perturbation pixels

results = tfp.optimizer.differential_evolution_minimize(
    predict_action, initial_population=init_pop, seed=42)

但是,如何定义输入的边界,使总体始终是有效像素?

我在 GitHub 上问过这个问题,实现这一点的可能方法是使用它们的双射器功能:

代码块 III

# First we squash `pixel_logits` to (0, 1), then scale it to (0, 255).
bijector = tfb.Affine(scale=255.)(tfb.Sigmoid())

def unconstrained_objective_fn(pixel_logits):
    return objective_fn(bijector.forward(pixel_logits))

results = minimize(unconstrained_objective_fn, initial_position=bijector.inverse(initial_pixels))
pixels = bijector.forward(results.position)

虽然我原则上理解该方法,但我未能将其应用于我当前的 situation/understanding 我的问题。

编辑:删除了与主要问题无关的信息。始终注意您的类型和尺寸!

根据我使用 tfp-0.6 和 tf-1.13.1 的经验,代码块 III 可以重写如下:

width = ... #some Python float
height = ... #some other Python float

bijectors = [
    tfb.Chain([tfb.AffineScalar(scale=width), tfb.Sigmoid()]),
    tfb.Chain([tfb.AffineScalar(scale=height), tfb.Sigmoid()]),
    tfb.Chain([tfb.AffineScalar(scale=255.), tfb.Sigmoid()]),
    tfb.Chain([tfb.AffineScalar(scale=255.), tfb.Sigmoid()]),
    tfb.Chain([tfb.AffineScalar(scale=255.), tfb.Sigmoid()])
  ]

def constrained_objective_fn(pixel_logits):
    constrained_pixel_logits = [b.forward(p) for b, p in zip(bijectors, pixel_logits)]
    return objective_fn(constrained_pixel_logits)

results = tfp.optimizer.differential_evolution_minimize(
constrained_objective_fn, 
initial_population=init_pop, 
seed=42)

pixels = [b.forward(p) for b, p in zip(bijectors, results.position)]

请注意,代码块 II 中的初始种群已保留,bijector.inverse 未应用。

这似乎是一个常规的 dtype 错误:您似乎将 tf.int64 类型传递给微分进化的初始 position/population 参数,而它期望(可以理解)浮点张量。这是适合我的最终代码片段版本:

initial_pixels = 0.5

bijector = tfb.AffineScalar(scale=255.)(tfb.Sigmoid())

def objective_fn(pixels):
  return tf.square(pixels - 0.75)

def unconstrained_objective_fn(pixel_logits):
    return objective_fn(bijector.forward(pixel_logits))

results = tfp.optimizer.differential_evolution_minimize(unconstrained_objective_fn, initial_position=bijector.inverse(initial_pixels))
pixels = bijector.forward(results.position)
print(pixels)