- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 MAP-Elites 进化策略和多项式变异算子(如 here 在第 2 点定义)来实现进化算法,如 this 中所述。纸。我创建了三个不同的 MNIST 模型,并使用 Keras API 使用tensorflow==2.0.0a 对其进行训练。这些模型表现良好(准确率均在 95% 左右)。
我对上述进化策略的理解是,我们创建一个起始种群,然后在每次迭代中从该种群中随机选择一个样本进行变异。如果突变后,新样本确定属于任何类别,高于之前为该类别选择的最佳样本,那么我们将其视为最佳样本并将其添加到种群中。预期的结果是,算法完成后,我们应该为每个类别提供一个样本,并能够高度确定地分类到该类别中。创建的初始图像群是使用均匀分布创建的。
问题是我的模型将均匀分布创建的随机输入始终高度确定地分类为同一类(即 CNN 模型始终将其分类为 8)。因此,即使在初始种群和迭代次数很大(即 1000 个起始样本和 20000 次迭代)之后,我最终得到的大多数或所有样本都被分类为同一类(属于其他类的确定性略有不同)。
输入样本标准化为范围 [0.0, 1.0]。为了简化起见,下面的所有推理都仅限于底部描述的密集模型(CNN 和简化的 LeNet5 产生类似的结果)。
使用平均值 = 0.0 和 stddev = 0.3 或平均值 = 0.5 和 stddev = 0.3 的正态分布来生成起始群体和 0.3 的突变机会(而不是论文中的 0.1)会产生类似的结果。
我尝试使用 (1 , λ) 进化策略,仅针对一个类(起始种群 100、100 代),它比下面实现的 MAP-精英产生更好的结果(我可以为多个类生成样本)。
我尝试不规范模型的数据并使用 [0, 255] 范围再次训练它,但结果几乎相同。我还尝试使用高斯变异算子而不是多项式,但似乎没有太大区别。
当训练似乎没有效果时关闭数据增强。
这是我编写的实现。
def evolutionary_attack(model, population_size, generations_nmb, min=0.0, max=1.0, mutation_chance=0.1, mutation_power=15):
population = [] #
best_in_class = {} #dictionary of specimen performing best for given class
for x in range(population_size):
population.append(np.random.uniform(min, max, model.get_input_shape())) #initialize specimens with random values
# population.append(np.random.normal(0.0, 0.3, model.get_input_shape())) #initialize specimens with random values
for i in range(generations_nmb):
current_specimen = random.choice(population) #choose specimen at random from the population
mutated_specimen = mutate_specimen(current_specimen, min, max, mutation_chance, mutation_power)
logits = model(tf.expand_dims(tf.convert_to_tensor(mutated_specimen, dtype=tf.float32), 0))
certainties_per_class = tf.squeeze(logits).numpy()
for cur_class in range(len(certainties_per_class)):
if cur_class in best_in_class:
_, best_certainty = best_in_class[cur_class]
if certainties_per_class[cur_class] > best_certainty:
#if the new specimen performs better in given class make it a new best and add it to the population
best_in_class[cur_class] = (mutated_specimen, certainties_per_class[cur_class])
population.append(mutated_specimen)
else:
best_in_class[cur_class] = (mutated_specimen, certainties_per_class[cur_class]) #handles the case when there is no best specimen for the given class
def mutate_specimen(specimen, min, max, mutation_chance, mutation_power=15):
specimen = np.copy(specimen)
with np.nditer(specimen, op_flags=['readwrite']) as it:
for old_val in it:
if np.random.uniform() < mutation_chance:
u = np.random.uniform()
if u <= 0.5:
delta = ((2.0 * u) ** (1.0 / (mutation_power))) - 1.0
new_val = old_val + delta * (old_val - min)
else:
delta = 1.0 - (2 * (1 - u))** (1 / (1 + mutation_power))
new_val = old_val + delta * (max - old_val)
old_val[...] = new_val
return np.clip(specimen, min, max)
在论文中,作者表示,在 50 代后,他们能够以 >99.99% 的置信度分类每个数字的样本。这与我得到的结果有很大不同。看来我做错了什么,但我无法查明问题所在。我不确定这是否只是代码中的一些小错误,还是我的实现背后的推理错误。
我的模型是这样构造的
input_1 (输入层) [(无, 28, 28, 1)] 0
<小时/>压平(压平)(无,784)0
<小时/>密集(密集)(无,784)615440
<小时/>dense_1(密集)(无,800)628000
<小时/>dense_2(密集)(无,800)640800
<小时/>dense_3(密集)(无,10)8010
它已经使用 Adam 优化器通过数据增强进行了多个时期的训练。
编辑:我刚刚注意到我没有在突变后剪切样本的值。如果我这样做,那么使用正态分布会产生与使用均匀分布类似的结果。我在发布的代码中修复了这个问题。愚蠢的错误
最佳答案
我认为您误解了 MAP-精英。您正在与精英分开跟踪仅附加人群,但根据 this reference你应该只追踪精英。所以我认为选择当前样本的行应该是:
current_specimen, _ = random.choice(list(best_in_class.values()))
因此 MNIST 的最大群体规模为 10。我不能 100% 确定这是您的主要问题,但它至少应该使算法更加贪婪,使搜索远离最旧的解决方案。
再考虑一下这个问题,我不确定为什么这个方法应该在具有直接像素参数的 MNIST 上工作。仅通过随机突变生成不同的数字是非常不可能的,尤其是在对同一类进行了几步优化之后,所有其他类都保持为空。
看来您的实现实际上根据论文正确地完成了这部分:
[...] and replaces the current champion for any objective if the new individual has higher fitness on that objective.
但在最初的 MAP-Elites 中,目标是跟踪整个人群的单一全局健身指标。某些单元格可能仍为空,因为从未将任何解决方案映射到该单元格。该论文实际上跟踪了每个细胞的不同适应度指标。这应该被更突出地表述为 MAP-Elites 的修改。通过此修改,这似乎应该可行,但允许空单元格不再有意义。
关于python - 使用进化算法实现对抗性示例生成器表现不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56105489/
我是一名优秀的程序员,十分优秀!