pythonによる最急降下法

最急降下法は、関数の最適化を行う手法として一番単純である。
多変数の場合、途中で直線探索を行う必要がある。
今回も参考図書は、金谷健一「これなら分かる最適化法」である。

最適化したい関数は
f(x,y) = -(x-2)^2-(y-2)^2
とする。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import numpy as np

def func(x):
    A = np.matrix([[1.0,0.0],[0.0,1.0]])
    b = np.matrix([[4.0],[4.0]])
    c = np.matrix([[8.0]])
    return -x.transpose()*A*x + b.transpose()*x - c

def nabrafunc(x):
    b = np.matrix([[4.0],[4.0]])
    return -2.0*x + b

def Func(x,t):
    return x + t*nabrafunc(x)

def dFunc(x,x0):
    return nabrafunc(x).transpose()*nabrafunc(x0)

def search(x0,t):
    T = 0.0
    Td = 0.0
    h = 0.0001
    eps = 1e-10
    x = Func(x0,t)
    xd = Func(x0,t)
    
    while(float(np.abs(dFunc(x,x0))[[0]]) > eps):
        h = np.sign(float(dFunc(x,x0)[[0]]))*np.abs(h)
        T = t
        Td = t + h
        x = Func(x0,T)
        xd = Func(x0,Td)       
        
        if(float(func(x)[[0]]) < float(func(xd)[[0]])):
            while(float(func(x)[[0]]) < float(func(xd)[[0]])):
                h = 2.0 * h
                T = Td
                Td = T + h
                x = Func(x0,T)
                xd = Func(x0,Td)
                
            t = T
            h = h/2.0
        else:
            while(float(func(x)[[0]]) > float(func(xd)[[0]])):
                h = h/2.0
                Td = Td - h
                x = Func(x0,T)
                xd = Func(x0,Td)
                
            t = Td
            h = 2.0*h
    
    print "t:"
    print t
    return t

def hillCliming(x):
    t = 1.0
    delta = 10e-5
    dx = t*nabrafunc(x)
    
    while(np.sqrt(float((dx.transpose()*dx)[[0]])) > delta):
        t = search(x,t)
        dx = t*nabrafunc(x)
        x = x + dx
    
    return x


X = np.matrix([[4.0],[4.0]])

Xr = hillCliming(X)
print "\nresult:"
print Xr

結果はこちら。

t:
0.5
t:
0.5

result:
[[ 2.]
 [ 2.]]

scipyのoptimizeとかはどれくらい最適化パッケージを搭載しているんだろうか。
気になるところである。