使用机器学习算法对未来数据进行预测——以PSO-SVR算法预测篮网队得分为例

之前做的实验都是基于历史数据进行实施预测并验证结果,今天写一篇文章来进行分步预测未来变化,其实和之前没有太大不同。

1.数据预处理

我这里有NBA篮网队的技术统计数据,如下:

得分前场板后场板总篮板助攻失误抢断盖帽犯规
125933422788317
115641472587621
123732392686721
1419273629981128
1191027371698323
13012344631147723
10414365018117722
1234333735129920
105844522696816
1283404333113919
1151338513274819
12523335271710524
10910415118138418
1186333921136625
11414395318165111
1091131422086318
1308425035133519
1167344130109620
12811334430106417
10964147261112719
10312385019133617
13410344430137221
10783038261110617
13073037351812517
11711324323156321
12711465731188422
10193342191961020
139103545371710831
11411344527106614
107431352853317
11113435634158518
12012334525116321
11274350311410718
11316334919103427
881335481999110
1161037472585217
11310253524711818
113930392489316
124153550221610220
1173384129153619
1005303522118716
12111344521143522
13210435333145124
1241338513556813
9814334721195416
12974451301311218
1271031413088516
1129314021610419
1098313923139318
1284333728104411
1369263531157316
1348374535139515
1049374620122520
1118263430158622
1088263421176318
1178324029185619
1246384425166417
1467384533176524
14710405033117425
13211253629971025
98643492476518
1289384734170626
1136232923115825
135133952301681124
1257424926172519
1224374124199514
1161234462963512
1228334131186618
1166374323173218
1104384226206413
122113748301211717
13084351311211422
1227445125205924
9610354519156616
145931403086324
111133750281713620
1046404623194517
12393443211551022
125134457242011722
         

 

我们需要对数据进行分步处理,即使用第一场的因素来预测第二场的得分。

前场板后场板总篮板助攻失误抢断盖帽犯规

删除第一场的得分情况,使上方单元格下移,并将第一行的得分情况设置为0即可。即使用上一场的前场板....犯规等数据预测下一场的得分。

如下:

得分前场板后场板总篮板助攻失误抢断盖帽犯规
0933422788317
125641472587621
115732392686721
1239273629981128
1411027371698323
11912344631147723
13014365018117722
1044333735129920
123844522696816
1053404333113919
1281338513274819
11523335271710524
12510415118138418
1096333921136625
11814395318165111
1141131422086318
1098425035133519
1307344130109620
11611334430106417
12864147261112719
10912385019133617
10310344430137221
13483038261110617
10773037351812517
13011324323156321
11711465731188422
12793342191961020
101103545371710831
13911344527106614
114431352853317
10713435634158518
11112334525116321
12074350311410718
11216334919103427
1131335481999110
881037472585217
11610253524711818
113930392489316
113153550221610220
1243384129153619
1175303522118716
10011344521143522
12110435333145124
1321338513556813
12414334721195416
9874451301311218
1291031413088516
1279314021610419
1128313923139318
1094333728104411
1289263531157316
1368374535139515
1349374620122520
1048263430158622
1118263421176318
1088324029185619
1176384425166417
1247384533176524
14610405033117425
14711253629971025
132643492476518
989384734170626
1286232923115825
113133952301681124
1357424926172519
1254374124199514
1221234462963512
1168334131186618
1226374323173218
1164384226206413
110113748301211717
12284351311211422
1307445125205924
12210354519156616
96931403086324
145133750281713620
1116404623194517
10493443211551022
123134457242011722
         

好了,转成CSV文件。

 

2.导入常用包

import csv
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.svm import SVR 
from sklearn.metrics import mean_squared_error 
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from sklearn.metrics import explained_variance_score
from sklearn import metrics
from sklearn.metrics import mean_absolute_error # 平方绝对误差
import random

3.引入数据

因为数据是从前到后的,所以需要转置一下。

#特征
feature=[]
#目标
target=[]

csv_file = csv.reader(open('lanwang.csv'))
for content in csv_file:
    content=list(map(float,content))
    if len(content)!=0:
        feature.append(content[1:9])
        target.append(content[0:1])
        
targets=[]
for i in target:
    targets.append(i[0])
    
feature.reverse()
targets.reverse()
 
# 标准化转换
scaler = StandardScaler()
# 训练标准化对象
scaler.fit(feature)
# 转换数据集
feature= scaler.transform(feature)

fig = plt.gcf()
fig.set_size_inches(18.5, 10.5)
plt.title('TURE')
plt.plot(targets)
plt.xlabel('Time')
plt.ylabel('Value')

得分变化图:

4.SVR验证

使用前90%训练,后10%验证。

注意:

1.训练集一定因为是随机划分。所以一定要把最后一行数据去掉,即存在0的那一行数据,因为那一行数据是不存在目标值的,所以特征值也毫无意义。

2.使用评价函数时也去掉最后一行,因为根本不知道真实数据,所以没有意义。

代码如下:

feature1=feature[0:int(len(feature))-1]
targets1=targets[0:int(len(targets))-1]

feature_train,feature_test,target_train,target_test = train_test_split(feature1,targets1,test_size=0.1,random_state=8)

feature_test=feature[int(len(feature)*0.9):int(len(feature))]
target_test=targets[int(len(targets)*0.9):int(len(targets))]

model_svr = SVR()
model_svr.fit(feature_train,target_train)
predict_results=model_svr.predict(feature_test)

target1=target_test[0:int(len(target_test))-1]
results=predict_results[0:int(len(predict_results))-1]

plt.plot(target1)#测试数组
plt.plot(predict_results)#测试数组
plt.legend(['True','SVR'])
fig = plt.gcf()
fig.set_size_inches(18.5, 10.5)
plt.title("SVR")  # 标题
plt.show()

print("MSE:",mean_squared_error(target1,results))
print("R2 = ",metrics.r2_score(target1,results)) # R2
print("MAE = ",mean_absolute_error(target1,results)) # results

结果太真实了..

5.PSO优化一下

注意:返回适应值那里一定要改成去掉最后一行。

代码如下:

class PSO:
    def __init__(self, parameters):
        """
        particle swarm optimization
        parameter: a list type, like [NGEN, pop_size, var_num_min, var_num_max]
        """
        # 初始化
        self.NGEN = parameters[0]    # 迭代的代数
        self.pop_size = parameters[1]    # 种群大小
        self.var_num = len(parameters[2])     # 变量个数
        self.bound = []                 # 变量的约束范围
        self.bound.append(parameters[2])
        self.bound.append(parameters[3])
 
        self.pop_x = np.zeros((self.pop_size, self.var_num))    # 所有粒子的位置
        self.pop_v = np.zeros((self.pop_size, self.var_num))    # 所有粒子的速度
        self.p_best = np.zeros((self.pop_size, self.var_num))   # 每个粒子最优的位置
        self.g_best = np.zeros((1, self.var_num))   # 全局最优的位置
 
        # 初始化第0代初始全局最优解
        temp = -1
        for i in range(self.pop_size):
            for j in range(self.var_num):
                self.pop_x[i][j] = random.uniform(self.bound[0][j], self.bound[1][j])
                self.pop_v[i][j] = random.uniform(0, 1)
            self.p_best[i] = self.pop_x[i]      # 储存最优的个体
            fit = self.fitness(self.p_best[i])
            if fit > temp:
                self.g_best = self.p_best[i]
                temp = fit
 
    def fitness(self, ind_var):
        X = feature_train
        y = target_train
        """
        个体适应值计算
        """
        x1 = ind_var[0]
        x2 = ind_var[1]
        x3 = ind_var[2]
        
        if x1==0:x1=0.001
        if x2==0:x2=0.001
        if x3==0:x3=0.001
            
        clf = SVR(C=x1,epsilon=x2,gamma=x3)
        clf.fit(X, y)
        predictval=clf.predict(feature_test)
        
        predictval1=predictval[0:int(len(predictval))-1]
        
        print("R2 = ",metrics.r2_score(target1,predictval1)) # R2
        
        return  metrics.r2_score(target1,predictval1)
 
    def update_operator(self, pop_size):
        """
        更新算子:更新下一时刻的位置和速度
        """
        c1 = 2     # 学习因子,一般为2
        c2 = 2
        w = 0.4    # 自身权重因子
        for i in range(pop_size):
            # 更新速度
            self.pop_v[i] = w * self.pop_v[i] + c1 * random.uniform(0, 1) * (
                        self.p_best[i] - self.pop_x[i]) + c2 * random.uniform(0, 1) * (self.g_best - self.pop_x[i])
            # 更新位置
            self.pop_x[i] = self.pop_x[i] + self.pop_v[i]
            # 越界保护
            for j in range(self.var_num):
                if self.pop_x[i][j] < self.bound[0][j]:
                    self.pop_x[i][j] = self.bound[0][j]
                if self.pop_x[i][j] > self.bound[1][j]:
                    self.pop_x[i][j] = self.bound[1][j]
            # 更新p_best和g_best
            if self.fitness(self.pop_x[i]) > self.fitness(self.p_best[i]):
                self.p_best[i] = self.pop_x[i]
            if self.fitness(self.pop_x[i]) > self.fitness(self.g_best):
                self.g_best = self.pop_x[i]
 
    def main(self):
        popobj = []
        self.ng_best = np.zeros((1, self.var_num))[0]
        for gen in range(self.NGEN):
            self.update_operator(self.pop_size)
            popobj.append(self.fitness(self.g_best))
            print('############ Generation {} ############'.format(str(gen + 1)))
            if self.fitness(self.g_best) > self.fitness(self.ng_best):
                self.ng_best = self.g_best.copy()
            print('最好的位置:{}'.format(self.ng_best))
            print('最大的函数值:{}'.format(self.fitness(self.ng_best)))
        print("---- End of (successful) Searching ----")
 
        plt.figure()
        fig = plt.gcf()
        fig.set_size_inches(18.5, 10.5)
        plt.title("Figure1")
        plt.xlabel("iterators", size=14)
        plt.ylabel("fitness", size=14)
        t = [t for t in range(self.NGEN)]
        plt.plot(t, popobj, color='b', linewidth=2)
        plt.show()
if __name__ == '__main__':
    NGEN = 20
    popsize = 20
    low = [0,0,0]
    up = [100,100,100]
    parameters = [NGEN, popsize, low, up]
    pso = PSO(parameters)
    pso.main()

可能是数据太少了,优化后R方也只能到达70左右。

6.获取PSO-SVR的对未来一场比赛得分的预测结果

model_svr = SVR(C=100,epsilon=0,gamma=100)
model_svr.fit(feature_train,target_train)
predict_results=model_svr.predict(feature_test)

target1=target_test[0:int(len(target_test))-1]
results=predict_results[0:int(len(predict_results))-1]

plt.plot(target1,marker='s')#测试数组
plt.plot(predict_results,marker='o')#测试数组
plt.legend(['True','SVR'])
fig = plt.gcf()
fig.set_size_inches(18.5, 10.5)
plt.title("SVR")  # 标题
plt.show()

print("MSE:",mean_squared_error(target1,results))
print("R2 = ",metrics.r2_score(target1,results)) # R2
print("MAE = ",mean_absolute_error(target1,results)) # results

结果很一般:

真实值:

预测值:

你看明白了吗?

 

我回去把数据集中的0改成1000000

再次调优化仍然是0.72左右,和之前差不多就不改参数了。

通过上一场的条件,预测下一场的结果就是119分左右。

 

LSTM自回归预测与此相同,只不过就是这样的格式。

21
32
43
54
05

 

 

*此项预测仅供娱乐,切勿拿去赌球之类的事情。

*还是那句话,只要和人相关,预测永远也可不能准确,因为你无法获取全部的影响因素。

预测得分 119  准确率70%左右,真实得分...

悟了吗,兄弟们。

  • 7
    点赞
  • 107
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值