如何以有效的方式调整图像处理算法的参数?

时间:2012-11-30 11:06:28

标签: java statistics artificial-intelligence mathematical-optimization

在开始解决我的问题的解决方案之前,我只想确定我是否会“重新发明轮子”,如果我可以重复使用以前曾做过的工作。所以我的问题是:

我使用OpenCV库制作了图像匹配器。此匹配器接收一组图像文件,并尝试在数据库中查找类似的图像。最后,它根据ROC Curves定义返回统计结果(True Positive,True Negative,False Positive和False Negative of matches)。由于OpenCV的库算法参数值大约为10,因此这些结果可能会有所不同。这意味着参数调整将带来更多的True Positive匹配和更少的False Positive匹配。由于我必须调整或多或少10个参数,强力调节器将非常缓慢。蛮力我的意思是:

While(param1 < 50){
  While(param2 < 50){
    While(param3 < 50){
      …
      PerformMatching();
      param3 +=2;
    }
    param2++;
  }
  pram1 +=5;
}

我想要做的是随机选择参数,然后分析统计结果是否变得更好。然后这个分析将有助于改变随机生成参数的方法,以便选择更好的参数。

所以我的问题是Java中是否有库或者是否存在任何AI算法,它会根据对True Positive和False Positive值的评估返回更好的参数集?

可以感谢一些帮助,谢谢。

2 个答案:

答案 0 :(得分:4)

爬山

您可以尝试一些随机优化算法,例如Hill Climbing,其中您从随机解决方案(如@Don Reba指出)开始,并查看相邻解决方案的集合到成本函数。我将使用一些示例python代码来解释这个想法。

获取邻居解决方案

对于你的邻居,你可以使用一个简单的函数,如:

n_params = 5  # number of parameters
upper_bound = 5  # upper limit of your parameters
lower_bound = 0  # lower limit of your parameters

def get_neighbors(solution):
    neighbors = []
    for i in range(n_params):
        x = copy.deepcopy(solution)
        if x[i] < upper_bound:
            x[i] += 1 # increment one of the components
            neighbors.append(x)
        x = copy.deepcopy(solution)
        if x[i] > lower_bound:
            x[i] -= 1 # decrement one of the components
            neighbors.append(x)
    return neighbors 

如果您有[1,3,4,2,2]的当前解决方案,通过递增或递减任何组件,您将得到10个不同的邻居,如下所示:

 [2, 3, 4, 2, 2],
 [0, 3, 4, 2, 2],
 [1, 4, 4, 2, 2],
 [1, 2, 4, 2, 2],
 [1, 3, 5, 2, 2],
 [1, 3, 3, 2, 2],
 [1, 3, 4, 3, 2],
 [1, 3, 4, 1, 2],
 [1, 3, 4, 2, 3],
 [1, 3, 4, 2, 1]

这里我们假设每个参数都是整数。您可以通过调整步长(例如0.05)来获得更大的粒度。

爬山的迭代

def hill_climb():
    initial_solution = np.random.randint(lower_bound, upper_bound, n_params)
    current_solution = initial_solution
    print 'initial solution', initial_solution
    current_cost = get_cost(initial_solution)
    step = 1
    while True:
        #try to replace each single component w/ its neighbors
        lowest_cost = current_cost
        lowest_solution = current_solution
        print 'hill-climbing cost at step %6d: %d' % (step, lowest_cost)
        neighbors = get_neighbors(current_solution)
        for new_solution in neighbors:
            neighbor_cost = get_cost(new_solution)
            if neighbor_cost < lowest_cost:
                lowest_cost = neighbor_cost
                lowest_solution = new_solution

        if lowest_cost >= current_cost:
            break
        else: 
            current_solution= lowest_solution
            current_cost = lowest_cost
            step += 1
    return current_solution

成本函数

为了完整起见,我将使用自己的成本函数(仅用于演示目的),即

f(x) = x1^1 - x2^2 + x3^3 - x4^4 + x5^5

那是:

def get_cost(solution):
    cost = 0
    for i,param in enumerate(solution):
        cost += (-1.)**i * param**(i+1)  
    return cost

优化结果:

结果如下。我们使用[4,0,1,3,1]的随机初始猜测。在14个步骤(14 * 10 = 140个邻居的评估)之后,我们找到[0,5,0,5,0]的最佳答案,其使成本最小化。对于蛮力,您必须评估6 ^ 6 = 46656解决方案。当您拥有高维解决方案时,可以节省更多的运行时间。

注意,因为这是一个随机方法,所以找到局部最小值作为最终结果(尽管有时它与全局最小值相同,但不能保证)。但实际上它已经足够好了。

initial solution:               [4 0 1 3 1]
hill-climbing cost at step      1: -75
hill-climbing cost at step      2: -250
hill-climbing cost at step      3: -619
hill-climbing cost at step      4: -620
hill-climbing cost at step      5: -621
hill-climbing cost at step      6: -622
hill-climbing cost at step      7: -623
hill-climbing cost at step      8: -624
hill-climbing cost at step      9: -627
hill-climbing cost at step     10: -632
hill-climbing cost at step     11: -639
hill-climbing cost at step     12: -648
hill-climbing cost at step     13: -649
hill-climbing cost at step     14: -650
Final solution:                 [0 5 0 5 0]

相关文章

这里有一个相关但更复杂的问题:Algorithm for selecting n vectors out of a set while minimizing cost

上面的所有代码都可以找到here

答案 1 :(得分:3)

有一系列算法优化技术,从您的示例中的简单网格搜索到各种自适应算法。如果您想了解更高级的技术,我建议您首先查看Frank Hutter的研究。他的PhD thesis包含对该领域的精彩概述。

如果您不想花太多时间,那么您可以做的一项重大改进是随机生成参数,而不是使用常规网格。这样,如果某些参数变得不重要,那么您就不会浪费时间来保持其他参数的固定。你想要这样的东西:

param1 = random.Next(50);
param2 = random.Next(50);
...
PerformMatching();

这种方法的另一个优点是,您可以根据需要收集样本点,而不必等到整个网格被探索。使用quasi-random参数序列可以做得更好,这样可以保持点均匀分布。有些库可以为您生成这些库。

生成积分后,您可以选择最佳组合,或使用图形工具分析它们或使用模式查找算法,例如MeanShift。