基于线性回归算法预测双色球彩票号码的不可预测性的研究

2019-11-06 08:04:26 来源: 作者:xuekanba
摘要:机器学习是学习和理解内在机制的重要手段。近年来,机器学习理论在许多领域中都得到了成功的应用和开发。对此本文基于线性回归算法预测双色球彩票的号码的出现概率问题,此预测方法不需要对双色球彩票深入理解系统动态变化机理,只需要通过其转移概率矩阵,就可统计出一个双色球彩票系统中动态变化的主要参数。然后根据彩票网站爬取的历年数据,分析双色球彩票的数据特征信息,包括:开奖日期、期号、红篮球号码等。使用机器学习算法对红篮球号码进行数据分析,绘制出柱状图,就可以清晰明了的看出红蓝球每个号码出现的次数多少。然后再用线性回归算
关键字:
线性回归算法;双色球彩票;概率问题
1 确定要证明的彩票类型
1.1彩票基本信息
彩票,也称奖券,以抽签给奖方式进行筹款,并非是赌博。彩票的英文名为“lottery ticket”。《现代汉语词典》对彩票和奖券分别是这样解释的:“彩票,奖券的通称。”奖券,一种证券,上面编有号码,按票面价格出售。开奖后,持有中奖号码奖券的,可按规定领奖。
在我国,国家发行的彩票有两种,分别是中国福利彩票和中国体育彩票。双色球是中国福利彩票的一种玩法。“双色球”是一种由中国福利彩票管理中心统一组织发行,在全国销售联合发行的“乐透型”福利彩票。2003年2月16日起在全国联网销售。采用计算机网络系统发行销售,定期电视开奖。参与“双色球”销售的省级福利彩票发行中心在福彩中心的直接领导下,负责对本地区的“双色球”销售活动实施具体的组织和管理。“双色球”彩票实行自愿购买,凡购买者均被视为同意并遵守本规则。
1.2 彩票背景信息
彩票是印有号码或图形(文字),由人们自愿购买并能够证明购买人拥有按特定规则获取奖励的书面凭证。它是一种建立在机会均等基础上的公平竞争的娱乐性游戏。彩票最早出现在二千年前的古罗马。我国南宋时期也有类似彩票形式的博彩。国家发行彩票的目的是筹集社会公众资金,资助福利、体育等社会公众事业发展的,财政部是彩票的主管机关。彩票的发行须经财政部审核同意后报国务院批准的,并由国务院批准的彩票发行机构发行,其它任何部门无权批准发行彩票的。彩票在我国发展已经有十几年了,随着彩票成为平常百姓生活的一部分,彩票因为自身的魅力影响着现代人的生活,彩票产业也逐渐形成规模。
1.3 与其它彩票的比较
彩票主要分为福利彩票和体育彩票还有即时开奖三大类,其中福利彩票、体育彩票、传统足彩胜负/半全场/进球彩.。福彩全国联销的有:福彩3D、双色球和七乐彩。体彩全国联销的有:排列3、排列5、大乐透、22选5和足球彩票。双色球是红球33个号选6个号,蓝球16个号选1个号,它以头奖高(500万到1000万),销量高(单期销量2亿多元),奖池高(经常是2亿到3亿元),中奖的机会多(平均4期就有1个1000万),是其它任何一种彩票都不能比的。
1.4 选择此彩票的原因
第一点,彩票开奖,看似杂乱无章,是随机事件,但是经过长期跟踪,做好数据统计,就会发现它的规律性很强。
第二点,中奖才是硬道理。博彩是智者的游戏,而非愚者的赌局,无数实事说明,中大奖是30%的选号方法,30%的投注技巧和40%的运气。
第三点,彩票期期开,机会天天有,就看你能否把握得住。世界上没有任何一种方法,是可以打败纯概率事件的彩票游戏,短期投注,可以靠运气,长远而论,就是靠概率,让收益率来说明问题。号码没有好坏之分,只有出现的时机问题。
第四点,双色球彩票的规则简单,购买者只需要在1-33中选择6位数作为红球,在1-16中选择1位数作为蓝球即可。不论是社会哪个阶层的人,都可以轻松购得双色球彩票。
2 研究彩票规则特征
2.1 描述彩票规则
玩法规则:
双色球投注区分为红色球号码区和蓝色球号码区,红色球号码区由1-33共三十三个号码组成,蓝色球号码区由1-16共十六个号码组成。投注时选择6个红色球号码和1个蓝色球号码组成一注进行单式投注,每注金额人民币2元。
奖项规则:
2.2 根据彩票规则从数学角度说明彩票特征
双色球奖级设置分为高奖级和低奖级,一等奖和二等奖为高奖级,三至六等奖为低奖级。当期奖金减去当期低奖级奖金为当期高奖级奖金。各奖级和奖金规定如下:
一等奖(6+1)中奖概率为:红球33选6乘以蓝球16选1=1/17721088=0.0000056%;
二等奖(6+0)中奖概率为:红球33选6乘以蓝球16选1=15/17721088=0.0000846%;
三等奖(5+1)中奖概率为:红球33选5乘以蓝球16选1=162/17721088=0.000914%;
四等奖(5+0、4+1)中奖概率为:红球33选5乘以蓝球16选0=7695/17721088=0.0434%;
五等奖(4+0、3+1)中奖概率为:红球33选4乘以蓝球16选0=137475/17721088=0.7758%;
六等奖(2+1、1+1、0+1)中奖概率为:红球33选2乘以蓝球16选1=1043640/17721088=5.889%;
共计中奖率:6.71%。
2.3 采集已有的彩票数据
爬取彩票历史数据的代码:(爬取到从2003-2019年的数据)
import requests
from bs4 import BeautifulSoup
from collections import Counter
# 获取内容
res = requests.get('http://kaijiang.zhcw.com/zhcw/html/ssq/list_1.html', timeout = 30)
res.encoding = 'utf-8'
htm = res.text
# 解析内容
soup = BeautifulSoup(htm, 'html.parser')
# url前缀
prefix_url = 'http://kaijiang.zhcw.com/zhcw/html/ssq/list'
#获取总页数
total = int(soup.find('p', attrs={"class": "pg"}).find_all('strong')[0].text)
#将获取的信息,写进文件
local_file = open('双色球数据集.txt', 'w')
red_num = [] #历史上开出的红球
blue_num = [] #历史上开出的蓝球
# 分页获取每一页的开奖信息
for page_num in range(1, total+1):
t_url = prefix_url + '_' + str(page_num) + '.html'
print(t_url)
res2 = requests.get(t_url, timeout = 30)
res2.encoding = 'utf-8'
page_context = res2.text
page_soup = BeautifulSoup(page_context, 'html.parser')
if page_soup.table is None:
continue
elif page_soup.table:
table_rows = page_soup.table.find_all('tr')
for row_num in range(2, len(table_rows)-1):
row_tds = table_rows[row_num].find_all('td')
ems = row_tds[2].find_all('em')
# result = '开奖日期:'+ row_tds[0].string +','+'期号:'+ row_tds[1].string +', '+ems[0].string+' '+ems[1].string+' '+ems[2].string+' '+ems[3].string+' '+ems[4].string+' '+ems[5].string+' '+ems[6].string
result = row_tds[0].string +','+ row_tds[1].string +', '+ems[0].string+' '+ems[1].string+' '+ems[2].string+' '+ems[3].string+' '+ems[4].string+' '+ems[5].string+' '+ems[6].string
local_file.write(result+'\n')
print(result)
red_num.append(ems[0].string) # 红球1
red_num.append(ems[1].string) # 红球2
red_num.append(ems[2].string) # 红球3
red_num.append(ems[3].string) # 红球4
red_num.append(ems[4].string) # 红球5
red_num.append(ems[5].string) # 红球6
blue_num.append(ems[6].string) # 蓝球
else:
continue
local_file.close
red_count = Counter(red_num)
blue_count = Counter(blue_num)
# 按照出现频率顺序
red_count_sorted = sorted(red_count.items(), key=lambda pair: pair[1], reverse=False)
blue_count_sorted = sorted(blue_count.items(), key=lambda pair: pair[1], reverse=False)
print(red_count_sorted)
print(blue_count_sorted)
ssq_red = red_count_sorted[0:6]
ssq_blue = blue_count_sorted[0:3]
print(list(map(lambda item:item[0], ssq_red)))
print(list(map(lambda item:item[0], ssq_blue)))
ssq_red = list(map(lambda item:item[0], ssq_red))
ssq_blue = list(map(lambda item:item[0], ssq_blue))
ssq_red.sort()
ssq_blue.sort()
print('顺选-1:'+str(ssq_red)+'|'+ssq_blue[0])
print('顺选-2:'+str(ssq_red)+'|'+ssq_blue[1])
print('顺选-3:'+str(ssq_red)+'|'+ssq_blue[2])
print('------------------------------------------------------------------------------')
# 按照出现频率倒序
red_count_sorted = sorted(red_count.items(), key=lambda pair: pair[1], reverse=True)
blue_count_sorted = sorted(blue_count.items(), key=lambda pair: pair[1], reverse=True)
print(red_count_sorted)
print(blue_count_sorted)
ssq_red = red_count_sorted[0:6]
ssq_blue = blue_count_sorted[0:3]
print(list(map(lambda item:item[0], ssq_red)))
print(list(map(lambda item:item[0], ssq_blue)))
ssq_red = list(map(lambda item:item[0], ssq_red))
ssq_blue = list(map(lambda item:item[0], ssq_blue))
ssq_red.sort()
ssq_blue.sort()
print('反选-1:'+str(ssq_red)+'|'+ssq_blue[0])
print('反选-2:'+str(ssq_red)+'|'+ssq_blue[1])
print('反选-3:'+str(ssq_red)+'|'+ssq_blue[2])
爬取到的数据格式样例:
2019-04-14,2019042, 15 17 19 22 25 26 04
2019-04-11,2019041, 02 09 13 23 24 26 16
2019-04-09,2019040, 05 06 09 18 23 31 11
2019-04-07,2019039, 06 07 11 14 27 32 08
2019-04-04,2019038, 09 12 21 27 29 30 05
2019-04-02,2019037, 01 07 12 14 18 25 10
2.4 进行数据分析
以蓝球数据的分析为例:
蓝球号码的数据分析代码:
#!/usr/bin/python
# -*- coding:UTF-8 -*-
#调用pandas numpy matplotlib包
import pandas as pd#pandas作为pd
import numpy as np#numpy作为np
import matplotlib.pyplot as plt#将matplotlib.pyplot导入为plt
#读入处理后数据集.txt文件
df = pd.read_table('处理后数据集.txt',header=None,sep=',')
# print df
# print df[1:3] #第2到第3行(索引0开始为第一行,1代表第二行,不包含第四行)
# print df.loc[0:10,:] #第1行到第9行的全部列
# print df.loc[:,[0,7]] #全部行的第1和第8列
tdate = sorted(df.loc[:,0]) #取第一列数据
# print tdate
tdate1 = [] #将tdate数据读取到列表中
for i in tdate:
tdate1.append(i)
print (tdate1)#输出print (tdate1)
# s = pd.Series(tdate1, index=tdate1)
s = pd.Series(range(1,len(tdate1)+1), index=tdate1) #将日期转换为对应的数值从1开始
# print s
tblue = list(reversed(df.loc[:,7])) #对数据取反
print (tblue)#输出print (tblue)
fenzu = pd.value_counts(tblue,ascending=False) #将数据进行分组统计,按照统计数降序排序
print(fenzu)#输出print(fenzu)
x=list(fenzu.index[:]) #获取蓝色号码
y=list(fenzu.values[:]) #获得蓝色统计数量
print(x)#输出x
print(y)#输出y
# print type(fenzu)
plt.figure(figsize=(10,6),dpi=70) #配置画图大小、和细度
plt.legend(loc='best')
# plt.plot(fenzu,color='red') #线图
plt.bar(x,y,alpha=.5, color='b',width=0.8) #直方图参数设置
plt.title('The blue ball number') #标题
plt.xlabel('blue number') #x轴内容
plt.ylabel('times') #y轴内容
plt.show() #显示图
蓝球号码的数据分析结果柱状图:
说明:柱状图的X轴表示1-16的蓝球各个号码,Y轴表示号码出现的统计数量。通过柱状图可以直观的看出数字8是出现次数最少的数字,而数字12、16、9出现的次数较多。
1-16号蓝球出现的次数按从大到小排序输出:
说明:从执行结果可以看出数字12出现的次数最多,因此选择数字12的中奖概率就比较大。同理,数字8的比数字12少出现了46次,因此,数字8的中奖概率较低。即预测结果表明:选择数字12比数字8更容易中奖。这里只是一个概率大小问题,并不能表面选择数字12就一定会中奖。
3 选择合适的机器学习算法
3.1 根据彩票规则特征和数据分析结果选定一种或多种机器学习算法
线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。其表达形式为y=w'x+e,e为误差服从均值为0的正态分布。
回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析。
3.2 详细说明选定算法的原因
线性回归分析法在分析多因素模型时,更加简单和方便,例如:结果易于理解,计算上不复杂;建模速度快,不需要很复杂的计算,在数据量大的情况下依然运行速度很快;可以根据系数给出每个变量的理解和解释;对异常值很敏感。
3.3 描述选定的机器学习算法
回归(regression):用已知样本对未知公式参数的估计。Y=f(X1,X2,X3),这里回归函数f(X1,X2,X3)可能是任意函数。
线性回归(linear regression):回归的一种,回归函数是一次函数,例如:
Y=f(X1,X2,X3)=aX1+bX2+cX3+d其中X1,X2,X3是训练样本集中样本的各个维度(feature),a,b,c,d是模型的未知参数。
线性回归预测法就是寻找变量之间的因果关系,并将这种关系用数学模型表示出来,通过历史资料计算这两种变量的相关程度,从而预测未来情况的一种方法。
4 实现算法得到预测结果
4.1 算法实现
为了更加明确的证实双色球是否可以预测,所以进行下面算法,来看预测结果,看成功概率,来看双色球是否可以预测。
1.引入数据包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn import datasets, linear_model
2.读取文件,文件在采取之后,需要对数据进行处理,整理成xxxx-xx-xx,xx,xx,xx,xx,xx,xx,xx的格式,seq是以什么方式分割采取数据。
df = pd.read_table('hun.txt', header=None, sep=',')
3.获取数据
tdate = sorted(df.loc[:,0])
读取文件中的数据,读取方式为,左右开区间取值,把获取的数据放到相应的文件中。
4.将以列项为数据,将球号码取出,写入到csv文件中,将.csv数据读入数据帧,并取50行数据。获取的数据在新的文件中为两列,数据第一行是数据含义,所以要-1,打开数据,读取其中,关闭运行程序,释放空间;写入数据后要在每一次获取后进行分行处理。获取数据方式,,对s中获取的数以w写入新文件中,运行之后还要进行结束,释放空间。
def RedToCsv(h_num,num,csv_name):
h_num = df.loc[:,num:num].values
h_num = h_num[50::-1]
renum2 = pd.DataFrame(h_num)
renum2.to_csv(csv_name,header=None)
fp = open(csv_name)
s = fp.read()
fp.close()
a = s.split('\n')
a.insert(0, 'numid,number')
s = '\n'.join(a)
fp = open(csv_name, 'w')
fp.write(s)
fp.close()
5.获取数据,X_parameter为numid数据,Y_parameter为number数据首先读取csv文件中的数据,定义x,y的数组,遍历数据按numid和number逐一访问,将行序列号追加到数据集,将对应行数据追加到数据集。
def get_data(file_name):
data = pd.read_csv(file_name)
X_parameter = []
Y_parameter = []
for single_square_feet ,single_price_value in zip(data['numid'],data['number']): X_parameter.append([float(single_square_feet)]) Y_parameter.append(float(single_price_value))
return X_parameter,Y_parameter
测试涉及部分代码
把X_parameter和Y_parameter拟合为线性回归模型;创建一个线性模型,用X_parameters和Y_parameter训练。
regr = linear_model.LinearRegression()
regr.fit(X_parameters, Y_parameters)
创建一个名称为predictions的字典,存'intercept',
predictions['intercept'] = regr.intercept_
4.2 分析预测结果
该算法预测的是爬取到的数据的最新的一期的双色球彩票中奖号码,本次爬取到2019-04-14日期,根据每周二、四、日开奖的规则,所以预测的是下一期双色球是2019-04-16的中奖号码,2019-04-16的实际中奖号码可从网站查询,结果如图:01 06 12 13 24 32 13
当运行预测双色球算法时,会调用函数并分别生成7个csv文件,这7个csv文件里有从数据集所有数据里采集的一部分数据,用该部分数据来进行下期彩票的预测,并且根据采集数据多少的变化,预测的结果发生改变。
首先,生成7个csv文件,代码如下:
#调用取号码函数
# create file
RedToCsv("red1",1,"rednum1data.csv")
RedToCsv("red2",2,"rednum2data.csv")
RedToCsv("red3",3,"rednum3data.csv")
RedToCsv("red4",4,"rednum4data.csv")
RedToCsv("red5",5,"rednum5data.csv")
RedToCsv("red6",6,"rednum6data.csv")
RedToCsv("blue1",7,"bluenumdata.csv")
然后通过改变代码选择取的数据集大小,来进行计算预测,并且对比预测结果,观察当取多少个数据时,预测结果的最为准确,这里分别采用数据和图像的方式来对预测结果进行观察。
#获取预测结果函数
def get_predicted_num(inputfile,num):
X,Y = get_data(inputfile)
predictvalue = 101#表示取多少个数据+1
predictvalue = np.array(predictvalue).reshape((1, -1))
result = linear_model_main(X,Y,predictvalue)
print( "num "+ str(num) +" 截距 " , result["intercept"])
print( "num "+ str(num) +" 斜率" , result["coefficient"])
print( "num "+ str(num) +" 预测值: ",result["predicted_value"])
#调用函数分别预测红球、蓝球
get_predicted_num("rednum1data.csv",1)
get_predicted_num("rednum2data.csv",2)
get_predicted_num("rednum3data.csv",3)
get_predicted_num("rednum4data.csv",4)
get_predicted_num("rednum5data.csv",5)
get_predicted_num("rednum6data.csv",6)
get_predicted_num("bluenumdata.csv",1)
#取50个数,预测的结果:
num 1 截距 4.4811463046757165
num 1 斜率 [0.01918552]
num 1 预测值: [5.45960784]
num 2 截距 9.854449472096531
num 2 斜率 [-0.00045249]
num 2 预测值: [9.83137255]
num 3 截距 14.48265460030166
num 3 斜率 [-0.01067873]
num 3 预测值: [13.93803922]
num 4 截距 18.75942684766214
num 4 斜率 [-0.01076923]
num 4 预测值: [18.21019608]
num 5 截距 22.95022624434389
num 5 斜率 [0.00904977]
num 5 预测值: [23.41176471]
num 6 截距 28.963046757164406
num 6 斜率 [-0.0118552]
num 6 预测值: [28.35843137]
num 1 截距 7.456259426847661
num 1 斜率 [0.05076923]
num 1 预测值: [10.0454902]
red num 1 Intercept value 4.4811463046757165
red num 1 coefficient [0.01918552]
red num 1 Predicted value: [4.88404223]
No handles with labels found to put in legend.
Process finished with exit code 0
四舍五入为:05 10 14 18 23 28 10
与实际开奖结果比较:01 06 12 13 24 32 13 一位也不对
线性回归图像分析:
# 获取X,Y数据预测结果
X,Y = get_data("rednum1data.csv")
predictvalue = 21
predictvalue = np.array(predictvalue).reshape((1, -1))
result = linear_model_main(X,Y,predictvalue)
print( "red num 1 Intercept value " , result["intercept"])
print("red num 1 coefficient" , result["coefficient"])
print("red num 1 Predicted value: ",result["predicted_value"])
# Function to show the resutls of linear fit model
def show_linear_line(X_parameters,Y_parameters):
# Create linear regression object
regr = linear_model.LinearRegression()
#regr = LogisticRegression()
regr.fit(X_parameters, Y_parameters)
plt.figure(figsize=(12,6),dpi=80)
plt.legend(loc="best")
plt.scatter(X_parameters,Y_parameters,color="blue")
plt.plot(X_parameters,regr.predict(X_parameters),color="red",linewidth=4)
plt.xticks(())
plt.yticks(())
plt.show()
#显示模型图像,如果需要画图,将“获取X,Y数据预测结果”这块注释去掉,“调用函数分别预测红球、蓝球”这块代码注释下
show_linear_line(X,Y)
#取100个数,预测的结果:
四舍五入为:05 10 15 18 23 29 10
与实际开奖结果比较:01 06 12 13 24 32 13 一位也不对
#取500个数,预测的结果:
四舍五入为:05 09 14 18 23 28 09
与实际开奖结果比较:01 06 12 13 24 32 13 一位也不对
#取1000个数,预测的结果:
四舍五入为:05 10 14 19 24 29 09
与实际开奖结果比较:01 06 12 13 24 32 13 一位也不对
#取2000个数,预测的结果:
四舍五入为:05 10 14 19 24 29 09
与实际开奖结果比较:01 06 12 13 24 32 13 一位也不对
4.3 评价预测模型
该预测模型不能有效的预测出双色球的开奖结果,因为双色球彩票的随机性太高,且选择数字较多导致概率很低,但通过多次试验,发现预测结果与实际结果之间数字也很相接近,因此,在选择双色球号码时,要上下浮动3进行选择中奖几率会更高。
5 验证预测准确率并证明彩票的预测性
通过多次验证,发现预测结果与实际开奖结果相比,一个数也不对,说明准确率为0,这也就是说明了最新的开奖结果与之前的中奖号码无关。即双色球彩票是不可预测的。
参考文献
[1]曾忠禄、张冬梅.彩票购买者特征实证分析[J].商业时代.2006,(29):86-87
[2]Public Choice.2010,142(1): 69-90.
[3]贾晨,谢衷洁.中国福利彩票销售额影响因素分析与基于残差主成分分析的预测[J].
[4]数理统计与管理.2009,28(2):191-203
[5]张兴永,周圣武,夏登俊.彩票模式设计的最优化研究[J].数学的实践与认识.2005,35(2):110-115
[6]Jue-ShyanWang,Mei-YinLin.Number Selection Strategyo fLottery Players:An Empirical Study of the Taiwan Lottery[J]. Taiwan Econ. Forecast Poly.2006,37(1),49–67.
