Value generalisation: value correction
Git Repo here.
I firmly believe that value generalisation[1]is the key to AI Alignment. That, indeed, it is necessary and almost sufficient for alignment.
But I won’t be arguing that grand point today; instead, I’ll focus on a specific RL example of an agent that displays value correction: it realises its current reward function is (probably) incorrect, and acts to correct it.
Thus there are:
The initial situation, in distribution, where the human displays how to maximise the true reward.
The out of distribution situation where the agent finds a hack to exploit its reward function estimate, and turns against what we wanted it to do.
The value error detection stage where the agent realises that its reward function estimate is probably incorrect.
The value correction stage where the agent corrects its reward function back to the original true reward.
In this post, all the methods presented will by syntactic: the agent is not assumed to have any understanding of the situations and the key features are not identified to it.
The game of human life
Introducing a new, very simple, game called “Humans[2]”. Humans, fleeing danger, enter the screen from the left. The objective is to save them by moving them off the right of the screen.

But there are obstacles on the way, and the humans will mill about if they are blocked.

And they will shortly expire if they can’t get out of the screen quickly.

There are two command: drill (‘d’) and explode (‘e’). Drill does… what, you want to know about explode? Well, if the player presses ‘e’, the rightmost human will explode, knocking away two obstacle blocks in front of them and behind them—but also killing themselves and any humans nearby.

This is almost never a good solution; to remind the player of the mistake, a large frowny face will appear to drive the disapproval home.

Much more reasonably, if the player presses ‘d’, the rightmost human will drill the obstacle just in front of them (better time it so that they’re facing the right way). Enough drilling, and the humans can get off the map.

The score, the true reward

Since there is a cooldown for drilling, the optimal policy
Learning agent with value correction
A learning agent will run a series of subagents to estimate the reward function from human-provided training data, then learn the optimal policy from that reward function, then question its learnt reward by comparing the high-reward states in its optimal policy versus those in the training data, re-compute another reward function estimate that is closer to the true reward, and finally settle on a prudent policy that is close to the true optimal policy.
Estimating the reward function
A human will generate several playthroughs of the game to illustrate how it works, efficiently choosing to drill through the obstacles and getting the humans off the map in time. The data is labelled: every time a human is saved, that is identified as a reward increase.
The learning agent runs an evaluation subagent on this data. It is given the ten frames before the human is saved, and the ten frames afterwards, and trains to recognise these are reward increase situations.

Zooming in on the critical two frames where the human is saved; note the human vanishing and the score bar expanding:

This evaluation agent thus computes the proxy reward
Reward hacking: failed value generalisation
Using the evaluation agent as the definition of
But soon things go very wrong. It turns out that “human walking off the screen” was not what
That isn’t a problem, yet, because the human being saved and the score bar expanding always trigger together. But, when an explosion is triggered, the frowny face appears—thus there is giant blob of yellow pasted all across the score bar:

High reward?
This activates
This graph compares the value of
So the RL-subagent quickly and merrily learns to explode the humans, one after the other, to maximise

Misalignment’s standard outcome
As is usual in these cases, the erroneous maximisation of the proxy turns out to be much easier than maximising the true reward. Trained on
As is not usual but sometimes happens, an ostensive safety precaution—the frowny face to remind a human player that they were playing poorly—ends up being the cause of misalignment.
Detecting the potential error
Ok, so far, that is a classical failure of goal misgeneralisation (or reward hacking, or a failure of symbol grounding, or Goodhart failure, or… most of these failure modes are tightly related). We humans can see the error clearly. But how could a relatively limited agent correct itself?
The first step is to identify that goal misgeneralisation may have happened. We have some advanced techniques for this, but there are much simpler methods that work here. The first step is to notice that the high-scoring events in the training data (human walks off to the right, score bar expands) are wildly different from the high-scoring events of the-maximising agent (explosions and frowny faces).

One of these things is not like the other.
To do this, the agent extracts the high-scoring events under
The data is stratified into four datasets—high-scoring under training data vs high-scoring under
The classifier separated the two high-scoring types instantly, in the first epoch, but took longer to separate levels 0-9 from 10-19. Thus high

This is not itself damning; it could just be that the maximising agent has found a clever hack to get more of the true
Calling for help
At this point, one of the options would be for the agent to route its decisions to a human, displaying the high-scoring events, contrasting them with the high reward events in its training data, and asking, in effect, ‘are these both genuine high rewards’?
But, so far, the correction process has been unsupervised since the initial training data; let’s see if we can push further without needing human intervention.
Re-evaluating the reward
The agent could now re-evaluate the reward in the following way. It runs an evaluation agent on the training data, as before. But it adds the high-
It thus learns a reward function
This turns out to be very close to the original true reward
It then trains an RL-subagent on
From these
Thus, though
Prudence in the face of uncertainty
So the agent has two rewards
Standard prudential moves would be maximise the worst case of the two rewards (minimise regret) either over each state or over the whole episode, or to maximise some normalised mix of the two[4].
We’ll consider all three mixes, and include two other variants of the normalised mix: where
Thus
Using these syntactic tools, a prudent RL agent could therefore switch to
Conclusion
This is just an illustration, in a small toy model, of simple value correction approaches. These can be used by agents—every very simple agents—to detect and correct errors in naive generalisations from initial training data.
More sophisticated agents will have more advanced value generalisation techniques available to them; I’m planning to push the frontier of what exists way further than it currently is.
Which I’ve also called value extrapolation, or concept extrapolation where the concept is a value. ↩︎
Inspired by this old game. ↩︎
- ^
Or there could be a spurious change in the data; that’s why we would, in general, need more advanced techniques that just checking if a binary classifier can tell the sets apart.
- ^
Formally, if
is a policy, the expected episodic reward for , and the expected reward for using the -maximising policy, we are looking for policies that maximise one of: with with
Hey Stuart! Great post. I got curious and forked the Humans repo to run a comparison between injecting negative and positive samples into the reward model.
The negatives that produce R_c seem to fix the agent’s outward behavior without actually fixing the concept. bar_only ends up being essentially unchanged between R_p and R_c (0.578 to 0.597), and frozen_bar stays near 0 in both, which suggests both models are probably treating the score bar as both sufficient and necessary for getting reward. This held consisently across the whole range of # neg. samples that I tested (from 0 up to 720, which was your original number). I’d bet it’s because negatives come from rollouts, and you’ll never find a rollout in which a human save occurred without the associated bar movement, so negatives can only ever remove a hack, but can’t install a concept.
On the other hand, using counterfactual positives moved both probes in their respective right directions. Using a range of # re-rendered frozen_bar frames labeled positive (as low as 40) ended up lifting the frozen_bar probe off 0, while also dropping bar_only significantly (0.516 → 0.191, even though no bar_only frame was ever labeled negative), all on held-out levels.
Code: https://github.com/Swaraag/Humans-the-game-Self-correcting-RL
Would love to hear your thoughts (sent you an email the other day as well in case you’d like to respond there).
That is very interesting. Thanks for continuing the work.
So it seems that, in this instance, even though R_c fixed the behaviour, it wasn’t by finding the correct feature but by filtering out the misbehaviour (giant frowny face). It seems that we may need to use the full machinery of ACE (see here and here) - or maybe even that wouldn’t be enough, with such sparse data?
Have sent you an email.
I actually think data sparsity may not be the concern here—mainly because I was able to begin disambiguating humans saved and bar movement with as few as 40 counterfactual samples. On the other hand, I only knew I had to freeze the bar because I already knew the bar was the confound, which is information the agent couldn’t have surfaced on its own. The work ACE would actually have to do is identify that axis, which depends on whether the true hypothesis exists in ACE’s generated ensemble. In this case, the environment is small enough that it probably does, but I doubt that holds up with much larger environments.
There’s also the question of what ACE would disagree on. The heads can diverge on novel unlabeled inputs, but for that divergence to be about the save/bar axis specifically, there’d have to be inputs where those two can come apart, and in this environment they don’t occur naturally either, since every rollout containing a save also contains bar movement. The frozen_bar frames had to be re-rendered before anything could use them, so the binding constraint might be less about how much data there is and more about whether data that could separate the concepts exists in the first place.