You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flappy Bird线性Q学习近似智能体无学习效果,求技术帮助

Flappy Bird线性Q学习智能体无法学习的问题排查

我来自瑞士,英语并非母语,在此先致歉。目前我正在开发一个强化学习智能体来玩Flappy Bird,采用线性Q学习近似方法,但智能体似乎无法学习。它持续获得相同的奖励,我不确定是代码存在问题,还是需要更长的训练时长(比如8小时)。我甚至尝试过DQN算法,但仍然没有效果。

以下是你的代码:

import flappy_bird_gymnasium  # Assuming this is a custom environment
import gymnasium as gym
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
from random import *
env = gym.make("FlappyBird-v0", render_mode="rgb_array")

lr = 0.01
decay = 0.0000001
max_steps = 1000
gamma = 0.95
min_eps = 0.001
max_eps = 1

neps = 100000
W = np.random.rand(12, 2)
print(env.observation_space)

def plot_win_rate(rewards_all_episodes):
    rewards_optimal = np.array(rewards_all_episodes)
    rewards_optimal = np.array([0 if x == -1 else x for x in rewards_optimal])
    rewards_optimal = rewards_optimal.cumsum()
    win_rate_optimal = rewards_optimal / np.arange(1, len(rewards_all_episodes) + 1)

    plt.plot(np.arange(1, len(rewards_all_episodes) + 1), win_rate_optimal)
    plt.xlabel('Episode')
    plt.ylabel('Win Rate')
    plt.title('Win Rate per Episode')
    plt.show()


def f(state):
    
    return np.array(state).reshape(12, -1)


def epsilon_greedy(W, epsilon, state):
    features = f(state)
    if np.random.uniform(0, 1) > epsilon:
        action = np.argmax(np.dot(W.T, features))
        retur=0
    else:
        action = 0 if uniform(0,1)>0.07 else 1
        retur=1

    return action, retur

def gradient(X,W,Y):
    m = X.shape[0]
    return (1/m) * (X.T @ (X @ W - Y))

def regression(X, W,Y):
    W-=lr*gradient(X,W,Y)
    return W
    
def update(W, state, reward, newstate):
    q_values = np.dot(f(state).T, W)
    next_q_values = np.dot(f(newstate).T, W)

    W += lr * np.outer(f(state), (reward + gamma * np.max(next_q_values) - q_values))
    

    return W


def train(neps, min_eps, max_eps, decay, env, max_steps, W, fr):
    rewards_all_episodes = []

    for episode in tqdm(range(1, neps + 1)):
        epsilon = min_eps + (max_eps - min_eps) * np.exp(-decay * episode)
        state, _ = env.reset()
        rewards = 0
        X=[]
        Y=[]
        while True:
            
            action, retur= epsilon_greedy(W, epsilon, state)
            
            new_state, reward, done, _, _ = env.step(action)
            W=update(W, state, reward, new_state)
            rewards += reward
            X.append(reward)
            Y.append(state)
            if done:
                rewards_all_episodes.append(rewards)
                break

            state = new_state
        
        if episode % fr == 0:
            q_values = np.dot(f(state).T, W)
            print(W)
            print("epsilon ", epsilon)
            print("\nQ-values:", q_values)
            print("Episode {}: Average Reward: {}".format(episode, rewards))

    return W, rewards_all_episodes


W, rewards_all_episodes = train(neps, min_eps, max_eps, decay, env, max_steps, W, 2500)
plot_win_rate(rewards_all_episodes)
np.save("trained_weightsQL.npy", W)


print(rewards_all_episodes, "gamma**step*")
while True:
    pass

核心问题排查与修正建议

  • 特征映射函数f(state)逻辑错误
    FlappyBird-v0的观测空间通常是4维(鸟的y坐标、垂直速度、管道x偏移、管道间隙y坐标),你直接将其reshape为12维,本质是对原始特征的无意义拆分,导致Q值计算完全偏离预期。正确做法是做特征扩展,比如生成原始特征的二次组合、常数项等,示例:

    def f(state):
        s = np.array(state)
        # 基础特征+二次组合+常数项,扩展到11维(可调整)
        features = np.concatenate([s, s**2, s[:2]*s[2:], [1]])
        return features.reshape(-1, 1)
    

    同时要对应调整权重W的维度(比如11×2)。

  • ε-贪心策略的随机动作分布不合理
    代码中随机动作93%概率选0(不跳),7%选1(跳),这种极端分布会让智能体无法探索到有效的跳跃时机。改成均匀随机选择动作:

    action = np.random.choice([0, 1])
    
  • ε衰减系数过小
    当前decay=0.0000001导致10万轮训练后ε仍接近1,智能体几乎全程随机探索,根本无法利用学到的策略。调整为decay=0.0001,让ε快速降到合理的探索-利用平衡区间。

  • 学习率设置偏大
    lr=0.01对于线性近似来说容易导致权重震荡,建议先降到0.001,根据训练曲线再微调。

  • 冗余代码干扰逻辑
    gradient、regression函数以及train中的X、Y列表均未被使用,直接删除以简化代码,避免混淆。

  • 奖励处理错误
    plot_win_rate中将-1的奖励改为0,会扭曲训练的反馈信号,直接用原始奖励计算即可:

    def plot_win_rate(rewards_all_episodes):
        rewards_cumsum = np.cumsum(rewards_all_episodes)
        win_rate = rewards_cumsum / np.arange(1, len(rewards_all_episodes)+1)
        plt.plot(np.arange(1, len(rewards_all_episodes)+1), win_rate)
        plt.xlabel('Episode')
        plt.ylabel('Average Cumulative Reward')
        plt.title('Reward Trend per Episode')
        plt.show()
    

训练建议

先修正上述问题后,尝试跑1-2万轮训练,观察奖励曲线是否有上升趋势。如果仍无改善,再考虑:

  1. 调整γ值(比如0.99,增强长期奖励的权重)
  2. 尝试对观测特征做归一化处理
  3. 验证环境的奖励机制是否符合预期(比如每存活一步+1,撞管道-1)

内容的提问来源于stack exchange,提问作者Aleksander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:36:02