OpenAI Gym
observations
reinforcement learning
AI environments
machine learning

Observations meaning - OpenAI Gym

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

In OpenAI Gym style environments, an observation is the information the environment gives the agent at each step. It is not the full world state in many tasks, but the view available for decision making. Understanding this distinction is crucial for building stable reinforcement learning pipelines.

What an Observation Represents

An observation is the input to the policy. After every reset and step, the environment returns an observation value that follows a declared observation space.

python
1import gymnasium as gym
2
3env = gym.make("CartPole-v1")
4obs, info = env.reset(seed=123)
5print("observation:", obs)
6print("shape:", obs.shape)
7print("space:", env.observation_space)
8
9env.close()

For CartPole, observation is a numeric vector. For other tasks, it can be an integer, image tensor, or dictionary.

Observation Space Types

Common observation space types include:

  • Box for continuous vectors or images.
  • Discrete for integer states.
  • Dict for structured observations.

Check space metadata before building your model so dimensions and dtypes are correct.

python
1import gymnasium as gym
2
3env = gym.make("FrozenLake-v1", is_slippery=False)
4obs, info = env.reset()
5print("obs:", obs)
6print("space:", env.observation_space)
7print("n states:", env.observation_space.n)
8
9env.close()

If your model expects vectors but receives integers, training will fail or silently learn poorly.

Observation Versus State

Many environments are partially observable. That means observation does not include every variable needed to infer the full underlying state in one step. This is normal in reinforcement learning and influences architecture decisions.

When partial observability is strong, you may need recurrent models or history stacking to improve decisions.

python
1from collections import deque
2import numpy as np
3
4class ObsStack:
5    def __init__(self, k):
6        self.k = k
7        self.buf = deque(maxlen=k)
8
9    def reset(self, first_obs):
10        self.buf.clear()
11        for _ in range(self.k):
12            self.buf.append(first_obs)
13        return np.concatenate(self.buf)
14
15    def push(self, obs):
16        self.buf.append(obs)
17        return np.concatenate(self.buf)

Simple stacking can improve learning in tasks where a single frame is ambiguous.

Preprocessing Observations Correctly

Normalize and cast observations consistently. A mismatch between training and evaluation preprocessing is a common source of unstable performance.

python
1import numpy as np
2
3def preprocess(obs):
4    arr = np.asarray(obs, dtype=np.float32)
5    return arr

For image environments, keep channel order and scaling explicit. For vector spaces, verify expected shape after wrappers are applied.

Debugging Observation Issues

Useful checks include:

  • Print observation shape after reset and after each wrapper.
  • Assert dtype and value ranges.
  • Validate model input tensor shape before optimization.
python
def validate_obs(obs, expected_shape):
    if obs.shape != expected_shape:
        raise ValueError(f"bad shape: {obs.shape}, expected: {expected_shape}")

A few assertions can save hours of debugging noisy reward curves.

Observation Wrappers in Practice

Gym wrappers can modify observation format and are commonly used to simplify training. For example, flattening structured observations or normalizing values helps make model input stable.

python
1import gymnasium as gym
2from gymnasium.wrappers import FlattenObservation
3
4env = gym.make("CartPole-v1")
5wrapped = FlattenObservation(env)
6
7obs, info = wrapped.reset(seed=0)
8print(obs.shape)
9wrapped.close()

Whenever wrappers are added, re-check observation shape and dtype, then update model input definitions. Many training failures come from wrappers introduced late without corresponding model updates.

Logging Observations During Rollouts

A simple rollout logger helps confirm that environment outputs stay within expected ranges.

python
1import gymnasium as gym
2import numpy as np
3
4env = gym.make("CartPole-v1")
5obs, info = env.reset(seed=1)
6
7for step in range(10):
8    action = env.action_space.sample()
9    obs, reward, terminated, truncated, info = env.step(action)
10    print(step, np.min(obs), np.max(obs), reward)
11    if terminated or truncated:
12        obs, info = env.reset()
13
14env.close()

This lightweight logging is especially helpful after environment upgrades or wrapper changes.

Common Pitfalls

  • Assuming observation contains complete environment state.
  • Ignoring observation space metadata and hardcoding shapes.
  • Mixing preprocessing logic between training and evaluation runs.
  • Feeding integer observations directly into vector models without encoding.
  • Applying wrappers that change shape without updating model input layers.

Summary

  • Observation is the agent input returned by reset and step.
  • Observation space defines valid shape, type, and bounds.
  • Observation may be partial, not full state.
  • Keep preprocessing consistent across all runs.
  • Add validation checks to catch shape and dtype errors early.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.