使用Keras编写神经网络预测大乐透彩票,并利用历史数据回测

您所在的位置:网站首页 彩票下一期预测号码 使用Keras编写神经网络预测大乐透彩票,并利用历史数据回测

使用Keras编写神经网络预测大乐透彩票,并利用历史数据回测

2024-07-17 07:06| 来源: 网络整理| 查看: 265

写在最前面

首先郑重声明,这个赚不了钱!赚不了钱!赚不了钱!重要的话说三遍!

纯粹出于兴趣和技术做了个小实验,指望这个赚钱不太可能鸭!emmm,但可能会让你赔钱赔的少一点?

image.png

转载请注明出处:https://blog.csdn.net/aaronjny/article/details/103276212

前言

以前从没买过彩票,前几天一时兴起,随机买了几注,然后兴致勃勃地等开奖。中奖序列出来后,比对一下,握草?!

果然没中~

image.png

然后我就在考虑机器选彩票的技术可行性。

首先,大乐透的中奖序列为35选5+12选2,每个球的选取是随机的,因此,想使用机器学习精准地预测出获奖序列是很难(或者说基本不可能)的。为什么这么说呢?我们可以类比于机器学习选股票。目前有很多机器学习应用在股票选择上的例子,并能够实现盈利。但机器学习选股和选彩票有几点显著差异:

股票只需要预测涨幅(回归)或者简单预测涨跌(二分类),但大乐透中奖序列需要从 C 35 5 ∗ C 12 2 C_{35}^5*C_{12}^2 C355​∗C122​种(我不是资深彩民,就是兴致一起随手买了两注,所以对各种彩票的规则了解不是很清楚,不清楚是否还有隐含规则,这个是根据字面意思计算得来的)组合中预测出一种,难度完全不是一个量级的 股票的涨跌存在各种因子、k线、舆情等参数用于评估和训练,但彩票的中奖序列是随机产生的,可供参考的可能仅有时间上的序列的概率分布。

所谓的概率分布指的是,假设彩票的中奖序列是完全随机产生的话,序列中每一个球在一次开奖过程中出现的概率应该是相同的(前区和后区要分开算),并且从时间序列上来看,连续的很多次开奖中,每一个球的出现与否也应当满足某种规律(当然,这是宏观上讲,实际上肯定不会严格满足,但能够体现某种趋势或倾向)。

而我们又不打算靠这个中大奖,目标不是预测出头等奖的开奖序列,而是尽可能多的预测出可能会出现在中奖序列中的球。听上去好像没什么区别,但在模型设计上能够体现出差异——如果是前者,我们的模型应该是一个分类器,从 C 35 5 ∗ C 12 2 C_{35}^5*C_{12}^2 C355​∗C122​种类别中预测出其中一个,但考虑数据集规模和概率问题,根本不现实;而后者,我们则设计一个多输入、多输出的模型,输入是七个球的时间序列,输出是每个位置出现某个球的概率,这样就靠谱的多~emmm,我们不求赚钱,少输点就行~!

image.png

行嘛,想了想好像没什么问题,那就开搞?于是,就有了这篇文章。

一、获取数据

想训练个模型的话,第一步肯定是获取数据啦。

我在网上找了一下,很快从[江苏体彩网](https://www.js-lottery.com/Pla  yZone/lottoData.html)找到了历史开奖记录,可以直接下载,文件格式为csv。

这就很舒服啦,不用写爬虫到处一点点爬了。把文件下载下来看一下,数据是以这种形式组织的:

image.png

很明显,最前面是期号,然后是前区的五个号码,最后是后区的两个号码。

ok,下面让我们来写一个下载数据集的脚本,以便于我们对数据进行更新:

# -*- coding: utf-8 -*- # @File : update_data.py # @Author: AaronJny # @Date : 2019/10/29 # @Desc : import requests import settings print('开始尝试从 {} 获取最新的大乐透数据...'.format(settings.LOTTO_DOWNLOAD_URL)) try: resp = requests.get(settings.LOTTO_DOWNLOAD_URL) if resp.status_code == 200: # 解析数据,查看数据集中最新的数据期数 lines = resp.content.decode('utf-8').split('\n') index = lines[0].replace('"', '').split(',')[0] print('获取成功!开始更新文件...') with open(settings.DATASET_PATH, 'wb') as f: f.write(resp.content) print('完成!当前最新期数为{}期,请确认期数是否正确!'.format(index)) else: raise Exception('获取数据失败!') except Exception as e: print(e)

我把一些常量提取出来了,放到了settings.py里,需要对照的话请看:

# -*- coding: utf-8 -*- # @File : settings.py # @Author: AaronJny # @Date : 2019/10/29 # @Desc : # 训练epochs数量 EPOCHS = 60 # 训练批大小 BATCH_SIZE = 128 # 输入的连续时间序列长度 MAX_STEPS = 256 # 前区号码种类数 FRONT_VOCAB_SIZE = 35 # 后区号码种类数 BACK_VOCAB_SIZE = 12 # dropout随机失活比例 DROPOUT_RATE = 0.5 # 长短期记忆网络单元数 LSTM_UNITS = 64 # 前区需要选择的号码数量 FRONT_SIZE = 5 # 后区需要选择的号码数量 BACK_SIZE = 2 # 保存训练好的参数的路径 CHECKPOINTS_PATH = 'checkpoints' # 预测下期号码时使用的训练好的模型参数的路径,默认使用完整数据集训练出的模型 PREDICT_MODEL_PATH = '{}/model_checkpoint_x'.format(CHECKPOINTS_PATH) # 预测的时候,预测几注彩票,默认5注 PREDICT_NUM = 5 # 数据集路径 DATASET_PATH = 'lotto.csv' # 数据集下载地址 LOTTO_DOWNLOAD_URL = 'https://www.js-lottery.com/PlayZone/downLottoData.html' # 大乐透中奖及奖金规则(没有考虑浮动情况,税前) AWARD_RULES = { (5, 2): 10000000, (5, 1): 800691, (5, 0): 10000, (4, 2): 3000, (4, 1): 300, (3, 2): 200, (4, 0): 100, (3, 1): 15, (2, 2): 15, (3, 0): 5, (2, 1): 5, (1, 2): 5, (0, 2): 5 }

我们尝试运行一下,看看效果:

image.png

很好,没有问题。

二、处理数据

虽然数据已经获取到了,但显然,这个数据无法直接应用于训练。我们需要对数据做一下简单的处理。

现在,我们为中奖序列中的数字(或者说球)编一下号,从前往后它们的编号分别为1到7,其中1-5是前区的5个球,6-7是后区的2个球。

好的,我们现在先考虑另外一个问题,假如我们有近一年以来的气温数据,需要预测明天的气温,应该怎么做?

你可能会脱口而出,用循环神经网络做序列的预测。假设按顺序给这近一年来的气温分别编号为1-365,其中t1表示第一天的气温,t365表示今天的气温。气温的变化应该是有规律的(一般情况下),我们想让机器来学习这种规律。我们选定一个合适的时间长度,比如30天,然后将这30天的连续数据作为输入(x),将接下来一天的气温数据作为输出(y),就构成了一条数据。然后使用长度为31天的扫描框,对一年的数据进行一次遍历,我们就得到了一组数据集。用它进行训练,完成后,输入30天前到今天的气温序列,即可预测明天的气温。

回到这个问题上来,其实和预测气温差不多,我们使用连续若干期的球1的数据来预测下期球1的分布概率,球2-球7都是同样的方法。单从输入输出看来就是这样,实际上实现起来肯定会有更多的处理和优化,在这里不讨论,说到模型的时候再细说。

和预测气温的例子不同,气温预测时只有一种因子参与,就是当天的气温值。而在这个例子里,输入的是7个球,输出的也是7个概率分布,所以这是个多输入、多输出的模型。我准备使用keras来实现模型,按照keras的接口,我需要把输入数据处理成这个格式:

x={ 'x1': [球1序列1, 球1序列2, ... , 球1序列n], 'x2': [球2序列1, 球2序列2, ... , 球2序列n], ... , 'x7': [球7序列1, 球7序列2, ... , 球7序列n]}

相应的,输出数据整理成这个格式:

y={ 'y1': [序列1的下一期球1值, 序列2的下一期球1值, ... 序列n的下一期球1值], 'y2': [序列1的下一期球2值, 序列2的下一期球2值, ... 序列n的下一期球2值], ... ,'y7': [序列1的下一期球7值, 序列2的下一期球7值, ... 序列n的下一期球7值], }

开搞!

# -*- coding: utf-8 -*- # @File : dataset.py # @Author: AaronJny # @Date : 2019/10/29 # @Desc : 对数据集进行相关处理 import time import numpy as np import settings class LottoDataSet: def __init__(self, path=settings.DATASET_PATH, train_data_rate=0.9, shuffle=True): # 数据集路径 self.path &#


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3