1 最优化问题
1.1 什么是最优化问题
1.2 名词与符号
1.3 最优解条件
2 用计算机求解问题
2.1 迭代搜索
2.2 质量评估
3 最小二乘问题——无约束最优化问题实例
点列的曲线拟合是我们高中开始就接触过的问题。为了寻找一个待定系数的函数,可以以最小的误差去描述点列,我们需要用到最小二乘法。有关最小二乘法可以参阅:https://www.zhihu.com/question/37031188
最小二乘法是我们研究无约束最优化问题的一个出色的实例。它具有广泛的应用价值,而且目标函数的局部最优解就是全局最优解。我们在接下来的无约束最优化问题部分将针对一个最小二乘法例题进行研究
4.代码实现
本博客所有代码在https://github.com/HarmoniaLeo/optimization-in-a-nutshell开源,如果帮助到你,请点个star,谢谢这对我真的很重要!
本次代码实现内容是梯度、梯度二范数、黑森矩阵等最优化问题基本件的python数值解法,以及简化的python线性代数库
梯度、梯度二范数、黑森矩阵求法
4.1制作Fuction.py
import numpy as np
class Function:
def __init__(self, _f):
self.fun = _f
def value(self, val):
return self.fun(val)
def part(self, var_index, val):
a = self.fun(val)
b = a + 1
i = 0
e = 2 ** 10 - 1
e1 = 2 ** 10
while 10 ** (-6) < e < e1 or i > -6:
e1 = e
a = b
val_ = list(val)
val_[var_index] += 10 ** i
m = self.fun(val_)
n = self.fun(val)
b = (m - n) / 10 ** i
i -= 2
e = abs(b - a)
return a
def part_2(self, x_index, y_index, val):
return self.__diff_(x_index).__diff_(y_index).value(val)
def diff(self, val):
a = self.fun(val)
b = a + 1
i = 0
e = 2 ** 10 - 1
e1 = 2 ** 10
while 10 ** (-6) < e < e1 or i > -6:
e1 = e
a = b
val_ = val + 10 ** i
m = self.fun(val_)
n = self.fun(val)
b = (m - n) / 10 ** i
i -= 2
e = abs(b - a)
return a
def grad(self, val):
g = np.array(val).astype('float')
for i in range(0, g.size):
g[i] = self.part(i, val)
return np.array(g)
def __diff_(self, index):
def diff_f(vals):
vals_ = list(vals)
vals_[index] = vals_[index] + 10 ** (-6)
m = self.fun(vals_)
n = self.fun(vals)
return (m - n) / 10 ** (-6)
return Function(diff_f)
def hesse(self, val):
v = np.mat(val)
G = np.mat(np.dot(v.T, v)).astype('float')
for i in range(0, v.size):
for j in range(0, v.size):
p = self.part_2(i, j, val)
G[i, j] = p
G=np.array(G)
return G
def norm(self, val):
s = 0
for x in self.grad(val):
s += x ** 2
return np.sqrt(s)
在之后的每个方法实现中,我们都会用到Fuction.py
from Function import Function
tar=Function(func) #func是一个以列表为参数的多元函数
val=tar.val(para) #传入参数获取值
diff=tar.diff(para) #一元函数求导
part=tar.part(index,para) #对第index个参数求导
grad=tar.grad(para) #求梯度数组
hesse=tar.hesse(para) #求hesse阵
norm=tar.norm(para) #求梯度范数
4.2 制作一个lagb.py
import numpy as np
def turn(a): #转置
if len(a.shape)==1:
a=a.reshape((1,a.shape[0]))
return a
else:
return np.array(np.mat(a).T)
def dot(a,b): #点乘
if len(a.shape)==1:
a=a.reshape((a.shape[0],1))
if len(b.shape)==1:
b=b.reshape((b.shape[0],1))
res=np.array(np.mat(a)*np.mat(b))
if res.shape==(1,1):
return res[0][0]
else:
if res.shape[1]==1:
return res.squeeze()
else:
return res
def muldot(*args): #连乘
res=args[0]
for i in range(1,len(args)):
res=dot(res,args[i])
return res
def rev(a): #求逆
return np.array(np.mat(a).I)
在之后的每个方法实现中,我们也都会用到lagb.py
from lagb import *
#输入参数可以为向量或矩阵,即numpy创建的数组
#用numpy创建的一维数组会默认为列向量
a=turn(a) #求转置
c=dot(a,b) #点乘,视情况会返回向量、矩阵、数值
d=dot([a,b,c]) #连续的点乘
b=rev(a) #求逆矩阵