貪婪演算法剪枝
『壹』 貪心演算法的介紹
貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的局部最優解。貪心演算法不是對所有問題都能得到整體最優解,關鍵是貪心策略的選擇,選擇的貪心策略必須具備無後效性,即某個狀態以前的過程不會影響以後的狀態,只與當前狀態有關。
『貳』 貪婪演算法指的是什麼
貪心演算法是指在對問題進行求解時,在每-步選擇中都採取最好或者最優(即最有利)的選擇,從而希望能夠導致結果是最好或者最優的。
貪婪演算法所得到的結果不一定是最優的結果(有時候會是最優解),但是都是相對近似(接近)最優解的結果。
例題、區間問題
問題描述:有n項工作,每項工作分別在si開始,ti結束。對每項工作,你都可以選擇參加或不參加,但選擇了參加某項工作就必須至始至終參加全程參與。
即參與工作的時間段不能有重疊(即使開始的時間和結束的時間重疊都不行)。限制條件:1<=n<=1000001<=si<=ti,=109樣例:輸入51 2 4 6 83 5 7 9 10輸出3(選擇工作1, 3, 5)。
『叄』 單機版的五子棋程序的演算法是什麼哦!
五子棋是一種受大眾廣泛喜愛的游戲,其規則簡單,變化多端,非常富有趣味性和消遣性。這里設計和實現了一個人機對下的五子棋程序,採用了博弈樹的方法,應用了剪枝和最大最小樹原理進行搜索發現最好的下子位置。介紹五子棋程序的數據結構、評分規則、勝負判斷方法和搜索演算法過程。
一、相關的數據結構
關於盤面情況的表示,以鏈表形式表示當前盤面的情況,目的是可以允許用戶進行悔棋、回退等操作。
CList StepList;
其中Step結構的表示為:
struct Step
{
int m; //m,n表示兩個坐標值
int n;
char side; //side表示下子方
};
以數組形式保存當前盤面的情況,
目的是為了在顯示當前盤面情況時使用:
char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];
其中FIVE_MAX_LINE表示盤面最大的行數。
同時由於需要在遞歸搜索的過程中考慮時間和空間有效性,只找出就當前情況來說相對比較好的幾個盤面,而不是對所有的可下子的位置都進行搜索,這里用變數CountList來表示當前搜索中可以選擇的所有新的盤面情況對象的集合:
CList CountList;
其中類CBoardSituiton為:
class CBoardSituation
{
CList StepList; //每一步的列表
char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];
struct Step machineStep; //機器所下的那一步
double value; //該種盤面狀態所得到的分數
}
二、評分規則
對於下子的重要性評分,需要從六個位置來考慮當前棋局的情況,分別為:-,¦,/,\,//,\\
實際上需要考慮在這六個位置上某一方所形成的子的布局的情況,對於在還沒有子的地方落子以後的當前局面的評分,主要是為了說明在這個地方下子的重要性程度,設定了一個簡單的規則來表示當前棋面對機器方的分數。
基本的規則如下:
判斷是否能成5, 如果是機器方的話給予100000分,如果是人方的話給予-100000 分;
判斷是否能成活4或者是雙死4或者是死4活3,如果是機器方的話給予10000分,如果是人方的話給予-10000分;
判斷是否已成雙活3,如果是機器方的話給予5000分,如果是人方的話給予-5000 分;
判斷是否成死3活3,如果是機器方的話給予1000分,如果是人方的話給予-1000 分;
判斷是否能成死4,如果是機器方的話給予500分,如果是人方的話給予-500分;
判斷是否能成單活3,如果是機器方的話給予200分,如果是人方的話給予-200分;
判斷是否已成雙活2,如果是機器方的話給予100分,如果是人方的話給予-100分;
判斷是否能成死3,如果是機器方的話給予50分,如果是人方的話給予-50分;
判斷是否能成雙活2,如果是機器方的話給予10分,如果是人方的話給予-10分;
判斷是否能成活2,如果是機器方的話給予5分,如果是人方的話給予-5分;
判斷是否能成死2,如果是機器方的話給予3分,如果是人方的話給予-3分。
實際上對當前的局面按照上面的規則的順序進行比較,如果滿足某一條規則的話,就給該局面打分並保存,然後退出規則的匹配。注意這里的規則是根據一般的下棋規律的一個總結,在實際運行的時候,用戶可以添加規則和對評分機制加以修正。
三、勝負判斷
實際上,是根據當前最後一個落子的情況來判斷勝負的。實際上需要從四個位置判斷,以該子為出發點的水平,豎直和兩條分別為 45度角和135度角的線,目的是看在這四個方向是否最後落子的一方構成連續五個的棋子,如果是的話,就表示該盤棋局已經分出勝負。具體見下面的圖示:
四、搜索演算法實現描述
注意下面的核心的演算法中的變數currentBoardSituation,表示當前機器最新的盤面情況, CountList表示第一層子節點可以選擇的較好的盤面的集合。核心的演算法如下:
void MainDealFunction()
{
value=-MAXINT; //對初始根節點的value賦值
CalSeveralGoodPlace(currentBoardSituation,CountList);
//該函數是根據當前的盤面情況來比較得到比較好的可以考慮的幾個盤面的情況,可以根據實際的得分情況選取分數比較高的幾個盤面,也就是說在第一層節點選擇的時候採用貪婪演算法,直接找出相對分數比較高的幾個形成第一層節點,目的是為了提高搜索速度和防止堆棧溢出。
pos=CountList.GetHeadPosition();
CBoardSituation* pBoard;
for(i=0;ivalue=Search(pBoard,min,value,0);
Value=Select(value,pBoard->value,max);
//取value和pBoard->value中大的賦給根節點
}
for(i=0;ivalue)
//找出那一個得到最高分的盤面
{
currentBoardSituation=pBoard;
PlayerMode=min; //當前下子方改為人
Break;
}
}
其中對於Search函數的表示如下:實際上核心的演算法是一個剪枝過程,其中在這個搜索過程中相關的四個參數為:(1)當前棋局情況;(2)當前的下子方,可以是機器(max)或者是人(min);(3)父節點的值oldValue;(4)當前的搜索深度depth。
double Search(CBoardSituation&
board,int mode,double oldvalue,int depth)
{
CList m_DeepList;
if(deptholdvalue))== TRUE)
{
if(mode==max)
value=select(value,search(successor
Board,min,value,depth+1),max);
else
&nb
sp; value=select(value,search(successor
Board,max,value,depth+1),min);
}
return value;
}
else
{
if ( goal(board)<>0)
//這里goal(board)<>0表示已經可以分出勝負
return goal(board);
else
return evlation(board);
}
}
注意這里的goal(board)函數是用來判斷當前盤面是否可以分出勝負,而evlation(board)是對當前的盤面從機器的角度進行打分。
下面是Select函數的介紹,這個函數的主要目的是根據 PlayerMode情況,即是機器還是用戶來返回節點的應有的值。
double Select(double a,double b,int mode)
{
if(a>b && mode==max)¦¦ (a< b && mode==min)
return a;
else
return b;
}
五、小結
在Windows操作系統下,用VC++實現了這個人機對戰的五子棋程序。和國內許多隻是採用規則或者只是採用簡單遞歸而沒有剪枝的那些程序相比,在智力上和時間有效性上都要好於這些程序。同時所討論的方法和設計過程為用戶設計其他的游戲(如象棋和圍棋等)提供了一個參考。
『肆』 5.10 決策樹與ID3演算法
https://blog.csdn.net/dorisi_h_n_q/article/details/82787295
決策樹(decision tree)是一個樹結構(可以是二叉樹或非二叉樹)。決策過程是從根節點開始,測試待分類項中相應的特徵屬性,並按照其值選擇輸出分支,直到到達葉子節點,將葉子節點存放的類別作為決策結果。
決策樹的關鍵步驟是分裂屬性。就是在某節點處按某一特徵屬性的不同劃分構造不同的分支,目標是讓各個分裂子集盡可能地「純」。即讓一個分裂子集中待分類項屬於同一類別。
簡而言之,決策樹的劃分原則就是:將無序的數據變得更加有序
分裂屬性分為三種不同的情況 :
構造決策樹的關鍵性內容是進行屬性選擇度量,屬性選擇度量(找一種計算方式來衡量怎麼劃分更劃算)是一種選擇分裂准則,它決定了拓撲結構及分裂點split_point的選擇。
屬性選擇度量演算法有很多,一般使用自頂向下遞歸分治法,並採用不回溯的貪心策略。這里介紹常用的ID3演算法。
貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,所做出的是在某種意義上的局部最優解。
此概念最早起源於物理學,是用來度量一個熱力學系統的無序程度。
而在信息學裡面,熵是對不確定性的度量。
在1948年,香農引入了信息熵,將其定義為離散隨機事件出現的概率,一個系統越是有序,信息熵就越低,反之一個系統越是混亂,它的信息熵就越高。所以信息熵可以被認為是系統有序化程度的一個度量。
熵定義為信息的期望值,在明晰這個概念之前,我們必須知道信息的定義。如果待分類的事務可能劃分在多個分類之中,則符號x的信息定義為:
在劃分數據集之前之後信息發生的變化稱為信息增益。
知道如何計算信息增益,就可計算每個特徵值劃分數據集獲得的信息增益,獲得信息增益最高的特徵就是最好的選擇。
條件熵 表示在已知隨機變數的條件下隨機變數的不確定性,隨機變數X給定的條件下隨機變數Y的條
件熵(conditional entropy) ,定義X給定條件下Y的條件概率分布的熵對X的數學期望:
根據上面公式,我們假設將訓練集D按屬性A進行劃分,則A對D劃分的期望信息為
則信息增益為如下兩者的差值
ID3演算法就是在每次需要分裂時,計算每個屬性的增益率,然後選擇增益率最大的屬性進行分裂
步驟:1. 對當前樣本集合,計算所有屬性的信息增益;
是最原始的決策樹分類演算法,基本流程是,從一棵空數出發,不斷的從決策表選取屬性加入數的生長過程中,直到決策樹可以滿足分類要求為止。CLS演算法存在的主要問題是在新增屬性選取時有很大的隨機性。ID3演算法是對CLS演算法的改進,主要是摒棄了屬性選擇的隨機性。
基於ID3演算法的改進,主要包括:使用信息增益比替換了信息增益下降度作為屬性選擇的標准;在決策樹構造的同時進行剪枝操作;避免了樹的過度擬合情況;可以對不完整屬性和連續型數據進行處理;使用k交叉驗證降低了計算復雜度;針對數據構成形式,提升了演算法的普適性。
信息增益值的大小相對於訓練數據集而言的,並沒有絕對意義,在分類問題困難時,也就是說在訓練數據集經驗熵大的時候,信息增益值會偏大,反之信息增益值會偏小,使用信息增益比可以對這個問題進行校正,這是特徵選擇
的另一個標准。
特徵對訓練數據集的信息增益比定義為其信息增益gR( D,A) 與訓練數據集的經驗熵g(D,A)之比 :
gR(D,A) = g(D,A) / H(D)
sklearn的決策樹模型就是一個CART樹。是一種二分遞歸分割技術,把當前樣本劃分為兩個子樣本,使得生成的每個非葉子節點都有兩個分支,因此,CART演算法生成的決策樹是結構簡潔的二叉樹。
分類回歸樹演算法(Classification and Regression Trees,簡稱CART演算法)是一種基於二分遞歸分割技術的演算法。該演算法是將當前的樣本集,分為兩個樣本子集,這樣做就使得每一個非葉子節點最多隻有兩個分支。因此,使用CART
演算法所建立的決策樹是一棵二叉樹,樹的結構簡單,與其它決策樹演算法相比,由該演算法生成的決策樹模型分類規則較少。
CART分類演算法的基本思想是:對訓練樣本集進行遞歸劃分自變數空間,並依次建立決策樹模型,然後採用驗證數據的方法進行樹枝修剪,從而得到一顆符合要求的決策樹分類模型。
CART分類演算法和C4.5演算法一樣既可以處理離散型數據,也可以處理連續型數據。CART分類演算法是根據基尼(gini)系
數來選擇測試屬性,gini系數的值越小,劃分效果越好。設樣本集合為T,則T的gini系數值可由下式計算:
CART演算法優點:除了具有一般決策樹的高准確性、高效性、模式簡單等特點外,還具有一些自身的特點。
如,CART演算法對目標變數和預測變數在概率分布上沒有要求,這樣就避免了因目標變數與預測變數概率分布的不同造成的結果;CART演算法能夠處理空缺值,這樣就避免了因空缺值造成的偏差;CART演算法能夠處理孤立的葉子結點,這樣可以避免因為數據集中與其它數據集具有不同的屬性的數據對進一步分支產生影響;CART演算法使用的是二元分支,能夠充分地運用數據集中的全部數據,進而發現全部樹的結構;比其它模型更容易理解,從模型中得到的規則能獲得非常直觀的解釋。
CART演算法缺點:CART演算法是一種大容量樣本集挖掘演算法,當樣本集比較小時不夠穩定;要求被選擇的屬性只能產生兩個子結點,當類別過多時,錯誤可能增加得比較快。
sklearn.tree.DecisionTreeClassifier
1.安裝graphviz.msi , 一路next即可
ID3演算法就是在每次需要分裂時,計算每個屬性的增益率,然後選擇增益率最大的屬性進行分裂
按照好友密度劃分的信息增益:
按照是否使用真實頭像H劃分的信息增益
**所以,按先按好友密度劃分的信息增益比按真實頭像劃分的大。應先按好友密度劃分。
『伍』 大學課程《演算法分析與設計》中動態規劃和貪心演算法的區別和聯系
對於,大學課程《演算法分析與設計》中動態規劃和貪心演算法的區別和聯系這個問題,首先要來聊聊他們的聯系:1、都是一種推導演算法;2、將它們分解為子問題求解,它們都需要有最優子結構。這兩個特徵師門的聯系。
拓展資料:
貪婪演算法是指在解決問題時,它總是在當前做出最佳選擇。也就是說,在不考慮全局優化的情況下,該演算法在某種意義上獲得了局部最優解。貪婪演算法不能得到所有問題的全局最優解。關鍵是貪婪策略的選擇。
動態規劃是運籌學的一個分支,是解決決策過程優化的過程。20世紀50年代初,美國數學家R·貝爾曼等人在研究多階段決策過程的最優化問題時,提出了著名的最優化原理,建立了動態規劃。動態規劃在工程技術、經濟、工業生產、軍事和自動控制等領域有著廣泛的應用,在背包問題、生產經營問題、資金管理問題、資源分配問題、最短路徑問題和復雜系統可靠性問題上都取得了顯著的成果。
『陸』 python裡面什麼是貪婪
Python裡面的貪婪演算法(又稱貪心演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,/不從整體最優上加以考慮,他所做出的是在某種意義上的局部最優解。
貪心演算法不是對所有問題都能得到整體最優解,關鍵是貪心策略的選擇,選擇的貪心策略必須具備無後效性,即某個狀態以前的過程不會影響以後的狀態,只與當前狀態有關。
基本思路
思想
貪心演算法的基本思路是從問題的某一個初始解出發一步一步地進行,根據某個優化測度,每一步都要確保能獲得局部最優解。每一步只考慮一個數據,他的選取應該滿足局部優化的條件。若下一個數據和部分最優解連在一起不再是可行解時,就不把該數據添加到部分解中,直到把所有數據枚舉完,或者不能再添加演算法停止 。貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的局部最優解。
貪心演算法不是對所有問題都能得到整體最優解,關鍵是貪心策略的選擇,選擇的貪心策略必須具備無後效性,即某個狀態以前的過程不會影響以後的狀態,只與當前狀態有關。
基本思路
思想
貪心演算法的基本思路是從問題的某一個初始解出發一步一步地進行,根據某個優化測度,每一步都要確保能獲得局部最優解。每一步只考慮一個數據,他的選取應該滿足局部優化的條件。若下一個數據和部分最優解連在一起不再是可行解時,就不把該數據添加到部分解中,直到把所有數據枚舉完,或者不能再添加演算法停止 。貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的局部最優解。
貪心演算法不是對所有問題都能得到整體最優解,關鍵是貪心策略的選擇,選擇的貪心策略必須具備無後效性,即某個狀態以前的過程不會影響以後的狀態,只與當前狀態有關。
基本思路
思想
貪心演算法的基本思路是從問題的某一個初始解出發一步一步地進行,根據某個優化測度,每一步都要確保能獲得局部最優解。每一步只考慮一個數據,他的選取應該滿足局部優化的條件。若下一個數據和部分最優解連在一起不再是可行解時,就不把該數據添加到部分解中,直到把所有數據枚舉完,或者不能再添加演算法停止 。
『柒』 XGBoost原理
更好的閱讀體驗請跳轉至 XGBoost原理
一.緒論
在實際應用的機器學習方法里,GradientTree Boosting (GBDT)是一個在很多應用里都很出彩的技術。XGBoost是一套提升樹可擴展的機器學習系統。2015年Kaggle發布的29個獲勝方法里有17個用了XGBoost。在這些方案里,有8個僅用了XGBoost,另外的大多數用它結合了神經網路。對比來看,第二流行的方法,深度神經網路,只被用了11次。這個系統的成功性也被KDDCup2015所見證了,前十的隊伍都用了XGBoost。此外,據勝出的隊伍說,很少有別的集成學習方法效果能超過調好參的XGBoost。
主要創新點:
設計和構建高度可擴展的端到端提升樹系統。
提出了一個理論上合理的加權分位數略圖(weighted quantile
sketch )來計算候選集。
引入了一種新穎的稀疏感知演算法用於並行樹學習。 令缺失值有默認方向。
提出了一個有效的用於核外樹形學習的緩存感知塊結構。 用緩存加速尋找排序後被打亂的索引的列數據的過程。
二.演算法原理
1.學習目標
首先來看下我們是如何預測的:
XGBoost是一個樹集成模型,他將K(樹的個數)個樹的結果進行求和,作為最終的預測值。即:
最終我們將關於樹模型的迭代轉化為關於樹的葉子節點的迭代,並求出最優的葉節點分數。
將葉節點的最優值帶入目標函數,最終目標函數的形式為:
上式可以作為得分函數用來測量樹結構q的質量,他類似與決策樹的不純度得分,只是他通過更廣泛的目標函數得到
節點劃分
而通常情況下,我們無法枚舉所有可能的樹結構然後選取最優的,所以我們選擇用一種貪婪演算法來代替:我們從單個葉節點開始,迭代分裂來給樹添加節點。節點切分後的損失函數:
上式用來評估切分後的損失函數,我們的目標是尋找一個特徵及對應的值,使得切分後的loss rection最大。γ除了控制樹的復雜度,另一個作用是作為閾值,只有當分裂後的增益大於γ時,才選擇分裂,起到了預剪枝的作用。
縮減與列采樣
除了在目標函數中引入正則項,為了防止過擬合,XGBoost還引入了縮減(shrinkage)和列抽樣(column subsampling),通過在每一步的boosting中引入縮減系數,降低每個樹和葉子對結果的影響;列采樣是借鑒隨機森林中的思想,根據反饋,列采樣有時甚至比行抽樣效果更好,同時,通過列采樣能加速計算。
尋找最佳分割點演算法
樹模型學習的一個關鍵問題是如何尋找最優分割點。第一種方法稱為基本精確貪心演算法(exact greedy algorithm):枚舉所有特徵的所有可能劃分,尋找最優分割點。該演算法要求為連續特徵枚舉所有可能的切分,這個對計算機要求很高,為了有效做到這一點,XGBoost首先對特徵進行排序,然後順序訪問數據,累計loss rection中的梯度統計量(式6)。
上述方法是一個非常精確的分割點演算法,但是當數據無法完全載入進內存或分布式的情況下,該演算法就不是特別有效了。為了支持這兩種場景,提出了一種近似演算法:根據特徵分布的百分位數,提出n個候選切分點,然後將樣本映射到對應的兩個相鄰的切分點組成的桶中,聚會統計值,通過聚會後的統計值及推薦分割點,計算最佳分割點。該演算法有兩種形式:全局近似和局部近似,其差別是全局近似是在生成一棵樹之前,對各個特徵計算其分位點並劃分樣本;局部近似是在每個節點進行分裂時採用近似演算法。近似演算法的流程:
帶權重的分位數略圖(weighted quantile sketch)演算法
在近似演算法中重要的一步是尋找候選分割點,通常情況下,特徵的百分位數使數據均勻的分布在數據上。現在我們定義一個數據集Dk = {(x1k, h1), (x2k, h2) ... }代表樣本的第k個特徵及其對應的二階梯度,現在我們定義一個函數rk:
參考: https://arxiv.org/pdf/1603.02754.pdf
https://www.hu.com/question/41354392/answer/98658997
『捌』 為什麼貪心演算法可用於解決最優化問題
最優化問題是程序設計中一類非常重要的問題。每一個最優化問題都包含一組約束條件和一個優化函數,滿足約束條件的問題求解方案稱為問題的可行解,使優化函數取得最優值的可行解稱為問題的最優解。貪婪演算法是解決最優化問題的一種基本方法。
它採用逐步構造最優解的思想,在問題求解的每一個階段,都作出一個在一定標准下看上去最優的決策;決策一旦作出,就不可再更改。制定決策的依據稱為貪婪准則。
『玖』 哪位大俠能提供具體的五子棋人機對戰程序設計思路具體一點,謝啦!
我們有一個學長是這樣子做的:
遍歷每一行,列,斜,看到敵方有3個的堵,沒三個的,連接自己最長的那條線
當然,你要復雜的設計思路網上可以自己找,什麼貪婪演算法,剪枝,演算法優化等的,你自己研究了
『拾』 迪傑斯特拉演算法的本質是貪心還是動態規劃
貪心是一種特殊的動態規劃,動態規劃的本質是獨立的子問題,而貪心則是每次可以找到最優的獨立子問題。
貪心和動歸不是互斥的,而是包含的,貪心更快,但約束更強,適應范圍更小。
動歸和bfs的關系也是一樣的。
展開一點講,在求解最優化問題時,有多個解。而求解的過程類似一個樹,我們稱之為求解樹。
一般的求解樹真的是一棵樹,所以我們只能用bfs來搜索,頂多剪枝。
有些特殊的求解樹,中間很多結點是重合的,結點個數比所有搜索分支的個數少很多個數量級。這類問題較特殊,我們可以保存中間的搜索過程。而記憶化搜索和動態規劃本質上就是一個東西,快就快在可以不用重復計算很多中間結果(所謂的最優子問題)。
還有一些特殊的求解樹,更特殊,它們不止有很多重復結點,而且每次選擇分支的時候,我們可以證明只要選擇一個分支,這個分支的解就一定比其他選擇更優。這類問題就是貪心了,
所以bfs,dp,貪心三個方法都是解決最優化問題的方法,根據問題的不同,約束越大的問題可以用越快的方法,越慢的方法可以解決的問題越普適。
動態規劃的狀態轉移函數,可以抽象成這樣一種函數:
f(x)=g(f(x1), f(x2), f(x3), ... f(xn))
其中f就是我們說的獨立問題,每個f都有一個唯一值,也就是沒有後效性。
貪心也是這個函數,但可以證明:
f(xi) >= f(x1|x2|...|xn)
那麼我們就不用再去計算除了f(xi)以外的任何子狀態了,所以就更快
而標準的bfs,雖然也有
f(x)=g(f(x1), f(x2), f(x3), ... f(xn))
但是因為對於任意的f(x),它的子問題f(xi)的輸入狀態xi都不同(換一種思路也可以說f(xi)在不同的路徑下值都不同,本質上是我們怎麼定義xi,到底是狹義的參數還是廣義的狀態),所以無法使用內存去換取時間,就只能去遍歷所有狀態了。