白話貝葉斯理論及在足球比賽結果預測中的應用和C#實現


   離去年“馬爾可夫鏈進行彩票預測”已經一年了,同時我也計划了一個彩票數據框架的搭建,分析和預測的框架,會在今年逐步發表,擬定了一個目錄,大家有什么樣的意見和和問題,可以看看,留言我會在后面的文章中逐步改善:彩票數據框架與分析預測總目錄。同時這篇文章也是“【彩票】彩票預測算法(一):離散型馬爾可夫鏈模型C#實現”的兄弟篇。所以這篇文章還有一個標題,應該是:【彩票】彩票預測算法(二):朴素貝葉斯分類器在足球勝平負預測中的應用及C#實現 

   以前了解比較多的是SVM,RF,特征選擇和聚類分析,實際也做過一些分類預測的任務。在近1年多的時間中,開始接觸足球賽事的預測,剛開始也想使用SVM,Rf來進行預測,一方面效果太差,二是其理論也的確不滿足我自己想法的要求。所以也一直在看很多機器學習,數據挖掘的文章。直到看到了貝葉斯的相關文章,在這2個多月的研究中,也積累了很多經驗,同時也在使用C#來完成自己的想法,在這個過程中,夾雜很多的知識要點,我自己也很亂,所以趁假期總結一下,由於寫太多的公式大家也不一定能耐心看,也不易於理解,所以我把這篇文章叫做“大話貝葉斯”,目的就是盡量通過自己的簡單語言和描述(當然如果確實需要學習貝葉斯來解決問題,有些基本概念,如條件概率,邊緣分布,分布函數等等還是需要自己搞清楚)讓大家更容易的懂得和理解貝葉斯相關理論及其應用。同時我通過實際的C#代碼來進行演示,如何來用程序和貝葉斯理論來解決生活中的一些預測問題。在接觸所謂的貝葉斯理論和公式之前,先簡單了解一下 貝葉斯。

  預告,下一篇文章將是本站第100篇正式文章,將與近期發布一個.NET平台機器學習資源匯總的隨筆,信息量很大,敬請關注,機不可失失不再來。。。。

1.貝葉斯及其相關的理論

1.1 貝葉斯 

       貝葉斯是一名1702年出生於倫敦的英國數學家,他首先將歸納推理法用於概率論基礎理論,並創立了貝葉斯統計理論,對於統計決策函數、統計推斷、統計的估算等做出了貢獻,對於現代概率論和數理統計都有很重要的作用。所以看到的 貝葉斯 其實都是為了紀念這位偉大的數學家的貢獻,貝葉斯公式也是他提出的,所以都是根據他的名字命名。

1.2 貝葉斯方法的來源

        貝葉斯方法來源於貝葉斯本人在生前寫過(死后朋友代為發表)的一篇關於“逆向概率”的文章,當時,人們已經可以根據實際的數據來計算“正向概率”。下面是一個“正向概率”的例子:
  “假設袋子里面有M個白色球,N個黑色球,如果伸手進去摸出一個球,那么摸出白色球的概率是多大?”。從這個問題,貝葉斯自然而然想到了“逆向概率”的問題:
   “假設我們事先並不知道袋子里面黑白球的個數,而是先閉着眼睛摸出一個(或好幾個)球,然后觀察這些取出來的球的顏色之后,那么根據取出的球的信息,對袋子里面的黑白球的比例作出什么樣的推測”。
       這個問題,就是所謂的逆概問題。從我個人的理解就是如何根據有限的已知信息來推斷未知情況的概率。
      貝葉斯的這篇論文雖然只是對這個問題的一個直接的求解嘗試,並沒有意識到這里面包含着的深刻的思想。由於復雜問題,貝葉斯推斷需要大量的計算,因此在計算機未出現之前,並沒有得到重視和廣泛應用;計算機誕生以后,人們發現許多統計量是無法事先進行客觀判斷的,而互聯網時代出現的大型數據集,再加上高速運算能力,為驗證這些統計量提供了方便,也為應用貝葉斯推斷創造了條件,它的威力正在日益顯現[]。現在貝葉斯方法已經在各個領域得到大量的應用,也成為機器學習的核心算法之一。因為這個世界越來越復雜,影響事物發展的因素也越來越多,不確定性和隨機性也不斷增加,這個時候貝葉斯就發揮了他的優勢。

1.3 貝葉斯公式與定理

     貝葉斯定理是概率論中的一個結論,它跟隨機變量的條件概率以及邊緣概率分布有關。貝葉斯定理能夠告知我們如何利用新證據修改已有的看法。作為一個普遍的原理,貝葉斯定理對於所有概率的解釋是有效的;通常,事件A在事件B(發生)的條件下的概率,與事件B在事件A的條件下的概率是不一樣的;然而,這兩者是有確定的關系,貝葉斯定理就是這種關系的陳述。

        設P(A|B)表示事件B已經發生的前提下,事件A發生的概率,叫做事件B發生下事件A的條件概率。下面就是貝葉斯公式:                

其中的符號定義為:

  • P(A)是事件A的先驗概率或邊緣概率,它不考慮任何B方面的因素。
  • P(A|B)是已知B發生后A的條件概率,也由於得自B的取值而被稱作A的后驗概率
  • P(B|A)是已知A發生后B的條件概率,也由於得自A的取值而被稱作B的后驗概率
  • P(B)是事件B的先驗概率或邊緣概率,也作標准化常量normalizing constant)。

  按這些術語,貝葉斯定理可表述為:后驗概率 = (相似度*先驗概率)/標准化常量簡單的講,貝葉斯定理是基於假設的先驗概率,給定假設條件下,觀察到不同數據的概率,提供一種計算后驗概率的方法。

  貝葉斯決策就是在不完全的信息下面,對部分未知的狀態用主觀概率來進行估計,然后用貝葉斯公式對發生概率進行修正,最后再利用期望值和修正概率做出最優決策。貝葉斯決策理論方法是統計模型決策中的一個基本方法,其基本思想是:

1、已知類條件概率密度參數表達式和先驗概率

2、利用貝葉斯公式轉換成后驗概率

3、根據后驗概率大小進行決策分類。

  貝葉斯的這種基本思想可以在大量的實際案例中得到使用,因為很多現實社會中,積累了很多歷史先驗數據,想進行一些決策推理,也可以說是預測,就可以按照上面的步驟進行,當然貝葉斯理論的發展中,出現了很多新的推理算法,更加復雜,和面向不同的領域。一般來說,使用貝葉斯推理就是,預測某個事件下一次出現的概率,或者屬於某些類別的概率,使用貝葉斯來進行分類的應用應該是最廣泛的,很多實際的推理問題也可以轉換為分類問題。下面將介紹一些貝葉斯理論的應用例子。

1.4.貝葉斯的類型和應用

  在人工智能領域,貝葉斯方法是一種非常有代表性的不確定性知識表示和推理方法。目前貝葉斯的應用非常廣泛,如文本分類,問題分類,反垃圾郵件等等,根據問題特征因素的獨立性可以分為:朴素貝葉斯和貝葉斯網絡。

  1.朴素貝葉斯的核心在於它假設向量的所有分量之間是獨立的。(這一點在很多復雜的實際情況中都不太容易達到,各個因素直接可能都有一定的關聯);

  2.貝葉斯網絡又叫概率因果網絡或者知識圖,是相對於朴素貝葉斯而言的。它是一種有方向的無環關系圖;貝葉斯網絡用圖形來表示變量之間的連接個概率關系;它是為了解決不確定性問題和不完整性問題而提出的,在如文字處理,圖像處理,決策支持等很多領域都得到廣泛的應用。

  相關的學術研究進展,主要集中在貝葉斯網絡的研究中:

      貝葉斯網絡推理是指在給定證據條件下查詢貝葉斯網絡中某些節點的后驗信息,其推理算法分為精確推理算法和近似推理算法兩大類,至於這些算法的細節可以參考本后的文獻 “貝葉斯網絡研究綜述”,這玩意太復雜,一時半會我也沒研究透徹,所以還是先搞懂下面幾個簡單的例子,對貝葉斯理論的應用有一個初步的認識比較好。 

2.朴素貝葉斯分類及例子

      貝葉斯分類的基礎是概率推理,就是在各種條件的存在不確定,僅知其出現概率的情況下,如何完成推理和決策任務。概率推理是與確定性推理相對應的。而朴素貝葉斯分類器是基於獨立假設的,即假設樣本每個特征與其他特征都不相關。舉個例子,如果一種水果其具有紅,圓,直徑大概4英寸等特征,該水果可以被判定為是蘋果。盡管這些特征相互依賴或者有些特征由其他特征決定,然而朴素貝葉斯分類器認為這些屬性在判定該水果是否為蘋果的概率分布上獨立的。朴素貝葉斯分類器依靠精確的自然概率模型,在有監督學習的樣本集中能獲取得非常好的分類效果。在許多實際應用中,朴素貝葉斯模型參數估計使用最大似然估計方法,換而言之朴素貝葉斯模型能工作並沒有用到貝葉斯概率或者任何貝葉斯模型。盡管是帶着這些朴素思想和過於簡單化的假設,但朴素貝葉斯分類器在很多復雜的現實情形中仍能夠取得相當好的效果。我們先看看一個簡單的例子,這里要特別感謝博客園網友:leoo2sk,因為這一節的內容和例子基本都來自他的這篇關於朴素貝葉斯分類器的簡單介紹的文章:文章鏈接,只不過我整理了一下,鑒於文章編輯不方便,我在word中編輯好了,截圖上來:

2.1 朴素貝葉斯分類的定義

 

注意:上述的推導有2個地方比較難懂,1個是把分母p(x)去掉了,應該好理解,分母都一樣,比較的時候,直接比較分子就可以了。另外一個是為什么這個公式是成立的:

P(x|yi) = P(a1|yi)*P(a2|yi)*...*P(aj|yi)  

這個公式的成立是因為各個屬性a1,a2,..,aj都是獨立的,才能成立。

根據上述原理,朴素貝葉斯分類主要分為三個階段:
1.准備階段,這個階段的任務是為朴素貝葉斯分類做必要的准備,主要工作是根據具體情況確定特征屬性,並對每個特征屬性進行適當划分,然后由人工對一部分待分類項進行分類,形成訓練樣本集合。這一階段的輸入是所有待分類數據,輸出是特征屬性和訓練樣本。這一階段是整個朴素貝葉斯分類中唯一需要人工完成的階段,其質量對整個過程將有重要影響,分類器的質量很大程度上由特征屬性、特征屬性划分及訓練樣本質量決定。
2.分類器訓練階段,這個階段的任務就是生成分類器,主要工作是計算每個類別在訓練樣本中的出現頻率及每個特征屬性划分對每個類別的條件概率估計,並將結果記錄。輸入是特征屬性和訓練樣本,輸出是分類器。這一階段是機械性階段,根據前面討論的公式可以由程序自動計算。
3.應用階段。這個階段的任務是使用分類器對待分類項進行分類,其輸入是分類器和待分類項,輸出是待分類項與類別的映射關系。這一階段也是機械性階段,由程序完成。

  至於貝葉斯的其他問題如 估計類別下特殊屬性划分的條件概率,以及分類器的評價問題,我認為對於初學者可以暫時跳過,等把基本流程理順了,懂了,越到更多的問題后再回過頭來反思后,按需學習。

2.2 朴素貝葉斯分類實例:檢測不真實賬號

  這個例子完全取自於博客園網友:leoo2sk,的文章“算法雜貨鋪——分類算法之朴素貝葉斯分類”,因為這個例子很短,而且有現成數據,手動計算量很小,所以我認為非常適合在這里使用。所以冒昧借用一下,同時3.3節中,我會介紹一個更加復雜的朴素貝葉斯分類器的代碼。這個例子適合入門,而且最好是動手拿筆在紙上畫一畫,這樣更容易理解,光看公式和數據雖然簡單,但未必能了解整個過程,要想自己寫出類似的代碼,這個過程還是要清楚的,至少我是這么過來的。看看SNS社區不真實帳號問題

  對於SNS社區來說,不真實賬號(使用虛假身份或用戶的小號)是一個普遍存在的問題,作為SNS社區的運營商,希望可以檢測出這些不真實賬號,從而在一些運營分析報告中避免這些賬號的干擾,亦可以加強對SNS社區的了解與監管。如果通過純人工檢測,需要耗費大量的人力,效率也十分低下,如能引入自動檢測機制,必將大大提升工作效率。這個問題說白了,就是要將社區中所有賬號在真實賬號和不真實賬號兩個類別上進行分類。

  下面我們一步一步的使用朴素貝葉斯實現這個過程。

2.2.1 准備階段:特征屬性及划分

1.首先設C=0表示真實賬號,C=1表示不真實賬號。其他例子中不一定只有2類,也可以是N個類別,只不過計算更復雜,要借助計算機和程序了。

2.找出可以區分真實與不真實賬號的特征屬性,實際應用中,特征屬性的數量可能很多,划分也會更細致。作為例子,這里只用少量的特征屬性以及較粗的划分,並對數據做了修改。同時我們也假設這3個屬性是獨立的,這是使用朴素貝葉斯的基本要求。

選擇三個特征屬性,在SNS社區中這三項是可以直接從數據庫里得到的。粗略划分如下幾個區間:

a1:日志數量/注冊天數,划分:{a1<=0.05, 0.05<a1<0.2, a1>=0.2} 

a2:好友數量/注冊天數,划分:{a2<=0.1, 0.1<a2<0.8, a2>=0.8}

a3:是否使用真實頭像。 划分:{a3=0(不是),a3=1(是)}

2.2.2 訓練階段:訓練樣本數據

這里並沒有提供實際的數據,而是直接提供了相關整理后的數據,實際例子中,也應該是這樣,這些基礎數據是可以獲取得到的。

使用1萬個人工檢測過的賬號作為訓練樣本。我們根據上面特征屬性的划分計算每個類別的頻率以及各個類別在各個條件下的條件概率,以供后面的預測需要。

計算類別頻率

P(C=0) = 0.89; 也就說這1萬個人工檢測過的帳號中,有89%是真實的

P(C=1) = 0.11;人工檢測的帳號中,有11%是不真實的

計算條件概率

1)計算已知C=0的條件下,a1屬性屬於不同划分類別的條件概率

P(      a1<=0.05| C=0) = 0.3 ; 在帳號真實的情況下,日志數量/注冊天數的值<=0.05的比例有30%

p(0.05<a1<0.2 | C=0) = 0.5 ;

P(      a1 >=0.2 | C=0) = 0.2 ;

2)計算已知C=1的條件下,a1屬性屬於不同划分類別的條件概率 

P(      a1<=0.05| C=1) = 0.8 ; 在帳號不真實的情況下,日志數量/注冊天數的值<=0.05的比例有80%

p(0.05<a1<0.2 | C=1) = 0.1 ;

P(      a1 >=0.2 | C=1) = 0.1 ;

3)計算已知C=0的條件下,a2屬性屬於不同划分類別的條件概率

P(  a2 <=  0.1  |  C=0) = 0.1 ;

P(  0.1<a2<0.8|  C=0) = 0.7 ;在帳號真實條件下,好友數量/注冊天數在0.1-0.8范圍的比例是70%

P(  a2 >=  0.8  |  C=0) = 0.2 ;

4)計算已知C=1的條件下,a2屬性屬於不同划分類別的條件概率

P(  a2 <=  0.1  |  C=1) = 0.7 ;不真實條件下的帳號,好友數量在這個范圍是非常多的

P(  0.1<a2<0.8|  C=1) = 0.2 ;

P(  a2 >=  0.8  |  C=1) = 0.1 ;

5)計算已知C=0的條件下,a3屬性屬於不同划分類別的條件概率

P(a3 = 0 | C=0) = 0.2 ;

P(a3 = 1 | C=0) = 0.8 ;真實帳號中,使用真實圖像的比例是80%

6)計算已知C=1的條件下,a3屬性屬於不同划分類別的條件概率

P(a3 = 0 | C=1) = 0.9 ;不真實帳號中,使用不真實圖像的比例是90%

P(a3 = 1 | C=1) = 0.1 ;

  上面這些數據從樣本中可以直接統計得到。我也手動對幾個條件概率進行了解釋,我們假設還是比較符合真實情況的,雖然這個數據是原作者修正過的。

2.2.3 應用階段:獲取分類概率

  根據上面貝葉斯公式得到的相關條件概率數據,那么如何來進行一個實際的預測分類。假設我們有一個如下的預測需求:

某帳號使用非真實頭像,日志數量與注冊天數的比率為0.1好友數與注冊天數的比率為0.2。這些數據是從該數據庫直接獲取的。

那么這個人的賬戶是真實賬戶 還是 不真實賬戶呢?相應的概率又有多少呢?

  直接使用3.1節中的公式,我們計算在當前數據x發生的情況下,屬於不同類別的概率,這里有2類,所以要計算一下2個東西:

  要計算 P(C=0|x)  和 P(C=1|x)的概率,然后比較大小,取最大值所在的類別就是我們分類的類別。當然我們不一定非要分類,而是可以將求出的概率提供給客戶,作為一個參考值等等。而根據3.1節的推導,上述2個值的計算完整公式應該是下面這樣的:

P(C=0|x) = P(x|C=0)*P(C=0)

     = P(a1|C=0)*P(a2|C=0)*P(a3|C=0)*P(C=0) 根據x的屬性范圍選擇對應的概率

     = P(0.05<a1<0.2|C=0) * P(0.1<a2<0.8|C=0)*P(a3=0|C=0) *P(C=0)

     = 0.5 * 0.7 * 0.2 * 0.89 = 0.0623

同理:

P(C=1|x) = P(0.05<a1<0.2|C=1) * P(0.1<a2<0.8|C=1)*P(a3=0|C=1) *P(C=1)

       = 0.1 * 0.2 * 0.9 * 0.11 = 0.00198

所以根據屬性結果和計算,當事件X發生時,屬於C=0的概率要高得多,是C=1的30倍。因此我們有理由將這個帳號划分為真實帳號的范疇。

當然實際中的情況可能更加復雜,計算量也更加大,朴素貝葉斯不一定能很好的完成復雜的任務。但有些時候,我們將文件簡化為朴素貝葉斯也能收獲一些意外的東西。下面我們就來看將貝葉斯分類應用到足球彩票勝平負結果的預測中的情況。純C#代碼。歡迎支持。

3.足球彩票的貝葉斯預測與C#實現

關於足球彩票預測的幾點說明:

1.本文分析的足球勝平負比賽的結果預測,采集的數據有近10年的全世界主要聯賽;

2.足球彩票的預測方法各種各樣,八仙過海各顯神通,我這里也只是初步的測試,還有很多工作待完成,有沒有完善的地方大家也不要急。

3.足球比賽的結果不僅與球隊實力,狀態,傷病,彩票,天氣,還與場上的重大隨機因素有關,因此想完成預測100%准確是一個不可能的任務,我們只是想在歐賠的概率基礎上有少部分(5-10%)的提高,這樣才可以做很多有意義的事情。

4.准確的說,足球比賽的很多因素都是有關聯的,我也只是處於好奇,先使用了朴素貝葉斯來進行了一些工作,同時也在着手開始研究貝葉斯網絡的預測方法,比較復雜,還在學習與堆碼中。

5.1場足球比賽的基本要點有:主隊,客隊,比分,結果,至於輔助的因素有很多,如賽前的主客隊積分,進球率,失球率,凈勝球等等。

6.本文使用的是數據庫ORM組件XCode,相關數據查詢及操作如果看不懂,可以參考本文博客的文章,點擊菜單導航欄的:“X組件”進入目錄即可。

  我們還是按照前面的步驟來逐步構造一個貝葉斯分類器,在這個過程中,也會講解相關細節,對於懂足球彩票的朋友,應該好懂,對於不懂,只是想了解的朋友,可以看看思路,了解初步過程,沒必要了解細節。

3.1 選擇屬性與獲取訓練數據

  為了簡單起見,我暫時只選取2個屬性:主客隊總積分的差;主隊主場積分與客隊客場積分的差;結果有勝平負3種類別,分別記為(3,1,0)。屬性集的划分我們在程序中動態獲取,這樣可以計算各種不同划分的准確率,更加方便,這和上面的例子是不一樣的。當然上面的例子也可以這樣做,只是一個小的技巧而已。

  在這個測試過程中,我們是選取前N輪的比賽場次數據,然后對后M輪的結果進行預測。所有首先要從數據庫獲取貝葉斯的訓練數據,看代碼:

/// <summary>獲取指定賽季,指定輪之間的比賽數據作為貝葉斯分類的訓練集合</summary>
/// <param name="seasonId">賽季編號</param>
/// <param name="roundIdL">起始輪號</param>
/// <param name="roundIdH">截至輪號</param>
/// <returns>返回貝葉斯需要的數據格式類型(自定義的)</returns>
static List<BayesDS> GetDataBySeason(Int32 seasonId,Int32 roundIdL,Int32 roundIdH)
{
    var season = SeasonInfoDc.FindBySeasonId(seasonId);
    GameScreenDc.SetDbConnName(season.EventName);
    EventRanking.SetDbConnName(season.EventName);
    //獲取所有場次
    var games = GameScreenDc.FindAll(GameScreenDc._.SeasonId == seasonId & 
                                       GameScreenDc._.RoundId >= roundIdL & 
                                       GameScreenDc._.RoundId <= roundIdH, 
                                       GameScreenDc._.RoundId.Asc(), null, 0, 0);
    //循環每場進行查找,組合
    List<BayesDS> res = new List<BayesDS>();

    foreach (var item in games)
    {
        //查找當前主客球隊,上一輪后的積分對象
        var home = EventRanking.Find(EventRanking._.SeasonId == seasonId &
                                      EventRanking._.TeamId == item.HomeId &
                                      EventRanking._.RoundId == item.RoundId -1);
        var visit = EventRanking.Find(EventRanking._.SeasonId == seasonId &
                                        EventRanking._.TeamId == item.VisiteId & 
                                        EventRanking._.RoundId == item.RoundId -1);
        double[] temp = new double[]{(double)(home.TotalScore - visit.TotalScore)/*總積分差*/,
                   (double)(home.HomeScore - visit.VisitScore)/*主隊主場積分-客隊客場積分*/,
            item.Result};
     res.Add(BayesDS.Create(item,temp));
}
return res;
}

  雖然只有2個參數,也需要進行划分,由於積分都是正整數,而且一般球隊的積分差距不是特別大,為了測試不同划分的情況,我們選擇手動輸入划分點,進行屬性的划分,下面是函數,根據輸入的點,自動確定划分區間的:

 1 /// <summary>獲取屬性分割的區間,根據斷點確定 ,data應該是從小到大的點排列</summary>
 2 /// <returns></returns>
 3 static double[][] GetRulesByPoint(List<double> data)
 4 {
 5     double[][] res = new double[data.Count +1][];
 6     res[0] = new double[] {-1000,data[0] };//下限-1000,不可能達到
 7     for (int i = 0; i < data.Count-1; i++)
 8     {
 9         res[i + 1] = new double[] { data[i], data[i +1] };
10     }
11     res[data.Count ] = new double[] {data[data.Count-1],1000 };//上限足夠大,不可能達到
12     return res;
13 }

3.2 建立貝葉斯分類預測模型

  有了數據和思路后,下一步就是要在C#中建立一個貝葉斯分類器,傳遞數據,和划分集然后才能進行預測。模型的定義如要有以下幾點:

1.幾個基本的屬性。注意字典存儲條件概率,直接全部計算,對數據量大的情況,可能會吃不消,應該按需計算比較好。不過這里是測試,無所謂了。先看看效果才行。

 1 #region 屬性
 2 /// <summary>測試數據:分別為屬性值,最后1個為結果類別</summary>
 3 public List<double[]> data { get; set; }
 4 /// <summary>對應的屬性划分集合</summary>
 5 public List<double[][]> rules { get; set; }
 6 /// <summary>所有的類別</summary>
 7 public List<Int32> C { get; set; }
 8 /// <summary>類別的比例字典</summary>
 9 public Dictionary<Int32,double> C_Ratio { get; set; }
10 /// <summary>條件概率字典</summary>
11 public Dictionary<String, double> ConRatio { get; set; }
12 #endregion

2.模型構造函數,主要是模型的初始化。這里我直接寫好了,在初始化的時候就把數據和划分方式給模型,進行相關條件概率的計算,相關的注釋已經在代碼里面了,有幾個注意的地方:條件概率在字典中的key是有格式的,后續也是根據這個來訪問。

 1 #region 構造函數,初始化
 2 public BayesianClassifier(List<double[]> data, List<double[][]> rules, List<Int32> C)
 3 {
 4     this.data = data;
 5     this.rules = rules;
 6     this.C = C;
 7     Int32 N = data[0].Length - 1;//屬性個數
 8     if (N != rules.Count) throw new Exception("屬性划分集與屬性個數對應錯誤");
 9     
10     //先計算樣本中各類別的比例,保存在dic中
11     C_Ratio = C.ToDictionary(n => n, n => (double)data.Where(k => n == k[N ]).Count() / (double)data.Count);
12 
13     //計算特征屬性划分概率,存儲在字典中
14     ConRatio = new Dictionary<String, double>();
15     for (int i = 0; i < C.Count; i++)//循環類別屬性
16     {
17         var temp1 = data.Where(n => n[N ] == C[i]);//當前類別的情況
18         //循環屬性
19         for (int j = 0; j < N; j++)
20         {
21             //  循環該屬性的所有划分集
22             for (int k = 0; k < rules[j].Length; k++)
23             {
24                 String key = String.Format("{0}{1}{2}", j,k,C[i] );//屬性位置-划分位置-類別
25                 //計算當前的條件概率,判斷data第j個屬性,在等於C[k]的結果中,滿足當前屬性划分上下限的比例
26                 var temp2 = temp1.Where(n => n[j].IsInRange(rules[j][k][0], rules[j][k][1]));
27                 double value = (double)temp2.Count() / (double)temp1.Count();
28                 ConRatio.Add(key, value);
29             }
30         }
31     }
32 }
33 #endregion

 3.足球比賽場次勝平負結果的分類預測

   預測的過程也和第2節的例子一樣,只不過是程序化了。預測的方法是每次一條記錄的數據,並計算屬於每一類的概率,所以返回的是一個字典,key為類別,value為概率。具體方法如下所示:

 1 /// <summary>分類:key為類別,value為概率</summary>
 2 public Dictionary<Int32, double> ClassificationForDic(double[] data)
 3 {
 4     //先要計算每個當前屬性的划分集合的順序,找出每個屬性所屬於的區間
 5     List<Int32> attIdList = new List<int>();
 6     for (int i = 0; i < data.Length -1; i++)
 7     {
 8         for (int j = 0; j < rules[i].Length ; j++)
 9         {
10             if (data[i].IsInRange(rules[i][j][0], rules[i][j][1])) attIdList.Add(j);
11         }
12     }
13     
14     Dictionary<Int32, double> res = C_Ratio.ToDictionary(n=>n.Key,n =>
15         {
16             double multip = n.Value;
17             for (int i = 0; i < data.Length -1; i++)
18             {
19                 for (int j = 0; j < attIdList.Count; j++)
20                 {   //屬性位置-划分位置-類別
21                     String key = String.Format("{0}{1}{2}",i,attIdList[j],n.Key);
22                     if (!ConRatio.ContainsKey(key)) multip = 0 ;
23                     else multip *= ConRatio[key];
24                 }
25             }
26             return multip;
27         });
28     return res;
29 }

返回這個字典后,要計算概率最大的結果也非常容易,直接對字典進行排序就可以了。具體代碼看總的cs文件。

3.3 貝葉斯預測算法的測試

  基本過程和代碼完成了,我們采集5大聯賽(西甲,德甲,英超,意甲,法甲)的數據進行測試,看看貝葉斯預測算法的准確性如何。測試的核心代碼如下:

 1 public static void TestBySeason()
 2 {
 3     //五大聯賽的賽季編號
 4     List<Int32> seasonList = new List<int>() {6000,4866 };//4865,16136,4863,4861,5994  
 5     //先初始化聯賽排名
 6     seasonList.ForEach(n => EventRanking.UpdateHisSeason(n));
 7     int trainRoundL = 8;int trainRoundH = 25;//訓練集的起至輪數
 8     int testRoundL = 26; int testRoundH = 35;//測試集的起至輪數
 9     List<double[]> trainData = new List<double[]>();//訓練集
10     foreach (var item in seasonList)
11     {
12         var temp = GetDataBySeason(item,trainRoundL,trainRoundH).Select(n=>n.Data).ToList();
13         trainData.AddRange(temp);
14     }  
15     //然后采集測試集的數據,標簽用於對比,測試時是不用的,只是最后對比使用
16     List<BayesDS> testData = new List<BayesDS>();//訓練集
17     foreach (var item in seasonList)
18     {
19         var temp = GetDataBySeason(item, testRoundL, testRoundH);
20         testData.AddRange(temp);
21     }    
22     while (true)//循環根據不同屬性划分進行測試
23     {
24         Console.Write("總積分差 屬性分割集(參考:-8, -2, +5, 10):");
25         var t1 = Console.ReadLine().StringToDoubleArray().ToList();
26         Console.Write("主客積分差 屬性分割集(參考:-5, -1, +5):");
27         var t2 = Console.ReadLine().StringToDoubleArray().ToList();
28         List<double[][]> rules = new List<double[][]>();
29         rules.Add(GetRulesByPoint(t1));//總積分差   參考:{ -8, -2, +5, 10 })
30         rules.Add(GetRulesByPoint(t2));//主客積分差 參考:{ -5, -1, +5 })
31         //初始化模型
32         BayesianClassifier bayesMode = new BayesianClassifier(trainData, rules, new List<int>() { 3, 1, 0 });    
33         var testResuult = testData.Select(n =>
34             {
35                 var res = bayesMode.Classification(n.Data);//預測結果
36             }).ToList();        
37     }
38 }

1.數據集采用2013-2014賽季,歐洲5大聯賽的比賽,我們選取前8-25輪的場次作為訓練集,26-35輪的比賽作為測試集合(考慮到聯賽初期和末期的不穩定性)。

  我們可以看到,針對不同的划分集,指數1的准確率都超過了57%,比正常的歐賠指數45-50%,高出了5-10%。結果還是比較可觀的。但是我們也看到指數3的比例都有22%,說明對於一些特別冷門的場次,算法還是做不到,這些特殊情況不是簡單2個因素就可以左右的,因此還有待對模型更深一步的研究,找出這些特別冷門場次的一些共同因素,從而進行一定程度的防范,減少指數3的比例,從而提高指數1,2的比例。

2.同時,我們對上一步的測試方法進行了一定的更改,將預測結果和歐賠bet 365指數1結果一致的比賽拿出來進行統計;將預測結果和歐賠bet 365指數1,2結果一致的比賽進行統計:

同樣是上述481場比賽進行篩選和屬性划分,我們對實際的准確率進行比較:

  通過結合歐賠指數,進行一定的過濾后,預測的整理准確率有了一定的提高。這個結果還是很理想的,懂的人應該知道里面的含義。所以貝葉斯理論的確是非常強大,當然這里只采用了2個因素,而且本身是關聯的,但實際中沒有考慮關聯性,看成了朴素貝葉斯,必定會對問題結果產生一定的影響。這和我解決問題的思路有關系,先簡單,后復雜,逐步過渡,延伸。。

4.參考文獻與資料

博客園很多網友多對偽原創網站抓取文章做出過防范對策,我也發現這個問題,所以也想出了2個辦法。

1.在博客正文加上本文的鏈接,當然部分網站會無良的把所有鏈接給去掉,但可以防范部分,另外水印這些也有點用,只是比較麻煩,懶得搞

2.也是我的必殺技,資料不直接開放下載,而是在文章發表后的12-24小時后再把鏈接發出來,或者通過郵箱發送。因為網站抓取一般都是對首頁文章進行抓取,在發表12-24小時后,在進行抓取的頻率就少多了。鑒於此,本文的資源將在發表后的24小時公開百度網盤的下載鏈接,所以大家可以關注博客,或者留下郵箱,在24小時后,統一郵箱發送。打包的資料文章有:

貝葉斯分類方法及其在冠心病診療中的應用研究.
貝葉斯網絡研究
基於WEKA平台的貝葉斯分類器的擴展
基於貝葉斯方法的分類問題研究
基於粗糙集的加權朴素貝葉斯分類算法研究
基於粗糙集的朴素貝葉斯分類算法研究
基於改進的K-均值算法的朴素貝葉斯分類及應用
基於聚類的朴素貝葉斯分類模型的研究與應用
加權貝葉斯增量學習中文文本分類研究
面向不確定性數據的貝葉斯分類方法研究

上述論文由於涉及到版權,已經取消下載取消下載,如需要請留言或者郵件索取。

請到原始網頁http://www.cnblogs.com/asxinyu/p/4394156.html 進行下載。

參考的相關網頁:

1.數學之美番外篇:平凡而又神奇的貝葉斯方法

2.百度百科-貝葉斯

3.貝葉斯定理

4.算法雜貨鋪——分類算法之朴素貝葉斯分類

  如果本文對大家有幫助或者非常感興趣,希望得到“推薦”,這樣我也會將抽空寫一篇關於更加復雜和實用的貝葉斯網絡推斷的例子和C#實現的文章,希望大家關注本博客。

  預告,下一篇文章將是本站第100篇正式文章,將與近期發布一個.NET平台機器學習資源匯總的隨筆,信息量很大,敬請關注,機不可失失不再來。。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM