用GAN网络生成彩票号码

1. 前言

生成对抗网络(GAN,Generative Adversarial Network)是由Ian Goodfellow等人在2014年提出的一种深度学习模型,用于学习和生成与真实数据分布相似的数据。GAN由生成器(Generator)和判别器(Discriminator)两个部分组成,通过相互对抗的方式进行训练。生成器接受随机噪声并生成假数据,试图欺骗判别器;判别器则试图区分真实数据和生成数据,通过不断竞争,两个网络共同提升各自的性能。

在CP预测的娱乐项目中,GAN用于学习历史CP数据的分布,并生成类似的号码。需要强调的是,这种应用仅限于技术学习和娱乐,不具备实际预测能力。通过训练,生成器生成与历史数据分布相似的号码,判别器提升其区分真假数据的能力。最终,GAN展示了其在数据分布学习中的强大能力。

2. 准据准备

大lott 由7个号码组成,前区5个不重复数字【1-35】,后区2个不重复数字【1-12】。先搜集2500左右历史样本
在这里插入图片描述

接下来进行数据处理,用于训练

def lotto_data_loader(file_path, val_n=50, seed=24, batch_size=32):
    # 读取文件
    data = pd.read_excel(file_path)

    # 数据预处理:拆分前区和后区号码并合并为一个数据集,然后进行归一化处理
    front_area_numbers = data['前区'].str.split(' ', expand=True).astype(int)
    back_area_numbers = data['后区'].str.split(' ', expand=True).astype(int)

    # 归一化处理
    front_area_numbers = (front_area_numbers - 1) / 34.0  # 前区号码范围1-35,归一化到0-1
    back_area_numbers = (back_area_numbers - 1) / 11.0   # 后区号码范围1-12,归一化到0-1

    # 合并前区和后区的号码
    all_numbers = pd.concat([front_area_numbers, back_area_numbers], axis=1).values
    all_numbers = torch.tensor(all_numbers, dtype=torch.float32)
    print(f"All numbers shape: {all_numbers.shape}")

    # Create TensorDataset
    dataset = TensorDataset(all_numbers)

    # 划分数据集
    data_size = len(all_numbers) - val_n
    train_dataset, val_dataset = random_split(dataset, 
                                              [data_size, val_n],
                                              generator=torch.Generator().manual_seed(seed))
    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
    val_loader = DataLoader(val_dataset, batch_size=1, shuffle=False)

    return train_loader, val_loader

CP中数字分布如下,是一个均匀分布
在这里插入图片描述

3. 定义GAN网络

GAN的大致原理如图
【1】判别器对正负样本进行打分,同时根据二者误差信号优化自身
【2】生成器只生成逼真的负样本,同时根据判别器的负样本打分优化自身
在这里插入图片描述

3.1 定义生成器

定义一个简单的全连接网络预测CP号码
模型输入:随机噪声 【正态分布】
模型输出:7位CP号码[0, 1] 预测打分,继而预测CP序列:Y[0:5] * 35 + Y[5:7] *12

class Generator(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(Generator, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(input_dim, 256),  # 输入层,输入维度为 input_dim,输出维度为256
            nn.LeakyReLU(0.2),  # LeakyReLU 激活函数
            nn.BatchNorm1d(256),  # 批量归一化
            nn.Linear(256, 512),  # 隐藏层,输入维度256,输出维度512
            nn.LeakyReLU(0.2),  # LeakyReLU 激活函数
            nn.BatchNorm1d(512),  # 批量归一化
            nn.Linear(512, 1024),  # 隐藏层,输入维度512,输出维度1024
            nn.LeakyReLU(0.2),  # LeakyReLU 激活函数
            nn.BatchNorm1d(1024),  # 批量归一化
            nn.Linear(1024, output_dim),  # 输出层,输入维度1024,输出维度 output_dim
            nn.Sigmoid()  # Sigmoid 激活函数,输出值在0到1之间
        )
    
    def forward(self, x):
        """前向传播函数"""
        return self.model(x)  # 将数据传入模型,得到输出,形状为 N x output_dim


3.2 定义判别器

判别器也采用简单全连接网络,输出采用sigmoid 对正负样本进行打分[0,1]
0:False, 1:True

class Discriminator(nn.Module):
    def __init__(self, input_dim):
        super(Discriminator, self).__init__()
        # 定义模型的全连接层和激活函数
        self.model = nn.Sequential(
            nn.Linear(input_dim, 512),  # 输入层,输入维度为 input_dim,输出维度为512
            nn.LeakyReLU(0.2),  # LeakyReLU 激活函数
            nn.Linear(512, 256),  # 隐藏层,输入维度512,输出维度256
            nn.LeakyReLU(0.2),  # LeakyReLU 激活函数
            nn.Linear(256, 1),  # 输出层,输入维度256,输出维度1
            nn.Sigmoid()  # Sigmoid 激活函数,输出值在0到1之间
        )
    
    def forward(self, x):
        return self.model(x)  # 前向传播函数,返回模型的输出

4. 定义损失函数

4.1 判别器损失函数

判别器用于鉴别真实样本和生成样本,前期鉴别的越准则生成器的仿真能力逐步越强【道高一尺魔高一丈】,我们考虑以下优化目标:
【1】使用经典的交叉熵来判别正负样本分布距离
【2】CP序列中前区和后区中每个数字唯一不重复,构建重复惩罚
【3】CP号段中前区号段5个号码不超过35,后区号段2个号码不超过12,构建溢出惩罚

def discriminator_loss(y_true, y_pred, generated_numbers):
    bce_loss = nn.BCELoss()(y_pred, y_true)

    # 获取生成的号码
    front_numbers = generated_numbers[:, :5] * 34.0 + 1.0  # 反归一化到1-35
    back_numbers = generated_numbers[:, 5:] * 11.0 + 1.0   # 反归一化到1-12

    # 前区和后区号码范围约束(仅最大值约束)
    front_range_loss = torch.sum(torch.clamp(front_numbers - 35.0, min=0.0))
    back_range_loss = torch.sum(torch.clamp(back_numbers - 12.0, min=0.0))

    # 使用torch.clamp确保前区和后区号码在适当范围内
    front_numbers = torch.clamp(front_numbers, 1, 35)
    back_numbers = torch.clamp(back_numbers, 1, 12)

    # 前区和后区号码不重复约束
    front_unique_loss = torch.sum((torch.nn.functional.one_hot(front_numbers.to(torch.int64) - 1, num_classes=35).sum(dim=1) > 1.0).float())
    back_unique_loss = torch.sum((torch.nn.functional.one_hot(back_numbers.to(torch.int64) - 1, num_classes=12).sum(dim=1) > 1.0).float())

    # 组合损失
    total_loss = bce_loss + 0.1 * (front_range_loss + back_range_loss + front_unique_loss + back_unique_loss)
    return total_loss

对正负样本的鉴别的联合损失

	# Labels for real and fake data
     valid = torch.ones(batch_size, 1)
     fake = torch.zeros(batch_size, 1)

     # Generate fake lottery numbers from random noise
     noise = torch.randn(batch_size, input_dim)
     fake_numbers = generator(noise)
     
     # Train the discriminator
     real_loss = discriminator_loss(valid, discriminator(real_numbers), real_numbers)
     fake_loss = discriminator_loss(fake, discriminator(fake_numbers.detach()), fake_numbers.detach())
     d_loss = 0.5 * (real_loss + fake_loss)
     d_loss.backward()

4.2 生成器损失

生成器的优化目标之和负样本有关,即构建逼真的伪样本

	g_loss = discriminator_loss(valid, discriminator(fake_numbers), fake_numbers)
    g_loss.backward()

5. G/D 联合训练

这里对生成器(G)/判别器(D)联合训练,在每个epoch里对判别器多训练优先培养鉴别能力
【训练停止条件】:(1)整体loss下降切收敛(2)判别器的识别率下降即无法分辨

for epoch in range(epochs):
    for real_numbers_batch in train_loader:
        real_numbers = real_numbers_batch[0]
        batch_size = real_numbers.size(0)
        # print(real_numbers.shape)
        
        # 更新判别器n_critic次
        for _ in range(n_critic):
            # 为真实和生成的数据设置标签
            valid = torch.ones(batch_size, 1)
            fake = torch.zeros(batch_size, 1)

            # 从随机噪声生成假的彩票号码
            noise = torch.randn(batch_size, input_dim)
            fake_numbers = generator(noise)
            
            # 训练判别器
            optimizer_D.zero_grad()
            real_loss = discriminator_loss(valid, discriminator(real_numbers), real_numbers)
            fake_loss = discriminator_loss(fake, discriminator(fake_numbers.detach()), fake_numbers.detach())
            d_loss = 0.5 * (real_loss + fake_loss)
            d_loss.backward()
            optimizer_D.step()
            
            # 计算判别器准确率
            real_acc = (discriminator(real_numbers) > 0.5).float().mean()
            fake_acc = (discriminator(fake_numbers.detach()) < 0.5).float().mean()
            d_acc = 0.5 * (real_acc + fake_acc)
        
        # 训练生成器
        optimizer_G.zero_grad()
        g_loss = discriminator_loss(valid, discriminator(fake_numbers), fake_numbers)
        g_loss.backward()
        optimizer_G.step()

    # 使用验证数据进行评估
    val_g_loss, val_d_loss, val_d_acc = evaluate(generator, discriminator, val_loader)

训练的日志如下
在这里插入图片描述
可以看到【1】生成器损失下降切收敛【2】判别器识别率下降,难以区分仿真样本


6. 生成CP号码

训练好生成器,开始预测CP号码啦

import torch
import numpy as np
from generator import Generator

# 定义生成器输入(噪声)的维度和生成器输出(彩票号码)的维度
input_dim = 100
output_dim = 7

# 实例化生成器模型
generator = Generator(input_dim, output_dim)

# 加载训练好的生成器模型权重
generator.load_state_dict(torch.load('generator_model.pth'))
generator.eval()  # 设置生成器为评估模式

# 生成新的噪声数据
batch_size = 10  # 生成10组彩票号码
noise = torch.randn(batch_size, input_dim)

# 通过生成器生成彩票号码
with torch.no_grad():  # 禁用梯度计算
    generated_numbers = generator(noise).numpy()

# 对生成的彩票号码进行后处理(反归一化)
# 假设前区号码范围1-35,后区号码范围1-12
front_area_numbers = generated_numbers[:, :5] * 34 + 1
back_area_numbers = generated_numbers[:, 5:] * 11 + 1

# 将彩票号码转换为整数
front_area_numbers = front_area_numbers.astype(int)
back_area_numbers = back_area_numbers.astype(int)

# 打印生成的彩票号码
print("Generated Lottery Numbers:")
for i in range(batch_size):
    print(f"Front Area: {front_area_numbers[i]}, Back Area: {back_area_numbers[i]}")

# 保存生成的彩票号码到文件
np.savetxt('generated_lottery_numbers.txt', np.hstack((front_area_numbers, back_area_numbers)), fmt='%d', delimiter=',')

运行完毕后,生成器给出10组建议号码
在这里插入图片描述


7. 总结

本文采用GAN网络范式来尝试拟合CP序列分布,内容仅为技术学习,含娱乐成分,不构成任何TZ建议

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/712700.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python编程环境搭建

简介&#xff1a; Python环境安装比较简单&#xff0c;无需安装其它依赖环境&#xff0c;主要步骤为&#xff1a; 1. 下载并安装Python对应版本解释器 2. 下载并安装一个ide编码工具 一、下载并安装Python解释器 1.1 下载 官网地址&#xff1a;Welcome to Python.org 选择…

STM32-CAN

一、CAN总线简介 1.1 CAN简介 CAN 是 Controller Area Network 的缩写&#xff08;以下称为 CAN&#xff09;&#xff0c;是 ISO 国际标准化的串行通信 协议。异步半双工。 ISO11898&#xff1a;123kbps~1Mbps。 ISO11519&#xff1a;125kbps 特点&#xff1a; 多主控制没…

Dify源码本地部署启动

背景 Dify是一个开源LLM应用程序开发平台。Dify的直观界面结合了人工智能工作流、RAG管道、代理功能、模型管理、可观察性功能等&#xff0c;让您快速从原型到生产。 Dify提供在线试用功能&#xff0c;可以直接在线体验其功能。同时也支持docker部署&#xff0c;源码部署等方…

【Vue】Pinia管理用户数据

Pinia管理用户数据 基本思想&#xff1a;Pinia负责用户数据相关的state和action&#xff0c;组件中只负责触发action函数并传递参数 步骤1&#xff1a;创建userStore 1-创建store/userStore.js import { loginAPI } from /apis/user export const useUserStore defineStore(…

ARP协议相关

把ip地址解析成mac地址这里的mac地址就是路由器的mac地址 免费ARP 源ip和目的ip都是一样的&#xff0c;那怎么让其他人更新arp表呢&#xff1f;&#xff1f; 是因为目标mac是全f&#xff0c;是一个广播报文 如果冲突就是ip一样但是mac又不一样 代理ARP pc1和pc4是在同一个子网…

算法训练营第六十天(延长12天添加图论) | LeetCode 647 回文子串、LeetCode 516 最长回文子序列

LeetCode 67 回文子串 思路很简单&#xff0c;每一个dp[i]等于dp[i-1]加上当前字符向前直到0各个长度字符串回文串个数即可 代码如下&#xff1a; class Solution {public boolean isValid(String s) {int l 0, r s.length() - 1;while (l < r) {if (s.charAt(l) ! s.ch…

谷歌企业开发者账号注册的常见问题及解决方法

今天跟大家分享一下注册谷歌开发者企业号的一些注意事项和干货&#xff0c;少走一些弯路。 首先&#xff0c;各位开发者朋友应该都知道&#xff0c;谷歌平台上有两种类型开发者账号&#xff1a;个人开发者账号和企业开发者账号。个人账号上架周期长&#xff0c;需要14天的封测&…

C#传值参数 -1值类型 -2引用类型

传值参数 -1值类型 -2引用类型 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; //传值参数-1、值类型 2、引用类型 namespace PamatetersExample {class Program{static void Main(string[] args){St…

2 选频网络

目录 选频网络 什么是选频网络 选频网络的分类 串联谐振回路 等效电路 阻抗特性 品质因素 电压谐振 广义失谐系数 谐振曲线&#xff08;幅频曲线&#xff09; 通频带 相频曲线 考虑信号源内阻与负载电阻 并联谐振回路 等效电路 导纳特性 品质因素 电流谐振…

C++11 move左值转化为右值

单纯的左值只能用左值引用和右值只能用右值引用有些局限&#xff0c;在一些情况下&#xff0c;我们也需要对左值去调用右值引用&#xff0c;从而实现将左值里的内容转移到右值中 标准定义&#xff1a; 功能就是将一个左值强制转化为右值&#xff0c;然后实现移动语义 注意&…

2024年7款硬盘恢复软件:即刻恢复硬盘删除的文件!

当文件被删除后&#xff0c;它并不是立即从硬盘中消失&#xff0c;而是被标记为“已删除”&#xff0c;等待垃圾回收处理。因此&#xff0c;在文件被删除后&#xff0c;有几种方法可以尝试恢复删除的数据。 以下是7款常用的数据恢复软件&#xff0c;以及它们的详细介绍&#xf…

Reactor 网络模型、Java代码实例

文章目录 1. 概述2. Reactor 单线程模型2.1 ByteBufferUtil2.2 服务端代码2.3 客户端2.4 运行截图 3. Reactor多线程模型3.1 服务端代码3.2 运行截图 4. 主从 Reactor多线程模型4.1 服务端代码4.2 运行截图 参考文献 1. 概述 在 I/O 多路复用的场景下&#xff0c;当有数据处于…

apt和apt-get有什么区别?内含常用命令以及软件源配置

有时候我们上网找与Linux相关的资料的时候&#xff0c;经常会需要安装一些软件包&#xff0c;找到的一些文章会贴出命令我们直接去命令行里执行就能一键下载安装&#xff0c;然后这些命令中逃不开的就是apt和apt-get。 那么apt和apt-get有什么区别呢&#xff1f; 首先我们先了…

类别不平衡

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、介绍1、过采样2、欠采样 二、过采样1、SMOTE&#xff08;常用&#xff09;1、算法流程2、算法实现3、参数介绍 2、ADASYN&#xff08;不常用&#xff09;1、算法流程…

snap nextcloud 通过不被信任的域名访问

安装向导 — Nextcloud latest 管理手册 latest 文档 find / -name config.php trusted_domains >array (0 > localhost,1 > server1.example.com,2 > 192.168.1.50,3 > [fe80::1:50], ), vim /var/snap/nextcloud/42567/nextcloud/config/config.php vim /va…

Java--多维数组

1.多维数组可以看成是数组的数组&#xff0c;比如二维数组就是一个特殊的一维数组&#xff0c;其每一个元素都是一个一维数组 2.二维数组 下列数组啊可看成一个两行五列的数组 int a[][] new int[2][5]; 3.输出二维数组的第一个数组中具体元素&#xff0c;通过调用打…

Makefile-快速掌握

引用 本文完全参照大佬的文档写的&#xff0c;写这篇文章只是为了梳理一下知识 https://github.com/marmotedu/geekbang-go/blob/master/makefile/Makefile%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md 介绍 Makefile是一个工程文件的编译规则&#xff0c;描述了整个工程的编译…

港风归来‖王晶监制首部民俗电影《民间憋宝传说》定档6月18日

随着暑期档的临近&#xff0c;本月即将上映一部备受期待的电影《民间憋宝传说》&#xff0c;本片被视为香港著名导演王晶的强势回归&#xff0c;重新捍卫属于他的“商业片之王”的宝座&#xff0c;无疑为这部电影增添了浓厚的情感色彩与期待值。 一&#xff1a;港风再现 王晶&…

Linxu开机出现 Generating “/run/initramfs/rdsosreport.txt“解决方案

Linxu开机出现 Generating "/run/initramfs/rdsosreport.txt"解决方案 解决&#xff1a; 一、找这个-root结尾的文件也不一样。 大家可以用ls /dev/mapper查看到自己装的镜像对应的以-root结尾的文件是哪个。 二、所以我们运行的是&#xff1a;xfs_repair /dev/map…

java:spring使用【XXXPostProcessor】添加bean定义,修改bean定义、代理bean

# 项目代码资源&#xff1a; 可能还在审核中&#xff0c;请等待。。。 https://download.csdn.net/download/chenhz2284/89433361 # 项目代码 【pom.xml】 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-start…