我尝试使用DEAP库最小化自定义函数来执行多目标优化。虽然我在最小化几个目标(目标)时得到了不错的结果,但是超过3或4个目标却未能收敛。通常情况下,它会将第一个目标最小化为0,同时让其他目标反弹(不是最小化)。
我使用sci-kit库构建了一个元模型(岭回归)来描述一些模拟数据,因此我的模型基于系数和截距(包含在我的代码中)。新预测基于~150个输入,这些输入均匀变化。
有一个年份选项最小化3个目标,一个月选项最小化8个目标。
我已将代码作为要点包含在内,因为它非常大。 请找到它HERE。
问题: 任何人都知道剩下的目标没有被最小化的原因是什么?我尝试过选择,变异和交叉过程,但还没有运气。或者它可能与模型本身有关?我也为健身尝试了不同的重量,但由于某种原因,它似乎没有什么作用。
答案 0 :(得分:1)
回答我自己的问题。
在评估期间,我似乎没有返回正确的价值观。
改变差异的RMSE而不是目标和预测之间的绝对差异就可以了:
def EvaluateObjective(individual):
prediction = calculate(individual, for_sensitivity)
prediction = [int(i) for i in prediction]
# diff = []
# for y in range(len(targets)):
# output = math.sqrt((targets[y] - prediction[y]) ** 2)
# #output = abs(targets[y] - prediction[y])
# diff.append(output)
rmse = np.sqrt((sum((i - j)**2 for i, j in zip(prediction, targets)) / len(targets)))
return (rmse,)
答案 1 :(得分:0)
你给我解决了我一直在努力解决的完全相同的问题。不错的方法,一个小技巧也让我的程序工作了!
我很确定必须有很多deap用户试图像我一样使用权重=( - 1.0,-1.0,1.0)这两个权重。
我将发布3个参数的简单示例(最小化2个参数,最大化1个参数。)
示例是关于"如何在最大重量,最大尺寸条件下加载尽可能多的物品"
条件:
from numpy import array
import numpy
import random
from deap import base, creator, tools, algorithms
### Multi-objective Optimization Problem ###
IND_INIT_SIZE = 5
MAX_WEIGHT = 2000 # kg
MAX_SIZE = 1500 # m**3
# Create the item dictionary:
r = array([[213, 508, 22], # 1st arg : weight / 2nd arg : size / 3rd arg : value
[594, 354, 50],
[275, 787, 43],
[652, 218, 46],
[728, 183, 43],
[856, 308, 33],
[727, 482, 45],
[762, 683, 26],
[707, 450, 19],
[909, 309, 45],
[979, 247, 42],
[259, 705, 42],
[260, 543, 14],
[899, 825, 17],
[446, 360, 35],
[491, 818, 47],
[647, 404, 17],
[604, 623, 32],
[900, 840, 45],
[374, 127, 33]] )
NBR_ITEMS = r.shape[0]
items = {}
# Create random items and store them in the items' dictionary.
for i in range(NBR_ITEMS):
items[i] = ( r[i][0] , r[i][1] , r[i][2] )
creator.create("Fitness", base.Fitness, weights=(-1.0, 1.0 )) # Note here <- I used only two weights! (at first, I tried weights=(-1.0 , -1.0, 1.0)) but it crashes. With deap, you cannot do such a thing.
creator.create("Individual", set, fitness=creator.Fitness)
toolbox = base.Toolbox()
# Attribute generator
toolbox.register("attr_item", random.randrange, NBR_ITEMS)
# Structure initializers
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_item, n=IND_INIT_SIZE) #
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
def evaluation(individual):
weight = 0.0
size =0.0
value = 0.0
# Maximize or Minimize Conditions
for item in individual:
weight += items[item][0] # It must be minimized.
size += items[item][1] # It must be minimized.
value += items[item][2] # It must be maximized.
# Limit Conditions
if weight > MAX_WEIGHT or size > MAX_SIZE:
return 10000, 0
if value == 0:
value = 0.0000001
MinFitess_score = weight + size # NOTE : Minimize weight, size
MaxFitenss_score = value # NOTE : Maximize weight, size
return MinFitess_score , MaxFitenss_score,
def cxSet(ind1, ind2):
"""Apply a crossover operation on input sets. The first child is the
intersection of the two sets, the second child is the difference of the
two sets.
"""
temp = set(ind1) # Used in order to keep type
ind1 &= ind2 # Intersection (inplace)
ind2 ^= temp # Symmetric Difference (inplace)
return ind1, ind2
def mutSet(individual):
"""Mutation that pops or add an element."""
if random.random() < 0.5:
if len(individual) > 0: # We cannot pop from an empty set
individual.remove(random.choice(sorted(tuple(individual))))
else:
individual.add(random.randrange(NBR_ITEMS))
return individual, # NOTE comma(,) , if there's no comma, an error occurs.
toolbox.register("mate", cxSet)
toolbox.register("mutate", mutSet)
toolbox.register("select", tools.selNSGA2) # NSGA-2 applies to multi-objective problems such as knapsack problem
toolbox.register("evaluate", evaluation)
def main():
ngen = 300 # a number of generation < adjustable value >
pop = toolbox.population(n= 300)
hof = tools.ParetoFront() # a ParetoFront may be used to retrieve the best non dominated individuals of the evolution
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", numpy.mean, axis=0)
stats.register("std", numpy.std, axis=0)
stats.register("min", numpy.min, axis=0)
stats.register("max", numpy.max, axis=0)
algorithms.eaSimple(pop, toolbox, 0.7, 0.2, ngen=ngen, stats=stats, halloffame=hof, verbose=True)
return hof, pop
if __name__ == "__main__":
hof, pop = main()
print(hof) # non-dominated individuals' list # the fittest value is placed on the most right side.
理想的结果:
因为他们的总得分非常相似。你会得到一个结果。