前言
一年一度的NBA总决赛即将开始,去年我们在 优化算法 | 基于GA的Bp神经网络预测20~21赛季NBA总冠军花落谁家这篇推文成功预测雄鹿为2021赛季NBA总冠军,今年我们继续预测21~22赛季NBA总冠军。
各位小伙伴可以点击下方投票,看看各位小伙伴支持勇士,还是支持凯尔特人。不管预测结果如何,希望总决赛的每一场比赛都能够精彩,这样球迷才能享受视觉盛宴。
今天我们准备用基于粒子群优化算法(PSO)的Bp神经网络为各位预测一下今年的NBA总冠军花落谁家?
一、数据准备
在查阅若干资料和文献后,粗略地归纳出影响一只球队夺冠的13个指标,分别如下:
1.季后赛球队场均投篮命中率
2.季后赛球队场均3分命中率
3.季后赛球队场均罚篮命中率
4.季后赛球队场均得分
5.季后赛球队场均篮板
6.季后赛球队场均助攻
7.季后赛球队场均抢断
8.季后赛球队场均盖帽
9.季后赛球队场均进攻篮板率
10.季后赛球队场均防守篮板率
11.季后赛球队场均失误率
12.球星数量
13.去年是否进入总决赛
在确认完影响因素后,https://www.basketball-reference.com/这个网站分别整理出2000~2021年冠亚军的上述13项指标数据,整理结果如下:
冠军球队数据
亚军球队数据
预测总冠军花落谁家,实际上就是根据球队的季后赛数据、球星数量、去年是否进入总决赛等因素来进行预测,冠军球队的输出结果是1,亚军球队的输出结果是0。
冠军球队数据和亚军球队数据各选择18条数据作为训练数据,其余数据作为测试数据。其中P_train.txt作为训练输入,T_train.txt作为训练输出,P_test.txt作为测试输入,T_test.txt作为测试输出,2021.txt为勇士和凯尔特人今年季后赛数据,用于预测今年NBA总冠军。
P_train.txt数据如下:
T_train.txt数据如下:
P_test.txt数据如下:
T_test.txt数据如下:
2022.txt数据如下:
二、基于PSO的Bp神经网络预测
我们在MATLAB数学建模(六) | 粒子群优化(PSO)算法讲解 (上)这篇推文中讲解了PSO的基本思想,喜欢看视频教学的小伙伴可以在B站PSO教学进行学习。
1.粒子表达方式
假设我们构建的Bp神经网络为3层网络,则Bp神经网络中需要优化的参数实际上包含4部分:输入层到隐含层的权值、隐层神经元阈值、隐含层到输出层的权值、输出层阈值。
假设输入层神经元个数用
i
n
p
u
t
n
u
m
inputnum
inputnum 表示,输出层神经元个数用
o
u
t
p
u
t
n
u
m
outputnum
outputnum表示,则隐层神经元个数
h
i
d
d
e
n
n
u
m
hiddennum
hiddennum可以用如下公式计算:
h
i
d
d
e
n
n
u
m
=
2
∗
i
n
p
u
t
n
u
m
+
1
hiddennum=2*inputnum+1
hiddennum=2∗inputnum+1
因此,输入层到隐层的权值个数为 w 1 n u m = i n p u t n u m ∗ h i d d e n n u m w1num=inputnum*hiddennum w1num=inputnum∗hiddennum ,隐层到输出层的权值个数为 w 2 n u m = o u t p u t n u m ∗ h i d d e n n u m w2num=outputnum*hiddennum w2num=outputnum∗hiddennum ,Bp神经网络中待优化的变量的个数为 N = w 1 n u m + h i d d e n n u m + w 2 n u m + o u t p u t n u m N=w1num+hiddennum+w2num+outputnum N=w1num+hiddennum+w2num+outputnum。
综上所述,一个粒子的变量数目为N。因为权值和阈值的初始值一般是在 [ − 0.5 , 0.5 ] [-0.5,0.5] [−0.5,0.5]之间的随机数,所以,粒子的变量取值下限为 V a r M i n = − 0.5 VarMin=-0.5 VarMin=−0.5 ,变量取值上限为 V a r M a x = 0.5 VarMax=0.5 VarMax=0.5 。速度取值上限为 V e l M a x = 0.1 ∗ ( V a r M a x − V a r M i n ) VelMax=0.1*(VarMax-VarMin) VelMax=0.1∗(VarMax−VarMin),速度取值上限为 V e l M i n = − V e l M a x VelMin=-VelMax VelMin=−VelMax。
2.目标函数
在当前权值和阈值下,Bp神经网络的预测性能怎么样,这里我们使用 n o r m ( T s i m − T t e s t ) norm(T_{sim}-T_{test}) norm(Tsim−Ttest) 函数来进行评价, T s i m T_{sim} Tsim是预测结果, T t e s t T_{test} Ttest是测试数据的输出结果。 e r r err err是预测结果与测试结果差的范数,范数越小说明预测得越准确,如果范数为0,说明预测得完全准确。
err=norm(T_sim-T_test); %预测结果与测试结果差的范数,范数越小说明预测得越准确,如果范数为0,说明预测得完全准确
3.粒子速度和位置的更新
粒子位置更新的目的是搜索到更好的解,随着粒子群位置的更新,搜索到的解的质量也随之提高。
PSO算法中粒子位置的更新离不开速度的影响,因此粒子位置更新的公式如下:
X
i
d
k
+
1
=
X
i
d
k
+
V
i
d
k
+
1
V
i
d
k
+
1
=
ω
V
i
d
k
+
c
1
r
1
(
P
i
d
k
−
X
i
d
k
)
+
c
2
r
2
(
P
g
d
k
−
X
i
d
k
)
\begin{array}{l} X_{i d}^{k+1}=X_{i d}^{k}+V_{i d}^{k+1} \\ V_{i d}^{k+1}=\omega V_{i d}^{k}+c_{1} r_{1}\left(P_{i d}^{k}-X_{i d}^{k}\right)+c_{2} r_{2}\left(P_{g d}^{k}-X_{i d}^{k}\right) \end{array}
Xidk+1=Xidk+Vidk+1Vidk+1=ωVidk+c1r1(Pidk−Xidk)+c2r2(Pgdk−Xidk)
其中,
k
k
k为迭代次数;
w
w
w为惯性权重, 其取值一般为随着迭代次数的增加从0.9到0.4线性递减;
X
i
d
k
+
1
X_{i d}^{k+1}
Xidk+1为第
k
+
1
k+1
k+1代粒子
i
i
i的位置;
X
i
d
k
X_{i d}^{k}
Xidk为第
k
k
k代粒子
i
i
i的位置;
V
i
d
k
+
1
V_{i d}^{k+1}
Vidk+1为第
k
+
1
k+1
k+1代粒子
i
i
i的速度;
V
i
d
k
V_{i d}^{k}
Vidk为第
k
k
k代粒子
i
i
i的速度;
P
i
d
k
P_{i d}^{k}
Pidk为第
k
k
k代个体最优粒子
i
i
i的位置;
P
g
d
k
P_{g d}^{k}
Pgdk为第
k
k
k代全局最优粒子的位置;
r
1
r_1
r1和
r
2
r_2
r2为
[
0
,
1
]
[0,1]
[0,1]之间的随机数;
c
1
c_1
c1和
c
2
c_2
c2为常数。
三、MATLAB代码
目标函数代码如下:
%% 输入
% x:一个个体的初始权值和阈值
% P:训练样本输入
% T:训练样本输出
% hiddennum:隐含层神经元数
% P_test:测试样本输入
% T_test:测试样本期望输出
%% 输出
% err:预测样本的预测误差的范数
function [err,T_sim]=BpFunction(x,P,T,hiddennum,P_test,T_test)
inputnum=size(P,2); %输入层神经元个数
outputnum=size(T,2); %输出层神经元个数
%% 数据归一化
[p_train,ps_train]=mapminmax(P',0,1);
p_test=mapminmax('apply',P_test',ps_train);
[t_train,ps_output]=mapminmax(T',0,1);
%% 开始构建BP网络
net=newff(p_train,t_train,hiddennum); %隐含层为hiddennum个神经元
%设定参数网络参数
net.trainParam.epochs=1000;
net.trainParam.goal=1e-3;
net.trainParam.lr=0.01;
net.trainParam.showwindow=false; %高版MATLAB使用 不显示图形框
%% BP神经网络初始权值和阈值
w1num=inputnum*hiddennum; %输入层到隐层的权值个数
w2num=outputnum*hiddennum; %隐含层到输出层的权值个数
W1=x(1:w1num); %初始输入层到隐含层的权值
B1=x(w1num+1:w1num+hiddennum); %隐层神经元阈值
W2=x(w1num+hiddennum+1:w1num+hiddennum+w2num); %隐含层到输出层的权值
B2=x(w1num+hiddennum+w2num+1:w1num+hiddennum+w2num+outputnum); %输出层阈值
net.iw{1,1}=reshape(W1,hiddennum,inputnum); %为神经网络的输入层到隐含层权值赋值
net.lw{2,1}=reshape(W2,outputnum,hiddennum); %为神经网络的隐含层到输出层权值赋值
net.b{1}=reshape(B1,hiddennum,1); %为神经网络的隐层神经元阈值赋值
net.b{2}=reshape(B2,outputnum,1); %为神经网络的输出层阈值赋值
%% 开始训练
net = train(net,p_train,t_train);
%% 测试网络
t_sim = sim(net,p_test);
T_sim1 = mapminmax('reverse',t_sim,ps_output); %反归一化
T_sim=T_sim1';
err=norm(T_sim-T_test); %预测结果与测试结果差的范数,范数越小说明预测得越准确,如果范数为0,说明预测得完全准确
index0= T_sim<0; %找到预测值小于0的索引
index1= T_sim>1; %找到预测值小于1的索引
penalty=1000*abs(sum(T_sim(index0)))+1000*sum(T_sim(index1)-1); %预测值小于0或大于1会有惩罚
err=err+penalty; %总误差
end
主函数代码如下:
%% 基于PSO的Bp神经网络预测2022赛季NBA总冠军
%%%%%%%%%%%%%%%%%%%%%%% @copyright 微信公众号:优化算法交流地 %%%%%%%%%%%%%%%%%%%%%%%
clc;
clear;
tic
close all;
%% 加载神经网络的训练样本 测试样本每列一个样本 输入P 输出T
P=importdata('P_train.txt'); %训练输入
T=importdata('T_train.txt'); %训练输出
P_test=importdata('P_test.txt'); %测试输入
T_test=importdata('T_test.txt'); %测试输出
cur_season=importdata('2022.txt'); %雄鹿和太阳今年NBA季后赛数据,第1行为勇士队数据,第2行为凯尔特人队数据
inputnum=size(P,2); %输入层神经元个数
hiddennum=2*inputnum+1; %初始隐层神经元个数
outputnum=size(T,2); %输出层神经元个数
w1num=inputnum*hiddennum; %输入层到隐层的权值个数
w2num=outputnum*hiddennum; %隐层到输出层的权值个数
N=w1num+hiddennum+w2num+outputnum; %待优化的变量的个数
%% 定义粒子群优化算法参数
nVar=N; %变量数目
VarSize=[1,nVar]; %变量矩阵大小
VarMin=-0.5; %变量取值下限
VarMax=0.5; %变量取值上限
MaxIt=200; %最大迭代次数
nPop=50; %种群数目
w=1; %惯性权重
wdamp=0.99; %惯性重量降低系数
c1=1.5; %个体学习系数
c2=2.0; %群体学习系数
VelMax=0.1*(VarMax-VarMin); %速度上限
VelMin=-VelMax; %速度下限
%% 初始化
empty_particle.Position=[];
empty_particle.Cost=[];
empty_particle.Velocity=[];
empty_particle.Best.Position=[];
empty_particle.Best.Cost=[];
particle=repmat(empty_particle,nPop,1);
GlobalBest.Cost=inf;
for i=1:nPop
%初始化位置
particle(i).Position=unifrnd(VarMin,VarMax,VarSize);
%初始化速度
particle(i).Velocity=zeros(VarSize);
%个体评价
particle(i).Cost=BpFunction(particle(i).Position,P,T,hiddennum,P_test,T_test);
%更新个体最优
particle(i).Best.Position=particle(i).Position;
particle(i).Best.Cost=particle(i).Cost;
%更新群体最优
if particle(i).Best.Cost<GlobalBest.Cost
GlobalBest=particle(i).Best;
end
end
BestCost=zeros(MaxIt,1);
%% 主循环
for it=1:MaxIt
for i=1:nPop
%更新速度
particle(i).Velocity = w*particle(i).Velocity ...
+c1*rand(VarSize).*(particle(i).Best.Position-particle(i).Position) ...
+c2*rand(VarSize).*(GlobalBest.Position-particle(i).Position);
%对超出范围的速度进行调整
particle(i).Velocity = max(particle(i).Velocity,VelMin);
particle(i).Velocity = min(particle(i).Velocity,VelMax);
%更新位置
particle(i).Position = particle(i).Position + particle(i).Velocity;
%对超出位置范围的速度进行调整
IsOutside=(particle(i).Position<VarMin | particle(i).Position>VarMax);
particle(i).Velocity(IsOutside)=-particle(i).Velocity(IsOutside);
%对超出范围的位置进行调整
particle(i).Position = max(particle(i).Position,VarMin);
particle(i).Position = min(particle(i).Position,VarMax);
%种群评估
particle(i).Cost=BpFunction(particle(i).Position,P,T,hiddennum,P_test,T_test);
%更新个体最优
if particle(i).Cost<particle(i).Best.Cost
particle(i).Best.Position=particle(i).Position;
particle(i).Best.Cost=particle(i).Cost;
%更新群体最优
if particle(i).Best.Cost<GlobalBest.Cost
GlobalBest=particle(i).Best;
end
end
end
BestCost(it)=GlobalBest.Cost;
disp(['Iteration ' num2str(it) ': Best Cost = ' num2str(BestCost(it))]);
w=w*wdamp;
end
BestSol=GlobalBest;
%% Results
figure;
%plot(BestCost,'LineWidth',2);
semilogy(BestCost,'LineWidth',2);
xlabel('迭代次数')
ylabel('误差的变化')
title('进化过程')
grid on;
fprintf(['最优初始权值和阈值:\n=',num2str(BestSol.Position),'\n最小误差=',num2str(BestSol.Cost),'\n'])
%% 预测今年总冠军概率
cur_test=zeros(size(cur_season,1),1);
[~,bestCur_sim]=BpFunction(BestSol.Position,P,T,hiddennum,cur_season,cur_test);
prob=softmax(bestCur_sim); %将预测结果映射为和为1的概率
disp(['勇士队获得2021年NBA总冠军概率为',num2str(prob(1))]);
disp(['凯尔特人队获得2021年NBA总冠军概率为',num2str(prob(2))]);
toc
%%%%%%%%%%%%%%%%%%%%%%% @copyright 微信公众号:优化算法交流地 %%%%%%%%%%%%%%%%%%%%%%%
四、预测结果
预测结果如下:
预测结果为两支球队夺冠的概率几乎相等,究其原因两支队伍的基础数据和高阶数据都十分接近,所以难分伯仲。
此外,因为训练数据量较少,所以训练结果准确性有待提高,各位还是欣赏比赛、支持自己喜欢的球队吧。
五、代码获取方式
在公众号后台回复关键词 PSOBPNBA,即可提取本篇推文代码。
总结
本次推文使用基于PSO的Bp神经网络预测21~22赛季NBA总冠军,重点讲解粒子的编码方式、目标函数和粒子速度和位置的更新,最终预测结果为两支球队夺冠概率各为50%。当然了,会有小伙伴说,我蒙的比这预测都准,反正都是一半一半的概率。不过,我们讲解的是思想,各位领会到了思想,我们的教学就达到目的了。
咱们下期再见
近期你可能错过了的好文章
新书上架 | 《MATLAB智能优化算法:从写代码到算法思想》
遗传算法(GA)求解带时间窗的车辆路径(VRPTW)问题MATLAB代码
粒子群优化算法(PSO)求解带时间窗的车辆路径问题(VRPTW)MATLAB代码
知乎 | bilibili | CSDN:随心390