前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:点击跳转
目录
一,最优化问题
http://faculty.bicmr.pku.edu.cn/~wenzw/optbook/opt1.pdf
最优化问题(也称优化问题)泛指定量决策问题,主要关心如何对有限 资源进行有效分配和控制,并达到某种意义上的最优。
最优化问题一般可以描述为
即求满足约数函数的条件下,目标函数的最小值。
第二章是所有优化问题的分类,第三四五六章是对应的所有优化算法,第七章是其他工具。
二,最优化问题分类
1,按照目标函数和约束函数的形式来分
(1)按照随机和确定来分
随机优化问题是指目标或者约束函数中涉及随机变量而带有不确定性 的问题.不像确定性优化问题中目标和约束函数都是确定的,随机优化问题 中总是包含一些未知的参数.
(2)最优化问题可以分为连续和离散优化问题两大类。
离散优化问题如:变量只能取整数的问题称为整数规划。
(3)当目标函数和约束函数均为线性函数时,称为线性规划,否则称为非线性规划。
线性规划问题如:在线性约束下极小化关于半正定矩阵的线性函数的问题称为半定规划,其广义形式为锥规划。
非线性规划问题如:目标函数是二次函数而约束函数是线性函数则称为二次规划;包含非光滑函数的问题称为非光滑优化。
(4)凸和非凸优化问题
凸优化问题是指最小化问题 中的目标函数和可行域分别是凸函 数和凸集.如果其中有一个或者两者都不是凸的,那么相应的最小化问题是 非凸优化问题。
因为凸优化问题的任何局部最优解都是全局最优解,其相应 的算法设计以及理论分析相对非凸优化问题简单很多.
优化问题分类 | 例子 | 方法 | |||
确定优化问题 | 离散优化问题 | 整数规划 | 动态规划 | ||
连续优化问题 | 线性规划 | 线性凸规划 | 半定规划、锥规划 | 单纯形、对偶单纯形、内点法 | |
非线性规划 | 4种组合 | ||||
随机优化问题 |
其中非线性规划的4种组合:
非线性规划问题分类 | 例子 | 方法 | |
非线性规划 | 非线性光滑凸规划 | 二次规划 | 各种梯度下降、推广内点法 |
非线性光滑非凸规划 | 模拟退火、各种牛顿法、推广内点法 | ||
非线性非光滑凸规划 | 无约束:近端梯度下降、次梯度下降、推广内点法 有约束:各种对偶算法、交替方向乘子、推广内点法 | ||
非线性非光滑非凸规划 | 推广内点法 |
2,按照最优解的性质来分
最优解只有少量非零元素的问题称为稀疏优化;最优解是低秩矩 阵的问题称为低秩矩阵优化.此外还有几何优化、二次锥规划、张量优化、 鲁棒优化、全局优化、组合优化、网络规划、随机优化、动态规划、带微分方程约束优化、微分流形约束优化、分布式优化等。
3,按照是否有约束来分
很多约束优化问题的求解也是转化为一系列的无约束优化问题来做,常见方式有 罚函数法、增广拉格朗日函数法等.
三,离散优化
四,线性规划
线性规划问题的研究很早便得到了人们的关注.在 1946—1947 年,George Bernard Dantzig 提出了线性规划的一般形式并提出了至今仍非常流行的单 纯形方法.虽然单纯形方法在实际问题中经常表现出快速收敛,但是其复杂 度并不是多项式的.1979 年,Leonid Khachiyan 证明了线性规划问题多项 式时间算法的存在性.1984 年,Narendra Karmarkar 提出了多项式时间的 内点法.后来,内点法也被推广到求解一般的非线性规划问题.目前,求解 线性规划问题最流行的两类方法依然是单纯形法和内点法.
线性规划 其中包括:
单纯形、对偶单纯形、内点法
五,非线性规划
1,非线性光滑凸规划
梯度下降 其中包含:
GD(梯度下降)
SGD(随机梯度下降)
AdaGrad(自适应梯度下降)
Momentum(带动量的梯度下降)
RMSProp(Root Mean Square Prop)
Adam(Adaptive Moment Estimation)
爬山算法
2,非线性光滑非凸规划
非凸的目标函数,如果用梯度下降,则会陷入局部最优解。
如果能从一个局部最优解跳出去,那么就能很接近全局最优解的局部最优解。
测试光滑非凸规划,可以使用Rosenbrock函数,这是一个光滑的非凸函数。
3,非线性非光滑凸规划
凸优化算法 其中包括:近端梯度下降、次梯度下降、对偶梯度下降、对偶近端梯度下降、
PDHG对偶混合梯度下降、Chambolle-Pock、随机PDHG算法
4,非线性非光滑非凸规划
六,随机优化问题
待补充
七,其他工具
1,约束优化转非约束优化
2,Rosenbrock函数
这是一个光滑的非凸函数,且最值处非常平缓,求解有一定的难度。
二元函数:
2n元函数:
代码实现:
class Rosenbrock
{
public:
Rosenbrock(int n) : n(n) {}
float operator()(const Vector& x, Vector& grad)
{
float fx = 0.0;
for (int i = 0; i < n; i += 2)
{
float t1 = 1.0 - x[i];
float t2 = 10 * (x[i + 1] - x[i] * x[i]);
grad[i + 1] = 20 * t2;
grad[i] = -2.0 * (x[i] * grad[i + 1] + t1);
fx += t1 * t1 + t2 * t2;
}
return fx;
}
private:
int n;
};
传入n个xi,这里的n是偶数,
出参grad输出该点处的梯度,返回值是该点处的函数值。