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中的应用
相关推荐
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
安静读书3 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
小二·5 小时前
java基础面试题笔记(基础篇)
java·笔记·python
小喵要摸鱼6 小时前
Python 神经网络项目常用语法
python
一念之坤8 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
wxl7812278 小时前
如何使用本地大模型做数据分析
python·数据挖掘·数据分析·代码解释器
NoneCoder8 小时前
Python入门(12)--数据处理
开发语言·python
LKID体9 小时前
Python操作neo4j库py2neo使用(一)
python·oracle·neo4j
小尤笔记9 小时前
利用Python编写简单登录系统
开发语言·python·数据分析·python基础
FreedomLeo19 小时前
Python数据分析NumPy和pandas(四十、Python 中的建模库statsmodels 和 scikit-learn)
python·机器学习·数据分析·scikit-learn·statsmodels·numpy和pandas