英雄聯盟勝負預測--簡易肯德基上校
# 定義決策樹類
class DecisionTree(object):
def __init__(self, classes, features,
max_depth=10, min_samples_split=10,
impurity_t='entropy'):
'''
傳入一些可能用到的模型引數,也可能不會用到
classes 表示模型分類總共有幾類
features 是每個特徵的名字,也方便查詢總的共特徵數
max_depth 表示構建決策樹時的最大深度
min_samples_split 表示構建決策樹分裂節點時,如果到達該節點的樣本數小於該值則不再分裂
impurity_t 表示計算混雜度(不純度)的計算方式,例如 entropy 或 gini
'''
self.classes = classes
self.features = features
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.impurity_t = impurity_t
self.root = None # 定義根節點,未訓練時為空
def impurity(self, data):
'''
計算某個特徵下的資訊增益
:param data: , numpy 一維陣列
:return: 混雜度
'''
cnt = Counter(data) # 計數每個值出現的次數
probability_lst = [1.0 * cnt[i] / len(data) for i in cnt]
if self.impurity_t == 'entropy': # 如果是資訊熵
return -np.sum([p * np.log2(p) for p in probability_lst if p > 0]), cnt # 返回熵 和可能用到的資料次數 ( 方便以後使用 )
return 1 - np.sum([p * p for p in probability_lst]), cnt # 否則返回 gini 係數
def gain(self, feature, label):
'''
計算某個特徵下的資訊增益
:param feature: 特徵的值, numpy 一維陣列
:param label: 對應的標籤, numpy 一維陣列
:return: 資訊增益
'''
c_impurity, _ = self.impurity(label) # 不考慮特徵時標籤的混雜度
# 記錄特徵的每種取值所對應的陣列下標
f_index = {}
for idx, v in enumerate(feature):
if v not in f_index:
f_index[v] = []
f_index[v].append(idx)
# 計算根據該特徵分裂後的不純度,根據特徵的每種值的數目加權和
f_impurity = 0
for v in f_index:
# 根據該特徵取值對應的陣列下標 取出對應的標籤列表 比如分支 1 有多少個正負例 分支 2 有 ...
f_l = label[f_index[v]]
f_impurity += self.impurity(f_l)[0] * len(f_l) / len(label) # 迴圈結束得到各分支混雜度的期望
gain = c_impurity - f_impurity # 得到 gain
# 有些特徵取值很多,天然不純度高、資訊增益高,模型會偏向於取值很多的特徵比如日期,但很可能過擬合
# 計算資訊增益率可以緩解該問題
splitInformation = self.impurity(feature)[0] # 計算該特徵在標籤無關時的不純度
gainRatio = gain / splitInformation if splitInformation > 0 else gain # 除數不為 0 時為資訊增益率
return gainRatio, f_index # 返回資訊增益率,以及每個特徵取值的陣列下標 ( 方便以後使用 )
def expand_node(self, feature, label, depth, skip_features=set()):
'''
遞迴函式分裂節點
:param feature: 二維 numpy ( n*m )陣列,每行表示一個樣本, n 行,有 m 個特徵
:param label: 一維 numpy ( n )陣列,表示每個樣本的分類標籤
:param depth: 當前節點的深度
:param skip_features: 表示當前路徑已經用到的特徵
在當前 ID3 演算法離散特徵的實現下,一條路徑上已經用過的特徵不會再用(其他實現有可能會選重複特徵)
'''
l_cnt = Counter(label) # 計數每個類別的樣本出現次數
if len(l_cnt) <= 1: # 如果只有一種類別了,無需分裂,已經是葉節點
return label[0] # 只需記錄類別
if len(label) < self.min_samples_split or depth > self.max_depth: # 如果達到了最小分裂的樣本數或者最大深度的閾值
return l_cnt.most_common(1)[0][0] # 則只記錄當前樣本中最多的類別
f_idx, max_gain, f_v_index = -1, -1, None # 準備挑選分裂特徵
for idx in range(len(self.features)): # 遍歷所有特徵
if idx in skip_features: # 如果當前路徑已經用到,不用再算
continue
f_gain, fv = self.gain(feature[:, idx], label) # 計算特徵的資訊增益, fv 是特徵每個取值的樣本下標
# if f_gain <= 0: # 如果資訊增益不為正,跳過該特徵
# continue
if f_idx < 0 or f_gain > max_gain: # 如果個更好的分裂特徵
f_idx, max_gain, f_v_index = idx, f_gain, fv # 則記錄該特徵
# if f_idx < 0: # 如果沒有找到合適的特徵,即所有特徵都沒有資訊增益
# return l_cnt.most_common(1)[0][0] # 則只記錄當前樣本中最多的類別
decision = {} # 用字典記錄每個特徵取值所對應的子節點, key 是特徵取值, value 是子節點
skip_features = set([f_idx] + [f for f in skip_features]) # 子節點要跳過的特徵包括當前選擇的特徵
for v in f_v_index: # 遍歷特徵的每種取值
decision[v] = self.expand_node(feature[f_v_index[v], :], label[f_v_index[v]], # 取出該特徵取值所對應的樣本
depth=depth + 1, skip_features=skip_features) # 深度 +1 ,遞迴呼叫節點分裂
# 返回一個元組,有三個元素
# 第一個是選擇的特徵下標,第二個特徵取值和對應的子節點 ( 字典 ) ,第三個是到達當前節點的樣本中最多的類別
return (f_idx, decision, l_cnt.most_common(1)[0][0])
def traverse_node(self, node, feature):
'''
預測樣本時從根節點開始遍歷節點,根據特徵路由。
:param node: 當前到達的節點,例如 self.root
:param feature: 長度為 m 的 numpy 一維陣列
'''
assert len(self.features) == len(feature) # 要求輸入樣本特徵數和模型定義時特徵數目一致
if type(node) is not tuple: # 如果到達了一個節點是葉節點(不再分裂),則返回該節點類別
return node
fv = feature[node[0]] # 否則取出該節點對應的特徵值, node[0] 記錄了特徵的下標
if fv in node[1]: # 外匯跟單gendan5.com 根據特徵值找到子節點,注意需要判斷訓練節點分裂時到達該節點的樣本是否有該特徵值(分支)
return self.traverse_node(node[1][fv], feature) # 如果有,則進入到子節點繼續遍歷
return node[-1] # 如果沒有,返回訓練時到達當前節點的樣本中最多的類別
def fit(self, feature, label):
'''
訓練模型
:param feature:feature 為二維 numpy ( n*m )陣列,每行表示一個樣本,有 m 個特徵
:param label:label 為一維 numpy ( n )陣列,表示每個樣本的分類標籤
'''
assert len(self.features) == len(feature[0]) # 輸入資料的特徵數目應該和模型定義時的特徵數目相同
self.root = self.expand_node(feature, label, depth=1) # 從根節點開始分裂,模型記錄根節點
def predict(self, feature):
'''
預測
:param feature: 輸入 feature 可以是一個一維 numpy 陣列也可以是一個二維 numpy 陣列
如果是一維 numpy ( m )陣列則是一個樣本,包含 m 個特徵,返回一個類別值
如果是二維 numpy ( n*m )陣列則表示 n 個樣本,每個樣本包含 m 個特徵,返回一個 numpy 一維陣列
'''
assert len(feature.shape) == 1 or len(feature.shape) == 2 # 只能是 1 維或 2 維
if len(feature.shape) == 1: # 如果是一個樣本
return self.traverse_node(self.root, feature) # 從根節點開始路由
return np.array([self.traverse_node(self.root, f) for f in feature]) # 如果是很多個樣本
def get_params(self, deep): # 要呼叫 sklearn 的 cross_validate 需要實現該函式返回所有引數
return {'classes': self.classes, 'features': self.features,
'max_depth': self.max_depth, 'min_samples_split': self.min_samples_split,
'impurity_t': self.impurity_t}
def set_params(self, **parameters): # 要呼叫 sklearn 的 GridSearchCV 需要實現該函式給類設定所有引數
for parameter, value in parameters.items():
setattr(self, parameter, value)
return self
# 定義決策樹模型,傳入演算法引數
DT = DecisionTree(classes=[0, 1], features=feature_names, max_depth=5, min_samples_split=10, impurity_t='gini')
DT.fit(x_train, y_train) # 在訓練集上訓練
p_test = DT.predict(x_test) # 在測試集上預測,獲得預測值
print(p_test) # 輸出預測值
test_acc = accuracy_score(p_test, y_test) # 將測試預測值與測試集標籤對比獲得準確率
print('accuracy: {:.4f}'.format(test_acc)) # 輸出準確率
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2904738/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- LOL英雄聯盟Theshy職業生涯資料統計,92勝27負,勝率達77.3%!
- 面試每日一題:怎麼推演肯德基上校的勝率曲線?(數值向)面試每日一題
- 《英雄聯盟》系列IP開發負責人:我們是如何打造《英雄聯盟》IP宇宙的?
- 《英雄聯盟手遊》動效簡析
- 《英雄聯盟》正版手遊預約開啟
- 《英雄聯盟手遊》iOS版本開放預約iOS
- Flutter之英雄聯盟Flutter
- 英雄聯盟(洛谷)
- 《英雄聯盟》手遊海外測試首日果然炸服了
- 用python對英雄聯盟選用英雄進行分析Python
- 英雄聯盟手遊奧拉夫打野怎麼玩 英雄聯盟手遊打野奧拉夫玩法攻略
- Python3爬取英雄聯盟英雄皮膚大圖Python
- 《英雄聯盟》VFX視覺風格指南視覺
- 《英雄聯盟》手遊UI設計分析UI
- 也聊兩句英雄聯盟自走棋
- 《英雄聯盟:雙城之戰》第二季預告前瞻 全新主題玩法及新英雄預告登場
- 足球預測app分析軟體 ai足球勝負資料的軟體APPAI
- 站在第三視角看直播簡史-《英雄聯盟》直播進化論
- win10英雄聯盟裝不了怎麼辦 win10英雄聯盟無法安裝處理方法Win10
- 海外首測之後,《英雄聯盟手遊》透露了哪些新資訊?
- 亞運會《英雄聯盟》表演賽中國隊3:1戰勝韓國隊獲得冠軍
- 英雄競技中英雄設計的一點隨想:加入肯德基爺爺
- 《英雄聯盟手遊》超燃測試今日開服 直播夜掉落測試資格
- 《英雄聯盟》全球日活躍八百萬
- 【賽事回放】英雄聯盟API資料介面API
- Moba秀--DOTA,LOL,英雄聯盟編年史
- 風暴英雄-神鑄裝備VS英雄聯盟-神話裝備
- 英雄聯盟十週年,拳頭遊戲公佈3款新遊 《英雄聯盟》手遊2020年上線遊戲
- win10玩英雄聯盟總卡屏怎麼辦_win10玩英雄聯盟總卡屏如何解決Win10
- win10英雄聯盟打字卡怎麼辦 win10玩英雄聯盟打字就卡當機解決方法Win10
- 英雄聯盟的祕密:140個英雄如何改,Riot大資料理論大資料
- 《英雄聯盟》高校聯賽故事:三個人的平行交叉人生
- 路透社:《英雄聯盟》手遊研發中
- 用Python爬取英雄聯盟(lol)全部皮膚Python
- w10系統英雄聯盟閃屏怎麼解決_win10英雄聯盟全屏模式閃屏修復方法Win10模式
- win10英雄聯盟出現directx怎麼辦 win10玩英雄聯盟顯示directx錯誤修復方法Win10
- win10 64位無法啟動英雄聯盟如何解決_win10英雄聯盟打不開修復方法Win10
- 開服即登頂,《英雄聯盟手遊》不刪檔測試正式開啟