<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 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 &lt; C &lt; B ![](http://www.scipy-lectures.org/_images/plot_convex_1.png) **非凸函數** ![](http://www.scipy-lectures.org/_images/plot_convex_2.png) **最優化凸函數簡單。最優化非凸函數可能非常困難。** > **注意**: 可以證明對于一個凸函數局部最小值也是全局最小值。然后,從某種意義上說,最小值是惟一的。 ### 2.7.1.2 平滑和非平滑問題 **平滑函數**: 梯度無處不在,是一個連續函數 ![](http://www.scipy-lectures.org/_images/plot_smooth_1.png) **非平滑函數**: ![](http://www.scipy-lectures.org/_images/plot_smooth_2.png) **優化平滑函數更簡單一些** (在黑盒最優化的前提是對的,此外[線性編程](http://en.wikipedia.org/wiki/Linear_programming)是一個非常高效處理分段線性函數的例子)。 ### 2.7.1.3 嘈雜 VS 精確成本函數 有噪音 (blue) 和無噪音 (green) 函數 ![](http://www.scipy-lectures.org/_images/plot_noisy_1.png) **噪音梯度** 許多優化方法都依賴于目標函數的梯度。如果沒有給出梯度函數,會從數值上計算他們,會產生誤差。在這種情況下,即使目標函數沒有噪音,基于梯度的最優化也可能是噪音最優化。 ### 2.7.1.4 限制 基于限制的最優化 這里是: $-1 &lt; x_1 &lt; 1$ $-1 &lt; x_2 &lt; 1$ ![](http://www.scipy-lectures.org/_images/plot_constraints_1.png) ## 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次迭代后收斂, 因為,稍后二元近似精確了。 ![](http://www.scipy-lectures.org/_images/plot_1d_optim_1.png) ![](http://www.scipy-lectures.org/_images/plot_1d_optim_2.png) **非凸函數的Brent方法**: 注意最優化方法避免了局部最小值其實是因為運氣。 ![](http://www.scipy-lectures.org/_images/plot_1d_optim_3.png) ![](http://www.scipy-lectures.org/_images/plot_1d_optim_4.png) 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 關于梯度下降的一些直覺 這里我們關注**直覺**,不是代碼。代碼在后面。 從根本上說,梯度下降在于在梯度方向上前進小步,即最陡峭梯度的方向。 **固定步數梯度下降** **狀況良好的二元函數。** ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_0.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_100.png) **狀況糟糕的二元函數。** 狀況糟糕問題的梯度下降算法的核心問題是梯度并不會指向最低點。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_2.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_102.png) 我們可以看到非常各向異性 (狀況糟糕) 函數非常難優化。 **帶回家的信息**: 條件數和預條件化 如果你知道變量的自然刻度,預刻度他們以便他們的行為相似。這與[預條件化](https://en.wikipedia.org/wiki/Preconditioner)相關。 并且,很明顯采用大步幅是有優勢的。這在梯度下降代碼中使用[直線搜索](https://en.wikipedia.org/wiki/Line_search)。 **適應步數梯度下降** 狀況良好的二元函數。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_1.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_101.png) 狀況糟糕的二元函數。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_3.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_103.png) 狀況糟糕的非二元函數。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_4.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_104.png) 狀況糟糕的極端非二元函數。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_5.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_105.png) 函數看起來越像二元函數 (橢圓半圓邊框線), 最優化越簡單。 #### 2.7.2.2.2 共軛梯度下降 上面的梯度下降算法是玩具不會被用于真實的問題。 正如從上面例子中看到的,簡單梯度下降算法的一個問題是,它試著搖擺穿越峽谷,每次跟隨梯度的方法,以便穿越峽谷。共軛梯度通過添加_摩擦力_項來解決這個問題: 每一步依賴于前兩個值的梯度然后急轉彎減少了。 **共軛梯度下降** 狀況糟糕的非二元函數。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_6.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_106.png) 狀況糟糕的極端非二元函數。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_7.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_107.png) 在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)。 **狀況糟糕的二元函數:** 注意,因為二元近似是精確的,牛頓法是非常快的。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_8.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_108.png) **狀況糟糕的非二元函數:** 這里我們最優化高斯分布,通常在它的二元近似的下面。因此,牛頓法超調量并且導致震蕩。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_9.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_109.png) **狀況糟糕的極端非二元函數:** ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_10.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_110.png) 在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的翻轉代價高昂并且不穩定 (大規模 &gt; 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并不像牛頓法那么快,但是還是很快。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_11.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_111.png) **狀況糟糕的非二元函數:** 這種情況下BFGS比牛頓好, 因為它的曲度經驗估計比Hessian給出的好。 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_12.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_112.png) **狀況糟糕的極端非二元函數:** ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_13.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_113.png) 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和共軛梯度之間: 在非常高的維度 (&gt; 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法對低維局部糟糕狀況并不很敏感 ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_14.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_114.png) **狀況糟糕的極端非二元函數:** ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_16.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_116.png) #### 2.7.2.4.2 單純形法: Nelder-Mead Nelder-Mead算法是對高維空間的對立方法的歸納。這個算法通過改進[單純形](http://en.wikipedia.org/wiki/Simplex)來工作,高維空間間隔和三角形的歸納,包裹最小值。 **長處**: 對噪音很強壯,他不依賴于計算梯度。因此,它可以在局部光滑的函數上工作,比如實驗數據點,只要他顯示了一個大規模的鐘形行為。但是,它在光滑、非噪音函數上比基于梯度的方法慢。 **狀況糟糕的非二元函數:** ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_17.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_117.png) **狀況糟糕的極端非二元函數:** ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_18.png) ![](http://www.scipy-lectures.org/_images/plot_gradient_descent_118.png) 在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 選擇一個方法 ![](http://www.scipy-lectures.org/_images/plot_compare_optimizers_1.png) **沒有關于梯度的知識:** * 一般來說,傾向于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 合成練習 **練習: 簡單的 (?) 二次函數** ![](http://www.scipy-lectures.org/_images/plot_exercise_ill_conditioned_1.png) 用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不好用了? **練習:局部扁平最小化** ![](http://www.scipy-lectures.org/_images/plot_exercise_flat_minimum_0.png) ![](http://www.scipy-lectures.org/_images/plot_exercise_flat_minimum_1.png) 考慮一下函數$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 曲線擬合 ![](http://www.scipy-lectures.org/_images/plot_curve_fit_1.png) 最小二乘問題通常出現在擬合數據的非線性擬合時。當我們自己構建優化問題時,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 箱邊界 ![](http://www.scipy-lectures.org/_images/plot_constraints_2.png) 箱邊界是指限制優化的每個函數。注意一些最初不是寫成箱邊界的問題可以通過改變變量重寫。 * [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)&lt; 0。 ![](http://www.scipy-lectures.org/_images/plot_non_bounds_constraints_1.png) * [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/)中)。一般來說,當特定求解器存在時不需要使用通用求解器。 **拉格朗日乘子法** 如果你有足夠的數學知識,許多限定優化問題可以被轉化為非限定性優化問題,使用被稱為拉格朗日乘子法的數學技巧。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看