『壹』 優化原理的內容
優勝劣汰、適者生存,這是自然法則。在技術和經濟活動中也是如此,因此在作技術經濟分析和評價選擇時,要遵從優化原理。 (一)局部優化與全局優化 局部優化是技術經濟子系統的優化;全局優化是大系統的優化,兩者之間在目標上有一致性,也存在矛盾。在量上即有疊加性,也有非疊加性。用部比比足基礎,全局優化是目的,局部比化要服從於全局優化。
(二)靜態優化和動態沈比 在技術經濟分析中,不考慮時間因素的影響的優比是的態比比,考慮時間因累的影響的』優化是動態優化。靜態優化過程簡便,動態優化更符合客觀實際,兩N2比比方式各有適用場合,當兩種的優化結果發生矛盾時,應以動態比化為准。
(三)單目標優化和多日標優化 優化過程中,按滿足的日際欽可分為單目標優化;多目標優化,單目標優化是多目標優化的基礎,多目標優化是單口際比比的綜合。單目標優比簡稱.多口際優化復雜。
(四)確定條件下的優化和模糊條件下的優化 確定條件下的優化是指在各種技術經濟條件都確定的情況下的優化,可用運籌學中的最優規劃方法(如線性規劃、動態規劃等)求解;模糊條件—1;的優化是指技術經濟條件不明朗情況下的優化,可用模糊數學理論將模糊條件定量化之後,再問常規方法求解;最後再根據模糊理論進行解的實際優化解釋。
(五)最優化和次優化 最優化是追求的目標,但由於各種客觀條件的限制和人們對於技術經濟客觀條件認識的局限性,往往難於達到技術經濟效果的最優而只能達到令人比較滿意的次優。 資源的最優配置是協調配置資源的結果,是經濟效益、社會效益、環境生態效益的統一。要對資源的用途作出選擇,對資源的開發利用從布局、規劃、規模、結構、順序等諸方面進行最優決策、合理配置、科學組合、綜合利用,以為社會提供更多更好的產品和服務為目的。從某種意義上說,資源最優配置就是提高資源的利用效果從而提高經濟效益。資源的有限性和需求無限性之間的矛盾,資源用途的多樣性與對資源佔用或消耗一次性之間的矛盾,必然要求要對資源進行優化配置。優化配置時。通常要解決好生產什麼和生產多少,如何進行生產,何時何地生產,為什麼進行生產等問題。
對資源的最優利用,一方面,要考慮列資源選擇具有排斥性,從而就會產生反映資源利用的機會成本;另一方面,資源選擇又具有替代性,用生產可能性邊界曲線可以說明資源的替代規律和最優配置問題,並可根據彈性經濟學理論,運用替代彈性方法尋求資源合理替代和合理組合與配置的途徑。
『貳』 編譯原理
C語言編譯過程詳解
C語言的編譯鏈接過程是要把我們編寫的一個C程序(源代碼)轉換成可以在硬體上運行的程序(可執行代碼),需要進行編譯和鏈接。編譯就是把文本形式源代碼翻譯為機器語言形式的目標文件的過程。鏈接是把目標文件、操作系統的啟動代碼和用到的庫文件進行組織形成最終生成可執行代碼的過程。過程圖解如下:
從圖上可以看到,整個代碼的編譯過程分為編譯和鏈接兩個過程,編譯對應圖中的大括弧括起的部分,其餘則為鏈接過程。
一、編譯過程
編譯過程又可以分成兩個階段:編譯和匯編。
1、編譯
編譯是讀取源程序(字元流),對之進行詞法和語法的分析,將高級語言指令轉換為功能等效的匯編代碼,源文件的編譯過程包含兩個主要階段:
第一個階段是預處理階段,在正式的編譯階段之前進行。預處理階段將根據已放置在文件中的預處理指令來修改源文件的內容。如#include指令就是一個預處理指令,它把頭文件的內容添加到.cpp文件中。這個在編譯之前修改源文件的方式提供了很大的靈活性,以適應不同的計算機和操作系統環境的限制。一個環境需要的代碼跟另一個環境所需的代碼可能有所不同,因為可用的硬體或操作系統是不同的。在許多情況下,可以把用於不同環境的代碼放在同一個文件中,再在預處理階段修改代碼,使之適應當前的環境。
主要是以下幾方面的處理:
(1)宏定義指令,如 #define a b。
對於這種偽指令,預編譯所要做的是將程序中的所有a用b替換,但作為字元串常量的 a則不被替換。還有 #undef,則將取消對某個宏的定義,使以後該串的出現不再被替換。
(2)條件編譯指令,如#ifdef,#ifndef,#else,#elif,#endif等。
這些偽指令的引入使得程序員可以通過定義不同的宏來決定編譯程序對哪些代碼進行處理。預編譯程序將根據有關的文件,將那些不必要的代碼過濾掉
(3) 頭文件包含指令,如#include "FileName"或者#include <FileName>等。
在頭文件中一般用偽指令#define定義了大量的宏(最常見的是字元常量),同時包含有各種外部符號的聲明。採用頭文件的目的主要是為了使某些定義可以供多個不同的C源程序使用。因為在需要用到這些定義的C源程序中,只需加上一條#include語句即可,而不必再在此文件中將這些定義重復一遍。預編譯程序將把頭文件中的定義統統都加入到它所產生的輸出文件中,以供編譯程序對之進行處理。包含到C源程序中的頭文件可以是系統提供的,這些頭文件一般被放在/usr/include目錄下。在程序中#include它們要使用尖括弧(<>)。另外開發人員也可以定義自己的頭文件,這些文件一般與C源程序放在同一目錄下,此時在#include中要用雙引號("")。
(4)特殊符號,預編譯程序可以識別一些特殊的符號。
例如在源程序中出現的LINE標識將被解釋為當前行號(十進制數),FILE則被解釋為當前被編譯的C源程序的名稱。預編譯程序對於在源程序中出現的這些串將用合適的值進行替換。
預編譯程序所完成的基本上是對源程序的「替代」工作。經過此種替代,生成一個沒有宏定義、沒有條件編譯指令、沒有特殊符號的輸出文件。這個文件的含義同沒有經過預處理的源文件是相同的,但內容有所不同。下一步,此輸出文件將作為編譯程序的輸出而被翻譯成為機器指令。
第二個階段編譯、優化階段。經過預編譯得到的輸出文件中,只有常量;如數字、字元串、變數的定義,以及C語言的關鍵字,如main,if,else,for,while,{,}, +,-,*,\等等。
編譯程序所要作得工作就是通過詞法分析和語法分析,在確認所有的指令都符合語法規則之後,將其翻譯成等價的中間代碼表示或匯編代碼。
優化處理是編譯系統中一項比較艱深的技術。它涉及到的問題不僅同編譯技術本身有關,而且同機器的硬體環境也有很大的關系。優化一部分是對中間代碼的優化。這種優化不依賴於具體的計算機。另一種優化則主要針對目標代碼的生成而進行的。
對於前一種優化,主要的工作是刪除公共表達式、循環優化(代碼外提、強度削弱、變換循環控制條件、已知量的合並等)、復寫傳播,以及無用賦值的刪除,等等。
後一種類型的優化同機器的硬體結構密切相關,最主要的是考慮是如何充分利用機器的各個硬體寄存器存放的有關變數的值,以減少對於內存的訪問次數。另外,如何根據機器硬體執行指令的特點(如流水線、RISC、CISC、VLIW等)而對指令進行一些調整使目標代碼比較短,執行的效率比較高,也是一個重要的研究課題。
2、匯編
匯編實際上指把匯編語言代碼翻譯成目標機器指令的過程。對於被翻譯系統處理的每一個C語言源程序,都將最終經過這一處理而得到相應的目標文件。目標文件中所存放的也就是與源程序等效的目標的機器語言代碼。目標文件由段組成。通常一個目標文件中至少有兩個段:
代碼段:該段中所包含的主要是程序的指令。該段一般是可讀和可執行的,但一般卻不可寫。
數據段:主要存放程序中要用到的各種全局變數或靜態的數據。一般數據段都是可讀,可寫,可執行的。
UNIX環境下主要有三種類型的目標文件:
(1)可重定位文件
其中包含有適合於其它目標文件鏈接來創建一個可執行的或者共享的目標文件的代碼和數據。
(2)共享的目標文件
這種文件存放了適合於在兩種上下文里鏈接的代碼和數據。
第一種是鏈接程序可把它與其它可重定位文件及共享的目標文件一起處理來創建另一個 目標文件;
第二種是動態鏈接程序將它與另一個可執行文件及其它的共享目標文件結合到一起,創建一個進程映象。
(3)可執行文件
它包含了一個可以被操作系統創建一個進程來執行之的文件。匯編程序生成的實際上是第一種類型的目標文件。對於後兩種還需要其他的一些處理方能得到,這個就是鏈接程序的工作了。
二、鏈接過程
由匯編程序生成的目標文件並不能立即就被執行,其中可能還有許多沒有解決的問題。
例如,某個源文件中的函數可能引用了另一個源文件中定義的某個符號(如變數或者函數調用等);在程序中可能調用了某個庫文件中的函數,等等。所有的這些問題,都需要經鏈接程序的處理方能得以解決。
鏈接程序的主要工作就是將有關的目標文件彼此相連接,也即將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來,使得所有的這些目標文件成為一個能夠被操作系統裝入執行的統一整體。
根據開發人員指定的同庫函數的鏈接方式的不同,鏈接處理可分為兩種:
(1)靜態鏈接
在這種鏈接方式下,函數的代碼將從其所在地靜態鏈接庫中被拷貝到最終的可執行程序中。這樣該程序在被執行時這些代碼將被裝入到該進程的虛擬地址空間中。靜態鏈接庫實際上是一個目標文件的集合,其中的每個文件含有庫中的一個或者一組相關函數的代碼。
(2) 動態鏈接
在此種方式下,函數的代碼被放到稱作是動態鏈接庫或共享對象的某個目標文件中。鏈接程序此時所作的只是在最終的可執行程序中記錄下共享對象的名字以及其它少量的登記信息。在此可執行文件被執行時,動態鏈接庫的全部內容將被映射到運行時相應進程的虛地址空間。動態鏈接程序將根據可執行程序中記錄的信息找到相應的函數代碼。
對於可執行文件中的函數調用,可分別採用動態鏈接或靜態鏈接的方法。使用動態鏈接能夠使最終的可執行文件比較短小,並且當共享對象被多個進程使用時能節約一些內存,因為在內存中只需要保存一份此共享對象的代碼。但並不是使用動態鏈接就一定比使用靜態鏈接要優越。在某些情況下動態鏈接可能帶來一些性能上損害。
我們在linux使用的gcc編譯器便是把以上的幾個過程進行捆綁,使用戶只使用一次命令就把編譯工作完成,這的確方便了編譯工作,但對於初學者了解編譯過程就很不利了,下圖便是gcc代理的編譯過程:
從上圖可以看到:
預編譯
將.c 文件轉化成 .i文件
使用的gcc命令是:gcc –E
對應於預處理命令cpp
編譯
將.c/.h文件轉換成.s文件
使用的gcc命令是:gcc –S
對應於編譯命令 cc –S
匯編
將.s 文件轉化成 .o文件
使用的gcc 命令是:gcc –c
對應於匯編命令是 as
鏈接
將.o文件轉化成可執行程序
使用的gcc 命令是: gcc
對應於鏈接命令是 ld
總結起來編譯過程就上面的四個過程:預編譯、編譯、匯編、鏈接。了解這四個過程中所做的工作,對我們理解頭文件、庫等的工作過程是有幫助的,而且清楚的了解編譯鏈接過程還對我們在編程時定位錯誤,以及編程時盡量調動編譯器的檢測錯誤會有很大的幫助的。
是否可以解決您的問題?
『叄』 編譯原理四——代碼優化
1、基本塊的劃分方法:
3、DAG圖實現基本塊的優化
1、程序流圖與循環
控制流程圖就是有唯一首節點的有向圖,用三元組G=(N,E,n 0 )表示(節點集,邊集,首節點)節點集就是基本塊集,有向邊表示如下:基本塊i出口語句不是轉向語句或停語句,i與緊隨其後的基本塊j有有向邊。或者i出口轉向j入口語句。
2、循環:程序流圖里的一個節點序列強連通,任意兩個節點都有至少一條通路,它們中有且只有一個入口節點。(從序列外某節點有一條有向邊引導它,或他是程序流圖的首節點。
3、找循環:
必經節點集:從流圖首節點出發,到n的任意通路都要經過m,m是n的必經節點,記為mDOMn;流圖中結點n的所有必經節點的集合稱為節點n的必經結點集,極為D(n)。
DOM的性質:自反性:流圖中任意節點a,都有aDOMa。傳遞性:aDOMb,bDOMc則aDOMc。反對稱性:aDOMb,bDOMa,a=b。DOM是一個偏序關系,任何節點n的必經節點集是一個有序集。
必經節點的求法:一定包括自己好吧。。。。。。必經節點集就是前驅節點必經節點集的交集加自己沒准。
找回邊:假設a b是流圖中的一條有向邊,如果bDOMa,則a b是流圖中的一條回邊。已知有向邊n d是一條回邊,則由它組成的循環就是由結點d、結點n以及有通路到達n但該通路不經過d的所有結點組成的。
4、可規約流圖:當且僅當一個流圖除去回邊後,其餘邊構成一個無環路流圖。性質:1. 圖中任何直觀環路都是循環。2. 找到所有回邊可以對應找出所有循環。3. 循環或嵌套或不相交(可能有公共入口節點),goto語句不可跳入循環。
5、循環優化
『肆』 編譯原理優化遵循哪些原則
真好奇的話,可以去翻翻《編譯原理》。不然,咱們只需要知道:1、優化有執行速度優化和空間優化兩種;2、優化級別越高,對代碼編寫質量的要求越高。如恰當地應用遞歸,使用volatile關鍵字等等,所以現實工程中一般不會開到最高優化級;3、想不出來了。。
『伍』 代碼優化的局部優化
在編譯原理中,局部優化指在程序的一個基本塊內進行的優化。 第1步:確定每個基本塊的入口語句。
根據基本塊的結構特點,它的入口語句是下述三種類型的語句之一:⑴ 程序的第一個語句;⑵ 由條件轉移語句或無條件轉移語句轉移 到的語句;⑶ 緊跟在條件轉移或無條件轉移後面的語句。
第2步:根據確定的基本塊的入口語句,構造其所屬的基本塊。
⑴ 由該入口語句直到下一個入口語句(不包含下一個入口語句)之間的所有語句構成一個基本塊;⑵ 由該入口語句到程序中的停止或暫停語句或最後一個語句(包含該停止或暫停或最後語句)之間的語句序列組成的。
第3步:凡是未包含在基本塊中的語句,都是程序的控制流不可到達的語句,直接從程序中刪除。
『陸』 編譯原理 代碼優化的方法有哪些
最直接有效的就是使用css+div的格式,將網頁中的樣式都放到css中,代碼直接調取相應的css文件
寫代碼的時候不需要的空格不要留,減小代碼所佔的空間
『柒』 編譯原理什麼是素短語
編譯原理中,素短語是至少含義一個終結符,並且自身不包含任何更小素短語的一種短語。
素短語是一種特殊的短語,它是一個遞歸的定義,至少含有一個終結符,並且除它自身之外不再含任何更小的素短語,所謂最左素短語就是處於句型最左邊的素短語的短語。
一個算符優先文法G的任何句型的最左素短語是滿足以下條件的最左子串NaNb…NcNdN(N是非終結符,a,b,c,d是終結符)。例如:句型T+T*F+id,T*F是最左素短語,id是素短語。
(7)常見的局部優化方法編譯原理擴展閱讀:
通過語法樹可以得知素短語:
1、每個句型對應一棵語法樹
2、每棵語法樹的葉子結點從左到右排列構成一個句型
3、每棵語法樹的子樹的葉子結點從左到右排列構成一個短語
4、每棵語法樹的簡單子樹(只有父子兩層結點)的葉子結點從左到右排列構成一個簡單(直接)短語。
5、素短語是至少包含一個終結符的短語,但它不能包含其它素短語。
『捌』 何謂局部優化,循環優化和全局優化優化工作在編譯的哪個階段進行
優化根據涉及的程序范圍可分為三種。 (1) 局部優化是指局限於基本塊范圍內的一種優化。一 個基本塊是指程序中一組順序執行的語句序列(或四元式序 列),其中只有一個入口(第一個語句)和一個出口(最後一個 語句)。對於一個給定的程序,我們可以把它劃分為一系列的 基本塊,然後在各個基本塊范圍內分別進行優化。通常應用 DAG方法進行局部優化。
『玖』 幾種常用最優化方法
學習和工作中遇到的大多問題都可以建模成一種最優化模型進行求解,比如我們現在學習的機器學習演算法,大部分的機器學習演算法的本質都是建立優化模型,通過最優化方法對目標函數(或損失函數)進行優化,從而訓練出最好的模型。常見的優化方法(optimization)有梯度下降法、牛頓法和擬牛頓法、共軛梯度法等等。
1. 梯度下降法(Gradient Descent)
梯度下降法是最早最簡單,也是最為常用的最優化方法。梯度下降法實現簡單,當目標函數是凸函數時,梯度下降法的解是全局解。一般情況下,其解不保證是全局最優解,梯度下降法的速度也未必是最快的。 梯度下降法的優化思想是用當前位置負梯度方向作為搜索方向,因為該方向為當前位置的最快下降方向,所以也被稱為是」最速下降法「。最速下降法越接近目標值,步長越小,前進越慢。
梯度下降 法的缺點:
(1)靠近極小值時收斂速度減慢;
(2)直線搜索時可能會產生一些問題;
(3)可能會「之字形」地下降。
在機器學習中,基於基本的梯度下降法發展了兩種梯度下降方法,分別為隨機梯度下降法和批量梯度下降法。
比如對一個線性回歸(Linear Logistics)模型,假設下面的h(x)是要擬合的函數,J( )為損失函數, 是參數,要迭代求解的值,求解出來了那最終要擬合的函數h( )就出來了。其中m是訓練集的樣本個數,n是特徵的個數。
1)批量梯度下降法(Batch Gradient Descent,BGD)
(1)將J( )對 求偏導,得到每個theta對應的的梯度:
(2)由於是要最小化風險函數,所以按每個參數 的梯度負方向,來更新每個 :
(3)從上面公式可以注意到,它得到的是一個全局最優解,但是每迭代一步,都要用到訓練集所有的數據,如果m很大,那麼可想而知這種方法的迭代速度會相當的慢。所以,這就引入了另外一種方法——隨機梯度下降。
對於批量梯度下降法,樣本個數m,x為n維向量,一次迭代需要把m個樣本全部帶入計算,迭代一次計算量為m*n2。
2)隨機梯度下降(Stochastic Gradient Descent,SGD)
(1)上面的風險函數可以寫成如下這種形式,損失函數對應的是訓練集中每個樣本的粒度,而上面批量梯度下降對應的是所有的訓練樣本:
(2)每個樣本的損失函數,對 求偏導得到對應梯度,來更新 :
(3)隨機梯度下降是通過每個樣本來迭代更新一次,如果樣本量很大的情況(例如幾十萬),那麼可能只用其中幾萬條或者幾千條的樣本,就已經將
迭代到最優解了,對比上面的批量梯度下降,迭代一次需要用到十幾萬訓練樣本,一次迭代不可能最優,如果迭代10次的話就需要遍歷訓練樣本10次。但是,SGD伴隨的一個問題是噪音較BGD要多,使得SGD並不是每次迭代都向著整體最優化方向。
隨機梯度下降每次迭代只使用一個樣本,迭代一次計算量為n2,當樣本個數m很大的時候,隨機梯度下降迭代一次的速度要遠高於批量梯度下降方法。 兩者的關系可以這樣理解:隨機梯度下降方法以損失很小的一部分精確度和增加一定數量的迭代次數為代價,換取了總體的優化效率的提升。增加的迭代次數遠遠小於樣本的數量。
對批量梯度下降法和隨機梯度下降法的總結:
批量梯度下降---最小化所有訓練樣本的損失函數,使得最終求解的是全局的最優解,即求解的參數是使得風險函數最小,但是對於大規模樣本問題效率低下。
隨機梯度下降---最小化每條樣本的損失函數,雖然不是每次迭代得到的損失函數都向著全局最優方向, 但是大的整體的方向是向全局最優解的,最終的結果往往是在全局最優解附近,適用於大規模訓練樣本情況。
2. 牛頓法和擬牛頓法(Newton's method & Quasi-Newton Methods)
1)牛頓法(Newton's method)
牛頓法是一種在實數域和復數域上近似求解方程的方法。方法使用函數 f ( x )的泰勒級數的前面幾項來尋找方程 f ( x ) = 0的根。牛頓法最大的特點就在於它的收斂速度很快。
具體步驟:
首先,選擇一個接近函數 f ( x )零點的x0,計算相應的 f ( x 0)和切線斜率 f ' ( x 0)(這里 f ' 表示函數 f 的導數)。然後我們計算穿過點( x 0, f ( x 0))並且斜率為 f '( x 0)的直線和 x 軸的交點的 x 坐標,也就是求如下方程的解:
我們將新求得的點的 x 坐標命名為 x 1,通常 x 1會比 x 0更接近方程 f ( x ) = 0的解。因此我們現在可以利用 x 1開始下一輪迭代。迭代公式可化簡為如下所示:
已經證明,如果 f '是連續的,並且待求的零點 x 是孤立的,那麼在零點 x 周圍存在一個區域,只要初始值 x 0位於這個鄰近區域內,那麼牛頓法必定收斂。 並且,如果 f ' ( x )不為0, 那麼牛頓法將具有平方收斂的性能. 粗略的說,這意味著每迭代一次,牛頓法結果的有效數字將增加一倍。下圖為一個牛頓法執行過程的例子。
由於牛頓法是基於當前位置的切線來確定下一次的位置,所以牛頓法又被很形象地稱為是"切線法"。
關於牛頓法和梯度下降法的效率對比:
從本質上去看,牛頓法是二階收斂,梯度下降是一階收斂,所以牛頓法就更快。如果更通俗地說的話,比如你想找一條最短的路徑走到一個盆地的最底部,梯度下降法每次只從你當前所處位置選一個坡度最大的方向走一步,牛頓法在選擇方向時,不僅會考慮坡度是否夠大,還會考慮你走了一步之後,坡度是否會變得更大。所以,可以說牛頓法比梯度下降法看得更遠一點,能更快地走到最底部。(牛頓法目光更加長遠,所以少走彎路;相對而言,梯度下降法只考慮了局部的最優,沒有全局思想。)
根據wiki上的解釋,從幾何上說,牛頓法就是用一個二次曲面去擬合你當前所處位置的局部曲面,而梯度下降法是用一個平面去擬合當前的局部曲面,通常情況下,二次曲面的擬合會比平面更好,所以牛頓法選擇的下降路徑會更符合真實的最優下降路徑。
註:紅色的牛頓法的迭代路徑,綠色的是梯度下降法的迭代路徑。
牛頓法的優缺點總結:
優點:二階收斂,收斂速度快;
缺點:牛頓法是一種迭代演算法,每一步都需要求解目標函數的Hessian矩陣的逆矩陣,計算比較復雜。
2)擬牛頓法(Quasi-Newton Methods)
擬牛頓法是求解非線性優化問題最有效的方法之一,於20世紀50年代由美國Argonne國家實驗室的物理學家W.C.Davidon所提出來。Davidon設計的這種演算法在當時看來是非線性優化領域最具創造性的發明之一。不久R. Fletcher和M. J. D. Powell證實了這種新的演算法遠比其他方法快速和可靠,使得非線性優化這門學科在一夜之間突飛猛進。
擬牛頓法的本質思想是改善牛頓法每次需要求解復雜的Hessian矩陣的逆矩陣的缺陷,它使用正定矩陣來近似Hessian矩陣的逆,從而簡化了運算的復雜度。 擬牛頓法和最速下降法一樣只要求每一步迭代時知道目標函數的梯度。通過測量梯度的變化,構造一個目標函數的模型使之足以產生超線性收斂性。這類方法大大優於最速下降法,尤其對於困難的問題。另外,因為擬牛頓法不需要二階導數的信息,所以有時比牛頓法更為有效。如今,優化軟體中包含了大量的擬牛頓演算法用來解決無約束,約束,和大規模的優化問題。
具體步驟:
擬牛頓法的基本思想如下。首先構造目標函數在當前迭代xk的二次模型:
這里Bk是一個對稱正定矩陣,於是我們取這個二次模型的最優解作為搜索方向,並且得到新的迭代點:
其中我們要求步長ak 滿足Wolfe條件。這樣的迭代與牛頓法類似,區別就在於用近似的Hesse矩陣Bk 代替真實的Hesse矩陣。所以擬牛頓法最關鍵的地方就是每一步迭代中矩陣Bk的更新。現在假設得到一個新的迭代xk+1,並得到一個新的二次模型:
我們盡可能地利用上一步的信息來選取Bk。具體地,我們要求
從而得到
這個公式被稱為割線方程。常用的擬牛頓法有DFP演算法和BFGS演算法。
原文鏈接: [Math] 常見的幾種最優化方法 - Poll的筆記 - 博客園
『拾』 常用優化器演算法歸納介紹
優化器是神經網路訓練過程中,進行梯度下降以尋找最優解的優化方法。不同方法通過不同方式(如附加動量項,學習率自適應變化等)側重於解決不同的問題,但最終大都是為了加快訓練速度。
這里就介紹幾種常見的優化器,包括其原理、數學公式、核心思想及其性能;
核心思想: 即針對每次輸入的訓練數據,計算輸出預測與真值的Loss的梯度;
從表達式來看,網路中參數的更新,是不斷向著最小化Loss函數的方向移動的:
優點:
簡單易懂,即對於相應的最優解(這里認為是Loss的最小函數),每次變數更新都是沿著局部梯度下降最快的方向,從而最小化損失函數。
缺點:
不同於標准梯度下降法(Gradient Descent)一次計算所有數據樣本的Loss並計算相應的梯度,批量梯度下降法(BGD, Batch Gradient Descent)每次只取一個小批次的數據及其真實標簽進行訓練,稱這個批次為mini-batch;
優點:
缺點:
隨機梯度下降法的 batch size 選擇不當可能導致模型難以收斂;由於這種方法是在一次更新中,就對整個數據集計算梯度,所以計算起來非常慢,遇到很大量的數據集也會非常棘手,而且不能投入新數據實時更新模型。
我們會事先定義一個迭代次數 epoch,首先計算梯度向量 params_grad,然後沿著梯度的方向更新參數 params,learning rate 決定了我們每一步邁多大。
Batch gradient descent 對於凸函數可以收斂到全局極小值,對於非凸函數可以收斂到局部極小值。
和 BGD 的一次用所有數據計算梯度相比,SGD 每次更新時對每個樣本進行梯度更新,對於很大的數據集來說,可能會有相似的樣本,這樣 BGD 在計算梯度時會出現冗餘,而 SGD 一次只進行一次更新,就沒有冗餘,而且比較快,並且可以新增樣本。
即訓練時,每次只從一批訓練樣本中隨機選取一個樣本進行梯度下降;對隨機梯度下降來說,只需要一次關注一個訓練樣本,一點點把參數朝著全局最小值的方向進行修改了。
整體數據集是個循環,其中對每個樣本進行一次參數更新
缺點:
梯度下降速度比較慢,而且每次梯度更新時往往只專注與局部最優點,而不會恰好指向全局最優點;
單樣本梯度更新時會引入許多雜訊(跟訓練目標無關的特徵也會被歸為該樣本分類的特徵);
SGD 因為更新比較頻繁,會造成 cost function 有嚴重的震盪。
BGD 可以收斂到局部極小值,當然 SGD 的震盪可能會跳到更好的局部極小值處。
當我們稍微減小 learning rate,SGD 和 BGD 的收斂性是一樣的。
優點:
當處理大量數據時,比如SSD或者faster-rcnn等目標檢測模型,每個樣本都有大量候選框參與訓練,這時使用隨機梯度下降法能夠加快梯度的計算。
隨機梯度下降是通過每個樣本來迭代更新一次,如果樣本量很大的情況,那麼可能只用其中部分的樣本,就已經將 迭代到最優解了,對比上面的批量梯度下降,迭代一次需要用到十幾萬訓練樣本,一次迭代不可能最優,如果迭代10次的話就需要遍歷訓練樣本10次。缺點是SGD的噪音較BGD要多,使得SGD並不是每次迭代都向著整體最優化方向。所以雖然訓練速度快,但是准確度下降,並不是全局最優。雖然包含一定的隨機性,但是從期望上來看,它是等於正確的導數的。
梯度更新規則:
MBGD 每一次利用一小批樣本,即 n 個樣本進行計算,這樣它可以降低參數更新時的方差,收斂更穩定,另一方面可以充分地利用深度學習庫中高度優化的矩陣操作來進行更有效的梯度計算。
和 SGD 的區別是每一次循環不是作用於每個樣本,而是具有 n 個樣本的批次。
超參數設定值: n 一般取值在 50~256
缺點:(兩大缺點)
鞍點就是:一個光滑函數的鞍點鄰域的曲線,曲面,或超曲面,都位於這點的切線的不同邊。例如這個二維圖形,像個馬鞍:在x-軸方嚮往上曲,在y-軸方嚮往下曲,鞍點就是(0,0)。
為了應對上面的兩點挑戰就有了下面這些演算法
核心思想:
不使用動量優化時,每次訓練的梯度下降方向,都是按照當前批次訓練數據計算的,可能並不能代表整個數據集,並且會有許多雜訊,下降曲線波動較大:
添加動量項之後,能夠有效減小波動,從而加快訓練速度:
當我們將一個小球從山上滾下來時,沒有阻力的話,它的動量會越來越大,但是如果遇到了阻力,速度就會變小。
加入的這一項,可以使得梯度方向不變的維度上速度變快,梯度方向有所改變的維度上的更新速度變慢,這樣就可以加快收斂並減小震盪。
優點:
通過動量更新,參數向量會在有持續梯度的方向上增加速度;
使梯度下降時的折返情況減輕,從而加快訓練速度;
缺點:
如果數據集分類復雜,會導致 和 時刻梯度 向量方向相差較大;在進行向量求和時,得到的 會非常小,反而使訓練速度大大下降甚至模型難以收斂。
這種情況相當於小球從山上滾下來時是在盲目地沿著坡滾,如果它能具備一些先知,例如快要上坡時,就知道需要減速了的話,適應性會更好。
目前為止,我們可以做到,在更新梯度時順應 loss function 的梯度來調整速度,並且對 SGD 進行加速。
核心思想:
自適應學習率優化演算法針對於機器學習模型的學習率,採用不同的策略來調整訓練過程中的學習率,從而大大提高訓練速度。
這個演算法就可以對低頻的參數做較大的更新,對高頻的做較小的更新,也因此,對於稀疏的數據它的表現很好,很好地提高了 SGD 的魯棒性,例如識別 Youtube 視頻裡面的貓,訓練 GloVe word embeddings,因為它們都是需要在低頻的特徵上有更大的更新。
Adagrad 的優點是減少了學習率的手動調節
式中, 表示第 個分類, 表示第 迭代同時也表示分類 累計出現的次數。 表示初始的學習率取值(一般為0.01)
AdaGrad的核心思想: 縮放每個參數反比於其所有梯度歷史平均值總和的平方根。具有代價函數最大梯度的參數相應地有較大的學習率,而具有小梯度的參數又較小的學習率。
缺點:
它的缺點是分母會不斷積累,這樣學習率就會收縮並最終會變得非常小。
這個演算法是對 Adagrad 的改進,
和 Adagrad 相比,就是分母的 換成了過去的梯度平方的衰減平均值,指數衰減平均值
這個分母相當於梯度的均方根 root mean squared (RMS),在數據統計分析中,將所有值平方求和,求其均值,再開平方,就得到均方根值 ,所以可以用 RMS 簡寫:
其中 的計算公式如下, 時刻的依賴於前一時刻的平均和當前的梯度:
梯度更新規則:
此外,還將學習率 換成了 RMS[Δθ],這樣的話,我們甚至都不需要提前設定學習率了:
超參數設定值: 一般設定為 0.9
RMSprop 是 Geoff Hinton 提出的一種自適應學習率方法。
RMSprop 和 Adadelta 都是為了解決 Adagrad 學習率急劇下降問題的,
梯度更新規則:
RMSprop 與 Adadelta 的第一種形式相同:(使用的是指數加權平均,旨在消除梯度下降中的擺動,與Momentum的效果一樣,某一維度的導數比較大,則指數加權平均就大,某一維度的導數比較小,則其指數加權平均就小,這樣就保證了各維度導數都在一個量級,進而減少了擺動。允許使用一個更大的學習率η)
超參數設定值:
Hinton 建議設定 為 0.9, 學習率 為 0.001。
這個演算法是另一種計算每個參數的自適應學習率的方法。相當於 RMSprop + Momentum
除了像 Adadelta 和 RMSprop 一樣存儲了過去梯度的平方 vt 的指數衰減平均值 ,也像 momentum 一樣保持了過去梯度 mt 的指數衰減平均值:
如果 和 被初始化為 0 向量,那它們就會向 0 偏置,所以做了偏差校正,通過計算偏差校正後的 和 來抵消這些偏差:
梯度更新規則:
超參數設定值:
建議
示例一
示例二
示例三
上面情況都可以看出,Adagrad, Adadelta, RMSprop 幾乎很快就找到了正確的方向並前進,收斂速度也相當快,而其它方法要麼很慢,要麼走了很多彎路才找到。
由圖可知自適應學習率方法即 Adagrad, Adadelta, RMSprop, Adam 在這種情景下會更合適而且收斂性更好。
如果數據是稀疏的,就用自適用方法,即 Adagrad, Adadelta, RMSprop, Adam。
RMSprop, Adadelta, Adam 在很多情況下的效果是相似的。
Adam 就是在 RMSprop 的基礎上加了 bias-correction 和 momentum,
隨著梯度變的稀疏,Adam 比 RMSprop 效果會好。
整體來講,Adam 是最好的選擇。
很多論文里都會用 SGD,沒有 momentum 等。SGD 雖然能達到極小值,但是比其它演算法用的時間長,而且可能會被困在鞍點。
如果需要更快的收斂,或者是訓練更深更復雜的神經網路,需要用一種自適應的演算法。
各種優化器Optimizer原理:從SGD到AdamOptimizer
深度學習——優化器演算法Optimizer詳解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)