陳鍾誠

Version 1.0

實作:簡易爬山演算法

簡介

以下是「爬山演算法」 (Hill-Climbing Algorithm) 的一個簡易版本,其方法超簡單,就是一直看旁邊有沒有更好的解,如果有就移過去。然後反覆的作這樣的動作,直到旁邊的解都比現在的更差時,程式就停止,然後將那個位於山頂的解傳回,就完成了。

Algorithm HillClimbing(f, x)
  x = 隨意設定一個解。
  while (x 有鄰居 x' 比 x 更高)
    x = x';
  end
  return x;
end

當然、這種演算法只能找到「局部最佳解」(local optimal),當整個空間有很多山頂的時候,這種方法會爬到其中一個山頂就停了,並不一定會爬到最高的山頂。

程式碼

檔案: HillClimbingSimple.py

def hillClimbing(f, x, dx=0.01):
    while (True):
        print('x={0:.3f} f(x)={1:.3f}'.format(x, f(x)))
        if f(x+dx)>f(x):
            x = x + dx
        elif f(x-dx)>f(x):
            x = x - dx
        else:
            break
    return x

def f(x):
    return -1*(x*x+3*x+5)

hillClimbing(f, 0)

執行結果

求解 : $-(x^2+3x+5)$ 的最高點,也就是 $^2+3x+5$ 的最低點。

PS D:\ccc\course\ai\python\02-optimize> python hillClimbing1.py
x=0.000 f(x)=-5.000
x=-0.010 f(x)=-4.970
x=-0.020 f(x)=-4.940
x=-0.030 f(x)=-4.911
x=-0.040 f(x)=-4.882
...
x=-1.470 f(x)=-2.751
x=-1.480 f(x)=-2.750
x=-1.490 f(x)=-2.750
x=-1.500 f(x)=-2.750

如果我們將上述程式的 f(x) 換成如下版本:

def f(x):
    return -1*abs(x*x-4)

那麼就可以用來求解 $|x^2-4|$ 的最低點,也就是尋找 4 的平方根,以下是執行結果:

PS D:\ccc\course\ai\python\02-optimize> python hillClimbing1.py
x=0.000 f(x)=-4.000
x=0.010 f(x)=-4.000
x=0.020 f(x)=-4.000
x=0.030 f(x)=-3.999
x=0.040 f(x)=-3.998
...
x=1.970 f(x)=-0.119
x=1.980 f(x)=-0.080
x=1.990 f(x)=-0.040
x=2.000 f(x)=-0.000

您可以看到上述程式正確的找到 4 的平方根是 2,而我們所用的方法與求解 $-(x^2+3x+5)$ 的最高點幾乎是一模一樣的,只是把函數換掉而已。

結語

您可以看到上述用爬山演算法尋找函數最高點或最低點的程式,其實非常的簡單,只不過是看看兩邊是否有更好的解,如果有就移過去罷了。

但是、這麼簡單的演算法,其實威力是非常強大的,這種方法可以求解的問題非常的多,很多人工智慧上非常重要的問題,其實都只不過是在進行函數優化的動作,也就是尋找某個函數的低點或高點而已,這些問題其實大部分都可以使用爬山演算法來求解。

當然、要能尋找更複雜函數的「區域最佳解」,還必須進一步的對上述程式進行封裝與抽象化,我們將在下一篇文章中解說將上述爬山程式抽象化後的版本,並用該程式來求更複雜函數的解。

參考文獻