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中的应用
相关推荐
3DVisionary4 分钟前
捕捉亚毫米级裂纹演化!DIC技术为裂纹扩展与抗裂研究带来全新方案
人工智能·python·3d·应变测量·金属3d打印·dic精度检验方法·各向异性
smchaopiao5 分钟前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python
Eward-an18 分钟前
LeetCode 76. 最小覆盖子串(详细技术解析)
python·算法·leetcode·职场和发展
李昊哲小课23 分钟前
Python itertools模块详细教程
数据结构·python·散列表
小猪弟44 分钟前
【app逆向】某壳逆向的wll-kgsa参数,signature参数
python·逆向·wll-kgsa·signature·
对方正在长头发2251 小时前
写了个 Windows 端口映射管理工具,再也不用敲命令了
python
tang777891 小时前
哪些行业用动态代理ip?哪些行业用静态代理IP?怎样区分动态ip和静态ip?(互联网人必码·实用长文)
大数据·网络·爬虫·python·网络协议·tcp/ip·智能路由器
龙泉寺天下行走1 小时前
LangChain Skills框架核心解析
python·langchain·aigc
echome8881 小时前
Python 装饰器详解:从入门到精通的实用指南
开发语言·python