06 案例 - 赌球神器

简介: 理论部分先告一段落,如果还有不清晰的地方可以选择留言或我私下沟通。今天起正式进入代码阶段,入门项目是赌球神器。一、建模步骤1、清洗数据集 。2、划分训练集和测试集:12个特征;1个目标 - 获胜队伍:主队、客队、平局;3、训练三种不同的分类器:Logistic Regression、Support Vector Machine、XGBoost 。

理论部分先告一段落,如果还有不清晰的地方可以选择留言或我私下沟通。今天起正式进入代码阶段,入门项目是赌球神器。

一、建模步骤

1、清洗数据集 。
2、划分训练集和测试集:12个特征;1个目标 - 获胜队伍:主队、客队、平局;
3、训练三种不同的分类器:Logistic Regression、Support Vector Machine、XGBoost 。
4、给定主队客队情况下,使用最佳分类器预测是哪支队伍获取胜利 。

----- 在做项目之前回答一个问题 ----

有很多人问我到底哪个分类器最好?

一个较为严谨的回答是:当你没有真正用数据跑出一个模型之前,你永远不知道哪个分类器的效果最好。

但事实上,个人感觉很多分类器预测出的准确率始终在75%~78%之间徘徊,可是一旦使用了XGBoost分类器进行分类,预测效果一下子可以达到80%以上。

所以如果实在想知道哪个模型更好,不负责任的回答是:
那你就用XGBoost吧,XGBoost不仅效果好,而且运算速度也比较快。至于为什么?请先观大略不求甚解,将来有机会再说。

二、数据来源

Kaggle每年都会举办 March Madness的预测竞赛
https://www.kaggle.com/c/march-machine-learning-mania-2017/kernels
在2014年世界杯的时候,Bing正确得预测了所有15场淘汰赛阶段比赛的结果。

获取到数据后要思考两个问题:
1、我们应该使用什么模型?
2、要预测哪支球队获胜,什么样的特征才能起到重要的作用?
这不仅是编程前需要考虑的问题,同时也是最后写报告时需要总结回报的内容。

三、编程
1、导入库

数据处理用到的库:《Python - 科学计算库》笔者在该文集对pandas、numpy等常用数据处理方法做了介绍。

XGBoost 安装请参考文集:《AI - 开发工具》中的《安装 xgboost 库
如果XGBoost 安装没有问题,那么import xgboost as xgb不会报错。

linear线性方法包中导入逻辑回归:
from sklearn.linear_model import LogisticRegression
ensemble集成方法包中导入随机森林:
from sklearn.ensemble import RandomForestClassifier
支撑向量分类器:
from sklearn.svm import SVC

逻辑回归(LogisticRegression)、随机森林(RandomForestClassifier)都是属于sklearn中的库,在安装Anaconda时就已经自动包含了,所以无需安装插件,直接导入即可。

%matplotlib inline 作用参考该文章:
01 matplotlib - 折线图、绘图属性、Web安全色、子图、保存画板

import warnings warnings.filterwarnings("ignore") 忽略一些警告

完整的头文件:

#数据处理
import pandas as pd
import numpy as np
#XGBoost 生成一个由弱分类器集成的强分类器,一般来说这个弱分类器是决策树
import xgboost as xgb
#Logistic Regression 其输出只有有限个可能的值,在目标变量为分类属性时可以使用。
from sklearn.linear_model import LogisticRegression
# 随机森林同样是一个集成算法,通过独特的抽样方式获得不同的子数据集,
# 通过这些子数据集来建立决策树模型,最终通过求平均的方式来提升结果的准确性,同时来控制过拟合。
from sklearn.ensemble import RandomForestClassifier
# 由一个分隔超平面定义的判别式学习器
from sklearn.svm import SVC
%matplotlib inline
import warnings
warnings.filterwarnings("ignore")
2、读取数据

《final_dataset.csv》文件里是样本集,如果需要请留邮箱,我单独发给大家。


img_25adf42e301281e8bc77103470168b17.png
final_dataset的部分特征值

data = pd.read_csv('./Datasets/final_dataset.csv') 读取数据,算法在如下文件中已介绍:
04 pandas DataFrame_创建、文件读取、编码
05 pandas DataFrame_删改查、索引器、读写文件

在处理特征前,首先要对数据的所有特征进行深入了解,比如查看数据描述:
HomeTeam:主队
AwayTeam:客队
FTR: (H: 主队胜 NH:不是主队胜)
HTGD:Home team goal difference(主队平均进球差)
ATGD:away team goal difference(客队平均进球差)
HTP:Home team points(主队平均每轮得分)
ATP:Away team points(客队平均每轮得分)
DiffFormPts:Diff in points(主队平均得分-客队平均得分)
DiffLP:Differnece in last years position(上一年度主客队排名差)

inplace参数的理解:
修改一个对象时:
inplace=True:不创建新的对象,直接对原始对象进行修改;
inplace=False:对数据进行修改,创建并返回新的对象承载其修改结果。

完整的代码:

#读取数据
data = pd.read_csv('./Datasets/final_dataset.csv')

#移除前三周比赛并移除多余特征
data = data[data.MW > 3]

data.drop(['Unnamed: 0','HomeTeam', 'AwayTeam', 'Date', 'MW', 'HTFormPtsStr', 'ATFormPtsStr', 'FTHG', 'FTAG',
           'HTGS', 'ATGS', 'HTGC', 'ATGC','HomeTeamLP', 'AwayTeamLP','DiffPts','HTFormPts','ATFormPts',
           'HM4','HM5','AM4','AM5','HTLossStreak5','ATLossStreak5','HTWinStreak5','ATWinStreak5',
           'HTWinStreak3','HTLossStreak3','ATWinStreak3','ATLossStreak3'],1, inplace=True)

data.head()

输出 - 读取数据的结果:


img_ff3c514328c734386e485bf357bd68c9.png
读取的数据
3、探索性分析

上述直接读取的数据机器能不能认识?或者说算法能不能直接使用这些数据跑出模型来?显然不行。我们还要做一步探索性分析的工作。

探索性分析首先要考虑的是:1、我们的研究是否有价值,2、能够从数据中分析出哪些信息。

a、总比赛场数

n_matches = data.shape[0]

b、特征数量,需要用总个数减去目标变量个数。

n_features = data.shape[1] - 1

c、主队获胜场数

n_homewins = len(data[data.FTR == 'H'])

d、计算主队胜率

win_rate = (float(n_homewins) / (n_matches)) * 100

打印结果

print("比赛总场数: {}".format(n_matches))
print("特征总数: %d" %n_features)
print("主场球队获胜场数: {}".format(n_homewins))
print("主队胜率: {:.2f}%".format(win_rate))
比赛总场数: 5600
特征总数: 12
主场球队获胜场数: 2603
主队胜率: 46.48%
4、数据可视化

增加一个头文件:
from pandas.tools.plotting import scatter_matrix

scatter matrix会画出某一特征和其余特征之间所建立的二维图像

scatter_matrix(data[['HTGD','ATGD','HTP','ATP','DiffFormPts','DiffLP']], figsize=(10,10))

从图片可以发现,对角线上的图片是直方图,这是该特征和自己所画出的图,描述了其分布状况

散点图表示了一个特征和另一个特征之间的关系。这种关系可以用相关系数来表达。

img_fc6fc04579e34b4bce41f7c3784dd892.png
scatter matrix
5、数据预处理

1、将数据划分为特征集和目标集

X_all = data.drop(['FTR'],1)
y_all = data['FTR']

2、标准化数据

from sklearn.preprocessing import scale
cols = [['HTGD','ATGD','HTP','ATP','DiffLP']]
for col in cols:
    X_all[col] = scale(X_all[col])

3、将数据转换为str型

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')

4、我们希望使用连续性变量,所以移除分类型变量

def preprocess_features(X):
    ''' 将比赛数据中的分类变量转化为哑变量 '''
    
    # 初始化新的输出数据集
    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):\n{}"
.format(len(X_all.columns), list(X_all.columns)))

输出结果:处理完后剩下24个特征

Processed feature columns (24 total features):
['HTP', 'ATP', 'HM1_D', 'HM1_L', 'HM1_W', 'HM2_D', 'HM2_L', 'HM2_W', 'HM3_D', 'HM3_L', 'HM3_W', 'AM1_D', 'AM1_L', 'AM1_W', 'AM2_D', 'AM2_L', 'AM2_W', 'AM3_D', 'AM3_L', 'AM3_W', 'HTGD', 'ATGD', 'DiffFormPts', 'DiffLP']

5、打印前五行数据

print("\nFeature values:")
X_all.head()
img_cc78163cbf6f553a5bff13211ca33722.png
打印前五行数据

from sklearn.model_selection import train_test_split

6、训练集、测试集划分
stratify参数是在数据不均衡情况下,保证训练集和测试集正例负例之间的比例保持不变

X_train, X_test, y_train, y_test = train_test_split(X_all, y_all, 
                                                    test_size = 50,
                                                    random_state = 2,
                                                    stratify = y_all)
6、训练模型
from time import time 
from sklearn.metrics import f1_score

def train_classifier(clf, X_train, y_train):
    ''' 使用训练集数据拟合分类器 '''
    
    # 开启计时、训练分类器、停止计时
    start = time()
    clf.fit(X_train, y_train)
    end = time()
    print("Trained model in {:.4f} seconds".format(end - start))

    
def predict_labels(clf, features, target):
    ''' 基于分类器进行预测,并给出F1得分 '''
    
    start = time()
    y_pred = clf.predict(features)
    end = time()
    
    print("Made predictions in {:.4f} seconds.".format(end - start))
    
    return f1_score(target, y_pred, pos_label='H'), sum(target == y_pred) / float(len(y_pred))


def train_predict(clf, X_train, y_train, X_test, y_test):
    ''' 训练和预测的模型整合 '''
    
    # 声明分类器和训练集规模
    print("Training a {} using a training set size of {}. . .".format(clf.__class__.__name__, len(X_train)))
    
    # 训练分类器
    train_classifier(clf, X_train, y_train)
    
    # 分别打印训练集和分类集的预测结果
    f1, acc = predict_labels(clf, X_train, y_train)
    print(f1, acc)
    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))
# 初始化三个模型
clf_A = LogisticRegression(random_state = 42)
clf_B = SVC(random_state = 912, kernel='rbf')
clf_C = xgb.XGBClassifier(seed = 82)

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('')
img_c999e1b91c0984d22447236d445420f7.png

显然,XGBoost看上去是我们的最佳模型,其F1和准确度是三个模型当中最高的。

XGBoost的超参设置:
img_e21082848ce7561c74ea4a7b9711c4ac.jpe
from sklearn.grid_search import GridSearchCV
from sklearn.metrics import make_scorer


# 设置想要调整的参数
parameters = { 'learning_rate' : [0.1, 0.2],
               'n_estimators' : [40, 50],
               'max_depth': [3],
               'min_child_weight': [3],
               'gamma':[0.4],
               'subsample' : [0.8],
               'colsample_bytree' : [0.8],
               'scale_pos_weight' : [1],
               'reg_alpha':[1e-5]
             }  

# 初始化分类器
clf = xgb.XGBClassifier(seed=2)

# 得到F1得分
f1_scorer = make_scorer(f1_score,pos_label='H')

# 使用网格搜索寻找最优模型
grid_obj = GridSearchCV(clf,
                        scoring=f1_scorer,
                        param_grid=parameters,
                        cv=5)

# 将数据带入模型进行训练
grid_obj = grid_obj.fit(X_train,y_train)

# Get the estimator获取最优超参
clf = grid_obj.best_estimator_
print(clf)

# 给出最优f1得分和准确率
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))
img_1f9a813c701e870830b8319b307aed10.png
相关文章
|
编解码 数据可视化 定位技术
神器-可视化分析之Basemap入门详(一)
今天咱们讲解一个画地图神器-BaseMap,看看这个神器讲给我们带来怎样的使用体验。
431 0
神器-可视化分析之Basemap入门详(一)
|
4月前
|
数据可视化
可视化神器,必须分享给宝子们,太香了
可视化神器,必须分享给宝子们,太香了
|
6月前
|
XML Web App开发 JavaScript
解析神器Xpath详解+实战
解析神器Xpath详解+实战
|
消息中间件 关系型数据库 MySQL
测试神器之MeterSphere
测试神器之MeterSphere
214 0
|
JavaScript 前端开发 uml
推荐 5 个开源的 yyds 效率神器
本期推荐开源项目目录: 1. Wox:效率神器 2. 图表编辑工具客户端 3. 在线白板工具 4. 分屏神器 5. 番茄钟
|
监控 数据安全/隐私保护 Windows
推荐5款能帮你解决各种问题的神器
今天我要向大家推荐5款超级好用的效率软件,无论是在学习还是办公中都能够极大地提高效率。这些软件可以帮助你解决许多问题,而且每个都是真正的神器。
199 0
|
Web App开发 测试技术
软件测试|web自动化测试神器playwright教程(二十)
软件测试|web自动化测试神器playwright教程(二十)
|
存储 运维 监控
突然发现一款优化神器
遭受这些新型的高级网络安全攻击很有可能和DNS有关,DNS是网络威胁流通的主管道,监控、存储、分析DNS数据对企业网络安全建设有着极其重要的意义,然而几乎所有的企业都允许DNS协议类型数据报文不受限制的传输,DNS覆盖超过91.3%的恶意软件与远控的通信。
205 0
突然发现一款优化神器