python 预测足球_利用 Python 预测英雄联盟胜负,分析了 5 万多场比赛才得出的数据!...
今天教大家用Python預(yù)測(cè)英雄聯(lián)盟比賽勝負(fù)。
Show me data,用數(shù)據(jù)說(shuō)話
今天我們聊一聊 Python預(yù)測(cè)LOL勝負(fù)
目前,英雄聯(lián)盟S10全球總決賽正在火熱進(jìn)行中,最終決賽于10月31日在浦東足球場(chǎng)舉行。作為當(dāng)下最火熱的電競(jìng)賽事,這點(diǎn)燃了全球無(wú)數(shù)玩家的關(guān)注,相信沒(méi)有哪個(gè)英雄聯(lián)盟玩家會(huì)錯(cuò)過(guò)這場(chǎng)受眾超廣、影響力超大的國(guó)際電競(jìng)賽事。LPL究竟能否在家門(mén)口拿下第三座世界賽獎(jiǎng)杯也成了許多玩家關(guān)注的話題。
對(duì)于每場(chǎng)比賽,大家最關(guān)注的莫過(guò)于最后的勝負(fù)了,那么比賽的勝負(fù)能否可以預(yù)測(cè)呢?
今天,我們就分析了5萬(wàn)多場(chǎng)英雄聯(lián)盟的排名比賽,教你如何用Python預(yù)測(cè)比賽勝負(fù)。
項(xiàng)目介紹
英雄聯(lián)盟(LOL)是美國(guó)游戲開(kāi)發(fā)商Riot Games(2011年由騰訊收購(gòu))開(kāi)發(fā)和發(fā)行的一款多人在線戰(zhàn)斗競(jìng)技游戲。
在游戲中,玩家扮演一個(gè)"召喚師"角色,每個(gè)召喚師控制一個(gè)擁有獨(dú)特技能的"英雄",并與一組其他玩家或電腦控制的英雄戰(zhàn)斗。游戲的目標(biāo)是摧毀對(duì)方的防御塔和基地。
召喚者峽谷是英雄聯(lián)盟中最受歡迎的地圖,在這種地圖類(lèi)型中,兩隊(duì)五名玩家競(jìng)爭(zhēng)摧毀一個(gè)被稱(chēng)為基地的敵人建筑,這個(gè)建筑由敵人的隊(duì)伍和一些防御塔護(hù)衛(wèi)。每個(gè)隊(duì)伍都希望保衛(wèi)自己的建筑,同時(shí)摧毀對(duì)方的建筑。這些主要包括:Towers(防御塔):每支隊(duì)伍總共有11座防御塔
Inhibitor(水晶):每條道有一個(gè)水晶
Elemental Drakes/Elder Dragon(大龍/遠(yuǎn)古龍)
Rift Herald(峽谷先鋒)
Baron Nasho(納什男爵)
Nexus(基地)
英雄聯(lián)盟最具爭(zhēng)議的元素之一,就是其嚴(yán)重的滾雪球效應(yīng)。許多職業(yè)選手接受賽后采訪時(shí)都提到其輸贏都因?yàn)椤皾L雪球”,我們研究各方面各指標(biāo)的數(shù)據(jù),來(lái)看這些因素的發(fā)展是否真的影響了比賽的成敗。
在這個(gè)項(xiàng)目中,我們分析了5萬(wàn)多場(chǎng)英雄聯(lián)盟的排名比賽,并嘗試使用決策樹(shù)算法來(lái)根據(jù)已有輸入屬性預(yù)測(cè)比賽勝負(fù)。
數(shù)據(jù)集概述
數(shù)據(jù)集收集了超過(guò)50000個(gè)從游戲英雄聯(lián)盟排位游戲的數(shù)據(jù),字段主要包含以下數(shù)據(jù):Game ID:游戲ID
Creation Time:創(chuàng)建時(shí)間
Game Duration (in seconds):游戲持續(xù)時(shí)間(秒)
Season ID:賽季ID
Winner (1=team1, 2=team2):獲勝隊(duì)伍
First Baron, dragon, tower, blood, inhibitor and Rift Herald (1 = team1, 2 = team2, 0 = none):第一條納什男爵,大龍,塔,一血,水晶,峽谷先鋒
Champions and summoner spells for each team (Stored as Riot's champion and summoner spell IDs):每只隊(duì)伍選擇的英雄和召喚術(shù)
The number of tower, inhibitor, Baron, dragon and Rift Herald kills each team has:塔,水晶,男爵,大龍和峽谷先鋒擊殺數(shù)
The 5 bans of each team (Again, champion IDs are used):每個(gè)隊(duì)伍的禁用英雄
數(shù)據(jù)讀入和預(yù)覽
首先導(dǎo)入所需包和讀入數(shù)據(jù)集。
# 數(shù)據(jù)整理import numpy as np import pandas as pd # 可視化import matplotlib.pyplot as plt import seaborn as sns import plotly as py import plotly.graph_objs as go # 建模from sklearn.tree import DecisionTreeClassifierfrom sklearn.model_selection import train_test_split, GridSearchCVfrom sklearn.metrics import confusion_matrix, classification_report
# 讀入數(shù)據(jù)df = pd.read_csv('./archive/games.csv')df.head()
ape(51490, 61)
數(shù)據(jù)可視化
我們將分別對(duì)影響比賽的相關(guān)因素進(jìn)行如下探索:
1. 目標(biāo)變量分布
數(shù)據(jù)集一共有51490條記錄,其中1隊(duì)獲勝的次數(shù)為26077次,占比50.6%,2隊(duì)獲勝的次數(shù)為25413次,占比49.4%。不存在樣本不平衡的情況。
代碼
# 餅圖trace0 = go.Pie(labels=df['winner'].value_counts().index, ? ? ? ? ? ? ? ? values=df['winner'].value_counts().values, ? ? ? ? ? ? ? ?hole=0.5, ? ? ? ? ? ? ? ?opacity=0.9, ? ? ? ? ? ? ? ?marker=dict(line=dict(color='white', width=1.3)) ? ? ? ? ? ? ? ) layout = go.Layout(title='目標(biāo)變量winner分布')
data = [trace0]fig = go.Figure(data, layout)py.offline.plot(fig, filename='./html/整體獲勝情況分布.html')
2. 游戲時(shí)長(zhǎng)分布
從直方圖可以看出,游戲時(shí)長(zhǎng)大致服從正態(tài)分布,其中最短的游戲時(shí)長(zhǎng)為3分鐘,3分鐘是游戲重開(kāi)的時(shí)間點(diǎn),最長(zhǎng)的游戲時(shí)長(zhǎng)是79分鐘。中間50%的時(shí)長(zhǎng)在26~36分鐘之間。
代碼
df['game_duration'] = round(df['gameDuration'] / 60)
# 選擇數(shù)據(jù)x1 = df[df['winner'] == 1]['game_duration']x2 = df[df['winner'] == 2]['game_duration']
# 直方圖trace0 = go.Histogram(x=x1, bingroup=25, name='team1', opacity=0.9)trace1 = go.Histogram(x=x2, bingroup=25, name='team2', opacity=0.9)
layout = go.Layout(title='比賽游戲時(shí)長(zhǎng)分布')
data = [trace0, trace1] fig = go.Figure(data, layout)py.offline.plot(fig, filename='./html/游戲時(shí)長(zhǎng)分布.html')
3. 一血對(duì)獲勝的影響
獲得一血的隊(duì)伍勝率相對(duì)較高,在第一隊(duì)的比賽中,首先獲得一血時(shí)的勝率為59.48%,相較未獲得一血的比賽高18%。在第二隊(duì)的比賽中,獲得一血時(shí)的勝率為58.72%,相較未獲得一血的比賽高18%。
代碼
plot_bar_horizontal(input_col='firstBlood',?target_col='winner',?title_name='一血對(duì)獲勝的影響')
4. 一塔對(duì)獲勝的影響
從數(shù)據(jù)來(lái)看,第一個(gè)防御塔看起來(lái)是比較有說(shuō)服力的指標(biāo)。在第一隊(duì)的比賽中,首先摧毀一塔時(shí)隊(duì)伍的勝率高達(dá)70.84%,相較未獲得一塔的比賽高41.64%。在第二隊(duì)的比賽中,有相近的數(shù)據(jù)表現(xiàn)。
代碼
plot_bar_horizontal(input_col='firstTower', target_col='winner', title_name='一塔對(duì)獲勝的影響')
5. 摧毀第一個(gè)水晶對(duì)獲勝的影響
在比賽中拿到第一座水晶塔的隊(duì)伍91%的情況下可以獲勝,這一點(diǎn)在某種程度上是可以預(yù)見(jiàn)的,因?yàn)槭紫却輾黻?duì)伍已經(jīng)積累的足夠的優(yōu)勢(shì),而且水晶塔力量很強(qiáng)大,并且更具有價(jià)值。
代碼
plot_bar_horizontal(input_col='firstInhibitor',?target_col='winner',?title_name='摧毀第一個(gè)水晶對(duì)獲勝的影響')
6. 擊殺第一條男爵對(duì)獲勝影響
統(tǒng)計(jì)數(shù)據(jù)顯示,在比賽中擊殺第一條男爵有80%的勝率。
plot_bar_horizontal(input_col='firstBaron', target_col='winner', title_name='擊殺第一條男爵對(duì)獲勝影響')
7. 擊殺第一條大龍對(duì)獲勝的影響
在第一個(gè)隊(duì)伍中,首先擊殺第一條大龍的隊(duì)伍勝率在68.6%,相較未取得優(yōu)先的比賽勝率高36%。
plot_bar_horizontal(input_col='firstDragon',?target_col='winner',?title_name='擊殺第一條大龍對(duì)獲勝的影響')
8. 擊殺第一條峽谷先鋒對(duì)獲勝的影響
在第一個(gè)隊(duì)伍中,首先擊殺第一條峽谷先鋒的隊(duì)伍勝率在69.45%,相較未取得優(yōu)先的比賽勝率高38.92%。
plot_bar_horizontal(input_col='firstRiftHerald', target_col='winner', ? ? ? ? ? ? ? ? ? ? title_name='擊殺第一條峽谷先鋒對(duì)獲勝的影響')
9. 摧毀防御塔數(shù)對(duì)獲勝影響
選擇第一個(gè)隊(duì)伍的摧毀防御塔數(shù)作為影響因素,可以看出,摧毀的防御塔數(shù)量越多,獲勝的概率越大。當(dāng)數(shù)量大于8個(gè)時(shí),勝率大于85%。11個(gè)防御塔全部摧毀時(shí)的勝率為99.16%,當(dāng)然也有8.4‰的翻盤(pán)概率。
plot_bar_vertical(input_col='t1_towerKills', target_col='winner', title_name='摧毀防御塔數(shù)對(duì)獲勝影響')
10. 摧毀水晶數(shù)對(duì)獲勝影響
摧毀水晶的數(shù)目越多,獲勝的概率越大。沒(méi)有摧毀水晶的獲勝概率為12.55%,摧毀一個(gè)的獲勝概率為81.11%,兩個(gè)為92.38%。
plot_bar_vertical(input_col='t1_inhibitorKills', target_col='winner', title_name='摧毀水晶數(shù)對(duì)獲勝影響')
11. 擊殺男爵數(shù)對(duì)獲勝影響
擊殺男爵數(shù)越多,獲勝的概率越大,擊殺5條男爵的數(shù)據(jù)僅有一條,后續(xù)需要?jiǎng)h除。
plot_bar_vertical(input_col='t1_baronKills', target_col='winner', title_name='擊殺男爵數(shù)對(duì)獲勝影響')
12. 擊殺大龍數(shù)對(duì)獲勝影響
擊殺大龍數(shù)數(shù)越多,獲勝的概率越大
plot_bar_vertical(input_col='t1_dragonKills', target_col='winner', title_name='擊殺大龍數(shù)對(duì)獲勝影響')
數(shù)據(jù)建模
首先進(jìn)行初步的清洗,并篩選建模所需變量。
# 刪除時(shí)間少于15分鐘和分類(lèi)數(shù)較少的記錄df = df[(df['gameDuration'] >= 900) & (df['t1_baronKills'] != 5)]print(df.shape)
(50180,?62)# 篩選建模變量df_model = df[['winner', 'firstBlood', 'firstTower', 'firstInhibitor', 'firstBaron', ? ? ? ? ? ? ?'firstDragon', 'firstRiftHerald', 't1_towerKills', 't1_inhibitorKills','t1_baronKills', ? ? ? ? ? ? ?'t1_dragonKills', 't2_towerKills', 't2_inhibitorKills', 't2_baronKills', 't2_dragonKills' ? ? ? ? ? ? ?]] df_model.head()
然后劃分訓(xùn)練集和測(cè)試集,采用分層抽樣方法劃分80%數(shù)據(jù)為訓(xùn)練集,20%數(shù)據(jù)為測(cè)試集。
# 劃分訓(xùn)練集和測(cè)試集x = df_model.drop('winner', axis=1)y = df_model['winner']
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, stratify=y, random_state=0)print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
(40144, 14) (10036, 14) (40144,) (10036,)
使用決策樹(shù)算法建模,使用GridSearchCV進(jìn)行參數(shù)調(diào)優(yōu)。
# 參數(shù)parameters = { ? ?'splitter': ('best', 'random'), ? ?'criterion':('gini', 'entropy'), ? ?'max_depth':[*range(1, 20, 2)],}
# 建立模型clf = DecisionTreeClassifier(random_state=0)GS = GridSearchCV(clf, parameters, cv=10)GS.fit(X_train, y_train)GridSearchCV(cv=10, estimator=DecisionTreeClassifier(random_state=0), ? ? ? ? ? ? param_grid={'criterion': ('gini', 'entropy'), ? ? ? ? ? ? ? ? ? ? ? ? 'max_depth': [1, 3, 5, 7, 9, 11, 13, 15, 17, 19], ? ? ? ? ? ? ? ? ? ? ? ? 'splitter': ('best', 'random')})# 輸出最佳得分 print("best score: ", GS.best_score_)print("best param: ", GS.best_params_)best?score:??0.9770077890521407best?param:??{'criterion':?'gini',?'max_depth':?7,?'splitter':?'best'}#?最佳模型best_clf?=?DecisionTreeClassifier(criterion="gini",?max_depth=7,?splitter="best")best_clf.fit(X_train,y_train)?print("score:",?best_clf.score(X_test,y_test))???score: 0.9799721004384216
使用最優(yōu)的模型重新評(píng)估測(cè)試數(shù)據(jù)集效果:
# 輸出分類(lèi)報(bào)告y_pred = best_clf.predict(X_test) cm = confusion_matrix(y_test, y_pred)cr = classification_report(y_test, y_pred)print('Classification?report?:?\n',?cr)
Classification report : ? ? ? ? ? ? ? ?precision ? ?recall ?f1-score ? support
1 ? ? ? 0.98 ? ? ?0.98 ? ? ?0.98 ? ? ?5077 ? ? ? ? ? 2 ? ? ? 0.98 ? ? ?0.98 ? ? ?0.98 ? ? ?4959
accuracy ? ? ? ? ? ? ? ? ? ? ? ? ? 0.98 ? ? 10036 ? macro avg ? ? ? 0.98 ? ? ?0.98 ? ? ?0.98 ? ? 10036weighted?avg???????0.98??????0.98??????0.98?????10036
# 熱力圖g1 = sns.heatmap(cm, annot=True, fmt=".1f", cmap="flag", linewidths=0.2, cbar=False)g1.set_ylabel('y_true', fontdict={'fontsize': 15})g1.set_xlabel('y_pred', fontdict={'fontsize': 15}) ?g1.set_title('confusion_matrix',?fontdict={'fontsize':?15})Text(0.5, 1, 'confusion_matrix')
# 輸出屬性重要性imp = pd.DataFrame(list(zip(X_train.columns, best_clf.feature_importances_))) imp.columns = ['columns', 'importances']imp = imp.sort_values('importances', ascending=False)imp
在屬性的重要性排序中,擊殺防御塔數(shù)量的重要性最高,其次是水晶摧毀數(shù)量、一塔、擊殺龍的數(shù)量。
以下代碼用于輸出這顆樹(shù):
# 可視化import graphvizfrom sklearn import tree
dot_data = tree.export_graphviz(decision_tree=best_clf, max_depth=3, ? out_file=None, ? feature_names=X_train.columns, ?class_names=['1', '2'], ? filled=True, ?rounded=True ?)graph = graphviz.Source(dot_data)graph
模型預(yù)測(cè)
我們假設(shè):
第一隊(duì)拿了第一血,第一塔,第一男爵,第一條大龍和第一峽谷先鋒,而第二隊(duì)只拿了第一個(gè)水晶。
第一隊(duì)的塔,水晶,男爵和龍殺死的數(shù)量分別是10,2,1,4和塔,水晶,男爵和龍的數(shù)量分別是7,2,1,1。
# 新數(shù)據(jù)new_data = [[1, 1, 2, 1, 1, 1, 10, 2, 1, 4, 7, 2, 1, 1]]c = best_clf.predict_proba(new_data).reshape(-1, 1) print("winner is :" , best_clf.predict(x1)) print("First team win probability is % ", list(c[0] * 100), ? ? ?"\nSecond team win probability is %:",list(c[1] * 100))
winner is : [1]First team win probability is % ?[89.87341772151899] Second team win probability is %: [10.126582278481013]
根據(jù)模型預(yù)測(cè)結(jié)果,第一隊(duì)將會(huì)獲勝,獲勝的概率為89.87%。
喜歡的記得三連哦,需要學(xué)習(xí)資料的可以私信UP主領(lǐng)取
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的python 预测足球_利用 Python 预测英雄联盟胜负,分析了 5 万多场比赛才得出的数据!...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 在校期间如何确保部队安全
- 下一篇: python缩进的用途和使用方法_如何用