Pytorch强化学习初学者笔记 -- 使用强化学习(Reinforcement Learning)来让程序自动学习玩乒乓小游戏

前言

  • 本文暂时并未完全实现,我还在努力学习中,这篇文章后续会随着我的学习进度,再来改进
  • 目前只是记录下暂时写下的代码而已
  • (边工作边学习个人爱好,所以经常会暂时性写下一些未完成的笔记,有意者看到的话请见谅哈)
  • *(若期待本文最终结果的话,可以持续关注)

案例功能描述

  • 有一个简易的打乒乓小游戏是这样的:一个小球会从顶部随机位置开始往下掉落,底部有个一定长度的横线,需要通过左右方向按键左右移动这顶部的横线来接住小球,如果没接住小球就算游戏失败,失败了再重新开始。
  • 我们可以使用强化学习(Reinforcement Learning)来让程序自动学习玩这个简单的小游戏。

代码在此

  • 下面是一个基于 PyTorch 和 OpenAI Gym 的示例实现
    • (【注】:以下代码暂时记录而已,我还没为实践证实,只是个思路,其中一定存在很多问题,待后续抽空学习并实践之后再来修改)
python 复制代码
import gym
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim

# 定义游戏环境
class BallCatchingEnv(gym.Env):
    def __init__(self):
        super(BallCatchingEnv, self).__init__()
        self.action_space = gym.spaces.Discrete(3)  # 左移、不动、右移
        self.observation_space = gym.spaces.Box(low=np.array([0, 0]), high=np.array([100, 100]), dtype=np.float32)
        self.bar_position = 50
        self.ball_position = np.random.randint(0, 100)
        self.ball_velocity = np.random.uniform(-5, 5)

    def step(self, action):
        # 根据动作更新bar位置
        if action == 0:
            self.bar_position = max(0, self.bar_position - 5)
        elif action == 1:
            pass
        else:
            self.bar_position = min(100, self.bar_position + 5)

        # 更新球位置
        self.ball_position += self.ball_velocity
        if self.ball_position <= 0 or self.ball_position >= 100:
            self.ball_velocity = -self.ball_velocity

        # 检查是否接住球
        reward = 0
        done = False
        if self.ball_position >= self.bar_position and self.ball_position <= self.bar_position + 10:
            reward = 1
        else:
            reward = -1
            done = True

        return np.array([self.bar_position, self.ball_position]), reward, done, {}

    def reset(self):
        self.bar_position = 50
        self.ball_position = np.random.randint(0, 100)
        self.ball_velocity = np.random.uniform(-5, 5)
        return np.array([self.bar_position, self.ball_position])

# 定义 Q 网络
class QNetwork(nn.Module):
    def __init__(self, input_size, output_size):
        super(QNetwork, self).__init__()
        self.fc1 = nn.Linear(input_size, 64)
        self.fc2 = nn.Linear(64, output_size)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 定义 DQN 代理
class DQNAgent:
    def __init__(self, env, lr=0.001, gamma=0.99, epsilon=1.0, epsilon_decay=0.995, epsilon_min=0.01):
        self.env = env
        self.q_network = QNetwork(env.observation_space.shape[0], env.action_space.n)
        self.optimizer = optim.Adam(self.q_network.parameters(), lr=lr)
        self.gamma = gamma
        self.epsilon = epsilon
        self.epsilon_decay = epsilon_decay
        self.epsilon_min = epsilon_min

    def select_action(self, state):
        if np.random.rand() < self.epsilon:
            return self.env.action_space.sample()
        else:
            state = torch.from_numpy(state).float().unsqueeze(0)
            q_values = self.q_network(state)
            return q_values.argmax().item()

    def train(self, num_episodes):
        for episode in range(num_episodes):
            state = self.env.reset()
            done = False
            while not done:
                action = self.select_action(state)
                next_state, reward, done, _ = self.env.step(action)
                target = reward + self.gamma * self.q_network(torch.from_numpy(next_state).float().unsqueeze(0)).max()
                loss = (self.q_network(torch.from_numpy(state).float().unsqueeze(0))[0][action] - target) ** 2
                self.optimizer.zero_grad()
                loss.backward()
                self.optimizer.step()
                state = next_state
            self.epsilon = max(self.epsilon_min, self.epsilon * self.epsilon_decay)
            print(f"Episode {episode}, Epsilon: {self.epsilon:.2f}")

# 训练代理
env = BallCatchingEnv()
agent = DQNAgent(env)
agent.train(1000)
  • 这个示例使用了深度 Q 网络(DQN)算法来学习玩这个简单的小游戏。我们首先定义了游戏环境 BallCatchingEnv,然后创建了一个 Q 网络 QNetwork 和一个 DQN 代理 DQNAgent

在训练过程中,代理会探索环境并学习如何选择最佳动作来接住下落的小球。它使用 epsilon-greedy 策略,在训练初期更倾向于探索(随机选择动作),而在训练后期更倾向于利用(选择预测的最佳动作)。

通过运行 agent.train(1000),代理会在 1000 个回合中学习如何玩这个游戏。你可以观察代理的表现,并根据需要调整训练参数,如学习率、折扣因子和 epsilon 衰减率等。

总结

  • 这只是一个简单的示例,我感觉是比较适合初学者入门的。我也是为了逐步迈入机器学习这个领域而想到的这个小案例,如果我能现在掌握这个小案例,再逐步扩展的话,这样学习会更有趣更有动力更合理一些;毕竟一下子去实现太大的目标或者直接去看一整套乏味的学习资料或教学视频的话,会很容易产生迷茫甚至厌烦;
  • 后续可以根据需求再进行慢慢扩展和优化,比如添加更复杂的游戏规则、调整网络结构、尝试其他强化学习算法等。通过实践和探索,可以慢慢掌握深度学习在游戏AI中的应用
相关推荐
SiYuanFeng42 分钟前
Colab复现 NanoChat:从 Tokenizer(CPU)、Base Train(CPU) 到 SFT(GPU) 的完整踩坑实录
python·colab
炸炸鱼.2 小时前
Python 操作 MySQL 数据库
android·数据库·python·adb
_深海凉_2 小时前
LeetCode热题100-颜色分类
python·算法·leetcode
AC赳赳老秦3 小时前
OpenClaw email技能:批量发送邮件、自动回复,高效处理工作邮件
运维·人工智能·python·django·自动化·deepseek·openclaw
zhaoshuzhaoshu3 小时前
Python 语法之数据结构详细解析
python
AI问答工程师3 小时前
Meta Muse Spark 的"思维压缩"到底是什么?我用 Python 复现了核心思路(附代码)
人工智能·python
zfan5204 小时前
python对Excel数据处理(1)
python·excel·pandas
小饕4 小时前
我从零搭建 RAG 学到的 10 件事
python
老歌老听老掉牙4 小时前
PyQt5+Qt Designer实战:可视化设计智能参数配置界面,告别手动布局时代!
python·qt
EmmaXLZHONG5 小时前
Deep Learning With Pytorch Notes
人工智能·pytorch·深度学习