導航:首頁 > 源碼編譯 > 剪枝演算法效率

剪枝演算法效率

發布時間:2023-04-13 21:30:37

『壹』 關於不完全動態信息博弈的正規表述,舉例說明博弈樹方法

這種的話一般可能就是自己怎麼去博弈,有一個正規的方法,你根據自己的邏輯世衛去參考吧。
一、啟發式搜索策略即為結點排序技術。α-β搜索/剪枝演算法的剪枝效率對同一結點下的孩子結點的排列順序非常敏感,這些結點的排列越理想,則剪枝越早發生,需要展開和估值的結點數越少,演算法效率越高,反之搜索效率越低。
二、雖然無法事先預知哪個結點是最佳結點,但卻可以採取一些措施,讓能產生剪枝的幾率越高的結點越排在前面,以優先搜索,使博弈樹盡可能接近最小樹。
三、在博弈過程中,任何一方都希望自己取得勝利。因此,在某一方當前有多個行動方案可供選擇時,他總是挑選對自己最為有利而對者遲緩對方最為不利的那個行動方案。首模此時,如果我們站在A方的立場上,則可供A方選擇的若干行動方案之間是「或」關系,因為主動權操在A方手裡,他或者選擇這個行動方案,或者選擇另一個行動方案,完全由A方決定。
四、若B方也有若干個可供選擇的行動方案,則對A方來說這些行動方案之間是「與」關系,因為這時主動權操在B方手裡,這些可供選擇的行動方案中地任何一個都可能被B方選中,A方必須考慮到對自己最不利的情況發生。
五、若把上述博弈過程用圖表示出來,得到的是一棵「與/或」樹。這里要特別指出,該「與/或」樹是始終站在某一方(例如A方)的立場上得出的,決不可一會兒站在這一方的立場上,一會兒又站在另一方的立場上。
六、在博弈問題中,每一個格局可供選擇的行動方案都有很多,因此會生成十分龐大的博弈樹。據統計西洋跳棋完整的博弈樹約有1040個節點。試圖利用完整的博弈樹來進行極大極小分析是困難的。可行的辦法是只生成一定深度的博弈樹,然後進行極大極小分析,找出當前最好的行動方案。以中國象棋為例,在開局狀態下,最初搜索時,置換表啟發、歷史啟發、殺手啟發這些動態啟發起的作用很小甚至來不及起作用,此時吃子啟發起的作用較大。因此,在著法生成時,考慮首先生成車、馬、炮的著法,最後生成帥的著法,往往旦友是很有效的。

『貳』 剪枝演算法怎麼弄 大數取模

α-β剪枝技術
首先分析極小極大分析法效率,上述的極小極大分析法,實際是先生成一棵博弈樹,然後再計算其倒推值,至使極小極大分析法效率較低。於是在極小極大分析法的基礎上提出了α-β剪枝技術。
α-β剪枝技術的基本思想或演算法是,邊生成博弈樹邊計算評估各節點的倒推值,並且根據評估出的倒推值范圍,及時停止擴展那些已無必要再擴展的子節點,即相當於剪去了博弈樹上的一些分枝,從而節約了機器開銷,提高了搜索效率。具體的剪枝方法如下:
(1) 對於一個與節點MIN,若能估計出其倒推值的上確界β,並且這個β值不大於 MIN的父節點(一定是或節點)的估計倒推值的下確界α,即α≥β,則就不必再擴展該 MIN節點的其餘子節點了(因為這些節點的估值對MIN父節點的倒推值已無任何影響 了)。這一過程稱為α剪枝。
(2) 對於一個或節點MAX,若能估計出其倒推值的下確界α,並且這個α值不小於 MAX的父節點(一定是與節點)的估計倒推值的上確界β,即α≥β,則就不必再擴展該MAX節點的其餘子節點了(因為這些節點的估值對MAX父節點的倒推值已無任何影響 了)。這一過程稱為β剪枝。

『叄』 極大極小演算法有些不明白

先來說極小極大演算法主要應用於什麼樣的游戲:
1. 零和游戲(Zero-sum Game):意思就是你死我活,一方的勝利代表另一方的失敗,比如,象棋,五子棋等。
2. 完全信息(Perfect Information):玩家知道之前所有的步驟。象棋就是完全信息,因為玩家是交替著落子,且之前的步驟都能在棋盤上體現,但是石頭剪子布就不是。
這樣的游戲通常可以把他們看作一個樹狀圖,把每一種可能性列出來。比如下面這個井字棋游戲,Max代表你自己,Min代表你的對手。
這個時候我們需要給每一種結果一個分數,就是這里的Utility。這個分數是站在我自己(也就是Max)的角度評估的,比如上圖中我贏了就是+1,輸了是-1,平局時0。所以,我希望最大化這個分數,而我的對手希望最小化這個分數。(在游戲中,這個分數被稱為static value。)這里要說一下,井字棋是個比較簡單的游戲,所以可以列出所有可能的結果。但是,大部分游戲是不太可能把所有結果都列出來的。根據計算機運算量,我們可能只能往前推7,8步,所以這個時候分數就不只-1,1,0這么簡單了,會有專門的演算法來根據當前結果給不同的分數。
假設我們有如下圖的游戲,我是先手,我應該如何利用Minmax演算法來選出第一步怎麼走呢?
當然對於一個復雜的游戲來說,比如象棋,肯定是需要非常多步才能完成的。這就導致結果的數量是成幾何增長的,也就是說,如果這個游戲每一步都有n個選擇,那麼在x步以後,將會有n^x個選擇。這個時候,我們就需要採取剪枝演算法(Alpha-Beta)來減少運算量。從剪枝演算法這個名字我們就能看出,這個演算法能讓我們剪掉樹狀圖中的一些分支,從而減少運算量。在這里也說一下剪枝演算法,因為這並不是個不同於極小極大的演算法,而是極小極大演算法的升級版。
我們將游戲簡化成如下圖,使用Minimax演算法,我們可以得出這樣的結果

『肆』 10、填空在AlphaBeta剪枝演算法中,我們把一個結點可能取值的上界記作____值

這個問題問的不是很清楚,個人理解,在AlphaBeta剪枝演算法中,可以把一個節點可能取值的上界記作 Beta 值。
AlphaBeta剪枝演算法是對極大極小演算法的優化,效率更高。極大極小是一種暴力搜索策略,需要遍歷所有可能的情況,隨著節點數特別是深度的增加,演算法性能會大幅下降。AlphaBeta剪枝演算法採用遞歸的方式進行倒推估算,可以在搜索過程中剪除無用的分支,從而減少不必要的搜索(這些搜索中不會有滿足要求的答案),提升演算法的效率。
可以這樣簡單地理解吧,每一層的節點都有Alpha(下界)、Beta(上界),而且是動態調整的,如果在推導過程中發現 Alpha>=Beta,那麼就可以終止當前節點往下各層級的搜索,達到提高效率的目的。

『伍』 如何等分上寬下窄桶的容積

要算水桶的容積,只需量出水桶口和水桶底的直徑,和水桶的高度,然後算出水桶中間的直徑即(桶口直徑+桶底直徑)/2。最後按3.14✘(水桶中間直徑/2)的平方✘高就可以計算出水桶的容積有一個容積為8升的水桶里裝滿了水,另外還有一個容積為3升的空桶和一個容積為5升的空桶,如何利用這兩個空桶等分8升水?附加條件是三個水桶都沒有體積刻度,也不能使用其它輔助容器。但是計算機並不能理解這個「1」的重要性,很難按照人類的思維方式按部就班地推導答案,因此用計算機解決這個問題,通常會選擇使用「窮舉法」。為什麼使用窮舉法?因為這不是一個典型意義上的求解最優解的問題,雖然可以暗含一個求解倒水次數最少的方法的要求,但就本質而言,常用的求解最優解問題的高效的方法都不適用於此問題。如果能夠窮舉解空間的全部合法解,然後通過比較找到最優解也是一種求解最優解的方法。不過就本題題意而言,並不關心什麼方法最快,能求出全部等分水的方法可能更符合題意。

如果我們把某一時刻三個水桶中存水的容積稱為一個狀態,則問題的初始狀態是8升的水桶裝滿水,求解的解出狀態(最終狀態)是8升水桶中4升水,5升水桶中4升水。窮舉法的實質就是把從初始狀態開始,根據某種狀態變化的規則搜索全部可能的狀態,每當找到一個從初始狀態到最終狀態的變化路徑,就可以理解為找到了一種答案。這樣的狀態變化搜索的結果通常是得到一棵狀態搜索樹,根節點是初始狀態,葉子節點可能是最終狀態,也可能是某個無法轉換到最終狀態的中間狀態,狀態樹有多少個最終狀態的葉子節點,就有多少種答案。根據以上分析結果,解決本問題的演算法關鍵有三點:首先,建立演算法的狀態模型;其次,確定狀態樹的搜索演算法(暗含狀態轉換的規則);最後,需要一些提高演算法效率的手段,比如應用「剪枝」條件避免重復的狀態搜索,還要避免狀態的循環生成導致搜索演算法在若干個狀態之間無限循環。建立狀態模型是整個演算法的關鍵,這個狀態模型不僅要能夠描述靜止狀態,還要能夠描述並記錄狀態轉換動作,尤其是對狀態轉換的描述,因為這會影響到狀態樹搜索演算法的設計。所謂的靜止狀態,就是某一時刻三個水桶中存水的容積,我們採用長度為3的一維向量描述這個狀態。這組向量的三個值分別是容積為8升的桶中的水量、容積為5升的桶中的水量和容積為3升的桶中的水量。因此演算法的初始狀態就可以描述為[8 ,0, 0],則終止狀態為[4, 4, 0]。

對狀態轉換的描述就是在兩個狀態之間建立關聯,在本演算法中這個關聯就是一個合法的倒水動作。某一此賣薯時刻三個水桶中的存水狀態,經過某個倒水動作後演變到一個新的存水狀態,這是對狀態轉換的文字描述,對演算法來講,倒水狀態描述就是「靜止狀態」+「倒水動作」。我們用一個三元組來描述倒水動作:{from, to, water},from是指從哪個桶中倒水,to是指將水倒向哪個桶,water是此次倒水動作所倒的水量。本模型的特例就是第一個狀態如何得到,也就是[8, 0, 0]這個狀態對應的倒水動作如何描述?我們用-1表示未知的水桶編號(上帝水桶),因此第一個狀態對應的倒水動作就是{-1, 1, 8}。應用本模型對前面提到的第一種解決方法進行狀態轉換描述確定了狀態模型後,就需要解決演算法面臨的第二個問題:狀態樹的搜索演算法。一個靜止狀態結合不同的倒水動作會遷移到不同的狀態,所有狀態轉換所展示的就是一棵以狀態[8, 0, 0]為根的狀態搜索樹,圖(2)畫出了這個狀態搜索樹的一部分,其中森者一個用不同顏色標識出來的狀態轉換過程(狀態樹的一個分支)就是本問題的一個解狀態樹的搜索就是對整個狀態樹進行遍歷,這中間其實暗含了狀態的生成,因為狀態樹一開始並不完整,只有一個初始狀態的根節點,當搜索(也就是遍歷)操作完成時,狀態樹才完整。樹的遍歷可以採用廣度配核優先遍歷演算法,也可以採用深度優先遍歷演算法,就本題而言,要求解所有可能的等分水的方法,暗含了要記錄從初始狀態到最終狀態,所以更適合使用深度優先遍歷演算法。狀態樹的遍歷暗含了一個狀態生成的過程,就是促使狀態樹上的一個狀態向下一個狀態轉換的驅動過程,這是一個很重要的部分,如果不能正確地驅動狀態變化,就不能實現狀態樹的遍歷(搜索)。

建立狀態模型一節中提到的動作模型,就是驅動狀態變化的關鍵因子。對一個狀態來說,它能轉換到哪些新狀態,取決於它能應用哪些倒水動作,一個倒水動作能夠在原狀態的基礎上「生成」一個新狀態,不同的倒水動作可以「生成」不同的新狀態。由此可知,狀態樹遍歷的關鍵是找到三個水桶之間所有合法的倒水動作,用這些倒水動作分別「生成」各自相應的新狀態。遍歷三個水桶的所有可能動作,就是對三個水桶任取兩個進行全排列(常用的排列組合演算法可以參考《排列組合演算法》一文),共有6種水桶的排列組合,也就是說有6種可能的倒水動作。將這6種倒水動作依次應用到當前狀態,就可以「生成」6種新狀態,從而驅動狀態發生變化(有些排列並不能組合出合法的倒水動作,關於這一點後面「演算法優化」部分會介紹)。
狀態搜索的核心是對三個水桶進行兩兩排列組合得到6種倒水動作,但是並不是每種倒水動作都是合法的,比如,需要倒出水的桶中沒有水的情況和需要倒進水的桶中已經滿的情況下,都組合不出合法的倒水動作。除此之外,因為水桶是沒有刻度的,因此倒水動作也是受限制的,也就是說合法的倒水動作只能有兩種結果:需要倒出水的桶被倒空和需要倒進水的桶被倒滿。加上這些限制之後,每次組合其實只有少數倒水動作是合法的,可以驅動當前的狀態到下一個狀態。利用這一點,就可以對狀態樹進行「剪枝」,避免對無效(非法)的狀態分支進行搜索。

除了通過「剪枝」提高演算法效率,對於深度優先的狀態搜索還需要防止因狀態的循環生成造成深度優先搜索無法終止的問題。狀態的循環生成有兩種表現形式:一種是在兩個桶之間互相倒水;另一種就是圖(2)中展示的一個例子,[3, 5, 0] -> [3, 2, 3] -> [6, 2, 0] -> [3, 5, 0]形成一個狀態環。要避免出現狀態環,就需要記錄一次深度遍歷過程中所有已經搜索過的狀態,形成一個當前搜索已經處理過的狀態表,每當生成一個新狀態,就先檢查是否是狀態表中已經存在的狀態,如果是則放棄這個狀態,回溯到上一步繼續搜索。如果新狀態是狀態表中沒有的狀態,則將新狀態加入到狀態表,然後從新狀態開始繼續深度優先遍歷。在這個過程中因重復出現被放棄的狀態,可以理解為另一種形式的「剪枝」,可以使一次深度優先遍歷很快收斂到初始狀態。桶的容積:V=πr²h。圓面積是指圓形所佔的平面空間大小,常用S表示。圓是一種規則的平面幾何圖形,其計算方法有很多種,比較常見的是開普勒的求解方法,卡瓦利里的求解方法等。圓的面積就是:圓的半徑(r)的平方乘以π。

圓柱體的體積=圓桶的容積=πr²h=0.25πD²h(π=3.14,r是桶的半徑,D是桶的直徑,h是桶的高)

圓柱體積公式是用於計算圓柱體體積的公式。

圓柱體積=πr²h=S底面積×高(h)

先求底面積,然後乘高。

π是圓周率,一般取3.14

r是圓柱底面半徑

h為圓柱的高

還可以是

v=1/2ch×r

側面積的一半×半徑

木桶底面是圓,底面積公式=πr²=0.25πD²(π=3.14,r是桶的半徑,D是桶的直徑)

容積和體積是不同的

1、含義不同。如一隻鐵桶的體積是指它外部所佔空間部分的大小,而這只鐵桶的容積卻是指它內部容納物體的多少。一種物體有體積,可不一定有容積。

2、測量方法不同。在計算物體的體積或容積前一般要先測量長、寬、高,求物體的體積是從該物體的外部來測量,而求容積卻是從物體的內部來測量。一種既有體積又有容積的封閉物體,它的體積一定大於它的容積。

3、單位名稱不完全相同。體積單位一般用:立方米、立方分米、立方厘米;固體的容積單位與體積單位相同,而液體和氣體的體積與容積單位一般都用升、毫升。

4.公式:V長方體=abh(長× 寬× 高); V正方體=aaa(棱長× 棱長× 棱長);V圓柱=Sh;V圓錐=1/3sh。

5.計量液體的體積,如水、油等,常用容積單位升和毫升,也可以寫成L和mL。

6.計算不規則的立體圖形體積可以把這個物體放入水中,用現在容積-未放入物體的容積就是體積或用放入物體後高-未放入物體*長*寬(1升=1立方分米;1毫升=1立方厘米)

7.硬碟的容量是以MB(兆)和GB(千兆)為單位的計算機上的單個文件的大小就是容積了!(如:500kb的一個圖片:是圖片的容積為500kb)

『陸』 如何實現C#五子棋難度等級設置

要實現 C# 五子棋的難度等級設置,你需要對計算機 AI(人工智慧)的思考深度進行調整。思考深度越深,計算機就會做出更優鋒梁秀的決策,但也會增加計算機的計算負擔和時間成本。

以下是實現 C# 五子棋難度等級設置的一般步驟銀敗運:

『柒』 衡量演算法效率的方法與准則

演算法效率與分析
數據結構作為程序設計的基礎,其對演算法效率的影響必然是不可忽視的。本文就如何合理選擇數據結構來優化演算法這一問題,對選擇數據結構的原則和方法進行了一些探討。首先對數據邏輯結構的重要性進行了分析,提出了選擇邏輯結構的兩個基本原則;接著又比較了順序和鏈式兩種存儲結構的優點和缺點,並討論了選擇數據存儲結構的方法;最後本文從選擇數據結構的的另一角度出發,進一步探討了如何將多種數據結構進行結合的方法。在討論方法的同時,本文還結合實際,選用了一些較具有代表性的信息學競賽試題舉例進行了分析
【正文】一、引論
「數據結構+演算法=程序」,這就說明程序設計的實質就是對確定的問題選擇一種合適的數據結構,加上設計一種好的演算法。由此可見,數據結構在程序設計中有著十分重要的地位。
數據結構是相互之間存在一種或多種特定關系的數據元素的集合。因為這其中的「關系」,指的是數據元素之間的邏輯關系,因此數據結構又稱為數據的邏輯結構。而相對於邏輯結構這個比較抽象的概念,我們將數據結構在計算機中的表示又稱為數據的存儲結構。
建立問題的數學模型,進而設計問題的演算法,直至編出程序並進行調試通過,這就是我們解決信息學問題的一般步驟。我們要建立問題的數學模型,必須首先找出問題中各對象之間的關系,也就是確定所使用的邏輯結構;同時,設計演算法和程序實現的過程,必須確定如何實現對各個對象的操作,而操作的方法是決定於數據所採用的存儲結構的。因此,數據邏輯結構和存儲結構的好壞,將直接影響到程序的效率。

二、選擇合理的邏輯結構

在程序設計中,邏輯結構的選用就是要分析題目中的數據元素之間的關系,並根據這些特定關系來選用合適的邏輯結構以實現對問題的數學描述,進一步解決問題。邏輯結構實際上是用數學的方法來描述問題中所涉及的操作對象及對象之間的關系,將操作對象抽象為數學元素,將對象之間的復雜關系用數學語言描述出來。
根據數據元素之間關系的不同特性,通常有以下四種基本邏輯結構:集合、線性結構、樹形結構、圖狀(網狀)結構。這四種結構中,除了集合中的數據元素之間只有「同屬於一個集合」的關系外,其它三種結構數據元素之間分別為「一對一」、「一對多」、「多對多」的關系。
因此,在選擇邏輯結構之前,我們應首先把題目中的操作對象和對象之間的關系分析清楚,然後再根據這些關系的特點來合理的選用邏輯結構。尤其是在某些復雜的問題中,數據之間的關系相當復雜,且選用不同邏輯結構都可以解決這一問題,但選用不同邏輯結構實現的演算法效率大不一樣。
對於這一類問題,我們應採用怎樣的標准對邏輯結構進行選擇呢?
下文將探討選擇合理邏輯結構應充分考慮的兩個因素。

一、 充分利用「可直接使用」的信息。
首先,我們這里所講的「信息」,指的是元素與元素之間的關系。
對於待處理的信息,大致可分為「可直接使用」和「不可直接使用」兩類。對於「可直接使用」的信息,我們使用時十分方便,只需直接拿來就可以了。而對於「不可直接使用」的這一類,我們也可以通過某些間接的方式,使之成為可以使用的信息,但其中轉化的過程顯然是比較浪費時間的。
由此可見,我們所需要的是盡量多的「可直接使用」的信息。這樣的信息越多,演算法的效率就會越高。
對於不同的邏輯結構,其包含的信息是不同的,演算法對信息的利用也會出現不同的復雜程度。因此,要使演算法能夠充分利用「可直接使用」的信息,而避免演算法在信息由「不可直接使用」向「可直接使用」的轉化過程中浪費過多的時間,我們必然需要採用一種合理的邏輯結構,使其包含更多「可直接使用」的信息。
〖問題一〗 IOI99的《隱藏的碼字》。
〖問題描述〗
問題中給出了一些碼字和一個文本,要求編程找出文本中包含這些碼字的所有項目,並將找出的項目組成一個最優的「答案」,使得答案中各項目所包含的碼字長度總和最大。每一個項目包括一個碼字,以及該碼字在文本中的一個覆蓋序列(如』abcadc』就是碼字』abac』的一個覆蓋序列),並且覆蓋序列的長度不超過1000。同時,「答案」要求其中每個項目的覆蓋序列互相沒有重疊。
〖問題分析〗
對於此題,一種較容易得出的基本演算法是:對覆蓋序列在文本中的終止位置進行循環,再判斷包含了哪些碼字,找出所有項目,並最後使用動態規劃的方法將項目組成最優的「答案」。
演算法的其它方面我們暫且不做考慮,而先對問題所採用的邏輯結構進行選擇。
如果我們採用線性的邏輯結構(如循環隊列),那麼我們在判斷是否包含某個碼字t時,所用的方法為:初始時用指針p指向終止位置,接著通過p的不斷前移,依次找出碼字t從尾到頭的各個字母。例如碼字為「ABDCAB」,而文本圖1-1,終止位置為最右邊的箭頭符號,每個箭頭代表依次找到的碼字的各個字母。
指針p的移動方向
A B D C A B

C D A C B D C A D C D B A D C C B A D

圖1-1

由於題目規定碼字的覆蓋序列長度不超過1000,所以進行這樣的一次是否包含的判斷,其復雜度為O(1000)。
由於碼字t中相鄰兩字母在文本中的位置,並非只有相鄰(如圖1-1中的』D』和』C』)這一種關系,中間還可能間隔了許多的字母(如圖1-1中』C』和』A』就間隔了2個字母),而線性結構中擁有的信息,僅僅只存在於相鄰的兩元素之間。通過這樣簡單的信息來尋找碼字的某一個字母,其效率顯然不高。
如果我們建立一個有向圖,其中頂點i(即文本的第i位)用52條弧分別連接』a』..』z』,』A』..』Z』這52個字母在i位以前最後出現的位置(如圖1-2的連接方式),我們要尋找碼字中某個字母的前一個字母,就可以直接利用已連接的邊,而不需用枚舉的方法。我們也可以把問題看為:從有向圖的一個頂點出發,尋找一條長度為length(t)-1的路徑,並且路徑中經過的頂點,按照碼字t中的字母有序。

C D A C B D C A D C D B A D C C B A D

圖1-2
通過計算,用圖進行記錄在空間上完全可以承受(記錄1000個點×52條弧×4位元組的長整型=200k左右)。在時間上,由於可以充分利用第i位和第i+1位弧的連接方式變化不大這一點(如圖1-2所示,第i位和第i+1位只有一條弧的指向發生了變化,即第i+1位將其中一條弧指向了第i位),所以要對圖中的弧進行記錄,只需對弧的指向進行整體賦值,並改變其中的某一條弧即可。
因此,我們通過採用圖的邏輯結構,使得尋找字母的效率大大提高,其判斷的復雜度為O(length(t)),最壞為O(100),比原來方法的判斷效率提高了10倍。
(附程序codes.pas)

對於這個例子,雖然用線性的數據結構也可以解決,但由於判斷的特殊性,每次需要的信息並不能從相鄰的元素中找到,而線性結構中只有相鄰元素之間存在關系的這一點,就成為了一個很明顯的缺點。因此,問題一線性結構中的信息,就屬於「不可直接使用」的信息。相對而言,圖的結構就正好滿足了我們的需要,將所有可能產生關系的點都用弧連接起來,使我們可以利用弧的關系,高效地進行判斷尋找的過程。雖然圖的結構更加復雜,但卻將「不可直接使用」的信息,轉化成為了「可直接使用」的信息,演算法效率的提高,自然在情理之中。。
二、 不記錄「無用」信息。
從問題一中我們看到,由於圖結構的信息量大,所以其中的信息基本上都是「可用」的。但是,這並不表示我們就一定要使用圖的結構。在某些情況下,圖結構中的「可用」信息,是有些多餘的。
信息都「可用」自然是好事,但倘若其中「無用」(不需要)的信息太多,就只會增加我們思考分析和處理問題時的復雜程度,反而不利於我們解決問題了。
〖問題二〗 湖南省1997年組隊賽的《乘船問題》
〖問題描述〗
有N個人需要乘船,而每船最多隻能載兩人,且必須同名或同姓。求最少需要多少條船。
〖問題分析〗
看到這道題,很多人都會想到圖的數據結構:將N個人看作無向圖的N個點,凡同名或同姓的人之間都連上邊。
要滿足用船最少的條件,就是需要盡量多的兩人共乘一條船,表現在圖中就是要用最少的邊完成對所有頂點的覆蓋。這就正好對應了圖論的典型問題:求最小邊的覆蓋。所用的演算法為「求任意圖最大匹配」的演算法。
使用「求任意圖最大匹配」的演算法比較復雜(要用到擴展交錯樹,對花的收縮等等),效率也不是很高。因此,我們必須尋找一個更簡單高效的方法。
首先,由於圖中任兩個連通分量都是相對獨立的,也就是說任一條匹配邊的兩頂點,都只屬於同一個連通分量。因此,我們可以對每個連通分量分別進行處理,而不會影響最終的結果。
同時,我們還可以對需要船隻s的下限進行估計:
對於一個包含Pi個頂點的連通分量,其最小覆蓋邊數顯然為[Pi/2]。若圖中共有L個連通分量,則s=∑[Pi/2](1<=i<=L)。
然後,我們通過多次嘗試,可得出一個猜想:
實際需要的覆蓋邊數完全等於我們求出的下限∑[Pi/2](1<=i<=L)。
要用圖的結構對上述猜想進行證明,可參照以下兩步進行:
1. 連通分量中若不存在度為1的點,就必然存在迴路。
2. 從圖中刪去度為1的點及其相鄰的點,或刪去迴路中的任何一邊,連通分量依然連通,即連通分量必然存在非橋邊。
由於圖的方法不是這里的重點,所以具體證明不做詳述。而由採用圖的數據結構得出的演算法為:每次輸出一條非橋的邊,並從圖中將邊的兩頂點刪去。此演算法的時間復雜度為O(n3)。(尋找一條非橋邊的復雜度為O(n2),尋找覆蓋邊操作的復雜度為O(n))
由於受到圖結構的限制,時間復雜度已經無法降低,所以如果我們要繼續對演算法進行優化,只有考慮使用另一種邏輯結構。這里,我想到了使用二叉樹的結構,具體說就是將圖中的連通分量都轉化為二叉樹,用二叉樹來解決問題。
首先,我們以連通分量中任一個頂點作為樹根,然後我們來確定建樹的方法。
1. 找出與根結點i同姓的點j(j不在二叉樹中)作為i的左兒子,再以j為樹根建立子樹。
2. 找出與根結點i同名的點k(k不在二叉樹中)作為i的右兒子,再以k為樹根建立子樹。
如圖2-1-1中的連通分量,我們通過上面的建樹方法,可以使其成為圖2-1-2中的二叉樹的結構(以結點1為根)。(兩點間用實線表示同姓,虛線表示同名)

圖2-1-2

圖2-1-1
接著,我就來證明這棵樹一定包含了連通分量中的所有頂點。
【引理2.1】
若二叉樹T中包含了某個結點p,那麼連通分量中所有與p同姓的點一定都在T中。
證明:
為了論證的方便,我們約定:s表示與p同姓的頂點集合;lc[p,0]表示結點p,lc[p,i](i>0)表示lc[p,i-1]的左兒子,顯然lc[p,i]與p是同姓的。
假設存在某個點q,滿足qs且qT。由於s是有限集合,因而必然存在某個lc[p,k]無左兒子。則我們可以令lc[p,k+1]=q,所以qT,與假設qT相矛盾。
所以假設不成立,原命題得證。

由引理2.1的證明方法,我們同理可證引理2.2。
【引理2.2】
若二叉樹T中包含了某個結點p,那麼連通分量中所有與p同名的點一定都在T中。

有了上面的兩個引理,我們就不難得出下面的定理了。
【定理一】
以連通分量中的任一點p作為根結點的二叉樹,必然能夠包含連通分量中的所有頂點。
證明:
由引理2.1和引理2.2,所有與p同姓或同名的點都一定在二叉樹中,即連通分量中所有與p有邊相連的點都在二叉樹中。由連通分量中任兩點間都存在路徑的特性,該連通分量中的所有點都在二叉樹中。

在證明二叉樹中包含了連通分量的所有頂點後,我們接著就需要證明我們的猜想,也就是下面的定理:
【定理二】包含m個結點的二叉樹Tm,只需要船的數量為boat[m]=[m/2](mN)。
證明:
(i) 當m=1,m=2,m=3時命題顯然成立。

圖2-2-1

圖2-2-2

圖2-2-3
(ii) 假設當m<k(k>3)時命題成立,那麼當m=k時,我們首先從樹中找到一個層次最深的結點,並假設這個結點的父親為p。那麼,此時有且只有以下三種情況(結點中帶有陰影的是p結點):
(1) 如圖2-2-1,p只有一個兒子。此時刪去p和p唯一的兒子,Tk就成為了Tk-2,則boat[k]=boat[k-2]+1=[(k-2)/2]+1=[k/2]。
(2) 如圖2-2-2,p有兩個兒子,並且p是其父親的左兒子。此時可刪去p和p的右兒子,並可將p的左兒子放到p的位置上。同樣地,Tk成為了Tk-2,boat[k]=boat[k-2]+1=[k/2]。
(3) 如圖2-2-3,p有兩個兒子,並且p是其父親的右兒子。此時可刪去p和p的左兒子,並可將p的右兒子放到p的位置上。情況與(2)十分相似,易得此時得boat[k]=boat[k-2]+1=[k/2]。
綜合(1)、(2)、(3),當m=k時,boat[k]=[k/2]。
最後,綜合(i)、(ii),對於一切mN,boat[m]=[m/2]。

由上述證明,我們將問題中數據的圖結構轉化為樹結構後,可以得出求一棵二叉樹的乘船方案的演算法:
proc try(father:integer;var root:integer;var rest:byte);
{輸出root為樹根的子樹的乘船方案,father=0表示root是其父親的左兒子,
father=1表示root是其父親的右兒子,rest表示輸出子樹的乘船方案後,
是否還剩下一個根結點未乘船}
begin
visit[root]:=true; {標記root已訪問}
找到一個與root同姓且未訪問的結點j;
if j<>n+1 then try(0,j,lrest);
找到一個與root同姓且未訪問的結點k;
if k<>n+1 then try(1,k,rrest);
if (lrest=1) xor (rrest=1) then begin {判斷root是否只有一個兒子,情況一}
if lrest=1 then print(lrest,root) else print(rrest,root);
rest:=0;
end
else if (lrest=1) and (rrest=1) then begin {判斷root是否有兩個兒子}
if father=0 then begin
print(rrest,root);root:=j; {情況二}
end
else begin
print(lrest,root);root:=k; {情況三}
end;
rest:=1;
end
else rest:=1;
end;

這只是輸出一棵二叉樹的乘船方案的演算法,要輸出所有人的乘船方案,我們還需再加一層循環,用於尋找各棵二叉樹的根結點,但由於每個點都只會訪問一次,尋找其左右兒子各需進行一次循環,所以演算法的時間復雜度為O(n2)。(附程序boat.pas)

最後,我們對兩種結構得出不同時間復雜度演算法的原因進行分析。其中最關鍵的一點就是因為二叉樹雖然結構相對較簡單,但已經包含了幾乎全部都「有用」的信息。由我們尋找乘船方案的演算法可知,二叉樹中的所有邊不僅都發揮了作用,而且沒有重復的使用,可見信息的利用率也是相當之高的。
既然採用樹結構已經足夠,圖結構中的一些信息就顯然就成為了「無用」的信息。這些多餘的「無用」信息,使我們在分析問題時難於發現規律,也很難找到高效的演算法進行解決。這正如迷宮中的牆一樣,越多越難走。「無用」的信息,只會干擾問題的規律性,使我們更難找出解決問題的方法。

小結
我們對數據的邏輯結構進行選擇,是構造數學模型一大關鍵,而演算法又是用來解決數學模型的。要使演算法效率高,首先必須選好數據的邏輯結構。上面已經提出了選擇邏輯結構的兩個條件(思考方向),總之目的是提高信息的利用效果。利用「可直接使用」的信息,由於中間不需其它操作,利用的效率自然很高;不不記錄「無用」的信息,就會使我們更加專心地研究分析「有用」的信息,對信息的使用也必然會更加優化。
總之,在解決問題的過程中,選擇合理的邏輯結構是相當重要的環
三、 選擇合理的存儲結構
數據的存儲結構,分為順序存儲結構和鏈式存儲結構。順序存儲結構的特點是藉助元素在存儲器中的相對位置來表示數據元素之間的邏輯關系;鏈式存儲結構則是藉助指示元素存儲地址的指針表示數據元素之間的邏輯關系。
因為兩種存儲結構的不同,導致這兩種存儲結構在具體使用時也分別存在著優點和缺點。
這里有一個較簡單的例子:我們需要記錄一個n×n的矩陣,矩陣中包含的非0元素為m個。
此時,我們若採用順序存儲結構,就會使用一個n×n的二維數組,將所有數據元素全部記錄下來;若採用鏈式存儲結構,則需要使用一個包含m個結點的鏈表,記錄所有非0的m個數據元素。由這樣兩種不同的記錄方式,我們可以通過對數據的不同操作來分析它們的優點和缺點。
1. 隨機訪問矩陣中任意元素。由於順序結構在物理位置上是相鄰的,所以可以很容易地獲得任意元素的存儲地址,其復雜度為O(1);對於鏈式結構,由於不具備物理位置相鄰的特點,所以首先必須對整個鏈表進行一次遍歷,尋找需進行訪問的元素的存儲地址,其復雜度為O(m)。此時使用順序結構顯然效率更高。
2. 對所有數據進行遍歷。兩種存儲結構對於這種操作的復雜度是顯而易見的,順序結構的復雜度為O(n2),鏈式結構為O(m)。由於在一般情況下m要遠小於n2,所以此時鏈式結構的效率要高上許多。
除上述兩種操作外,對於其它的操作,這兩種結構都不存在很明顯的優點和缺點,如對鏈表進行刪除或插入操作,在順序結構中可表示為改變相應位置的數據元素。
既然兩種存儲結構對於不同的操作,其效率存在較大的差異,那麼我們在確定存儲結構時,必須仔細分析演算法中操作的需要,合理地選擇一種能夠「揚長避短」的存儲結構。

一、合理採用順序存儲結構。
我們在平常做題時,大多都是使用順序存儲結構對數據進行存儲。究其原因,一方面是出於順序結構操作方便的考慮,另一方面是在程序實現的過程中,使用順序結構相對於鏈式結構更便於對程序進行調試和查找錯誤。因此,大多數人習慣上認為,能夠使用順序結構進行存儲的問題,最「好」採用順序存儲結構。
其實,這個所謂的「好」只是一個相對的標准,是建立在以下兩個前提條件之下的:
1. 鏈式結構存儲的結點與順序結構存儲的結點數目相差不大。這種情況下,由於存儲的結點數目比較接近,使用鏈式結構完全不能體現出記錄結點少的優點,並且可能會由於指針操作較慢而降低演算法的效率。更有甚者,由於指針自身佔用的空間較大,且結點數目較多,因而演算法對空間的要求可能根本無法得到滿足。
2. 並非演算法效率的瓶頸所在。由於不是演算法最費時間的地方,這里是否進行改進,顯然是不會對整個演算法構成太大影響的,若使用鏈式結構反而會顯得操作過於繁瑣。

二、必要時採用鏈式存儲結構。
上面我對使用順序存儲結構的條件進行了分析,最後就只剩下何時應該採用鏈式存儲結構的問題了。
由於鏈式結構中指針操作確實較繁瑣,並且速度也較慢,調試也不方便,因而大家一般都不太願意用鏈式的存儲結構。但是,這只是一般的觀點,當鏈式結構確實對演算法有很大改進時,我們還是不得不進行考慮的。
〖問題三〗 IOI99的《地下城市》。
〖問題描述〗
已知一個城市的地圖,但未給出你的初始位置。你需要通過一系列的移動和探索,以確定初始時所在的位置。題目的限制是:
1. 不能移動到有牆的方格。
2. 只能探索當前所在位置四個方向上的相鄰方格。
在這兩個限制條件下,要求我們的探索次數(不包括移動)盡可能的少。
〖問題分析〗
由於存儲結構要由演算法的需要確定,因此我們首先來確定問題的演算法。
經過對問題的分析,我們得出解題的基本思想:先假設所有無牆的方格都可能是初始位置,再通過探索一步步地縮小初始位置的范圍,最終得到真正的初始位置。同時,為提高演算法效率,我們還用到了分治的思想,使我們每一次探索都盡量多的縮小初始位置的范圍(使程序盡量減少對運氣的依賴)。
接著,我們來確定此題的存儲結構。
由於這道題的地圖是一個二維的矩陣,所以一般來講,採用順序存儲結構理所當然。但是,順序存儲結構在這道題中暴露了很大的缺點。我們所進行的最多的操作,一是對初始位置的范圍進行篩選,二是判斷要選擇哪個位置進行探索。而這兩種操作,所需要用到的數據,只是龐大地圖中很少的一部分。如果採用順序存儲結構(如圖3-1中陰影部分表示已標記),無論你需要用到多少數據,始終都要完全的遍歷整個地圖。

4
3
2
1
1 2 3 4
圖3-1

head

圖3-2
然而,如果我們採用的是鏈式存儲結構(如圖3-2的鏈表),那麼我們需要多少數據,就只會遍歷多少數據,這樣不僅充分發揮了鏈式存儲結構的優點,而且由於不需單獨對某一個數據進行提取,每次都是對所有數據進行判斷,從而避免了鏈式結構的最大缺點。
我們使用鏈式存儲結構,雖然沒有降低問題的時間復雜度(鏈式存儲結構在最壞情況下的存儲量與順序存儲結構的存儲量幾乎相同),但由於體現了前文所述選擇存儲結構時揚長避短的原則,因而演算法的效率也大為提高。(程序對不同數據的運行時間見表3-3)
測試數據編號 使用順序存儲結構的程序 使用鏈式存儲結構的程序
1 0.06s 0.02s
2 1.73s 0.07s
3 1.14s 0.06s
4 3.86s 0.14s
5 32.84s 0.21s
6 141.16s 0.23s
7 0.91s 0.12s
8 6.92s 0.29s
9 6.10s 0.23s
10 17.41s 0.20s

表3-3
(附使用鏈式存儲結構的程序under.pas)
我們選擇鏈式的存儲結構,雖然操作上可能稍復雜一些,但由於改進了演算法的瓶頸,演算法的效率自然也今非昔比。由此可見,必要時選擇鏈式結構這一方法,其效果是不容忽視的。
小結
合理選擇邏輯結構,由於牽涉建立數學模型的問題,可能大家都會比較注意。但是對存儲結構的選擇,由於不會對演算法復雜度構成影響,所以比較容易忽視。那麼,這種不能降低演算法復雜度的方法是否需要重視呢?
大家都知道,剪枝作為一種常用的優化演算法的方法,被廣泛地使用,但剪枝同樣是無法改變演算法的復雜度的。因此,作用與剪枝相似的存儲結構的合理選擇,也是同樣很值得重視的。
總之,我們在設計演算法的過程中,必須充分考慮存儲結構所帶來的不同影響,選擇最合理的存儲結構。

四、 多種數據結構相結合

上文所探討的,都是如何對數據結構進行選擇,其中包含了邏輯結構的選擇和存儲結構的選擇,是一種具有較大普遍性的演算法優化方法。對於多數的問題,我們都可以通過選擇一種合理的邏輯結構和存儲結構以達到優化演算法的目的。
但是,有些問題卻往往不如人願,要對這類問題的數據結構進行選擇,常常會顧此失彼,有時甚至根本就不存在某一種合適的數據結構。此時,我們是無法選擇出某一種合適的數據結構的,以上的方法就有些不太適用了。
為解決數據結構難以選擇的問題,我們可以採用將多種數據結構進行結合的方法。通過多種數據結構相結合,達到取長補短的作用,使不同的數據結構在演算法中發揮出各自的優勢。
這只是我們將多種數據結構進行結合的總思想,具體如何進行結合,我們可以先看下面的例子。
我們可以採用映射的方法,將線性結構中的元素與堆中間的結點一一對應起來,若線性的數組中的元素發生變化,堆中相應的結點也接著變化,堆中的結點發生變化,數組中相應的元素也跟著變化。
將兩種結構進行結合後,無論是第一步還是第二步,我們都不需對所有元素進行遍歷,只需進行常數次復雜度為O(log2n)的堆化操作。這樣,整個時間復雜度就成為了O(nlog2n),演算法效率無疑得到了很大提高。

五、 總結
我們平常使用數據結構,往往只將其作為建立模型和演算法實現的工具,而沒有考慮這種工具對程序效率所產生的影響。信息學問題隨著難度的不斷增大,對演算法時空效率的要求也越來越高,而演算法的時空效率,在很大程度上都受到了數據結構的制約。

『捌』 模型壓縮:剪枝演算法

過參數化主要是指在訓練階段,在數學上需要進行大量的微分求解,去捕抓數據中的微小變化信息,一旦完成迭代式的訓練之後,網路模型推理的時候就不需要這么多參數。而剪枝演算法正是基於過參數化的理論基礎而提出的。

剪枝演算法核心思想就是減少網路模型中參數量和計算量,同時盡量保證模型的性能不受影響。

那在AI框架中,實際上剪枝主要作用在右下角的端側模型推理應用場景中,為的就是讓端側模型更小,無論是平板、手機、手錶、耳機等小型IOT設備都可以輕松使用AI模型。而實際在訓練過程更多體現在剪枝演算法和框架提供的剪枝API上面。

實際上大部分剛接觸剪枝演算法的時候,都會從從宏觀層面去劃分剪枝技術,主要是分為Drop Out和Drop Connect兩種經典的剪枝演算法,如下圖所示。

1)Drop Out:隨機的將一些神經元的輸出置零,稱之為神經元剪枝。

2)Drop Connect:隨機將部分神經元間的連接Connect置零,使得權重連接矩陣變得稀疏。

下面會把剪枝的更多種方式呈現出來,可能會稍微復雜哈。從剪枝的粒度來劃分,可以分為結構化剪枝和非結構化剪枝,2個剪枝結構方法。下面來看看具體的剪枝方法有4種:

細粒度剪枝、向量剪枝、核剪枝在參數量與模型性能之間取得了一定的平衡,但是網路模型單層的神經元之間的組合結構發生了變化,需要專門的演算法或者硬體結構來支持稀疏的運算,這種叫做 結構化剪枝(Unstructured Pruning)

其中,非結構化剪枝能夠實現更高的壓縮率,同時保持較高的模型性能,然而會帶來網路模型稀疏化,其稀疏結構對於硬體加速計算並不友好,除非底層硬體和計算加速庫對稀疏計算有比較好的支持,否則剪枝後很難獲得實質的性能提升。

濾波器剪枝(Filter-level)主要改變網路中的濾波器組和特徵通道數目,所獲得的模型不需要專門的演算法和硬體就能夠運行,被稱為 結構化剪枝(Structured Pruning) 。結構化剪枝又可進一步細分:可以是channel-wise,也可以是filter-wise,還可以是在shape-wise。

結構化剪枝與非結構化剪枝恰恰相反,可以方便改變網路模型的結構特徵,從而達到壓縮模型的效果,例如知識蒸餾中的student網路模型、NAS搜索或者如VGG19和VGG16這種裁剪模型,也可以看做變相的結構化剪枝行為。

雖然剪枝演算法的分類看上去很多,但是核心思想還是對神經網路模型進行剪枝,目前剪枝演算法的總體流程大同小異,可以歸結為三種:標准剪枝、基於子模型采樣的剪枝、以及基於搜索的剪枝,如下圖所示。

標准剪枝是目前最流行的剪枝流程,在Tensorflow、Pytroch都有標準的介面。主要包含三個部分:訓練、剪枝、以及微調。

1) 訓練 :首先是對網路模型進行訓練。在剪枝流程中,訓練部分主要指預訓練,訓練的目的是為剪枝演算法獲得在特定基礎SOTA任務上訓練好的原始模型。

3) 微調 :微調是恢復被剪枝操作影響的模型表達能力的必要步驟。結構化模型剪枝會對原始模型結構進行調整,因此剪枝後的模型參數雖然保留了原始的模型參數,但是由於模型結構的改變,剪枝後模型的表達能力會受到一定程度的影響。實現上,微調網路模型,參數在計算的時候先乘以該Mask,Mask為1的參數值將繼續訓練通過BP調整梯度,而Mask為0的部分因為輸出始終為0則不對後續部分產生影響。

4) 再剪枝 :再剪枝過程將微調之後的網路模型再送到剪枝模塊中,再次進行模型結構評估和執行剪枝演算法。目的是使得每次剪枝都在性能更優的模型上面進行,不斷迭代式地進行優化剪枝模型,直到模型能夠滿足剪枝目標需求。

最後輸出模型參數儲存的時候,因為有大量的稀疏,所以可以重新定義儲存的數據結構, 僅儲存非零值以及其矩陣位置。重新讀取模型參數的時候,就可以還原矩陣。

除標准剪枝之外,基於子模型采樣的剪枝《EagleEye: Fast sub-net evaluation for efficient neural network pruning》最近也表現出比較好的剪枝效果。得到訓練好的模型之後,進行子模型采樣過程。一次子模型采樣過程為:

1)對訓練好的原模型中可修剪的網路結構,按照剪枝目標進行采樣,采樣過程可以是隨機的,也可以按照網路結構的重要性或者通過KL散度計算進行概率采樣。

2)對采樣後的網路結構進行剪枝,得到采樣子模型。子模型采樣過程通常進行 次,得到 個子模型( ≥1), 之後對每一個子模型進行性能評估。子模型評估結束之後,選取最優的子模型進行微調以得倒最後的剪枝模型。

基於搜索的剪枝主要依靠強化學習等一系列無監督學習或者半監督學習演算法,也可以是神經網路結構搜索相關理論。

給定剪枝目標之後,基於搜索的剪枝在網路結構中搜索較優的子結構,這個搜索過程往往伴隨著網路參數的學習過程,因此一些基於搜索的剪枝演算法在剪枝結束後不需要再進行微調。

這幾年神經網路剪枝pruning作為模型壓縮技術的四小龍之一,正在受到越來越多的關注。當然,各種更好的pruning參數選取方法一定還會層出不窮。另外,從趨勢來看,以下幾個方向值得關註:

打破固定假設 :挑戰已有的固有的假設,例如ICLR2019會議的best paper彩票假說《The Lottery Ticket Hypothesis: Finding Sparse, Trainable Neural Networks 》的出現。還有一開始提到的對於over-parameterization,與重用已有參數是否有有益的反思非常有意思。這樣的工作會給剪枝演算法非常大的啟發,從而根本改變解決問題的思路。

自動化剪枝 :隨著AutoML的大潮,越來越多的演算法開始走向自動化。模型壓縮能拉下嗎?當然不能。經過前面的介紹我們知道,像ADC,RNP,N2N Learning這些工作都是試圖將剪枝中部分工作自動化。如量化中的《HAQ: Hardware-Aware Automated Quantization》考慮網路中不同層信息的冗餘程度不一樣,所以自動化使用混合量化比特進行壓縮。

與NAS融合 :如前面模型剪枝流程中提到,剪枝演算法與神經網路搜索NAS的界限已經模糊了。NAS有針對結構化剪枝進行搜索方法,如One-Shot Architecture Search是先有一個大網路,然後做減法。NAS與模型壓縮兩個一開始看似關系不是那麼大的分支,在近幾年的發展過程中因為下游任務和部署場景的需求,最後似乎會走到一塊去。這兩個分支今天有了更多的交集,也必將擦出更多的火花。

與GAN融合 :這幾年機器學習最火熱的分支之一GAN,正在不斷滲透到已有領域,在pruning中也開始有它的身影。如2019年《Towards Optimal Structured CNN Pruning via Generative Adversarial Learning》讓generator生成裁剪後網路,discrimintor來判別是否屬於原網路還是裁剪後網路,從而進行更有效的網路結構化裁剪。

硬體稀疏性支持 :剪枝會給神經網路模型帶來稀疏性特徵,參數稀疏性在計算中會有大量的索引,所以並不能加速。現在雖然有像cuSPARSE這樣的計算庫,但底層硬體AI晶元本身設計並不是專門為稀疏數據處理打造的。如果能將稀疏計算和處理能力做進晶元那必將極大提高計算效率。僅2021年中國就推出了10+款基於ASIC的AI加速晶元,相信針對稀疏性場景的支持在未來會有所突破。

模型壓縮演算法中針對已有的模型,有:張量分解,模型剪枝,模型量化。針對新構建的網路,有:知識蒸餾,緊湊網路設計等方法。

剪枝只是模型壓縮方法中的一種,它與其它模型壓縮方法並不沖突,因此會與量化、蒸餾、NAS、強化學習等方法慢慢融合,這些都是很值得研究的方向。另外在上面的發展來看,打破固有的假設定義,與NAS、GAN、AutoML、RL等技術進行相互的融合,可能到最後會模糊purning方式,出現新的範式或者壓縮模式也是很吸引的。

『玖』 如何對決策樹進行剪枝

決策樹洞橡衡的剪枝通常有兩種方法,預剪枝(Pre-Pruning)和後剪枝(Post- Pruning)。那麼這兩種方法是如何進行的呢如渣?它們又各有什麼優缺點?
■ 預剪枝
預剪枝的核心思想是在樹中結點進行擴展之前,先計算當前的劃分是否能帶 來模型泛化能力的提升,如果不能,則不再繼續生長子樹。此時可能存在不同類 別的樣本同時存於結點中,按照多數投票的原則判斷該結點所屬類別。預剪枝對 於何時納做停止決策樹的生長有以下幾種方法。
(1)當樹到達一定深度的時候,停止樹的生長。
(2)當到達當前結點的樣本數量小於某個閾值的時候,停止樹的生長。
(3)計算每次分裂對測試集的准確度提升,當小於某個閾值的時候,不再繼 續擴展。
預剪枝具有思想直接、演算法簡單、效率高等特點,適合解決大規模問題。但 如何准確地估計何時停止樹的生長(即上述方法中的深度或閾值),針對不同問 題會有很大差別,需要一定經驗判斷。且預剪枝存在一定局限性,有欠擬合的風 險,雖然當前的劃分會導致測試集准確率降低,但在之後的劃分中,准確率可能 會有顯著上升。
■ 後剪枝
後剪枝的核心思想是讓演算法生成一棵完全生長的決策樹,然後從最底層向上
計算是否剪枝。剪枝過程將子樹刪除,用一個葉子結點替代,該結點的類別同樣 按照多數投票的原則進行判斷。同樣地,後剪枝也可以通過在測試集上的准確率 進行判斷,如果剪枝過後准確率有所提升,則進行剪枝。相比於預剪枝,後剪枝 方法通常可以得到泛化能力更強的決策樹,但時間開銷會更大。
常見的後剪枝方法包括錯誤率降低剪枝(Reced Error Pruning,REP)、悲 觀剪枝(Pessimistic Error Pruning,PEP)、代價復雜度剪枝(Cost Complexity Pruning,CCP)、最小誤差剪枝(Minimum Error Pruning,MEP)、CVP(Critical Value Pruning)、OPP(Optimal Pruning)等方法,這些剪枝方法各有利弊,關注 不同的優化角度,本文選取著名的CART剪枝方法CCP進行介紹。
代價復雜剪枝主要包含以下兩個步驟。

閱讀全文

與剪枝演算法效率相關的資料

熱點內容
什麼是編譯器指令 瀏覽:219
微控制器邏輯命令使用什麼匯流排 瀏覽:885
程序員在學校里是學什麼的 瀏覽:601
oraclejava數據類型 瀏覽:890
程序員考注冊會計師 瀏覽:957
怎麼使用access的命令按鈕 瀏覽:899
有點錢app在哪裡下載 瀏覽:832
博途v15解壓後無法安裝 瀏覽:205
什麼是根伺服器主機 瀏覽:438
安卓手游怎麼申請退款 瀏覽:555
安卓系統如何分享網頁 瀏覽:278
ad如何編譯pcb工程 瀏覽:414
除了滴滴app哪裡還能用滴滴 瀏覽:399
截圖怎麼保存文件夾然後壓縮 瀏覽:8
幻影伺服器怎麼樣 瀏覽:27
具體哪些廣東公司招程序員 瀏覽:870
嵌入式編譯器教程 瀏覽:306
ssl數據加密傳輸 瀏覽:86
51單片機定時器方式2 瀏覽:332
命令行查看開機時間 瀏覽:814