Я пытаюсь обучить агента PPO, используя стабильные Baselines3 в простой физике, основанной на животе, построенной с Pymunk. Цель состоит в том, чтобы найти угол запуска, который делает землю снаряда максимально близкой к цели при x = 1400. < /P>
Однако модель, похоже, вообще не учится. Действие остается в нижней границе (10.), и награда не улучшается. Вот моя настройка: < /p>
Пользовательская среда (Wordileenv) < /p>
from gym import spaces, Env
from simulation.simul import Simulation
import numpy as np
class ProjectileEnv(Env):
def __init__(self):
super().__init__()
self.min_angle = 10.0
self.max_angle = 80.0
self.last_angle = 45.0
self.last_landing_x = 0.0
self.target_x = 1400.0
self.action_space = spaces.Box(
low=np.array([self.min_angle], dtype=np.float32),
high=np.array([self.max_angle], dtype=np.float32),
dtype=np.float32
)
self.observation_space = spaces.Box(
low=np.array([0.0, 0.0, 0.0], dtype=np.float32),
high=np.array([1.0, 1.0, 1.0], dtype=np.float32),
dtype=np.float32
)
self.simulation = Simulation(1500, 500)
self.state = self._get_state()
def _get_state(self):
angle_norm = self.last_angle / 90.0
landing_x_norm = min(self.last_landing_x / 1500.0, 1.0)
error_norm = min(abs(self.last_landing_x - self.target_x) / 1500.0, 1.0)
return np.array([angle_norm, landing_x_norm, error_norm], dtype=np.float32)
def reset(self):
self.last_angle = np.random.uniform(self.min_angle, self.max_angle)
self.last_landing_x = 0.0
self.state = self._get_state()
return self.state
def step(self, action):
angle = float(action[0])
self.last_angle = angle
simulation_result = self.simulation.run(
angle=angle,
speed=500,
apply_air_resistance=True,
step=1/120,
record_trajectory=False
)
self.last_landing_x = simulation_result["landing_x"]
error = abs(self.last_landing_x - self.target_x)
reward = -error / self.target_x # normalized negative distance
self.state = self._get_state()
done = True
return self.state, reward, done, {}
def render(self, mode='human'):
pass
< /code>
Моделирование двигателя < /p>
import pymunk
import math
class SimulationEngine:
def __init__(self, width, ground_y, gravity=(0, 900)):
self.space = pymunk.Space()
self.space.gravity = gravity
self.width = width
self.ground_y = ground_y
self.add_ground()
def add_ground(self, friction=5.0):
body = pymunk.Body(body_type=pymunk.Body.STATIC)
body.position = (self.width / 2, self.ground_y)
shape = pymunk.Segment(body, (-self.width // 2, 0), (self.width // 2, 0), 5)
shape.friction = friction
self.space.add(body, shape)
def create_projectile(self, angle_deg, speed, mass=1, radius=5, friction=0.5, elasticity=0.0):
angle_rad = math.radians(angle_deg)
inertia = pymunk.moment_for_circle(mass, 0, radius)
body = pymunk.Body(mass, inertia)
body.position = (100, self.ground_y)
velocity = speed * pymunk.Vec2d(math.cos(angle_rad), -math.sin(angle_rad))
body.velocity = velocity
shape = pymunk.Circle(body, radius)
shape.friction = friction
shape.elasticity = elasticity
self.space.add(body, shape)
return body
def apply_air_resistance(self, body, k=0.002):
v = body.velocity
if v.length > 0:
drag = -k * v.length**2 * v.normalized()
body.apply_force_at_local_point(drag)
< /code>
runner < /p>
from simulation.engine import SimulationEngine
class Simulation:
def __init__(self, width, height):
self.engine = SimulationEngine(width, height - 50)
def run(self, angle=45, speed=400, apply_air_resistance=True, step=1/120, record_trajectory=False):
body = self.engine.create_projectile(angle_deg=angle, speed=speed, friction=5)
trajectory = [] if record_trajectory else None
direction_changed = False
while True:
if apply_air_resistance:
self.engine.apply_air_resistance(body)
self.engine.space.step(step)
if record_trajectory:
trajectory.append(body.position)
if body.velocity.y > 0 and not direction_changed:
direction_changed = True
if abs(body.position.y - self.engine.ground_y) < 10 and direction_changed:
break
self.engine.space.remove(body, *body.shapes)
return {
"landing_x": body.position.x,
"trajectory": trajectory if record_trajectory else None
}
< /code>
код обучения < /p>
from stable_baselines3 import PPO
from learning.env import ProjectileEnv
env = ProjectileEnv()
model = PPO("MlpPolicy", env, verbose=1, ent_coef=0.05, policy_kwargs={"log_std_init": 1.0})
model.learn(total_timesteps=50000)
obs = env.reset()
action, _ = model.predict(obs)
obs, reward, done, info = env.step(action)
print(f"Action taken: {action}, Reward: {reward}, Done: {done}")
< /code>
Симптомы < /p>
-action всегда начинается с [10.] и не меняется. < /p>
-reward постоянна между итерациями. Избавиться.>
Подробнее здесь: https://stackoverflow.com/questions/796 ... nment-rewa
Стабильный агент PPO-BASELINES3 не учится в пользовательской среде снаряда (постоянная вознаграждение/действие) ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение