# 2.7 數學優化:找到函數的最優解
In?[2]:
```
%matplotlib inline
import numpy as np
```
> **作者**: Ga?l Varoquaux
[數學優化](http://en.wikipedia.org/wiki/Mathematical_optimization)處理尋找一個函數的最小值(最大值或零)的問題。在這種情況下,這個函數被稱為_成本函數_,或_目標函數_,或_能量_。
這里,我們感興趣的是使用[scipy.optimize](http://docs.scipy.org/doc/scipy/reference/optimize.html#scipy.optimize)來進行黑盒優化: 我們不依賴于我們優化的函數的算術表達式。注意這個表達式通常可以用于高效的、非黑盒優化。
> 先決條件
>
> * Numpy, Scipy
> * matplotlib
**也可以看一下: 參考**
數學優化是非常 ... 數學的。如果你需要性能,那么很有必要讀一下這些書:
* [Convex Optimization](http://www.stanford.edu/~boyd/cvxbook/) Boyd and Vandenberghe (pdf版線上免費)。
* [Numerical Optimization](http://users.eecs.northwestern.edu/~nocedal/book/num-opt.html), Nocedal and Wright。 關于梯度下降方法的詳細參考。
* [Practical Methods of Optimization](http://www.amazon.com/gp/product/0471494631/ref=ox_sc_act_title_1?ie=UTF8&smid=ATVPDKIKX0DER) Fletcher: 擅長揮手解釋。
**章節內容**
* 了解你的問題
* 凸優化 VS 非凸優化
* 平滑問題和非平滑問題
* 嘈雜VS精確的成本函數
* 限制
* 不同最優化方法的回顧
* 入門: 一維最優化
* 基于梯度的方法
* 牛頓和擬牛頓法
* 較少梯度方法
* 全局優化
* 使用scipy優化的操作指南
* 選擇一個方法
* 讓你的優化器更快
* 計算梯度
* 虛擬練習
* 特殊情境: 非線性最小二乘
* 最小化向量函數的范數
* 曲線擬合
* 有限制的最優化
* 箱邊界
* 通用限制
## 2.7.1 了解你的問題
每個問題都是不相同。了解你的問題使你可以選擇正確的工具。
**問題的維數**
優化問題的規模非常好的由問題的維數來決定,即,進行搜索的標量變量的數量。
### 2.7.1.1 凸優化 VS 非凸優化
**凸函數**:
* $f$ 在它的所有切線之上。
* 相應的, 對于兩個點point A, B, f(C) 在線段[f(A), f(B])]之下, 如果 A < C < B

**非凸函數**

**最優化凸函數簡單。最優化非凸函數可能非常困難。**
> **注意**: 可以證明對于一個凸函數局部最小值也是全局最小值。然后,從某種意義上說,最小值是惟一的。
### 2.7.1.2 平滑和非平滑問題
**平滑函數**:
梯度無處不在,是一個連續函數

**非平滑函數**:

**優化平滑函數更簡單一些** (在黑盒最優化的前提是對的,此外[線性編程](http://en.wikipedia.org/wiki/Linear_programming)是一個非常高效處理分段線性函數的例子)。
### 2.7.1.3 嘈雜 VS 精確成本函數
有噪音 (blue) 和無噪音 (green) 函數

**噪音梯度**
許多優化方法都依賴于目標函數的梯度。如果沒有給出梯度函數,會從數值上計算他們,會產生誤差。在這種情況下,即使目標函數沒有噪音,基于梯度的最優化也可能是噪音最優化。
### 2.7.1.4 限制
基于限制的最優化
這里是:
$-1 < x_1 < 1$
$-1 < x_2 < 1$

## 2.7.2 不同最優化方法的回顧
### 2.7.2.1 入門: 一維最優化
使用[scipy.optimize.brent()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.brent.html#scipy.optimize.brent) 來最小化一維函數。它混合拋物線近似與區間策略。
**二元函數的Brent方法**: 在3次迭代后收斂, 因為,稍后二元近似精確了。


**非凸函數的Brent方法**: 注意最優化方法避免了局部最小值其實是因為運氣。


In?[4]:
```
from scipy import optimize
def f(x):
return -np.exp(-(x - .7)**2)
x_min = optimize.brent(f) # 實際上在9次迭代后收斂!
x_min
```
Out[4]:
```
0.6999999997839409
```
In?[4]:
```
x_min - .7
```
Out[4]:
```
-2.160590595323697e-10
```
> **注意**: Brent方法也可以用于_限制區間最優化_使用[scipy.optimize.fminbound()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fminbound.html#scipy.optimize.fminbound)
>
> **注意**: 在scipy 0.11中, [scipy.optimize.minimize_scalar()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize_scalar.html#scipy.optimize.minimize_scalar) 給出了一個一維標量最優化的通用接口。
### 2.7.2.2 基于梯度的方法
#### 2.7.2.2.1 關于梯度下降的一些直覺
這里我們關注**直覺**,不是代碼。代碼在后面。
從根本上說,梯度下降在于在梯度方向上前進小步,即最陡峭梯度的方向。
**固定步數梯度下降**
**狀況良好的二元函數。**


**狀況糟糕的二元函數。**
狀況糟糕問題的梯度下降算法的核心問題是梯度并不會指向最低點。


我們可以看到非常各向異性 (狀況糟糕) 函數非常難優化。
**帶回家的信息**: 條件數和預條件化
如果你知道變量的自然刻度,預刻度他們以便他們的行為相似。這與[預條件化](https://en.wikipedia.org/wiki/Preconditioner)相關。
并且,很明顯采用大步幅是有優勢的。這在梯度下降代碼中使用[直線搜索](https://en.wikipedia.org/wiki/Line_search)。
**適應步數梯度下降**
狀況良好的二元函數。


狀況糟糕的二元函數。


狀況糟糕的非二元函數。


狀況糟糕的極端非二元函數。


函數看起來越像二元函數 (橢圓半圓邊框線), 最優化越簡單。
#### 2.7.2.2.2 共軛梯度下降
上面的梯度下降算法是玩具不會被用于真實的問題。
正如從上面例子中看到的,簡單梯度下降算法的一個問題是,它試著搖擺穿越峽谷,每次跟隨梯度的方法,以便穿越峽谷。共軛梯度通過添加_摩擦力_項來解決這個問題: 每一步依賴于前兩個值的梯度然后急轉彎減少了。
**共軛梯度下降**
狀況糟糕的非二元函數。


狀況糟糕的極端非二元函數。


在scipy中基于共軛梯度下降方法名稱帶有‘cg’。最小化函數的簡單共軛梯度下降方法是[scipy.optimize.fmin_cg()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_cg.html#scipy.optimize.fmin_cg):
In?[5]:
```
def f(x): # The rosenbrock函數
return .5*(1 - x[0])**2 + (x[1] - x[0]**2)**2
optimize.fmin_cg(f, [2, 2])
```
```
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 13
Function evaluations: 120
Gradient evaluations: 30
```
Out[5]:
```
array([ 0.99998968, 0.99997855])
```
這些方法需要函數的梯度。方法可以計算梯度,但是如果傳遞了梯度性能將更好:
In?[6]:
```
def fprime(x):
return np.array((-2*.5*(1 - x[0]) - 4*x[0]*(x[1] - x[0]**2), 2*(x[1] - x[0]**2)))
optimize.fmin_cg(f, [2, 2], fprime=fprime)
```
```
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 13
Function evaluations: 30
Gradient evaluations: 30
```
Out[6]:
```
array([ 0.99999199, 0.99998336])
```
注意函數只會評估30次,相對的沒有梯度是120次。
### 2.7.2.3 牛頓和擬牛頓法
#### 2.7.2.3.1 牛頓法: 使用Hessian (二階微分))
[牛頓法](http://en.wikipedia.org/wiki/Newton%27s_method_in_optimization)使用局部二元近似來計算跳躍的方向。為了這個目的,他們依賴于函數的前兩個導數_梯度_和[Hessian](http://en.wikipedia.org/wiki/Hessian_matrix)。
**狀況糟糕的二元函數:**
注意,因為二元近似是精確的,牛頓法是非常快的。


**狀況糟糕的非二元函數:**
這里我們最優化高斯分布,通常在它的二元近似的下面。因此,牛頓法超調量并且導致震蕩。


**狀況糟糕的極端非二元函數:**


在scipy中, 最優化的牛頓法在[scipy.optimize.fmin_ncg()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_ncg.html#scipy.optimize.fmin_ncg)實現 (cg這里是指一個內部操作的事實,Hessian翻轉, 使用共軛梯度來進行)。[scipy.optimize.fmin_tnc()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_tnc.html#scipy.optimize.fmin_tnc) 可以被用于限制問題,盡管沒有那么多用途:
In?[7]:
```
def f(x): # rosenbrock函數
return .5*(1 - x[0])**2 + (x[1] - x[0]**2)**2
def fprime(x):
return np.array((-2*.5*(1 - x[0]) - 4*x[0]*(x[1] - x[0]**2), 2*(x[1] - x[0]**2)))
optimize.fmin_ncg(f, [2, 2], fprime=fprime)
```
```
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 9
Function evaluations: 11
Gradient evaluations: 51
Hessian evaluations: 0
```
Out[7]:
```
array([ 1., 1.])
```
注意與共軛梯度(上面的)相比,牛頓法需要較少的函數評估,更多的梯度評估,因為它使用它近似Hessian。讓我們計算Hessian并將它傳給算法:
In?[7]:
```
def hessian(x): # Computed with sympy
return np.array(((1 - 4*x[1] + 12*x[0]**2, -4*x[0]), (-4*x[0], 2)))
optimize.fmin_ncg(f, [2, 2], fprime=fprime, fhess=hessian)
```
```
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 9
Function evaluations: 11
Gradient evaluations: 19
Hessian evaluations: 9
```
Out[7]:
```
array([ 1., 1.])
```
> **注意**:在超高維,Hessian的翻轉代價高昂并且不穩定 (大規模 > 250)。
>
> **注意**:牛頓最優化算法不應該與基于相同原理的牛頓根發現法相混淆,[scipy.optimize.newton()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html#scipy.optimize.newton)。
#### 2.7.2.3.2 擬牛頓方法: 進行著近似Hessian
**BFGS**: BFGS (Broyden-Fletcher-Goldfarb-Shanno算法) 改進了每一步對Hessian的近似。
**狀況糟糕的二元函數:**
在準確的二元函數中, BFGS并不像牛頓法那么快,但是還是很快。


**狀況糟糕的非二元函數:**
這種情況下BFGS比牛頓好, 因為它的曲度經驗估計比Hessian給出的好。


**狀況糟糕的極端非二元函數:**


In?[9]:
```
def f(x): # rosenbrock函數
return .5*(1 - x[0])**2 + (x[1] - x[0]**2)**2
def fprime(x):
return np.array((-2*.5*(1 - x[0]) - 4*x[0]*(x[1] - x[0]**2), 2*(x[1] - x[0]**2)))
optimize.fmin_bfgs(f, [2, 2], fprime=fprime)
```
```
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 16
Function evaluations: 24
Gradient evaluations: 24
```
Out[9]:
```
array([ 1.00000017, 1.00000026])
```
**L-BFGS**: 限制內存的BFGS介于BFGS和共軛梯度之間: 在非常高的維度 (> 250) 計算和翻轉的Hessian矩陣的成本非常高。L-BFGS保留了低秩的版本。此外,scipy版本, [scipy.optimize.fmin_l_bfgs_b()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_l_bfgs_b.html#scipy.optimize.fmin_l_bfgs_b), 包含箱邊界:
In?[8]:
```
def f(x): # rosenbrock函數
return .5*(1 - x[0])**2 + (x[1] - x[0]**2)**2
def fprime(x):
return np.array((-2*.5*(1 - x[0]) - 4*x[0]*(x[1] - x[0]**2), 2*(x[1] - x[0]**2)))
optimize.fmin_l_bfgs_b(f, [2, 2], fprime=fprime)
```
Out[8]:
```
(array([ 1.00000005, 1.00000009]),
1.4417677473011859e-15,
{'funcalls': 17,
'grad': array([ 1.02331202e-07, -2.59299369e-08]),
'nit': 16,
'task': 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL',
'warnflag': 0})
```
> **注意**:如果你不為L-BFGS求解器制定梯度,你需要添加approx_grad=1
### 2.7.2.4 較少梯度方法
#### 2.7.2.4.1 打靶法: Powell算法
接近梯度方法
**狀態糟糕的二元函數:**
Powell法對低維局部糟糕狀況并不很敏感


**狀況糟糕的極端非二元函數:**


#### 2.7.2.4.2 單純形法: Nelder-Mead
Nelder-Mead算法是對高維空間的對立方法的歸納。這個算法通過改進[單純形](http://en.wikipedia.org/wiki/Simplex)來工作,高維空間間隔和三角形的歸納,包裹最小值。
**長處**: 對噪音很強壯,他不依賴于計算梯度。因此,它可以在局部光滑的函數上工作,比如實驗數據點,只要他顯示了一個大規模的鐘形行為。但是,它在光滑、非噪音函數上比基于梯度的方法慢。
**狀況糟糕的非二元函數:**


**狀況糟糕的極端非二元函數:**


在scipy中, [scipy.optimize.fmin()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin.html#scipy.optimize.fmin) 實現了Nelder-Mead法:
In?[11]:
```
def f(x): # rosenbrock函數
return .5*(1 - x[0])**2 + (x[1] - x[0]**2)**2
optimize.fmin(f, [2, 2])
```
```
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 46
Function evaluations: 91
```
Out[11]:
```
array([ 0.99998568, 0.99996682])
```
### 2.7.2.5 全局最優化算法
如果你的問題不允許惟一的局部最低點(很難測試除非是凸函數),如果你沒有先前知識來讓優化起點接近答案,你可能需要全局最優化算法。
#### 2.7.2.5.1 暴力: 網格搜索
[scipy.optimize.brute()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.brute.html#scipy.optimize.brute)在 函數網格內來評價函數,根據最小值返回參數。參數由[numpy.mgrid](http://docs.scipy.org/doc/numpy/reference/generated/numpy.mgrid.html#numpy.mgrid)給出的范圍來指定。默認情況下,每個方向進行20步:
In?[4]:
```
def f(x): # rosenbrock函數
return .5*(1 - x[0])**2 + (x[1] - x[0]**2)**2
optimize.brute(f, ((-1, 2), (-1, 2)))
```
Out[4]:
```
array([ 1.00001462, 1.00001547])
```
## 2.7.3 使用scipy優化的現實指南
### 2.7.3.1 選擇一個方法

**沒有關于梯度的知識:**
* 一般來說,傾向于BFGS ([scipy.optimize.fmin_bfgs()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_bfgs.html#scipy.optimize.fmin_bfgs)) 或 L-BFGS (), 即使你有大概的數值梯度
* 在狀況良好的問題上,Powell () 以及 Nelder-Mead ([scipy.optimize.fmin()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin.html#scipy.optimize.fmin)), 都是在高維上效果良好的梯度自有的方法,但是 ,他們無法支持狀況糟糕的問題。
**有關于梯度的知識:**
* BFGS ([scipy.optimize.fmin_bfgs()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_bfgs.html#scipy.optimize.fmin_bfgs)) 或 L-BFGS ([scipy.optimize.fmin_l_bfgs_b()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_l_bfgs_b.html#scipy.optimize.fmin_l_bfgs_b))。
* BFGS的計算開支要大于L-BFGS, 它自身也比共軛梯度法開銷大。另一方面,BFGS通常比CG(共軛梯度法)需要更少函數評估。因此,共軛梯度法在優化計算量較少的函數時比BFGS更好。
**帶有Hessian**:
* 如果你可以計算Hessian, 推薦牛頓法 ([scipy.optimize.fmin_ncg()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_ncg.html#scipy.optimize.fmin_ncg))。
**如果有噪音測量**:
使用Nelder-Mead ([scipy.optimize.fmin()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin.html#scipy.optimize.fmin)) 或者 Powell ([scipy.optimize.fmin_powell()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_powell.html#scipy.optimize.fmin_powell))。
### 2.7.3.2 讓優化器更快
* 選擇正確的方法 (見上面), 如果可以的話,計算梯度和Hessia。
* 可能的時候使用[preconditionning](http://en.wikipedia.org/wiki/Preconditioner)。
* 聰明的選擇你的起點。例如,如果你正在運行許多相似的優化,那么在其他結果上軟啟動。
* 如果你不需要準確,那么請放松并容忍
### 2.7.3.3 計算梯度
計算梯度甚至是Hessians的努力, 是枯燥的但是也是值得的。使用[Sympy](http://www.scipy-lectures.org/packages/sympy.html#sympy)來進行象征計算將非常方便。
優化不能很好收斂的一個來源是計算梯度過程的人為錯誤。你可以用[scipy.optimize.check_grad()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.check_grad.html#scipy.optimize.check_grad)來檢查一下梯度是否正確。它返回給出的梯度與計算的梯度之間差異的基準:
In?[9]:
```
optimize.check_grad(f, fprime, [2, 2])
```
Out[9]:
```
2.384185791015625e-07
```
也看一下[scipy.optimize.approx_fprime()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.approx_fprime.html#scipy.optimize.approx_fprime)找一下你的錯誤。
#### 2.7.3.4 合成練習
**練習: 簡單的 (?) 二次函數**

用K[0]作為起始點優化下列函數:
In?[2]:
```
np.random.seed(0)
K = np.random.normal(size=(100, 100))
def f(x):
return np.sum((np.dot(K, x - 1))**2) + np.sum(x**2)**2
```
計時你的方法。找到最快的方法。為什么BFGS不好用了?
**練習:局部扁平最小化**


考慮一下函數$exp(-1/(.1*x^2 + y^2)$。這個函數在(0,0)存在一個最小值。從起點(1,1)開始,試著在$1e-8$達到這個最低點。
## 2.7.4 特殊案例: 非線性最小二乘
### 2.7.4.1 最小化向量函數的基準
最小二乘法,向量函數基準值的最小化,有特定的結構可以用在[scipy.optimize.leastsq()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html#scipy.optimize.leastsq)中實現的[Levenberg–Marquardt 算法](https://en.wikipedia.org/wiki/Levenberg-Marquardt_algorithm)。
讓我們試一下最小化下面向量函數的基準:
In?[5]:
```
def f(x):
return np.arctan(x) - np.arctan(np.linspace(0, 1, len(x)))
x0 = np.zeros(10)
optimize.leastsq(f, x0)
```
Out[5]:
```
(array([ 0\. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
0.55555556, 0.66666667, 0.77777778, 0.88888889, 1\. ]), 2)
```
這用了67次函數評估(用'full_output=1'試一下)。如果我們自己計算基準并且使用一個更好的通用優化器(BFGS)會怎么樣:
In?[6]:
```
def g(x):
return np.sum(f(x)**2)
optimize.fmin_bfgs(g, x0)
```
```
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 11
Function evaluations: 144
Gradient evaluations: 12
```
Out[6]:
```
array([ -7.44987291e-09, 1.11112265e-01, 2.22219893e-01,
3.33331914e-01, 4.44449794e-01, 5.55560493e-01,
6.66672149e-01, 7.77779758e-01, 8.88882036e-01,
1.00001026e+00])
```
BFGS需要更多的函數調用,并且給出了一個并不精確的結果。
注意只有當輸出向量的維度非常大,比需要優化的函數還要大,`leastsq`與BFGS相類比才是有趣的。
如果函數是線性的,這是一個線性代數問題,應該用[scipy.linalg.lstsq()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.lstsq.html#scipy.linalg.lstsq)解決。
### 2.7.4.2 曲線擬合

最小二乘問題通常出現在擬合數據的非線性擬合時。當我們自己構建優化問題時,scipy提供了這種目的的一個幫助函數: [scipy.optimize.curve_fit()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html#scipy.optimize.curve_fit):
In?[7]:
```
def f(t, omega, phi):
return np.cos(omega * t + phi)
x = np.linspace(0, 3, 50)
y = f(x, 1.5, 1) + .1*np.random.normal(size=50)
optimize.curve_fit(f, x, y)
```
Out[7]:
```
(array([ 1.50600889, 0.98754323]), array([[ 0.00030286, -0.00045233],
[-0.00045233, 0.00098838]]))
```
**練習**
用omega = 3來進行相同的練習。困難是什么?
## 2.7.5 有限制條件的優化
### 2.7.5.1 箱邊界

箱邊界是指限制優化的每個函數。注意一些最初不是寫成箱邊界的問題可以通過改變變量重寫。
* [scipy.optimize.fminbound()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fminbound.html#scipy.optimize.fminbound)進行一維優化
* [scipy.optimize.fmin_l_bfgs_b()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_l_bfgs_b.html#scipy.optimize.fmin_l_bfgs_b)帶有邊界限制的quasi-Newton方法:
In?[8]:
```
def f(x):
return np.sqrt((x[0] - 3)**2 + (x[1] - 2)**2)
optimize.fmin_l_bfgs_b(f, np.array([0, 0]), approx_grad=1, bounds=((-1.5, 1.5), (-1.5, 1.5)))
```
Out[8]:
```
(array([ 1.5, 1.5]),
1.5811388300841898,
{'funcalls': 12,
'grad': array([-0.94868331, -0.31622778]),
'nit': 2,
'task': 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL',
'warnflag': 0})
```
### 2.7.5.2 通用限制
相等和不相等限制特定函數: f(x) = 0 and g(x)< 0。

* [scipy.optimize.fmin_slsqp()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_slsqp.html#scipy.optimize.fmin_slsqp) 序列最小二乘程序: 相等和不相等限制:
In?[10]:
```
def f(x):
return np.sqrt((x[0] - 3)**2 + (x[1] - 2)**2)
def constraint(x):
return np.atleast_1d(1.5 - np.sum(np.abs(x)))
optimize.fmin_slsqp(f, np.array([0, 0]), ieqcons=[constraint, ])
```
```
Optimization terminated successfully. (Exit mode 0)
Current function value: 2.47487373504
Iterations: 5
Function evaluations: 20
Gradient evaluations: 5
```
Out[10]:
```
array([ 1.25004696, 0.24995304])
```
* [scipy.optimize.fmin_cobyla()](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_cobyla.html#scipy.optimize.fmin_cobyla)通過線性估計的限定優化:只有不相等限制:
In?[11]:
```
optimize.fmin_cobyla(f, np.array([0, 0]), cons=constraint)
```
Out[11]:
```
array([ 1.25009622, 0.24990378])
```
上面這個問題在統計中被稱為[Lasso](http://en.wikipedia.org/wiki/Lasso_(statistics)#LASSO_method)問題, 有許多解決它的高效方法 (比如在[scikit-learn](http://scikit-learn.org/)中)。一般來說,當特定求解器存在時不需要使用通用求解器。
**拉格朗日乘子法**
如果你有足夠的數學知識,許多限定優化問題可以被轉化為非限定性優化問題,使用被稱為拉格朗日乘子法的數學技巧。
- 介紹
- 1.1 科學計算工具及流程
- 1.2 Python語言
- 1.3 NumPy:創建和操作數值數據
- 1.4 Matplotlib:繪圖
- 1.5 Scipy:高級科學計算
- 1.6 獲取幫助及尋找文檔
- 2.1 Python高級功能(Constructs)
- 2.2 高級Numpy
- 2.3 代碼除錯
- 2.4 代碼優化
- 2.5 SciPy中稀疏矩陣
- 2.6 使用Numpy和Scipy進行圖像操作及處理
- 2.7 數學優化:找到函數的最優解
- 2.8 與C進行交互
- 3.1 Python中的統計學
- 3.2 Sympy:Python中的符號數學
- 3.3 Scikit-image:圖像處理
- 3.4 Traits:創建交互對話
- 3.5 使用Mayavi進行3D作圖
- 3.6 scikit-learn:Python中的機器學習