alexhutcheson
Joined 13 years ago
Joined 13 years ago
In addition, the "reasoning-oriented reinforcement learning" step (section 2.3.2) used an approach that is almost identical to RLHF in theory and implementation. The main difference is that they used a rule-based reward system, rather than a model trained on human preference data.
If you want to train a model like DeepSeek-R1, you'll need to know the fundamentals of reinforcement learning on language models, including RLHF.
My friendly feedback on this work-in-progress: I believe it could benefit from more introductory material to establish motivations and set expectations for what is achievable with RLHF. In particular, I think it would be useful to situate RLHF in comparison with supervised fine-tuning (SFT), which readers are likely familiar with.
Stuff I'd cover (from the background of an RLHF user but non-specialist):
Advantages of RLHF over SFT:
- Tunes on the full generation (which is what you ultimately care about), not just token-by-token.
- Can tune on problems where there are many acceptable answers (or ways to word the answer), and you don't want to push the model into one specific series of tokens.
- Can incorporate negative feedback (e.g. don't generate this).
Disadvantages of RLHF over SFT:
- Regularization (KL or otherwise) puts an upper bound on how much impact RLHF can have on the model. Because of this, RLHF is almost never enough to get you "all the way there" by itself.
- Very sensitive to reward model quality, which can be hard to evaluate.
- Much more resource and time intensive.
Non-obvious practical considerations:
- How to evaluate quality? If you have a good measurement of quality, it's tempting to just incorporate it in your reward model. But you want to make sure you're able to measure "is this actually good for my final use-case", not just "does this score well on my reward model?".
- How prompt engineering interacts with fine-tuning (both SFT and RLHF). Often some iteration on the system prompt will make fine-tuning converge faster, and with higher quality. Conversely, attempting to tune on examples that don't include a task-specific prompt (surprisingly common) will often yield subpar results. This is a "boring" implementation detail that I don't normally see included in papers.
Excited to see where this goes, and thanks to the author for willingness to share a work in progress!
The one nice thing about GUD is that the interface is consistent across debuggers, so I don’t need to refresh myself on the keyboard shortcuts when switching between debugging Python with pdb and C++ with lldb.
[1] https://www.gnu.org/software/emacs/manual/html_node/emacs/GD...
[2] https://www.gnu.org/software/emacs/manual/html_node/emacs/St...
[1] https://sourceware.org/gdb/current/onlinedocs/gdb.html/TUI.h...
(setq vc-ignore-dir-regexp
(format "\\(%s\\)\\|\\(%s\\)"
vc-ignore-dir-regexp
tramp-file-name-regexp))
VC is quite chatty and assumes that filesystem operations have a negligible cost. Before I disabled it, VC was adding >1 second to every find-file operation over Tramp.I also recommend using the direct-async-process connection property[2], which significantly decreases the latency of async process creation.
[1] https://www.gnu.org/software/emacs/manual/html_node/tramp/Fr...
[2] https://www.gnu.org/software/emacs/manual/html_node/tramp/Re...
In general, fine-tuned models often fail to generalize well on inputs that aren’t very close to examples in the fine-tuning data set.
The downside is that not every package is packaged for Debian, and the versions are a bit stale.
https://packages.debian.org/search?keywords=ELPA+&searchon=n...
I used to self-host a Phabricator instance, which I liked a lot, but the upstream maintainer made the reasonable decision to step away.
My guess is there is not much of a niche for self-hosted solutions anymore. The GitHub Issues free tier covers most of the low-complexity use-cases, while higher-complexity use-cases are addressed by enterprise SaaS.
It doesn’t get that many visitors, because it’s within Fort Meade (home of the NSA), and most people probably don’t even realize it’s open to the public.
A typical example would be: you have an array of objects of constant size, and you’re reading a double field from a constant offset within each object. The hardware prefetcher will “recognize” this access pattern and prefetch that offset every sizeof(obj) bytes.
The major downsides (vs. a struct-of-arrays design with full spatial locality) are:
1. Every prefetch pulls a full cache line, but the cache line will include data you don’t need. In this example, every cache line might have 64 bytes of data, but you only needed the one double field (8 bytes) - the rest is not useful. If you were iterating over an array of doubles you could have pulled 8 double fields in a single cache line.
2. Specific performance is hardware-dependent, so it’s hard to guarantee performance on e.g. low-end cores, short loops, or unusually long strides.
It’s interesting to me that they’ve settled on using standard Neoverse cores, when almost everything else is custom designed and tuned for the expected workloads.
[Disclosure: Work at Google, but not on that. Just thought that course was particularly well-designed.]