【问题标题】:Minimizing multi-objective function using DEAP使用 DEAP 最小化多目标函数
【发布时间】:2017-12-29 06:19:46
【问题描述】:

我正在尝试通过使用DEAP 库最小化自定义函数来执行多目标优化。尽管在最小化多个目标(目标)时我得到了不错的结果,但对于超过 3 或 4 个它无法收敛。通常它会将第一个目标最小化为 0,同时让其他目标反弹(而不是最小化)。

我使用sci-kit 库构建了一个元模型(岭回归)来描述一些模拟数据,因此我的模型基于系数和截距(包含在我的代码中)。新预测基于约 150 个均匀变化的输入。

有一个最小化 3 个目标的年份选项和一个最小化 8 个目标的月份选项。

我已将我的代码作为要点包含在内,因为它相当大。 请找到HERE

问题: 任何人都知道剩余目标未被最小化的原因可能是什么?我尝试过选择、变异和交叉过程,但还没有运气。还是可能与模型本身有关?我也尝试过不同的健身重量,但由于某种原因,它似乎没有什么不同。

年度目标的结果:

每月目标的结果:

【问题讨论】:

    标签: python scikit-learn deap


    【解决方案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,)
    

    【讨论】:

      【解决方案2】:

      您为我解决了我一直在努力解决的完全相同的问题。不错的方法,一个小技巧让我的程序也能正常运行!

      我很确定一定有很多笨蛋用户像我一样尝试使用两个以上的权重,例如 weights=(-1.0, -1.0, 1.0)。

      我将发布3个参数的简单示例(2个参数最小化,1个参数最大化。)

      • 示例是关于“如何在最大重量、最大尺寸的条件下装载尽可能多的物品”

      • 条件:

        1. 最小化权重总和。
        2. 最小化大小总和。
        3. 最大化值的总和。
      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.
      

      理想的结果:

      1. 个人({1, 2, 19, 4}) 或
      2. 个人({1, 2, 19, 3})

      因为他们的总分非常相似。您将获得其中一项结果。

      【讨论】:

      • 与 Chirs 评估分数不同(使用 RMSE),在我的情况下,我将分数分为“MinFitess_score = weight + size”和“MaxFitenss_score = value”:) 这样我就可以让 GA 使用“权重=(-1.0 , 1.0)"
      猜你喜欢
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 2014-12-04
      • 2018-06-25
      • 2021-09-08
      • 1970-01-01
      相关资源
      最近更新 更多