魅力程序猿

  • 首页
  • Java
  • Android
  • APP
    • 扑克计分器
    • Video Wallpaper
  • 联系我
  • 关于我
  • 资助
道子
向阳而生
  1. 首页
  2. AI技术
  3. 正文

20253431 2025-2026-2 《Python程序设计》实验四报告

2026年6月2日 7点热度 0人点赞 0条评论

📰 来源: 博客园


课程:《Python程序设计》
班级: 2534
姓名: 吕俊孜
学号:20253431
实验教师:王志强
实验日期:2026年5月25日
必修/选修: 公选课

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。

本来是写了一个关于word文档格式判断的小工具,想着有时候还能用到,但是后来发现好像并不切题……就很坏了
ps:如果您乐意看看,这里有链接
所以在思考了很久以后,我决定写一个简单的贪吃蛇小游戏!
但是光有这么个小游戏有什么意思,现在可是大ai时代,那我就打算训练一个简单的ai来玩这个小游戏,感觉有种电子宠物的乐趣了对吧

我们不难想到,要完成这样一个实验,在代码阶段,我们只需要写一个简单的贪吃蛇和一个ai训练模型,接下来就只需要等ai训练完成就好了。
所以我们的目标就一目了然了。
经过查阅资料,使用DQN作为ai的模型似乎是不错的选择,由于在这方面网上有一些先例,所以我们就可以借鉴一下前人的思路

以下是对DQN的介绍,如果您了解DQN,那么请移步2.3
DQN(Deep Q-Network)大概就是用一个函数Q(s,a)来反馈自己当前的动作有多好(奖励),通过一个很复杂的公式然后慢慢优化自己的算法
有没有感觉很像在训狗?狗狗乖的时候就给他点吃的(奖励),让他能优化自己的动作
由于我们的状态变量维度比较多,所以我们需要创建一个神经网络来近似Q函数
我们会把拿到奖励的经历放在一起,训练时抽取,来让他反复学习为什么这里得到了奖励
我们复制一份神经网络,这一份当做目标网络,当一个“靶子”,让神经网络有一个训练的目标
接下来我们进行一步误差处理:

Loss = [Q(s, a) - (r + γ × max Q_target(s', a'))]²

这一步反正就是在这里,我也不知道为什么是这样的公式,反正就是处理误差的一步
这样就可以进行迭代了,很简单吧(?)
总之接下来是我们具体的操作了

贪吃蛇作为一个老牌游戏,写起来虽然不简单,但也不是特别复杂
我们创建一个snake_game.py文件,准备开始写代码
首先,为了让我们最终能看得到ai训练的结果,我们一定需要可视化,那么我们选用最简单的tk来完成
由于贪吃蛇的代码不是我们的重点,在此我大概介绍一下写的过程:

框架:首先我们要先想好加入的库,因为是一个比较简单的游戏,我只选择了pygame(提供游戏基础),random(随机位置生成食物)和sys(提供退出键)这三个库
然后我们设定常量:其中包括屏幕设置,颜色,方向和游戏速度,这些都是我们写在函数之前的

接下来就该重头了,函数部分:

函数:首先要明确,我们不把函数直接写在文件中,而是选择创建一个类,将其他函数写为这个类的方法,这样会让后续ai训练的代码能直接创建实例来调用我们写的游戏函数,非常方便
其次,我们要写的函数大概有:

初始化函数init
重置游戏函数reset
生成食物函数(顺便附带游戏结算)generate_food
改变方向函数change_direction
执行游戏函数step
绘制地图,蛇等等可视化元素的函数(好多好多)
渲染函数render
游玩函数human_play
具体代码请点击这里~

ps:这部分代码有ai生成的部分

接下来才是本次实验的重头戏:训练ai的代码:

我们导入了一堆模块,抛去我们常用的pygame,random,os,numpy,datetime,csv以外,还有:
collections.deque——双端队列,可以自动淘汰新数据,用来充当经验池
matplotlib.pyplot——用于绘图,生成训练曲线(这个是问了ai,说这样结果会比较直观)
torch.PyTorch——深度学习框架,提供张量运算和自动求导
ps:张量就是三维及以上的数字容器
snake_game.py——引入游戏的代码,方便让ai直接进行游玩
这一系列模块,让我们能够实现ai的训练

接下来,我们要配置一系列参数,包括:

STATE_DIM = 11          # 状态维度
ACTION_DIM = 4          # 动作维度
MEMORY_SIZE = 50000     # 经验池大小
BATCH_SIZE = 64         # 批次大小
GAMMA = 0.9             # 折扣因子
EPSILON_START = 1.0     # 初始探索率
EPSILON_END = 0.01      # 最终探索率
EPSILON_DECAY = 200000  # 探索率衰减步数
LEARNING_RATE = 0.0003  # 学习率
TARGET_UPDATE = 2000    # 目标网络更新步数
TRAIN_STEPS = 500000    # 总训练步数
SAVE_INTERVAL = 50000   # 模型保存间隔
FRAME_SKIP = 2          # 帧跳过
LOG_INTERVAL = 100      # 数据记录间隔

STATE_DIM = 11
我们设计了十一个状态维度,分别是:

食物与蛇头的相对位置,2个维度
各个方向是否有危险,4个维度
当前移动方向,4个维度
蛇身长度占最大长度的比例,1个维度

这十一个状态维度将作为神经网络的输入

ACTION_DIM = 4
动作维度作为神经网络的输出,反映了ai模型对于当前状况的反应,分别对应了四个方向

MEMORY_SIZE = 50000
经验池大小设定为50000条数据,超出时自动删去最旧的

BATCH_SIZE = 64
每一批次随机抽取64条经验

GAMMA = 0.9
折扣因子决定了ai模型更关注短期还是长期,我们设定为0.9,让ai模型较少地考虑长期奖励。这是因为贪吃蛇本身是一个较为看重短期奖励的游戏,如果是棋牌博弈类的游戏,则更看重长期的奖励
类似于:我们在玩贪吃蛇的时候,不需要考虑一百步后会发生什么,但是下棋、打牌的时候就需要更长远的考虑
而我们并没有一杆子把长期奖励的权重拉的太低,太低的话会导致ai模型完全靠当前的反应操作,而没有了我们想要的“智能”效果

EPSILON_START
开始时 100% 随机探索,让ai模型尝试各种动作,快速积累各种经验

EPSILON_END
最终只剩 1% 随机动作,其余靠网络决策

EPSILON_DECAY
在 20 万步内从 1.0 线性衰减到 0.01

LEARNING_RATE
学习率 0.0003,较小值让训练更稳定

TARGET_UPDATE
每 2000 步同步一次目标网络

TRAIN_STEPS
总共训练 50 万步

FRAME_SKIP
每 2 帧执行一次动作,加快训练

我们定义了一个简单的神经网络,作为我们的策略网络和目标网络:

class DQN(nn.Module):
def __init__(self, state_dim=11, a


🔗 原文链接: 点击阅读原文

标签: AI 人工智能 技术博客
最后更新:2026年6月2日

daozi

这个人很懒,什么都没留下

点赞
< 上一篇

文章评论

您需要 登录 之后才可以评论
搜索
联系方式

QQ群:179730949
QQ群:114559024
欢迎您加入Android大家庭
本人QQ:136049925

赐我一丝安慰
给我一点鼓励

COPYRIGHT © 2023 魅力程序猿. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

豫ICP备15000477号