前言
- 本文暂时并未完全实现,我还在努力学习中,这篇文章后续会随着我的学习进度,再来改进
- 目前只是记录下暂时写下的代码而已
- (边工作边学习个人爱好,所以经常会暂时性写下一些未完成的笔记,有意者看到的话请见谅哈)
- *(若期待本文最终结果的话,可以持续关注)
案例功能描述
- 有一个简易的打乒乓小游戏是这样的:一个小球会从顶部随机位置开始往下掉落,底部有个一定长度的横线,需要通过左右方向按键左右移动这顶部的横线来接住小球,如果没接住小球就算游戏失败,失败了再重新开始。
- 我们可以使用强化学习(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中的应用