首页 > 技术文章 > 科学预测世界杯-采用机器学习方法

dawnminghuang 2014-06-27 23:02 原文

    最近不管是在哪,世界杯永远是大家闲聊的话题。而随着互联网的发展,购买足彩越发便利和火爆了,体彩不像福彩,我们可以根据各个球队的情况做一些猜测。但作为一名看世界杯只记的住场边广告的伪球迷,也想凑热闹买一把,怎么才能保证在前面几次比赛的基础上,比较科学靠谱的预测比赛结果呢?做为一名略懂机器学习的伪球迷,当然要发挥学科的优势来凑凑热闹预测一下。

    机器学习算法很多,我们分别实现了用SVM,神经网络,和KNN来预测。要用这些分类器首先要有训练和测试的数据,比赛进行到今天,我们已经积累了很多比赛的数据了,所以应用学习分类器是合理的。那我们应该怎么得到这些数据呢?

1.量化世界杯比赛结果和影响因素

     比赛结果比较好量化,比如美国-德国,3代表美国赢,2代表打平,1代表美国输。

影响因素怎么选呢?一名伪球迷对各个队的历史,球员,教练是很难了解周全的,另外天气,球员心理状态,身体状态等等因素也是很难控制的,所以我们无法量化这些因素,而且这些信息也是很难获取的。于是一个比较合理而且简单的数据-赔率可以选用为量化了这些影响因素的综合数据。这个合不合理呢?我们知道一般赔率高的肯定胜率低,赔率低的胜率高,而赔率是怎么计算的呢?可以看这篇文章http://www.guokr.com/article/20199/了解。所以赔率和比赛胜负是相关的,通过赔率,我们可以做出比较好的判断。

2.准备训练测试数据

    赔率和输赢这些数据很容易获取,比如在http://zx.500.com/jczq/kaijiang.php?playid=2&d=2014-06-26这里就可以得到平均欧赔和输赢。于是根据第一步整理好数据,训练的标签就是输赢量化后的结果,特征就是平均欧赔。而一般买彩票前平均欧赔都会提前公布的,这就是我们测试数据的特征,根据这些特征得到的预测标签就是比赛的结果。比如我们根据前几天的情况预测今天的结果。

3    1.29    5.05    11.13
3    1.43    4.24    8.08     
1    1.83    3.33    4.75     
3    2.18    3.11    3.55
3    2.58    3.13    2.79
1    2.69    2.97    2.88     
1    1.42    4.17    8.36     
3    1.82    3.24    4.93
3    1.34    5.05    8.85     
3    1.28    5.35    11.12     
3    2.37    3.12    3.13
1    2.42    3.25    2.92     
2    4.19    3.32    1.94     
3    2.01    3.43    3.71
2    1.86    3.47    4.32     
2    1.32    5.19    9.26     
3    1.35    4.85    8.91         
1    5.39    3.80    1.64     
1    1.56    4.27    5.54     
1    12.92   6.39    1.21     
2    2.27    3.28    3.19     
3    3.58    3.55    2.02     
3    2.04    3.38    3.65
1    5.52    3.95    1.60     
1    4.57    3.49    1.81     
1    1.52    4.04    6.59    
3    4.20    3.51    1.87     
1    1.30    5.45    9.20     
3    1.13    8.36    19.99
2    4.45    3.77    1.75     
1    2.42    3.21    3.00     
3    2.12    3.29    3.55    
1    2.62    3.31    2.66     
2    1.12    8.53    19.89     
3    2.55    3.38    2.69     
1    7.51    4.91    1.39    
3    3.78    3.48    1.97     
1    3.46    3.57    2.05     
2    4.32    3.80    1.78     
1    2.53    3.31    2.76
2    5.21    3.96    1.63     
1    7.22    4.37    1.44     
3    2.12    3.45    3.45     
1    8.49    3.99    1.45

上面是6-12到6-25的数据。根据这些过去的数据来训练模型

9.60000000000000    2.86000000000000    1.64000000000000
2.15000000000000    3.65000000000000    3.11000000000000
4.70000000000000    3.58000000000000    1.75000000000000
3.59000000000000    3.42000000000000    2.04000000000000
1.60000000000000    3.89000000000000    5.52000000000000
2.06000000000000    3.30000000000000    3.66000000000000
2.08000000000000    3.30000000000000    3.57000000000000
2.55000000000000    3.05000000000000    2.92000000000000


上面是今天(6.27,6.28,6.29)的赔率。根据这些现在的数据来预测这三天的情况。

3.测试分类器

    首先我们采用的SVM分类器,利用LIBSVM工具箱可以很容易实现,当然为了使模型更加合理,在训练过程加了交叉验证,即在过去的数据里去拿一部分来训练一个模型,另一些数据来测试这个模型,然后取出使这个模型正确率最高的一些参数。在交叉验证过程大部分正确率都在50%左右,这说明赔率确实提供了一些信息,应该一般随机猜正确的概率是1/3(33.3%).

下面是这个过程的代码,要运行保证计算机上装好libsvm了。

% 数据提取
load('worldcuptry.mat','worldcuptry');
load('test.mat','test');
train_histograms=worldcuptry(:,(2:4));
test_histograms=test(:,(2:4));
train_label=worldcuptry(:,1);
test_label=test(:,1);
% 选定训练集和测试集
train_data=double(train_histograms);
test_data=double(test_histograms);

% 选择最佳的SVM参数c&g

% 首先进行粗略选择: c&g 的变化范围是 2^(-10),2^(-9),...,2^(10)
[bestacc,bestc,bestg] = SVMcgForClass(train_label,train_histograms,-10,10,-10,10);

% 打印粗略选择结果
disp('打印粗略选择结果');
str = sprintf( 'Best Cross Validation Accuracy = %g%% Best c = %g Best g = %g',bestacc,bestc,bestg);
disp(str);

% 根据粗略选择的结果图再进行精细选择: c 的变化范围是 2^(-2),2^(-1.5),...,2^(4), g 的变化范围是 2^(-4),2^(-3.5),...,2^(4),
[bestacc,bestc,bestg] = SVMcgForClass(train_label,train_histograms,-2,4,-4,4,3,0.5,0.5,0.9);

% 打印精细选择结果
disp('打印精细选择结果');
str = sprintf( 'Best Cross Validation Accuracy = %g%% Best c = %g Best g = %g',bestacc,bestc,bestg);
disp(str);


% 利用最佳的参数进行SVM网络训练
option = ['-c ',num2str(bestc),' -g ',num2str(bestg)];

% SVM网络训练
model = svmtrain(train_label, train_data, option);

%SVM网络预测
[predict_label,accuracy,prob_estimates1] = svmpredict(test_label, test_data, model,'-b 0');

最后得到的结果是

1
3
2
3
1
3
3
1

。说明我们成功预测了6.27的前三场比赛结果。

 

 

G组
    美国    0    
    德国    1
G组
    葡萄牙    2
    加纳      1

H组
    阿尔及利亚    1    
    俄罗斯        1

H组
    韩国      0    
    比利时    1

   其次我们采用另外一种策略KNN来看看结果

load('worldcuptry.mat','worldcuptry');
load('test.mat','test');
train_histograms=worldcuptry(:,(2:4));
test_histograms=test(:,(2:4));
train_label=worldcuptry(:,1);
test_label=test(:,1);
% 选定训练集和测试集
train_data=double(train_histograms);
test_data=double(test_histograms);
mdl =ClassificationKNN.fit(train_data,train_label,'NumNeighbors',1); %训练生成一个模型-1NN
predict_label= predict(mdl,test_data);

结果为:

1
2
1
3
1
3
3
3

和SVM相差不大。

最后我们用神经网络来看看结果

clc;
clear all;
close all;
load('worldcuptry.mat','worldcuptry');
load('test.mat','test');
train_histograms=worldcuptry(:,(2:4));
test_histograms=test(:,(2:4));
train_label=worldcuptry(:,1);
test_label=test(:,1);
% 选定训练集和测试集
train_data=double(train_histograms);
test_data=double(test_histograms);
ann_train_label=zeros(3,length(train_label));
for i=1:length(train_label)
    if train_label(i)==3
        ann_train_label(3,i)=1;
    elseif train_label(i)==2
        ann_train_label(2,i)=1;
    elseif train_label(i)==1
        ann_train_label(1,i)=1;
    end
end
ann_test_label=zeros(3,length(test_label));
for i=1:length(test_label)
    if test_label(i)==3
        ann_test_label(3,i)=1;
    elseif test_label(i)==2
        ann_test_label(2,i)=1;
    elseif test_label(i)==1
        ann_test_label(1,i)=1;
    end
end
%======BP神经网络创建,训练和测试==========================%
net=network_train(train_data',ann_train_label);
predict_label=network_test(test_data',net);

function net = network_train(charvec1,label )
%从1到tn间随机排序(在[0,1]之间产生b个随机数),将数据顺序打乱
[~,b]=size(charvec1);
k=rand(1,b);
[~,n]=sort(k);
%随机提取b个样本为训练样本,个样本为预测样本
input=charvec1;
output =label;
input_train=input(:,n(1:b));
output_train=output(:,n(1:b));
% BP网络训练
% %初始化网络结构
net=newff(input_train,output_train,3);
net.trainParam.epochs=60;
net.trainParam.lr=0.1;
net.trainParam.goal=0.001;
% net.trainFcn='trainrp';
%网络训练
net=train(net,input_train,output_train);
save('network.mat','net')
end


function out = network_test(charvec,net)
input_test=charvec;
[a,b]=size(charvec);
% BP网络预测
an=sim(net,input_test);
for i=1:b
    an1(i)=find(an(:,i)==max(an(:,i)));  
end
end

结果为:1    3    2    1    3    3    3    3

预测6.27全对!!!!

今天过了,让我们预测下6.28,6.29的情况

SVM的结果:

1
3
3
1

 

KNN的结果:

1

3

3

3

ANN的结果:

3

3

3

3

明天见分晓。

推荐阅读