摘要:采用機(jī)器學(xué)習(xí)預(yù)測(cè)足球比賽結(jié)果足球是世界上最火爆的運(yùn)動(dòng)之一,世界杯期間也往往是球迷們最亢奮的時(shí)刻。特征工程在機(jī)器學(xué)習(xí)中占有非常重要的作用,一般認(rèn)為括特征構(gòu)建特征提取特征選擇三大部分。
采用 Python 機(jī)器學(xué)習(xí)預(yù)測(cè)足球比賽結(jié)果
足球是世界上最火爆的運(yùn)動(dòng)之一,世界杯期間也往往是球迷們最亢奮的時(shí)刻。比賽狂歡季除了炸出了熬夜看球的鐵桿粉絲,也讓足球競(jìng)猜也成了大家茶余飯后最熱衷的話題。甚至連原來(lái)不怎么看足球的人,也是暗中努力惡補(bǔ)了很多足球相關(guān)知識(shí),想通過(guò)賽事競(jìng)猜先賺一個(gè)小目標(biāo)。今天我們將介紹如何用機(jī)器學(xué)習(xí)來(lái)預(yù)測(cè)足球比賽結(jié)果!
本 Chat 采用 Python 編程語(yǔ)言,使用 人工智能建模平臺(tái) Mo 作為在線開(kāi)發(fā)環(huán)境進(jìn)行編程,通過(guò)獲取 2000 年到 2018 年共 19 年英超的比賽數(shù)據(jù),然后基于監(jiān)督學(xué)習(xí)中邏輯回歸模型、支持向量機(jī)模型和 XGBoost 模型,對(duì)英超比賽結(jié)果進(jìn)行預(yù)測(cè)。
下面我們一起來(lái)看看預(yù)測(cè)英超比賽結(jié)果的機(jī)器學(xué)習(xí)步驟:
主要流程步驟獲取數(shù)據(jù)和讀取數(shù)據(jù)的信息
數(shù)據(jù)清洗和預(yù)處理
特征工程
建立機(jī)器學(xué)習(xí)模型并進(jìn)行預(yù)測(cè)
總結(jié)與展望
1. 獲取數(shù)據(jù)和讀取數(shù)據(jù)的信息首先我們進(jìn)入 Mo 工作臺(tái),創(chuàng)建一個(gè)空白項(xiàng)目,點(diǎn)擊 開(kāi)始開(kāi)發(fā) 進(jìn)入內(nèi)嵌 JupyterLab 的 Notebook 開(kāi)發(fā)環(huán)境。
接著我們需要在項(xiàng)目中上傳數(shù)據(jù)集。
英超每年舉辦一個(gè)賽季,在每年的 8 月到第二年的 5 月進(jìn)行,共有 20 支球隊(duì),實(shí)行主客場(chǎng)雙循環(huán)賽制,每個(gè)賽季共 38 輪比賽(其中 19 場(chǎng)主場(chǎng)比賽,19 場(chǎng)客場(chǎng)比賽),每輪比賽共計(jì) 10 場(chǎng)比賽,所以每個(gè)賽季,英超共有 380 場(chǎng)比賽。
數(shù)據(jù)集地址
數(shù)據(jù)集中特征說(shuō)明文檔
如果您已經(jīng)在 MO 平臺(tái)新建項(xiàng)目,可以在平臺(tái)直接導(dǎo)入數(shù)據(jù)集,流程如下:
1.1 讀取 csv 數(shù)據(jù)接口解釋
采用 Pandas 讀取、寫(xiě)入數(shù)據(jù) API 匯總網(wǎng)址
讀取 csv 數(shù)據(jù)一般采用 pandas.read_csv():
pandas.read_csv(filepath_or_buffer, sep ="," , delimiter = None)
filepath_or_buffer:文件路徑
sep:指定分隔符,默認(rèn)是逗號(hào)
delimiter:定界符,備選分隔符(如果指定改參數(shù),則sep失效)
usecols: 指定讀取的列名,列表形式
# 導(dǎo)入必須的包 import warnings warnings.filterwarnings("ignore") # 防止警告文件的包 import pandas as pd # 數(shù)據(jù)分析包 import os import matplotlib.pyplot as plt # 可視化包 import matplotlib %matplotlib inline import seaborn as sns # 可視化包 from time import time from sklearn.preprocessing import scale # 標(biāo)準(zhǔn)化操作 from sklearn.model_selection import train_test_split # 將數(shù)據(jù)集分成測(cè)試集和訓(xùn)練集 from sklearn.metrics import f1_score # F1得分 import xgboost as xgb # XGBoost模型 from sklearn.svm import SVC ## 支持向量機(jī)分類模型 from sklearn.linear_model import LogisticRegression # 邏輯回歸模型 from sklearn.model_selection import GridSearchCV # 超參數(shù)調(diào)參模塊 from sklearn.metrics import make_scorer # 模型評(píng)估 import joblib # 模型的保存與加載模塊
下面開(kāi)始我們的表演:
# 獲取地址中的所有文件 loc = ".//football//" # 存放數(shù)據(jù)的路徑 res_name = [] # 存放數(shù)據(jù)名的列表 filecsv_list = [] # 獲取數(shù)據(jù)名后存放的列表 def file_name(file_name): # root:當(dāng)前目錄路徑 dirs:當(dāng)前目錄下所有子目錄 files:當(dāng)前路徑下所有非目錄文件 for root,dirs,files in os.walk(file_name): files.sort() # 排序,讓列表里面的元素有順序 for i,file in enumerate(files): if os.path.splitext(file)[1] == ".csv": filecsv_list.append(file) res_name.append("raw_data_"+str(i+1)) print(res_name) print(filecsv_list) file_name(loc)
["raw_data_1", "raw_data_2", "raw_data_3", "raw_data_4", "raw_data_5", "raw_data_6", "raw_data_7", "raw_data_8", "raw_data_9", "raw_data_10", "raw_data_11", "raw_data_12", "raw_data_13", "raw_data_14", "raw_data_15", "raw_data_16", "raw_data_17", "raw_data_18", "raw_data_19"] ["2000-01.csv", "2001-02.csv", "2002-03.csv", "2003-04.csv", "2004-05.csv", "2005-06.csv", "2006-07.csv", "2007-08.csv", "2008-09.csv", "2009-10.csv", "2010-11.csv", "2011-12.csv", "2012-13.csv", "2013-14.csv", "2014-15.csv", "2015-16.csv", "2016-17.csv", "2017-18.csv", "2018-19.csv"]1.2 時(shí)間列表
獲取每一年的數(shù)據(jù)后,將每一年的年份放入到 time_list 列表中:
time_list = [filecsv_list[i][0:4] for i in range(len(filecsv_list))] time_list
["2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017","2018"]
1.3 用 Pandas.read_csv() ?接口讀取數(shù)據(jù)讀取時(shí)將數(shù)據(jù)與 res_name 中的元素名一一對(duì)應(yīng)。
for i in range(len(res_name)): res_name[i] = pd.read_csv(loc+filecsv_list[i],error_bad_lines=False) print("第%2s個(gè)文件是%s,數(shù)據(jù)大小為%s"%(i+1,filecsv_list[i],res_name[i].shape))
第 1個(gè)文件是2000-01.csv,數(shù)據(jù)大小為(380, 45) 第 2個(gè)文件是2001-02.csv,數(shù)據(jù)大小為(380, 48) 第 3個(gè)文件是2002-03.csv,數(shù)據(jù)大小為(316, 48) 第 4個(gè)文件是2003-04.csv,數(shù)據(jù)大小為(335, 57) 第 5個(gè)文件是2004-05.csv,數(shù)據(jù)大小為(335, 57) 第 6個(gè)文件是2005-06.csv,數(shù)據(jù)大小為(380, 68) 第 7個(gè)文件是2006-07.csv,數(shù)據(jù)大小為(380, 68) 第 8個(gè)文件是2007-08.csv,數(shù)據(jù)大小為(380, 71) 第 9個(gè)文件是2008-09.csv,數(shù)據(jù)大小為(380, 71) 第10個(gè)文件是2009-10.csv,數(shù)據(jù)大小為(380, 71) 第11個(gè)文件是2010-11.csv,數(shù)據(jù)大小為(380, 71) 第12個(gè)文件是2011-12.csv,數(shù)據(jù)大小為(380, 71) 第13個(gè)文件是2012-13.csv,數(shù)據(jù)大小為(380, 74) 第14個(gè)文件是2013-14.csv,數(shù)據(jù)大小為(380, 68) 第15個(gè)文件是2014-15.csv,數(shù)據(jù)大小為(381, 68) 第16個(gè)文件是2015-16.csv,數(shù)據(jù)大小為(380, 65) 第17個(gè)文件是2016-17.csv,數(shù)據(jù)大小為(380, 65) 第18個(gè)文件是2017-18.csv,數(shù)據(jù)大小為(380, 65) 第19個(gè)文件是2018-19.csv,數(shù)據(jù)大小為(304, 62)1.4 刪除特定文件的空值
經(jīng)過(guò)查看第 15 個(gè)文件讀取的第 381 行為空值,故采取刪除行空值操作。
Pandas.dropna(axis=0,how="any")
axis: 0 表示是行;1表示是列
how:"all"表示只去掉所有值均缺失的行、列;any表示只去掉有缺失值的行、列
res_name[14] = res_name[14].dropna(axis=0,how="all") res_name[14].tail()
Div | Date | HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTHG | HTAG | HTR | ... | BbAv<2.5 | BbAH | BbAHh | BbMxAHH | BbAvAHH | BbMxAHA | BbAvAHA | PSCH | PSCD | PSCA | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
375 | E0 | 24/05/15 | Hull | Man United | 0.0 | 0.0 | D | 0.0 | 0.0 | D | ... | 1.99 | 25.0 | 0.50 | 1.76 | 1.71 | 2.27 | 2.19 | 3.20 | 3.76 | 2.27 |
376 | E0 | 24/05/15 | Leicester | QPR | 5.0 | 1.0 | H | 2.0 | 0.0 | H | ... | 2.41 | 28.0 | -1.00 | 1.98 | 1.93 | 1.98 | 1.93 | 1.53 | 4.94 | 6.13 |
377 | E0 | 24/05/15 | Man City | Southampton | 2.0 | 0.0 | H | 1.0 | 0.0 | H | ... | 2.66 | 28.0 | -1.00 | 2.00 | 1.94 | 2.03 | 1.93 | 1.60 | 4.35 | 6.00 |
378 | E0 | 24/05/15 | Newcastle | West Ham | 2.0 | 0.0 | H | 0.0 | 0.0 | D | ... | 2.25 | 25.0 | -0.50 | 1.82 | 1.78 | 2.20 | 2.10 | 1.76 | 4.01 | 4.98 |
379 | E0 | 24/05/15 | Stoke | Liverpool | 6.0 | 1.0 | H | 5.0 | 0.0 | H | ... | 1.99 | 25.0 | 0.25 | 2.07 | 2.02 | 1.88 | 1.85 | 3.56 | 3.60 | 2.17 |
5 rows × 68 columns
1.5 刪除行數(shù)不是 380 的文件名考慮到英超一般是 19 個(gè)球隊(duì),每個(gè)球隊(duì)需要打 20 場(chǎng)球,故把行數(shù)不是 380 的數(shù)據(jù)刪除掉,并找到器原 CSV 文件一一對(duì)應(yīng)。
for i in range(len(res_name),0,-1): # 采用從大到小的遍歷方式,然后進(jìn)行刪除不滿足條件的。 if res_name[i-1].shape[0] != 380: key = "res_name[" + str(i) + "]" print("刪除的數(shù)據(jù)是:%s年的數(shù)據(jù),文件名:%s大小是:%s"%(time_list[i-1],key,res_name[i-1].shape)) res_name.pop(i-1) time_list.pop(i-1) continue
刪除的數(shù)據(jù)是:2018年的數(shù)據(jù),文件名:res_name[19]大小是:(304, 62) 刪除的數(shù)據(jù)是:2004年的數(shù)據(jù),文件名:res_name[5]大小是:(335, 57) 刪除的數(shù)據(jù)是:2003年的數(shù)據(jù),文件名:res_name[4]大小是:(335, 57) 刪除的數(shù)據(jù)是:2002年的數(shù)據(jù),文件名:res_name[3]大小是:(316, 48)1.6 查看某一個(gè)數(shù)據(jù)集前n行數(shù)據(jù)
文件名.head(n)
n:默認(rèn)是5,想獲取多少行數(shù)據(jù)就填寫(xiě)數(shù)字值。
讀取數(shù)據(jù)前五行操作:
res_name[0].head()
Div | Date | HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTHG | HTAG | HTR | ... | IWA | LBH | LBD | LBA | SBH | SBD | SBA | WHH | WHD | WHA | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | E0 | 19/08/00 | Charlton | Man City | 4 | 0 | H | 2 | 0 | H | ... | 2.7 | 2.20 | 3.25 | 2.75 | 2.20 | 3.25 | 2.88 | 2.10 | 3.2 | 3.10 |
1 | E0 | 19/08/00 | Chelsea | West Ham | 4 | 2 | H | 1 | 0 | H | ... | 4.2 | 1.50 | 3.40 | 6.00 | 1.50 | 3.60 | 6.00 | 1.44 | 3.6 | 6.50 |
2 | E0 | 19/08/00 | Coventry | Middlesbrough | 1 | 3 | A | 1 | 1 | D | ... | 2.7 | 2.25 | 3.20 | 2.75 | 2.30 | 3.20 | 2.75 | 2.30 | 3.2 | 2.62 |
3 | E0 | 19/08/00 | Derby | Southampton | 2 | 2 | D | 1 | 2 | A | ... | 3.5 | 2.20 | 3.25 | 2.75 | 2.05 | 3.20 | 3.20 | 2.00 | 3.2 | 3.20 |
4 | E0 | 19/08/00 | Leeds | Everton | 2 | 0 | H | 2 | 0 | H | ... | 4.5 | 1.55 | 3.50 | 5.00 | 1.57 | 3.60 | 5.00 | 1.61 | 3.5 | 4.50 |
5 rows × 45 columns
讀取數(shù)據(jù)前10行:
res_name[0].head(10)
Div | Date | HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTHG | HTAG | HTR | ... | IWA | LBH | LBD | LBA | SBH | SBD | SBA | WHH | WHD | WHA | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | E0 | 19/08/00 | Charlton | Man City | 4 | 0 | H | 2 | 0 | H | ... | 2.7 | 2.20 | 3.25 | 2.75 | 2.20 | 3.25 | 2.88 | 2.10 | 3.20 | 3.10 |
1 | E0 | 19/08/00 | Chelsea | West Ham | 4 | 2 | H | 1 | 0 | H | ... | 4.2 | 1.50 | 3.40 | 6.00 | 1.50 | 3.60 | 6.00 | 1.44 | 3.60 | 6.50 |
2 | E0 | 19/08/00 | Coventry | Middlesbrough | 1 | 3 | A | 1 | 1 | D | ... | 2.7 | 2.25 | 3.20 | 2.75 | 2.30 | 3.20 | 2.75 | 2.30 | 3.20 | 2.62 |
3 | E0 | 19/08/00 | Derby | Southampton | 2 | 2 | D | 1 | 2 | A | ... | 3.5 | 2.20 | 3.25 | 2.75 | 2.05 | 3.20 | 3.20 | 2.00 | 3.20 | 3.20 |
4 | E0 | 19/08/00 | Leeds | Everton | 2 | 0 | H | 2 | 0 | H | ... | 4.5 | 1.55 | 3.50 | 5.00 | 1.57 | 3.60 | 5.00 | 1.61 | 3.50 | 4.50 |
5 | E0 | 19/08/00 | Leicester | Aston Villa | 0 | 0 | D | 0 | 0 | D | ... | 2.5 | 2.35 | 3.20 | 2.60 | 2.25 | 3.25 | 2.75 | 2.40 | 3.25 | 2.50 |
6 | E0 | 19/08/00 | Liverpool | Bradford | 1 | 0 | H | 0 | 0 | D | ... | 8.0 | 1.35 | 4.00 | 8.00 | 1.36 | 4.00 | 8.00 | 1.33 | 4.00 | 8.00 |
7 | E0 | 19/08/00 | Sunderland | Arsenal | 1 | 0 | H | 0 | 0 | D | ... | 2.1 | 4.30 | 3.20 | 1.70 | 3.30 | 3.10 | 2.05 | 3.75 | 3.00 | 1.90 |
8 | E0 | 19/08/00 | Tottenham | Ipswich | 3 | 1 | H | 2 | 1 | H | ... | 4.7 | 1.45 | 3.60 | 6.50 | 1.50 | 3.50 | 6.50 | 1.44 | 3.60 | 6.50 |
9 | E0 | 20/08/00 | Man United | Newcastle | 2 | 0 | H | 1 | 0 | H | ... | 5.0 | 1.40 | 3.75 | 7.00 | 1.40 | 3.75 | 7.50 | 1.40 | 3.75 | 7.00 |
10 rows × 45 columns
讀取最后 5 行操作:
res_name[0].tail()
Div | Date | HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTHG | HTAG | HTR | ... | IWA | LBH | LBD | LBA | SBH | SBD | SBA | WHH | WHD | WHA | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
375 | E0 | 19/05/01 | Man City | Chelsea | 1 | 2 | A | 1 | 1 | D | ... | 1.65 | 4.0 | 3.60 | 1.67 | 4.20 | 3.40 | 1.70 | 4.00 | 3.1 | 1.80 |
376 | E0 | 19/05/01 | Middlesbrough | West Ham | 2 | 1 | H | 2 | 1 | H | ... | 3.20 | 1.8 | 3.25 | 3.75 | 1.90 | 3.20 | 3.50 | 1.83 | 3.4 | 3.50 |
377 | E0 | 19/05/01 | Newcastle | Aston Villa | 3 | 0 | H | 2 | 0 | H | ... | 2.90 | 2.4 | 3.25 | 2.50 | 2.38 | 3.30 | 2.50 | 2.25 | 3.4 | 2.60 |
378 | E0 | 19/05/01 | Southampton | Arsenal | 3 | 2 | H | 0 | 1 | A | ... | 2.35 | 2.5 | 3.25 | 2.37 | 2.63 | 3.25 | 2.30 | 2.62 | 3.5 | 2.20 |
379 | E0 | 19/05/01 | Tottenham | Man United | 3 | 1 | H | 1 | 1 | D | ... | 2.10 | 2.6 | 3.20 | 2.37 | 2.60 | 3.25 | 2.35 | 2.62 | 3.3 | 2.25 |
5 rows × 45 columns
讀取最后 4 行操作:
res_name[0].tail(4)
Div | Date | HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTHG | HTAG | HTR | ... | IWA | LBH | LBD | LBA | SBH | SBD | SBA | WHH | WHD | WHA | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
376 | E0 | 19/05/01 | Middlesbrough | West Ham | 2 | 1 | H | 2 | 1 | H | ... | 3.20 | 1.8 | 3.25 | 3.75 | 1.90 | 3.20 | 3.50 | 1.83 | 3.4 | 3.50 |
377 | E0 | 19/05/01 | Newcastle | Aston Villa | 3 | 0 | H | 2 | 0 | H | ... | 2.90 | 2.4 | 3.25 | 2.50 | 2.38 | 3.30 | 2.50 | 2.25 | 3.4 | 2.60 |
378 | E0 | 19/05/01 | Southampton | Arsenal | 3 | 2 | H | 0 | 1 | A | ... | 2.35 | 2.5 | 3.25 | 2.37 | 2.63 | 3.25 | 2.30 | 2.62 | 3.5 | 2.20 |
379 | E0 | 19/05/01 | Tottenham | Man United | 3 | 1 | H | 1 | 1 | D | ... | 2.10 | 2.6 | 3.20 | 2.37 | 2.60 | 3.25 | 2.35 | 2.62 | 3.3 | 2.25 |
4 rows × 45 columns
1.8 獲取某一年主場(chǎng)隊(duì)伍的名稱res_name[0]["HomeTeam"].unique()
array(["Charlton", "Chelsea", "Coventry", "Derby", "Leeds", "Leicester", "Liverpool", "Sunderland", "Tottenham", "Man United", "Arsenal", "Bradford", "Ipswich", "Middlesbrough", "Everton", "Man City", "Newcastle", "Southampton", "West Ham", "Aston Villa"], dtype=object)1.9 解析數(shù)據(jù)集列表頭含義
數(shù)據(jù)集行數(shù)已經(jīng)固定,一般都是 380 行,而列數(shù)可能每年統(tǒng)計(jì)指標(biāo)有變化,不一定相等,而且我們也比較關(guān)心列數(shù)表表頭。由于比較小,可以直接看數(shù)據(jù)集列數(shù),這樣比較快,也可以代碼實(shí)現(xiàn),找到最大的列數(shù),然后獲取列數(shù)的表頭進(jìn)行一般性介紹解釋。
# 獲取列表頭最大的列數(shù),然后獲取器參數(shù) shape_list = [res_name[i].shape[1] for i in range(len(res_name))] for i in range(len(res_name)): if res_name[i].shape[1] == max(shape_list): print("%s年數(shù)據(jù)是有最大列數(shù):%s,列元素表頭: %s"%(time_list[i],max(shape_list),res_name[i].columns))
2012年數(shù)據(jù)是有最大列數(shù):74,列元素表頭: Index(["Div", "Date", "HomeTeam", "AwayTeam", "FTHG", "FTAG", "FTR", "HTHG", "HTAG", "HTR", "Referee", "HS", "AS", "HST", "AST", "HF", "AF", "HC", "AC", "HY", "AY", "HR", "AR", "B365H", "B365D", "B365A", "BWH", "BWD", "BWA", "GBH", "GBD", "GBA", "IWH", "IWD", "IWA", "LBH", "LBD", "LBA", "PSH", "PSD", "PSA", "WHH", "WHD", "WHA", "SJH", "SJD", "SJA", "VCH", "VCD", "VCA", "BSH", "BSD", "BSA", "Bb1X2", "BbMxH", "BbAvH", "BbMxD", "BbAvD", "BbMxA", "BbAvA", "BbOU", "BbMx>2.5", "BbAv>2.5", "BbMx<2.5", "BbAv<2.5", "BbAH", "BbAHh", "BbMxAHH", "BbAvAHH", "BbMxAHA", "BbAvAHA", "PSCH", "PSCD", "PSCA"], dtype="object")
我們看到數(shù)據(jù)包括 Date(比賽的時(shí)間),Hometeam(主場(chǎng)隊(duì)伍名),Awayteam(客場(chǎng)隊(duì)伍名),F(xiàn)THG(主場(chǎng)球隊(duì)全場(chǎng)進(jìn)球數(shù)),HTHG(主場(chǎng)球隊(duì)半場(chǎng)進(jìn)球數(shù)),F(xiàn)TR(全場(chǎng)比賽結(jié)果)等等,更多關(guān)于數(shù)據(jù)集中特征信息可以參考數(shù)據(jù)集特征說(shuō)明文檔 。
2. 數(shù)據(jù)清洗和預(yù)處理我們挑選 Hometeam,Awayteam,F(xiàn)THG,F(xiàn)TAG,F(xiàn)TR 這五列數(shù)據(jù),作為我們的原始的特征數(shù)據(jù),后面基于這些原始特征,我們?cè)贅?gòu)造一些新的特征。
2.1 ?挑選信息列HomeTeam: 主場(chǎng)球隊(duì)名
AwayTeam: 客場(chǎng)球隊(duì)名
FTHG: 全場(chǎng) 主場(chǎng)球隊(duì)進(jìn)球數(shù)
FTAG: ?全場(chǎng) 客場(chǎng)球隊(duì)進(jìn)球數(shù)
FTR: ?比賽結(jié)果 ( H= 主場(chǎng)贏, D= 平局, A= 客場(chǎng)贏)
# 將挑選的信息放在一個(gè)新的列表中 columns_req = ["HomeTeam","AwayTeam","FTHG","FTAG","FTR"] playing_statistics = [] # 創(chuàng)造處理后數(shù)據(jù)名存放處 playing_data = {} # 鍵值對(duì)存儲(chǔ)數(shù)據(jù) for i in range(len(res_name)): playing_statistics.append("playing_statistics_"+str(i+1)) playing_statistics[i] = res_name[i][columns_req] print(time_list[i],"playing_statistics["+str(i)+"]",playing_statistics[i].shape)
2000 playing_statistics[0] (380, 5) 2001 playing_statistics[1] (380, 5) 2005 playing_statistics[2] (380, 5) 2006 playing_statistics[3] (380, 5) 2007 playing_statistics[4] (380, 5) 2008 playing_statistics[5] (380, 5) 2009 playing_statistics[6] (380, 5) 2010 playing_statistics[7] (380, 5) 2011 playing_statistics[8] (380, 5) 2012 playing_statistics[9] (380, 5) 2013 playing_statistics[10] (380, 5) 2014 playing_statistics[11] (380, 5) 2015 playing_statistics[12] (380, 5) 2016 playing_statistics[13] (380, 5) 2017 playing_statistics[14] (380, 5)2.2 分析原始數(shù)據(jù)
我們首先預(yù)測(cè)所有主場(chǎng)球隊(duì)全都勝利,然后預(yù)測(cè)所有的客場(chǎng)都會(huì)勝利,對(duì)結(jié)果進(jìn)行對(duì)比分析:
def predictions_0(data): """ 當(dāng)我們統(tǒng)計(jì)所有主場(chǎng)球隊(duì)都贏,那么我們預(yù)測(cè)的結(jié)果是什么 返回值是預(yù)測(cè)值和實(shí)際值 """ predictions = [] for _, game in data.iterrows(): if game["FTR"]=="H": predictions.append(1) else: predictions.append(0) # 返回預(yù)測(cè)結(jié)果 return pd.Series(predictions) # 那我們對(duì)19年全部主場(chǎng)球隊(duì)都贏的結(jié)果進(jìn)行預(yù)測(cè),獲取預(yù)測(cè)的準(zhǔn)確率。 avg_acc_sum = 0 for i in range(len(playing_statistics)): predictions = predictions_0(playing_statistics[i]) acc=sum(predictions)/len(playing_statistics[i]) avg_acc_sum += acc print("%s年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是%s"%(time_list[i],acc)) print("共%s年的平均準(zhǔn)確率是:%s"%(len(playing_statistics),avg_acc_sum/len(playing_statistics)))
2000年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4842105263157895 2001年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4342105263157895 2005年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.5052631578947369 2006年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4789473684210526 2007年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4631578947368421 2008年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.45526315789473687 2009年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.5078947368421053 2010年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4710526315789474 2011年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.45 2012年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4368421052631579 2013年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4710526315789474 2014年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.45263157894736844 2015年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4131578947368421 2016年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.4921052631578947 2017年數(shù)據(jù)主場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.45526315789473687 共15年的平均準(zhǔn)確率是:0.46473684210526317
def predictions_1(data): """ 當(dāng)我們統(tǒng)計(jì)所有客場(chǎng)球隊(duì)都贏,那么我們預(yù)測(cè)的結(jié)果是什么 返回值是預(yù)測(cè)值和實(shí)際值 """ predictions = [] for _, game in data.iterrows(): if game["FTR"]=="A": predictions.append(1) else: predictions.append(0) # 返回預(yù)測(cè)結(jié)果 return pd.Series(predictions) # 那我們對(duì)19年客場(chǎng)球隊(duì)都贏的結(jié)果進(jìn)行預(yù)測(cè),獲取預(yù)測(cè)的準(zhǔn)確率。 for i in range(len(playing_statistics)): predictions = predictions_1(playing_statistics[i]) acc=sum(predictions)/len(playing_statistics[i]) print("%s年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是%s"%(time_list[i],acc))
2000年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.25 2001年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.3 2005年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.29210526315789476 2006年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.2631578947368421 2007年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.2736842105263158 2008年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.2894736842105263 2009年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.2394736842105263 2010年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.23684210526315788 2011年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.30526315789473685 2012年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.2789473684210526 2013年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.3236842105263158 2014年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.3026315789473684 2015年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.30526315789473685 2016年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.2868421052631579 2017年數(shù)據(jù)客場(chǎng)全勝預(yù)測(cè)的準(zhǔn)確率是0.28421052631578947
綜上比較:我們可以看出主場(chǎng)勝利的概率相對(duì)于輸和平局來(lái)說(shuō),確實(shí)概率要大。
2.3 我們想知道 Arsenal 作為主場(chǎng)隊(duì)伍時(shí),他們的表現(xiàn),如何求出 2005-06 所有比賽累計(jì)進(jìn)球數(shù) ?我們知道 2005-06 年數(shù)據(jù)在 playing_statistics[2] 中:
def score(data): """ Arsenal作為主場(chǎng)隊(duì)伍時(shí),累計(jì)進(jìn)球數(shù) """ scores=[] for _,game in data.iterrows(): if game["HomeTeam"]=="Arsenal": scores.append(game["FTHG"]) return np.sum(scores) Arsenal_score=score(playing_statistics[2]) print("Arsenal作為主場(chǎng)隊(duì)伍在2005年時(shí),累計(jì)進(jìn)球數(shù):%s"%(Arsenal_score))
Arsenal 作為主場(chǎng)隊(duì)伍在2005年時(shí),累計(jì)進(jìn)球數(shù):482.4 我們想知道各個(gè)球隊(duì)作為主場(chǎng)隊(duì)伍時(shí),他們的表現(xiàn)如何 ?
先試試求 2005-06 所有比賽各個(gè)球隊(duì)累計(jì)進(jìn)球數(shù)。
print(playing_statistics[5].groupby("HomeTeam").sum()["FTHG"])
HomeTeam Arsenal 31 Aston Villa 27 Blackburn 22 Bolton 21 Chelsea 33 Everton 31 Fulham 28 Hull 18 Liverpool 41 Man City 40 Man United 43 Middlesbrough 17 Newcastle 24 Portsmouth 26 Stoke 22 Sunderland 21 Tottenham 21 West Brom 26 West Ham 23 Wigan 17 Name: FTHG, dtype: int643. 特征工程
特征工程指的是把原始數(shù)據(jù)轉(zhuǎn)變?yōu)槟P偷挠?xùn)練數(shù)據(jù)的過(guò)程,它的目的就是獲取更好的訓(xùn)練數(shù)據(jù)特征,得到更好的訓(xùn)練模型。特征工程能使得模型的性能得到提升,有時(shí)甚至在簡(jiǎn)單的模型上也能取得不錯(cuò)的效果。特征工程在機(jī)器學(xué)習(xí)中占有非常重要的作用,一般認(rèn)為括特征構(gòu)建、特征提取、特征選擇三大部分。
3.1 構(gòu)造特征因?yàn)檫@個(gè)比賽是一年一個(gè)賽季,是有先后順序的,那我們就可以統(tǒng)計(jì)到截止到本場(chǎng)比賽之前,整個(gè)賽季內(nèi),主客場(chǎng)隊(duì)伍的凈勝球的數(shù)量。那么對(duì)于每一個(gè)賽季的每一周,都統(tǒng)計(jì)出每個(gè)球隊(duì)到本周為止累計(jì)的進(jìn)球數(shù)和丟球數(shù)之差,也就是凈勝球的數(shù)量。
處理后的數(shù)據(jù),我們可以通過(guò)看某一年的某幾條數(shù)據(jù)來(lái)體現(xiàn),比如:05-06 年的后五條數(shù)據(jù)
def get_goals_diff(playing_stat): # 創(chuàng)建一個(gè)字典,每個(gè) team 的 name 作為 key teams = {} for i in playing_stat.groupby("HomeTeam").mean().T.columns: teams[i] = [] # 對(duì)于每一場(chǎng)比賽 for i in range(len(playing_stat)): # 全場(chǎng)比賽,主場(chǎng)隊(duì)伍的進(jìn)球數(shù) HTGS = playing_stat.iloc[i]["FTHG"] # 全場(chǎng)比賽,客場(chǎng)隊(duì)伍的進(jìn)球數(shù) ATGS = playing_stat.iloc[i]["FTAG"] # 把主場(chǎng)隊(duì)伍的凈勝球數(shù)添加到 team 這個(gè) 字典中對(duì)應(yīng)的主場(chǎng)隊(duì)伍下 teams[playing_stat.iloc[i].HomeTeam].append(HTGS-ATGS) # 把客場(chǎng)隊(duì)伍的凈勝球數(shù)添加到 team 這個(gè) 字典中對(duì)應(yīng)的客場(chǎng)隊(duì)伍下 teams[playing_stat.iloc[i].AwayTeam].append(ATGS-HTGS) # 創(chuàng)建一個(gè) GoalsDifference 的 dataframe # 行是 team 列是 matchweek, # 39解釋:19個(gè)球隊(duì),每個(gè)球隊(duì)分主場(chǎng)客場(chǎng)2次,共38個(gè)賽次,但是range取不到最后一個(gè)值,故38+1=39 GoalsDifference = pd.DataFrame(data=teams, index = [i for i in range(1,39)]).T GoalsDifference[0] = 0 # 累加每個(gè)隊(duì)的周比賽的凈勝球數(shù) for i in range(2,39): GoalsDifference[i] = GoalsDifference[i] + GoalsDifference[i-1] return GoalsDifference def get_gss(playing_stat): # 得到凈勝球數(shù)統(tǒng)計(jì) GD = get_goals_diff(playing_stat) j = 0 # 主客場(chǎng)的凈勝球數(shù) HTGD = [] ATGD = [] # 全年一共380場(chǎng)比賽 for i in range(380): ht = playing_stat.iloc[i].HomeTeam at = playing_stat.iloc[i].AwayTeam HTGD.append(GD.loc[ht][j]) ATGD.append(GD.loc[at][j]) if ((i + 1)% 10) == 0: j = j + 1 # 把每個(gè)隊(duì)的 HTGD ATGD 信息補(bǔ)充到 dataframe 中 playing_stat.loc[:,"HTGD"] = HTGD playing_stat.loc[:,"ATGD"] = ATGD return playing_stat for i in range(len(playing_statistics)): playing_statistics[i] = get_gss(playing_statistics[i]) #### 查看構(gòu)造特征后的05-06年的后五條數(shù)據(jù) playing_statistics[2].tail()
HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTGD | ATGD | |
---|---|---|---|---|---|---|---|
375 | Fulham | Middlesbrough | 1 | 0 | H | -11 | -9 |
376 | Man United | Charlton | 4 | 0 | H | 34 | -10 |
377 | Newcastle | Chelsea | 1 | 0 | H | 4 | 51 |
378 | Portsmouth | Liverpool | 1 | 3 | A | -23 | 30 |
379 | West Ham | Tottenham | 2 | 1 | H | -4 | 16 |
通過(guò)以上數(shù)據(jù):我們發(fā)現(xiàn) 376 行數(shù)據(jù)的特點(diǎn), 截止到這一場(chǎng)比賽之前,本賽季主場(chǎng)曼聯(lián)隊(duì)的凈勝球數(shù)是 34 , 客場(chǎng)查爾頓隊(duì)的凈勝球數(shù)是 -10 。
統(tǒng)計(jì)整個(gè)賽季主客場(chǎng)隊(duì)伍截止到當(dāng)前比賽周的累計(jì)得分。一場(chǎng)比賽勝利計(jì) 3 分, 平局計(jì) 1 分,輸了計(jì) 0 分。我們根據(jù)本賽季本周之前的比賽結(jié)果來(lái)統(tǒng)計(jì)這個(gè)值。我們繼續(xù)觀看 ?05-06 年的后五條數(shù)據(jù):
# 把比賽結(jié)果轉(zhuǎn)換為得分,贏得三分,平局得一分,輸不得分 def get_points(result): if result == "W": return 3 elif result == "D": return 1 else: return 0 def get_cuml_points(matchres): matchres_points = matchres.applymap(get_points) for i in range(2,39): matchres_points[i] = matchres_points[i] + matchres_points[i-1] matchres_points.insert(column =0, loc = 0, value = [0*i for i in range(20)]) return matchres_points def get_matchres(playing_stat): # 創(chuàng)建一個(gè)字典,每個(gè) team 的 name 作為 key teams = {} for i in playing_stat.groupby("HomeTeam").mean().T.columns: teams[i] = [] # 把比賽結(jié)果分別記錄在主場(chǎng)隊(duì)伍和客場(chǎng)隊(duì)伍中 # H:代表 主場(chǎng) 贏 # A:代表 客場(chǎng) 贏 # D:代表 平局 for i in range(len(playing_stat)): if playing_stat.iloc[i].FTR == "H": # 主場(chǎng) 贏,則主場(chǎng)記為贏,客場(chǎng)記為輸 teams[playing_stat.iloc[i].HomeTeam].append("W") teams[playing_stat.iloc[i].AwayTeam].append("L") elif playing_stat.iloc[i].FTR == "A": # 客場(chǎng) 贏,則主場(chǎng)記為輸,客場(chǎng)記為贏 teams[playing_stat.iloc[i].AwayTeam].append("W") teams[playing_stat.iloc[i].HomeTeam].append("L") else: # 平局 teams[playing_stat.iloc[i].AwayTeam].append("D") teams[playing_stat.iloc[i].HomeTeam].append("D") return pd.DataFrame(data=teams, index = [i for i in range(1,39)]).T def get_agg_points(playing_stat): matchres = get_matchres(playing_stat) cum_pts = get_cuml_points(matchres) HTP = [] ATP = [] j = 0 for i in range(380): ht = playing_stat.iloc[i].HomeTeam at = playing_stat.iloc[i].AwayTeam HTP.append(cum_pts.loc[ht][j]) ATP.append(cum_pts.loc[at][j]) if ((i + 1)% 10) == 0: j = j + 1 # 主場(chǎng)累計(jì)得分 playing_stat.loc[:,"HTP"] = HTP # 客場(chǎng)累計(jì)得分 playing_stat.loc[:,"ATP"] = ATP return playing_stat for i in range(len(playing_statistics)): playing_statistics[i] = get_agg_points(playing_statistics[i]) #查看構(gòu)造特征后的05-06年的后五條數(shù)據(jù) playing_statistics[2].tail()
HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTGD | ATGD | HTP | ATP | |
---|---|---|---|---|---|---|---|---|---|
375 | Fulham | Middlesbrough | 1 | 0 | H | -11 | -9 | 45 | 45 |
376 | Man United | Charlton | 4 | 0 | H | 34 | -10 | 80 | 47 |
377 | Newcastle | Chelsea | 1 | 0 | H | 4 | 51 | 55 | 91 |
378 | Portsmouth | Liverpool | 1 | 3 | A | -23 | 30 | 38 | 79 |
379 | West Ham | Tottenham | 2 | 1 | H | -4 | 16 | 52 | 65 |
我們處理得到 HTP (本賽季主場(chǎng)球隊(duì)截止到本周的累計(jì)得分), ATP (本賽季客場(chǎng)球隊(duì)截止到本周的累計(jì)得分)。
我們?cè)倏?376 行,截止到這一場(chǎng)比賽,本賽季,曼聯(lián)隊(duì)一共積了80分, 查爾頓隊(duì)積了 47 分。
前面我們構(gòu)造的特征反映了一只隊(duì)伍本賽季的歷史總表現(xiàn),我們看看隊(duì)伍在最近三場(chǎng)比賽的表現(xiàn)。
我們用:
HM1 代表主場(chǎng)球隊(duì)上一次比賽的輸贏,
AM1 代表客場(chǎng)球隊(duì)上一次比賽是輸贏。
同理,HM2 AM2 就是上上次比賽的輸贏, HM3 AM3 就是上上上次比賽的輸贏。
我們繼續(xù)觀看處理后 05-06 年的后 5 五條數(shù)據(jù):
def get_form(playing_stat,num): form = get_matchres(playing_stat) form_final = form.copy() for i in range(num,39): form_final[i] = "" j = 0 while j < num: form_final[i] += form[i-j] j += 1 return form_final def add_form(playing_stat,num): form = get_form(playing_stat,num) # M 代表 unknown, 因?yàn)闆](méi)有那么多歷史 h = ["M" for i in range(num * 10)] a = ["M" for i in range(num * 10)] j = num for i in range((num*10),380): ht = playing_stat.iloc[i].HomeTeam at = playing_stat.iloc[i].AwayTeam past = form.loc[ht][j] h.append(past[num-1]) past = form.loc[at][j] a.append(past[num-1]) if ((i + 1)% 10) == 0: j = j + 1 playing_stat["HM" + str(num)] = h playing_stat["AM" + str(num)] = a return playing_stat def add_form_df(playing_statistics): playing_statistics = add_form(playing_statistics,1) playing_statistics = add_form(playing_statistics,2) playing_statistics = add_form(playing_statistics,3) return playing_statistics for i in range(len(playing_statistics)): playing_statistics[i] = add_form_df(playing_statistics[i]) #查看構(gòu)造特征后的05-06年的后5五條數(shù)據(jù) playing_statistics[2].tail()
HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTGD | ATGD | HTP | ATP | HM1 | AM1 | HM2 | AM2 | HM3 | AM3 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
375 | Fulham | Middlesbrough | 1 | 0 | H | -11 | -9 | 45 | 45 | L | D | W | D | W | L |
376 | Man United | Charlton | 4 | 0 | H | 34 | -10 | 80 | 47 | D | L | L | L | W | W |
377 | Newcastle | Chelsea | 1 | 0 | H | 4 | 51 | 55 | 91 | D | L | W | W | W | W |
378 | Portsmouth | Liverpool | 1 | 3 | A | -23 | 30 | 38 | 79 | W | W | W | W | L | W |
379 | West Ham | Tottenham | 2 | 1 | H | -4 | 16 | 52 | 65 | W | W | L | D | L | L |
然后我們把比賽周的信息也放在里面,也就是這一場(chǎng)比賽發(fā)生在第幾個(gè)比賽周。
特征構(gòu)造后的結(jié)果,我們可以直接查看 05-06 年的后 5 條數(shù)據(jù):
def get_mw(playing_stat): j = 1 MatchWeek = [] for i in range(380): MatchWeek.append(j) if ((i + 1)% 10) == 0: j = j + 1 playing_stat["MW"] = MatchWeek return playing_stat for i in range(len(playing_statistics)): playing_statistics[i] = get_mw(playing_statistics[i]) #查看構(gòu)造特征后的05-06年的后五條數(shù)據(jù) playing_statistics[2].tail()
HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTGD | ATGD | HTP | ATP | HM1 | AM1 | HM2 | AM2 | HM3 | AM3 | MW | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
375 | Fulham | Middlesbrough | 1 | 0 | H | -11 | -9 | 45 | 45 | L | D | W | D | W | L | 38 |
376 | Man United | Charlton | 4 | 0 | H | 34 | -10 | 80 | 47 | D | L | L | L | W | W | 38 |
377 | Newcastle | Chelsea | 1 | 0 | H | 4 | 51 | 55 | 91 | D | L | W | W | W | W | 38 |
378 | Portsmouth | Liverpool | 1 | 3 | A | -23 | 30 | 38 | 79 | W | W | W | W | L | W | 38 |
379 | West Ham | Tottenham | 2 | 1 | H | -4 | 16 | 52 | 65 | W | W | L | D | L | L | 38 |
我們打算把數(shù)據(jù)集比賽的信息都合并到一個(gè)表里面,然后我們把我們剛才計(jì)算得到的這些得分?jǐn)?shù)據(jù),凈勝球數(shù)據(jù)除以周數(shù),就得到了周平均后的值。結(jié)果就可以通過(guò)查看構(gòu)造特征后數(shù)據(jù)集的后 5 條數(shù)據(jù)。
# 將各個(gè)DataFrame表合并在一張表中 playing_stat = pd.concat(playing_statistics, ignore_index=True) # HTGD, ATGD ,HTP, ATP的值 除以 week 數(shù),得到平均分 cols = ["HTGD","ATGD","HTP","ATP"] playing_stat.MW = playing_stat.MW.astype(float) for col in cols: playing_stat[col] = playing_stat[col] / playing_stat.MW #查看構(gòu)造特征后數(shù)據(jù)集的后5五條數(shù)據(jù) playing_stat.tail()
HomeTeam | AwayTeam | FTHG | FTAG | FTR | HTGD | ATGD | HTP | ATP | HM1 | AM1 | HM2 | AM2 | HM3 | AM3 | MW | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
5695 | Newcastle | Chelsea | 3.0 | 0.0 | H | -0.289474 | 0.710526 | 1.078947 | 1.842105 | L | D | L | W | L | W | 38.0 |
5696 | Southampton | Man City | 0.0 | 1.0 | A | -0.473684 | 2.052632 | 0.947368 | 2.552632 | W | W | D | D | W | W | 38.0 |
5697 | Swansea | Stoke | 1.0 | 2.0 | A | -0.710526 | -0.894737 | 0.868421 | 0.789474 | L | L | L | D | L | D | 38.0 |
5698 | Tottenham | Leicester | 5.0 | 4.0 | H | 0.973684 | -0.078947 | 1.947368 | 1.236842 | W | W | L | L | W | L | 38.0 |
5699 | West Ham | Everton | 3.0 | 1.0 | H | -0.578947 | -0.315789 | 1.026316 | 1.289474 | D | D | W | W | L | W | 38.0 |
我們看到數(shù)據(jù)集最后一行的行數(shù)是 5699 ,加上第一行為 0 行,則一共 5700 條數(shù)據(jù);我們總共統(tǒng)計(jì)了 15 年的數(shù)據(jù),每一年有 380 條數(shù)據(jù),計(jì)算后發(fā)現(xiàn)我們統(tǒng)計(jì)后的數(shù)據(jù)集大小是準(zhǔn)確的。
3.2 刪除某些數(shù)據(jù)前面我們根據(jù)初始的特征構(gòu)造出了很多的特征。這其中有一部分是中間的特征,我們需要把這些中間特征拋棄掉。因?yàn)榍叭艿谋荣?,每個(gè)隊(duì)的歷史勝負(fù)信息不足,所以我們打算棄掉前三周的數(shù)據(jù)。
# 拋棄前三周的比賽 playing_stat = playing_stat[playing_stat.MW > 3] playing_stat.drop(["HomeTeam", "AwayTeam", "FTHG", "FTAG", "MW"],1, inplace=True) #我們查看下此時(shí)的數(shù)據(jù)的特征 playing_stat.keys()
Index(["FTR", "HTGD", "ATGD", "HTP", "ATP", "HM1", "AM1", "HM2", "AM2", "HM3","AM3"], dtype="object")3.3 分析我們構(gòu)造的數(shù)據(jù)
在前面,我們計(jì)算了每一的年主客場(chǎng)的勝率,現(xiàn)在我們看看有效數(shù)據(jù)中,是主場(chǎng)勝利的多呢,還是客場(chǎng)勝利的多呢?
# 比賽總數(shù) n_matches = playing_stat.shape[0] # 特征數(shù) n_features = playing_stat.shape[1] - 1 # 主場(chǎng)獲勝的數(shù)目 n_homewins = len(playing_stat[playing_stat.FTR == "H"]) # 主場(chǎng)獲勝的比例 win_rate = (float(n_homewins) / (n_matches)) * 100 # Print the results print("比賽總數(shù): {}".format(n_matches)) print("總特征數(shù): {}".format(n_features)) print("主場(chǎng)勝利數(shù): {}".format(n_homewins)) print("主場(chǎng)勝率: {:.2f}%".format(win_rate))
比賽總數(shù): 5250 總特征數(shù): 10 主場(chǎng)勝利數(shù): 2451 主場(chǎng)勝率: 46.69%
通過(guò)統(tǒng)計(jì)結(jié)果看到:我們主場(chǎng)勝率 46.69% 與我們第 2.2.1 小節(jié)原始數(shù)據(jù)分析的結(jié)果是一致的,說(shuō)明我們前面構(gòu)造的特征是有效的,比較貼近實(shí)際的。
3.4 解決樣本不均衡問(wèn)題通過(guò)構(gòu)造特征之后,發(fā)現(xiàn)主場(chǎng)獲勝的比例接近 50% ,所以對(duì)于這個(gè)三分類的問(wèn)題,標(biāo)簽比例是不均衡的。
我們把它簡(jiǎn)化為二分類問(wèn)題,也就是主場(chǎng)球隊(duì)會(huì)不會(huì)勝利,這也是一種解決標(biāo)簽比例不均衡的問(wèn)題的方法。
# 定義 target ,也就是否 主場(chǎng)贏 def only_hw(string): if string == "H": return "H" else: return "NH" playing_stat["FTR"] = playing_stat.FTR.apply(only_hw)3.5 將數(shù)據(jù)分為特征值和標(biāo)簽值
# 把數(shù)據(jù)分為特征值和標(biāo)簽值 X_all = playing_stat.drop(["FTR"],1) y_all = playing_stat["FTR"] # 特征值的長(zhǎng)度 len(X_all)
52503.6 數(shù)據(jù)歸一化、標(biāo)準(zhǔn)化
我們對(duì)所有比賽的特征 HTP 進(jìn)行最大最小值歸一化。
def convert_1(data): max=data.max() min=data.min() return (data-min)/(max-min) r_data=convert_1(X_all["HTGD"])
# 數(shù)據(jù)標(biāo)準(zhǔn)化 from sklearn.preprocessing import scale cols = [["HTGD","ATGD","HTP","ATP"]] for col in cols: X_all[col] = scale(X_all[col])3.7 轉(zhuǎn)換特征數(shù)據(jù)類型
# 把這些特征轉(zhuǎn)換成字符串類型 X_all.HM1 = X_all.HM1.astype("str") X_all.HM2 = X_all.HM2.astype("str") X_all.HM3 = X_all.HM3.astype("str") X_all.AM1 = X_all.AM1.astype("str") X_all.AM2 = X_all.AM2.astype("str") X_all.AM3 = X_all.AM3.astype("str") def preprocess_features(X): """把離散的類型特征轉(zhuǎn)為啞編碼特征 """ output = pd.DataFrame(index = X.index) for col, col_data in X.iteritems(): if col_data.dtype == object: col_data = pd.get_dummies(col_data, prefix = col) output = output.join(col_data) return output X_all = preprocess_features(X_all) print("Processed feature columns ({} total features): {}".format(len(X_all.columns), list(X_all.columns)))
Processed feature columns (22 total features): ["HTGD", "ATGD", "HTP", "ATP", "HM1_D", "HM1_L", "HM1_W", "AM1_D", "AM1_L", "AM1_W", "HM2_D", "HM2_L", "HM2_W", "AM2_D", "AM2_L", "AM2_W", "HM3_D", "HM3_L", "HM3_W", "AM3_D", "AM3_L", "AM3_W"]
# 預(yù)覽處理好的數(shù)據(jù) print(" Feature values:") display(X_all.head())
Feature values:
HTGD | ATGD | HTP | ATP | HM1_D | HM1_L | HM1_W | AM1_D | AM1_L | AM1_W | ... | HM2_W | AM2_D | AM2_L | AM2_W | HM3_D | HM3_L | HM3_W | AM3_D | AM3_L | AM3_W | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
30 | 0.724821 | 0.339985 | -0.043566 | -0.603098 | 1 | 0 | 0 | 1 | 0 | 0 | ... | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 |
31 | -0.702311 | -1.088217 | -1.097731 | -2.192828 | 0 | 1 | 0 | 1 | 0 | 0 | ... | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
32 | 0.011255 | 0.339985 | -0.570649 | -0.603098 | 0 | 1 | 0 | 1 | 0 | 0 | ... | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 |
33 | -0.345528 | -0.374116 | -1.097731 | -1.662918 | 0 | 1 | 0 | 1 | 0 | 0 | ... | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
34 | 0.011255 | 1.054086 | -0.570649 | 0.456723 | 1 | 0 | 0 | 0 | 0 | 1 | ... | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 |
5 rows × 22 columns
3.8 皮爾遜相關(guān)熱力圖我們生成一些特征的相關(guān)圖,以查看特征與特征之間的相關(guān)性。 為此,我們將利用 Seaborn 繪圖軟件包,使我們能夠非常方便地繪制熱力圖,如下所示:
import matplotlib.pyplot as plt import seaborn as sns # 防止中文出現(xiàn)錯(cuò)誤 plt.rcParams["font.sans-serif"]=["SimHei"] plt.rcParams["axes.unicode_minus"]=False #制成皮爾森熱圖 #把標(biāo)簽映射為0和1 y_all=y_all.map({"NH":0,"H":1}) #合并特征集和標(biāo)簽 train_data=pd.concat([X_all,y_all],axis=1) colormap = plt.cm.RdBu plt.figure(figsize=(21,18)) plt.title("Pearson Correlation of Features", y=1.05, size=15) sns.heatmap(train_data.astype(float).corr(),linewidths=0.1,vmax=1.0, square=True, cmap=colormap, linecolor="white", annot=True)
通過(guò)上圖我們可以看出特征 HTP 特征和 HTGD 特征相關(guān)性很強(qiáng),同樣 ATP 特征和 ATGD 特征相關(guān)性很強(qiáng),可以表明多重共線性的情況。這個(gè)我們也很容易理解,主場(chǎng)周平均得分?jǐn)?shù)越高,那么主場(chǎng)周平均凈勝球數(shù)也同樣越高。如果我們考慮這些變量,我們可以得出結(jié)論,它們給出了幾乎相同的信息,因此實(shí)際上發(fā)生了多重共線性,這里我們會(huì)考慮刪除 HTP 和 "ATP" 這兩個(gè)特征,保留 HTGD 和 ATGD 這兩個(gè)特征。皮爾森熱圖非常適合檢測(cè)這種情況,并且在特征工程中,它們是必不可少的工具。同時(shí),我們也可以看出上上上次球隊(duì)的比賽結(jié)果對(duì)目前比賽的結(jié)果影響較小,這里我們考慮保留這些特征。
考慮到樣本集特征 HTP 和 HTGD,ATP 和 ATGD 的相關(guān)性都超過(guò)了 90% ,故我們刪除特征 HTP , ATP :
X_all=X_all.drop(["HTP","ATP"],axis=1)
看看與FTR最相關(guān)的10個(gè)特征
#FTR correlation matrix plt.figure(figsize=(14,12)) k = 10 # number of variables for heatmap cols = abs(train_data.astype(float).corr()).nlargest(k, "FTR")["FTR"].index cm = np.corrcoef(train_data[cols].values.T) sns.set(font_scale=1.25) hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt=".2f", annot_kws={"size": 10}, yticklabels=cols.values, xticklabels=cols.values) plt.show()
我們可以看出最相關(guān)的特征是 HTGD ,表明一個(gè)球隊(duì)主場(chǎng)周平均凈勝球數(shù)越高,他們贏的概率也就越大。
4.建立機(jī)器學(xué)習(xí)模型并進(jìn)行預(yù)測(cè) 4.1 切分?jǐn)?shù)據(jù)將數(shù)據(jù)集隨機(jī)分成為訓(xùn)練集和測(cè)試集,并返回劃分好的訓(xùn)練集測(cè)試集樣本和訓(xùn)練集測(cè)試集標(biāo)簽。我們直接采用 train_test_split 接口進(jìn)行處理。
X_train, X_test, y_train, y_test =cross_validation.train_test_split(train_data,train_target,test_size=0.3, random_state=0)
參數(shù)解釋:
train_data:被劃分的樣本特征集
train_target:被劃分的樣本標(biāo)簽
test_size:如果是浮點(diǎn)數(shù),在0-1之間,表示樣本占比;如果是整數(shù)的話就是樣本的數(shù)量
random_state:是隨機(jī)數(shù)的種子。
返回值解釋:
x_train:訓(xùn)練集特征值
x_test:測(cè)試集特征值
y_train:訓(xùn)練集目標(biāo)值
y_test:測(cè)試集目標(biāo)值
隨機(jī)數(shù)種子:其實(shí)就是該組隨機(jī)數(shù)的編號(hào),在需要重復(fù)試驗(yàn)的時(shí)候,保證得到一組一樣的隨機(jī)數(shù)。比如你每次都填1,其他參數(shù)一樣的情況下你得到的隨機(jī)數(shù)組是一樣的。但填0或不填,每次都會(huì)不一樣。隨機(jī)數(shù)的產(chǎn)生取決于種子,隨機(jī)數(shù)和種子之間的關(guān)系遵從以下兩個(gè)規(guī)則:種子不同,產(chǎn)生不同的隨機(jī)數(shù);種子相同,即使實(shí)例不同也產(chǎn)生相同的隨機(jī)數(shù)。
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X_all, y_all,test_size = 0.3,random_state = 2,stratify = y_all)4.2 相關(guān)模型及其接口介紹
下面我們分別使用邏輯回歸、支持向量機(jī)和 XGBoost 這三種不同的模型,來(lái)看看他們的表現(xiàn)。我們先定義一些輔助函數(shù),記錄模型的訓(xùn)練時(shí)長(zhǎng)和評(píng)估時(shí)長(zhǎng),計(jì)算模型的準(zhǔn)確率和 f1 分?jǐn)?shù)。我們首先介紹一下這三個(gè)模型聯(lián)系與區(qū)別和相關(guān)的接口:
邏輯回歸模型是:假設(shè)數(shù)據(jù)服從伯努利分布,通過(guò)極大化似然函數(shù)的方法,運(yùn)用梯度下降來(lái)求解參數(shù),來(lái)達(dá)到將數(shù)據(jù)二分類的目的。該模型的主要優(yōu)點(diǎn)是解釋性比較好;如果特征工程做得好,模型效果也非常不錯(cuò);訓(xùn)練速度也比較快;輸出結(jié)果也很容易調(diào)整。但是該模型的缺點(diǎn)也很突出,比如:準(zhǔn)確率不是很高,比較難處理數(shù)據(jù)不均衡問(wèn)題等。
API:sklearn.linear_model.LogisticRegression(penalty="l2", dual=False, tol=0.0001, C=1.0,fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None,solver="liblinear", max_iter=100, multi_class="ovr", verbose=0,warm_start=False, n_jobs=1)
主要參數(shù)解析:
penalty:正則化參數(shù),l1 or ?l2, default: l2;
C:正則化系數(shù)λ的倒數(shù),default: 1.0;
fit_intercept : 是否存在截距, default: True
solver:損失函數(shù)的優(yōu)化方法,有以下四種可供選擇{newton-cg, lbfgs, liblinear,sag}, ?default: liblinear
multi_class:分類方式選擇,一般有{ovr, multinomial}, default:ovr;
class_weight:類型權(quán)重參數(shù),默認(rèn)為None
random_state:隨機(jī)數(shù)種子,默認(rèn)為無(wú)
tol:迭代終止判據(jù)的誤差范圍
n_jobs:并行數(shù),為-1時(shí)跟CPU核數(shù)一致,默認(rèn)值為1。
以上是主要參數(shù)的簡(jiǎn)單解析,如果大家想深入了解,可以參看官方網(wǎng)址 。
SVM(Support Vector Machine) 是一種二類分類模型。它的基本模型是在特征空間中尋找間隔最大化的分離超平面的線性分類器。
(1)當(dāng)訓(xùn)練樣本線性可分時(shí),通過(guò)硬間隔最大化,學(xué)習(xí)一個(gè)線性分類器,即線性可分支持向量機(jī);
(2)當(dāng)訓(xùn)練數(shù)據(jù)近似線性可分時(shí),引入松弛變量,通過(guò)軟間隔最大化,學(xué)習(xí)一個(gè)線性分類器,即線性支持向量機(jī);
(3)當(dāng)訓(xùn)練數(shù)據(jù)線性不可分時(shí),通過(guò)使用核技巧及軟間隔最大化,學(xué)習(xí)非線性支持向量機(jī)。
sklearn.svm.SVC(C=1.0,kernel="rbf",degree=3,gamma="auto",coef0=0.0,shrinking=True,probability=False,tol=0.001,cache_size=200,class_weight=None,verbose=False,max_iter=-1,decision_function_shape=None,random_state=None)
主要參數(shù)解析:
C:C-SVC的懲罰參數(shù)C,默認(rèn)值是1.0。C越大,相當(dāng)于懲罰松弛變量,希望松弛變量接近0,即對(duì)誤分類的懲罰增大,趨向于對(duì)訓(xùn)練集全分對(duì)的情況,這樣對(duì)訓(xùn)練集測(cè)試時(shí)準(zhǔn)確率很高,但泛化能力弱。C值小,對(duì)誤分類的懲罰減小,允許容錯(cuò),將他們當(dāng)成噪聲點(diǎn),泛化能力較強(qiáng)。
kernel :核函數(shù),默認(rèn)是rbf,可以是‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’
0 – 線性:u"v
1 – 多項(xiàng)式:(gamma_u"_v + coef0)^degree
2 – RBF函數(shù):exp(-gamma|u-v|^2)
3 –sigmoid:tanh(gamma_u"_v + coef0)
degree :多項(xiàng)式poly函數(shù)的維度,默認(rèn)是3,選擇其他核函數(shù)時(shí)會(huì)被忽略。
gamma :rbf,poly 和sigmoid的核函數(shù)參數(shù)。默認(rèn)是auto,則會(huì)選擇1/n_features
coef0 :核函數(shù)的常數(shù)項(xiàng)。對(duì)于poly和 sigmoid有用。
max_iter :最大迭代次數(shù)。-1為無(wú)限制。
decision_function_shape :ovo, ovr or None, default=None。
主要調(diào)節(jié)的參數(shù)有:C、kernel、degree、gamma、coef0;參數(shù)詳解請(qǐng)參考官網(wǎng)。
XGBoost 是 Boosting算法的其中一種, Boosting 算法的思想是許多弱分類器集成在一起,形成一個(gè)強(qiáng)分類器,基本原理是下一棵決策樹(shù)輸入樣本會(huì)與前面決策樹(shù)的訓(xùn)練和預(yù)測(cè)相關(guān)。以為 XGBoost 是一種提升樹(shù)模型,所以他是將許多樹(shù)模型集成在一起,形成一個(gè)很強(qiáng)的分類器。而所用到的樹(shù)模型則是 CART 回歸樹(shù)模型。
XGBoost.XGBRegressor(max_depth=3, learning_rate=0.1, n_estimators=100, silent=True, objective="reg:linear", booster="gbtree", n_jobs=1, nthread=None, gamma=0, min_child_weight=1, max_delta_step=0, subsample=1, colsample_bytree=1, colsample_bylevel=1, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, base_score=0.5, random_state=0, seed=None, missing=None, **kwargs)
主要參數(shù)解析:
booster:模型類別,主要有2種,gbtree 和 gbliner,默認(rèn)是: gbtree ;
nthread:使用 CPU 個(gè)數(shù),為 -1 時(shí)表示使用全部 CPU 進(jìn)行并行運(yùn)算(默認(rèn)),等于 1 時(shí)表示使用1個(gè) CPU 進(jìn)行運(yùn)算;
scale_pos_weight:正樣本的權(quán)重,在二分類任務(wù)中,當(dāng)正負(fù)樣本比例失衡時(shí),設(shè)置正樣本的權(quán)重,模型效果更好。例如,當(dāng)正負(fù)樣本比例為 1:10 時(shí),scale_pos_weight=10;
n_estimatores:總共迭代的次數(shù),即決策樹(shù)的個(gè)數(shù);
early_stopping_rounds:在驗(yàn)證集上,當(dāng)連續(xù)n次迭代,分?jǐn)?shù)沒(méi)有提高后,提前終止訓(xùn)練
max_depth:樹(shù)的深度,默認(rèn)值為6,典型值3-10;
min_child_weight:值越大,越容易欠擬合;值越小,越容易過(guò)擬合(值較大時(shí),避免模型學(xué)習(xí)到局部的特殊樣本),默認(rèn)為1;
learning_rate:學(xué)習(xí)率,控制每次迭代更新權(quán)重時(shí)的步長(zhǎng),默認(rèn)0.3;
gamma:懲罰項(xiàng)系數(shù),指定節(jié)點(diǎn)分裂所需的最小損失函數(shù)下降值;
alpha:L1 正則化系數(shù),默認(rèn)為 1 ;
lambda:L2 正則化系數(shù),默認(rèn)為 1 ;
seed:隨機(jī)種子。
如想詳細(xì)學(xué)習(xí)該 API ,可以參考官網(wǎng)網(wǎng)址 。
4.3 建立機(jī)器學(xué)習(xí)模型并評(píng)估from time import time from sklearn.metrics import f1_score def train_classifier(clf, X_train, y_train): """ 訓(xùn)練模型 """ # 記錄訓(xùn)練時(shí)長(zhǎng) start = time() clf.fit(X_train, y_train) end = time() print("訓(xùn)練時(shí)間 {:.4f} 秒".format(end - start)) def predict_labels(clf, features, target): """ 使用模型進(jìn)行預(yù)測(cè) """ # 記錄預(yù)測(cè)時(shí)長(zhǎng) start = time() y_pred = clf.predict(features) end = time() print("預(yù)測(cè)時(shí)間 in {:.4f} 秒".format(end - start)) return f1_score(target, y_pred, pos_label=1), sum(target == y_pred) / float(len(y_pred)) def train_predict(clf, X_train, y_train, X_test, y_test): """ 訓(xùn)練并評(píng)估模型 """ # Indicate the classifier and the training set size print("訓(xùn)練 {} 模型,樣本數(shù)量 {}。".format(clf.__class__.__name__, len(X_train))) # 訓(xùn)練模型 train_classifier(clf, X_train, y_train) # 在測(cè)試集上評(píng)估模型 f1, acc = predict_labels(clf, X_train, y_train) print("訓(xùn)練集上的 F1 分?jǐn)?shù)和準(zhǔn)確率為: {:.4f} , {:.4f}。".format(f1 , acc)) f1, acc = predict_labels(clf, X_test, y_test) print("測(cè)試集上的 F1 分?jǐn)?shù)和準(zhǔn)確率為: {:.4f} , {:.4f}。".format(f1 , acc))
import xgboost as xgb from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC # 分別建立三個(gè)模型 clf_A = LogisticRegression(random_state = 42) clf_B = SVC(random_state = 42, kernel="rbf",gamma="auto") clf_C = xgb.XGBClassifier(seed = 42) train_predict(clf_A, X_train, y_train, X_test, y_test) print("") train_predict(clf_B, X_train, y_train, X_test, y_test) print("") train_predict(clf_C, X_train, y_train, X_test, y_test) print("")
訓(xùn)練 LogisticRegression 模型,樣本數(shù)量 3675。 訓(xùn)練時(shí)間 0.0050 秒 預(yù)測(cè)時(shí)間 in 0.0010 秒 訓(xùn)練集上的 F1 分?jǐn)?shù)和準(zhǔn)確率為: 0.6232 , 0.6648。 預(yù)測(cè)時(shí)間 in 0.0010 秒 測(cè)試集上的 F1 分?jǐn)?shù)和準(zhǔn)確率為: 0.6120 , 0.6457。 訓(xùn)練 SVC 模型,樣本數(shù)量 3675。 訓(xùn)練時(shí)間 0.5755 秒 預(yù)測(cè)時(shí)間 in 0.3620 秒 訓(xùn)練集上的 F1 分?jǐn)?shù)和準(zhǔn)確率為: 0.6152 , 0.6746。 預(yù)測(cè)時(shí)間 in 0.1486 秒 測(cè)試集上的 F1 分?jǐn)?shù)和準(zhǔn)確率為: 0.5858 , 0.6400. 訓(xùn)練 XGBClassifier 模型,樣本數(shù)量 3675. . . 訓(xùn)練時(shí)間 0.4079 秒 預(yù)測(cè)時(shí)間 in 0.0110 秒 訓(xùn)練集上的 F1 分?jǐn)?shù)和準(zhǔn)確率為: 0.6652 , 0.7067. 預(yù)測(cè)時(shí)間 in 0.0060 秒 測(cè)試集上的 F1 分?jǐn)?shù)和準(zhǔn)確率為: 0.5844 , 0.6279。
通過(guò)運(yùn)行結(jié)果,我們發(fā)現(xiàn):
在訓(xùn)練時(shí)間上,邏輯回歸耗時(shí)最短,XGBoost 耗時(shí)最長(zhǎng),為 2 秒多。
在預(yù)測(cè)時(shí)間上,邏輯回歸耗時(shí)最短,支持向量機(jī)耗時(shí)最長(zhǎng)。
在訓(xùn)練集上 F1 分?jǐn)?shù)方面,XGBoost 得分最高,支持向量機(jī)得分最低,但是差距不是很大。
在訓(xùn)練集上準(zhǔn)確率方面分析,XGBoost得分最高,邏輯回歸最低。
在測(cè)試集上 F1 分?jǐn)?shù)方面分析,邏輯回歸的最好,其余兩個(gè)模型基本相等,相對(duì)較低。
在測(cè)試集上準(zhǔn)確率方面分析,邏輯回歸支持向量機(jī)** 2 個(gè)模型基本相等,稍微比 XBGoost 高一點(diǎn)。
4.4 超參數(shù)調(diào)整我們使用 sklearn 的 GridSearch 來(lái)進(jìn)行超參數(shù)調(diào)參。
from sklearn.model_selection import GridSearchCV from sklearn.metrics import make_scorer import xgboost as xgb # 設(shè)置想要自動(dòng)調(diào)參的參數(shù) parameters = { "n_estimators":[90,100,110], "max_depth": [5,6,7], } # 初始化模型 clf = xgb.XGBClassifier(seed=42) f1_scorer = make_scorer(f1_score,pos_label=1) # 使用 grdi search 自動(dòng)調(diào)參 grid_obj = GridSearchCV(clf, scoring=f1_scorer, param_grid=parameters, cv=5) grid_obj = grid_obj.fit(X_train,y_train) # 得到最佳的模型 clf = grid_obj.best_estimator_ # print(clf) # 查看最終的模型效果 f1, acc = predict_labels(clf, X_train, y_train) print("F1 score and accuracy score for training set: {:.4f} , {:.4f}。".format(f1 , acc)) f1, acc = predict_labels(clf, X_test, y_test) print("F1 score and accuracy score for test set: {:.4f} , {:.4f}。".format(f1 , acc))
預(yù)測(cè)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/20027.html
摘要:系列安裝報(bào)錯(cuò)結(jié)果一樣的錯(cuò)解決方法成功了過(guò)擬合當(dāng)你觀察訓(xùn)練精度高但檢測(cè)精度低很可能你遇到過(guò)度擬合問(wèn)題。正如其名,它是的一個(gè)實(shí)現(xiàn),作者為正在華盛頓大學(xué)研究機(jī)器學(xué)習(xí)的大牛陳天奇。為了方便大家使用,陳天奇將封裝成了庫(kù)。 xgboost系列 ubuntu14.04 安裝 pip install xgboost 報(bào)錯(cuò) sudo apt-get update 結(jié)果一樣的錯(cuò) 解決方法: sudo -...
摘要:你是如何開(kāi)始參加比賽的正如之前所說(shuō)的,我一直在閱讀大量機(jī)器學(xué)習(xí)和深度學(xué)習(xí)方面的書(shū)籍和論文,但發(fā)現(xiàn)很難將我學(xué)到的算法應(yīng)用于小型數(shù)據(jù)集。機(jī)器學(xué)習(xí)中,你對(duì)哪個(gè)子領(lǐng)域最感興趣我對(duì)深度學(xué)習(xí)的各種進(jìn)步都很感興趣。 showImg(https://segmentfault.com/img/bVboxKz?w=800&h=600); 作者 Kaggle Team中文翻譯 MikaCDA 數(shù)據(jù)分析師...
摘要:作者微信公眾號(hào)的皮卡丘歡迎大家搜索關(guān)注知乎機(jī)器學(xué)習(xí)美顏簡(jiǎn)單品讀小說(shuō)實(shí)現(xiàn)顏值預(yù)測(cè)預(yù)測(cè)比賽結(jié)果制作且版飛機(jī)大戰(zhàn)實(shí)現(xiàn)簡(jiǎn)單的換臉術(shù)遺傳算法擬合圖像實(shí)現(xiàn)貓臉檢測(cè)分析個(gè)人音樂(lè)收藏垃圾郵件識(shí)別深度學(xué)習(xí)強(qiáng)化學(xué)習(xí)玩破解游戲?qū)崿F(xiàn)簡(jiǎn)單的機(jī)器翻譯模型學(xué)寫(xiě)作實(shí)現(xiàn)文本 作者:Charles微信公眾號(hào):Charles的皮卡丘(歡迎大家搜索關(guān)注)知乎:https://zhuanlan.zhihu.com/p/... ...
閱讀 3110·2019-08-30 15:56
閱讀 1259·2019-08-29 15:20
閱讀 1600·2019-08-29 13:19
閱讀 1514·2019-08-29 13:10
閱讀 3412·2019-08-26 18:27
閱讀 3092·2019-08-26 11:46
閱讀 2256·2019-08-26 11:45
閱讀 3799·2019-08-26 10:12