当前位置:   article > 正文

从几个简单例子谈随机优化技术

随机优化

1. 关于随机优化(stochastic optimization)

随机优化技术常被用来处理协作类问题,它特别擅长处理:受多种变量的影响,存在许多可能解的问题,以及结果因这些变量的组合而产生很大变化的问题。例如:

  • 在物理学中,研究分子的运动
  • 在生物学中,预测蛋白质的结构
  • 在计算机科学中,预测算法的最坏可能运行时间
  • NASA甚至使用优化技术来设计具有正确操作特性的天线,而这些天线看起似乎不像是人类设计者创造出来的

优化算法是通过尝试许多不同解并给这些解打分以确定其质量的方式,来找到一个问题的最优解。优化算法的典型应用场景是,存在大量可能的解(解搜索空间)以至于我们无法对其进行一一尝试的情况

最粗暴简单但也是最低效的求解方法,是去尝试随机猜测上千个题解,并从中找出最佳解。而相对的,更有效率的方法,则是一种对题解可能有改进的方式来对其进行智能地修正。

优化算法是否管用的最关键因素

文章的前面提到了优化算法的几个核心因素,但这里笔者希望强调的是,一种优化算法是否管用很大程度取决于问题本身。大多数优化算法都依赖于这样一个事实:最优解应该接近于其他的优解(即损失函数连续可微),来看一个可能不起作用的例子,

在图的右边,成本的最低点实际上处在一个非常陡峭的峡谷区域内,接近它的任何解都有可能被排除在外,因为这些解的成本都很高,所以我们可能永远都无法找到通往全局最小值的途径。大多数优化算法都会陷入到图中左边某个局部最小化的区域里。

Relevant Link: 

《集体智慧编程》Toby segaran - 第5章

 

2. 日常和工程中常见的需要用到优化技术的典型场景

这一章节,笔者这里会先描述定义出2种典型场景,分别是无约束搜索问题和带约束搜索问题,它们的区别如下,

  • 无约束搜索问题:参数的搜索空间充满了所有随机变量的整个定义域,每一个随机变量的取值都对其他随机变量的取值没有任何影响
  • 带约束搜索问题:参数的搜索空间是所有随机变量定义域的一个子集,某个随机变量的取值确定后会对其他余下随机变量的取值产生约束影响

我们日常生活中和工程中遇到的很多问题,都可以抽象为上述两类问题。本文我们会通过3个具体的例子,来从不同方面考察优化算法的灵活性。

0x1:无约束搜索空间问题的随机优化 - 组团旅游问题

第一个例子是关于为一个团队安排去某地开会的往返航班,这种场景在现实生活中很常见,例如笔者所在的公司在全球多地有不同的分部,而每年的BlackHat会议会在一个估计的地点(例如拉斯维加斯)和时间召开,这个时候,就需要为各个不同地方的员工安排航班,使他们在同一天到达,并且同样安排其在同一天返航会各自的城市。

计划的制定要求有许多不同的输入,比如:

  • 每个人的航班时间表应该是什么?
  • 需要租用多少辆汽车?
  • 哪个飞机场是最通畅的?

许多输出结果也必须考虑,比如:

  • 总的成本
  • 候机时间
  • 起飞的时间

很显然,我们对输出的期望是总成本和总候机时间越短越好,但是我们无法将这些输入用一个简单的公式映射到输出。要解决这个问题,就需要转换思维,将公式思维转换到计算机的优化思维上。

1. 描述题解

为来自不同地方去往同一个地点的人们(本例是Glass一家)安排一次旅游是一件极富挑战的事情。下面虚构出一个家庭成员及其所在地,

people = [('Seymour', 'BOS'),
          ('Franny', 'DAL'),
          ('Zooey', 'CAK'),
          ('Walt', 'MIA'),
          ('Buddy', 'ORD'),
          ('Les', 'OMA')]
# Laguardia airport in NewYork
destination = 'LGA'

家庭成员们来自全美各地,并且它们希望在纽约会面。他们将在同一天到达,并在同一天离开,而且他们想搭乘相同的交通工具往返(到达接机,离开送机)纽约机场,从各自所在地前往所在地的机场的交通不用安排。每天有许多航班从任何一位家庭成员的所在地飞往纽约,飞机的起飞时间都是不同的,这些航班在价格和飞行时间上也都不尽相同。数据示例如下,

LGA,OMA,6:19,8:13,239
OMA,LGA,6:11,8:31,249
LGA,OMA,8:04,10:59,136
OMA,LGA,7:39,10:24,219
LGA,OMA,9:31,11:43,210
OMA,LGA,9:15,12:03,99
LGA,OMA,11:07,13:24,171
OMA,LGA,11:08,13:07,175
LGA,OMA,12:31,14:02,234
OMA,LGA,12:18,14:56,172
LGA,OMA,14:05,15:47,226

数据中每一列代表分别为:起点、终点、起飞时间、到达时间、价格。

接下来的问题是,家庭成员的每个成员应该乘坐哪个航班呢?当然,使总的票价降下来是一个目标,但是还有其他因素要考虑,例如:总的候机时间、等地其他成员到达的时间、总的飞行时间等。

描述题解的第一步要做的是,抽象化表达

当处理类似这样的问题时,我们有必要明确潜在的题解将如何抽象的表达,使之不局限于某个具体的业务问题场景。有一种非常通用的表达方式,就是数字序列,在本例中,一个数字可以代表某人选择乘坐的航班,0代表第一次航班、1代表第二次,以此类推。因为每个人都要往返两个航班,所以列表长度是人数的两倍。

例如,

[1, 4, 3, 2, 7, 3, 6, 3, 2, 4, 5, 3]

Seymour BOS 8:04-10:11 $ 95 12:08-14:05 $142
Franny DAL 12:19-15:25 $342 10:51-14:16 $256
Zooey CAK 10:53-13:36 $189 9:58-12:56 $249
Walt MIA 9:15-12:29 $225 16:50-19:26 $304
Buddy ORD 16:43-19:00 $246 10:33-13:11 $132
Les OMA 11:08-13:07 $175 15:07-17:21 $129

上述列表代表了一种题解:Seymour搭乘当天的第2次航班从Boston飞往New York,并搭乘当天的第5次航班返回到Boston。Franny搭乘第4次航班从Dallas飞往New York,并搭乘第3次航班返回。

即使不考虑价格,上述安排仍然是有问题的。例如Les的航班是下午3点的,但是因为Zooey的航班是早上9点的,所以所有人都必须在早晨6点到达机场。

基本上看,所有人的航班”到达纽约时间“和”从纽约出发时间“应该尽可能接近,这样总体的候机时间会减少,但是这没有将总票价和总飞行时间考虑进去。所以,为了确定最佳组合,程序需要一种方法来为不同日程安排的各种属性进行量化地评估,从而决定哪一个方案是最好的。

2. 成本函数(cost function)

成本函数是用优化算法解决问题的关键,任何优化算法的目标,就是要寻找一组能够使成本函数的返回结果达到最小化的输入(本例中即为所有人的航班安排序列),因此成本函数需要返回一个值,用以表示方案的好坏。对于好坏程度的度量没有固定不变的衡量尺度,但是有以下几点基本准则:

  • 损失函数返回的值越大,表示该方案越差
  • 损失函数需要连续可微,这样保证较低损失的方案是接近于其他低损失方案,让优化的过程是连续渐进的
  • 坏方案(无效解)的损失值不宜过大,因为这会导致优化算法很难找到一个次优的解(better solution),因为算法无法确定返回结果是否接近于其他优解,甚或是有效的解
  • 尽可能让最优解的损失为零,这样当算法找到一个最优解时,就可以让优化算法停止搜寻更优的解

通常来说,对多个随机变量进行综合评估方案的好坏是比较困难的,主要问题在于不同随机变量之间的量纲维度不一致,我们来考察一些在组团旅游的例子中能够被度量的变量,

  • 价格:所有航班的总票价,或者有可能是考虑财务因素之后的加权平均
  • 旅行时间:每个人在飞机上花费的总时间
  • 等待时间:在机场等待其他成员到达的时间(在达纽约机场等其他人一起拼车前往市区)
  • 出发时间:早晨太早起飞的航班也许会产生额外的成本,因为这要求旅行者减少睡眠时间
  • 汽车租用时间:如果集体租用一辆汽车,那么他们必须在一天内早于起租时刻之前将车归还,否则将多付一天的租金

确定了对成本产生影响的所有变量因素之后,我们就必须要找到办法将他们”组合“在一起行程一个值。

例如在本例中,我们就需要做如下转换:

  • 飞机上时间的时间价值:假定旅途中每一分钟值1美元,这相当于,再加90美元选择直达航班,就可以节省1个半小时的时间
  • 机场等待时间的时间价值:机场等待中每节省1分钟则价值0.5美元
  • 如果汽车是在租用时间之后归还的,还会追加50美元的罚款
def schedulecost(sol):
    totalprice = 0
    latestarrival = 0
    earliestdep = 24 * 60

    for d in range(len(sol) / 2):
        # Get the inbound and outbound flights
        origin = people[d][1]
        outbound = flights[(origin, destination)][int(sol[d])]
        returnf = flights[(destination, origin)][int(sol[d + 1])]

        # Total price is the price of all outbound and return flights
        totalprice += outbound[2]
        totalprice += returnf[2]

        # Track the latest arrival and earliest departure
        if latestarrival < getminutes(outbound[1]): latestarrival = getminutes(outbound[1])
        if earliestdep > getminutes(returnf[0]): earliestdep = getminutes(returnf[0])

    # Every person must wait at the airport until the latest person arrives.
    # They also must arrive at the same time and wait for their flights.
    totalwait = 0
    for d in range(len(sol) / 2):
        origin = people[d][1]
        outbound = flights[(origin, destination)][int(sol[d])]
        returnf = flights[(destination, origin)][int(sol[d + 1])]
        totalwait += latestarrival - getminutes(outbound[1])
        totalwait += getminutes(returnf[0]) - earliestdep

        # Does this solution require an extra day of car rental? That'll be $50!
    if latestarrival > earliestdep: totalprice += 50

    
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/872024
推荐阅读
相关标签
  

闽ICP备14008679号