feat: refactor AlphaBetaSearch and ClassicalBot for improved evaluation and organization

This commit is contained in:
2026-04-07 22:46:44 +02:00
parent 558f43d0f6
commit 6a9ac55b31
28 changed files with 3618 additions and 12 deletions
+173
View File
@@ -0,0 +1,173 @@
# NNUE Training Pipeline
This directory contains the complete NNUE (Efficiently Updatable Neural Network) training pipeline for the Now-Chess bot.
## Overview
The pipeline generates 500,000 random chess positions, evaluates them with Stockfish, trains a neural network, and exports the weights as Scala code for integration into the engine.
## Prerequisites
Install Python dependencies:
```bash
pip install -r requirements.txt
```
Ensure Stockfish is installed. You can:
- Install via package manager: `apt-get install stockfish` (Linux) or `brew install stockfish` (macOS)
- Or download from [stockfish.org](https://stockfishchess.org)
Set the Stockfish path:
```bash
export STOCKFISH_PATH=/path/to/stockfish
```
## Pipeline Steps
### Quick Run
Run the entire pipeline:
```bash
chmod +x run_pipeline.sh
./run_pipeline.sh
```
This automatically runs all 4 steps in sequence and confirms each succeeds before continuing.
### Individual Steps
#### Step 1: Generate Positions
Generate 500,000 random chess positions:
```bash
python3 generate_positions.py positions.txt
```
Output: `positions.txt` (one FEN per line)
- Plays 8-20 random opening moves
- Filters out checks, captures available, and game-over positions
- Shows progress bar with tqdm
#### Step 2: Label with Stockfish
Evaluate each position with Stockfish at depth 12:
```bash
export STOCKFISH_PATH=/path/to/stockfish
python3 label_positions.py positions.txt training_data.jsonl $STOCKFISH_PATH
```
Output: `training_data.jsonl` (one JSON per line)
- Format: `{"fen": "...", "eval": 123}` (centipawns)
- Evals clamped to [-2000, 2000] to avoid mate score outliers
- Supports resuming if interrupted (checks for existing entries)
- Shows progress bar with tqdm
**Note:** This step is slow (~24-36 hours for 500K positions at depth 12). You can reduce games or use lower depth for testing.
#### Step 3: Train NNUE Model
Train the neural network:
```bash
python3 train_nnue.py training_data.jsonl nnue_weights.pt
```
Output: `nnue_weights.pt` (PyTorch model weights)
Architecture:
- Input: 768 binary features (12 piece types × 64 squares)
- Hidden 1: 256 neurons + ReLU
- Hidden 2: 32 neurons + ReLU
- Output: 1 neuron (sigmoid applied to eval/400)
Training:
- 20 epochs, batch size 4096, Adam optimizer (lr=1e-3)
- 90% train / 10% validation split
- Saves best weights by validation loss
- Shows train/val loss per epoch
**Note:** Requires GPU for reasonable speed (~2-4 hours). CPU falls back to ~8-16 hours.
#### Step 4: Export to Scala
Export weights as Scala code:
```bash
python3 export_weights.py nnue_weights.pt ../src/main/scala/de/nowchess/bot/bots/nnue/NNUEWeights.scala
```
Output: `NNUEWeights.scala`
- Object with `val` arrays for each layer's weights and biases
- Format: `Array[Float]` with precision sufficient for inference
- Includes shape comments for reference
## Scala Integration
### Step 5: NNUE Evaluator
Create `NNUE.scala` in `src/main/scala/de/nowchess/bot/bots/nnue/`:
```scala
package de.nowchess.bot.bots.nnue
class NNUE:
// Load weights from NNUEWeights.scala
// Convert Position to 768-feature vector
// Run inference: l1→ReLU→l2→ReLU→l3
// Return centipawn score
```
### Step 6: Integration
Implement `NNUEBot` that uses the NNUE evaluator for move selection.
## File Reference
| File | Purpose |
|------|---------|
| `requirements.txt` | Python dependencies |
| `generate_positions.py` | Step 1: Position generator |
| `label_positions.py` | Step 2: Stockfish labeler |
| `train_nnue.py` | Step 3: NNUE trainer |
| `export_weights.py` | Step 4: Weight exporter |
| `run_pipeline.sh` | Master script (runs steps 1-4) |
| `positions.txt` | Output: Raw FENs (500K) |
| `training_data.jsonl` | Output: FEN+eval pairs |
| `nnue_weights.pt` | Output: Trained weights |
| `../src/main/scala/.../NNUEWeights.scala` | Output: Scala weights |
## Tips
- **For testing:** Reduce `generate_positions.py` to 10,000 games for quick iteration
- **Resume labeling:** Run step 2 again; it skips already-evaluated positions
- **GPU acceleration:** Install CUDA for PyTorch to speed up training
- **Stockfish tuning:** Lower depth (e.g., 8 instead of 12) for faster labeling
- **Batch size:** Increase to 8192 if OOM; decrease if out of memory
## Troubleshooting
**ImportError: No module named 'chess'**
- Run: `pip install -r requirements.txt`
**Stockfish not found**
- Check: `which stockfish` or set `export STOCKFISH_PATH=/full/path/to/stockfish`
**CUDA out of memory**
- Reduce batch size in `train_nnue.py` (e.g., 2048)
- Or use CPU: Remove CUDA check and device setup
**Training loss not decreasing**
- Check data quality: Sample some entries from `training_data.jsonl`
- Increase learning rate to 1e-2 or 5e-4 for experimentation
- Verify Stockfish depth was sufficient (depth ≥ 10)
## References
- [NNUE Overview](https://www.chessprogramming.org/NNUE)
- [python-chess](https://python-chess.readthedocs.io/)
- [PyTorch](https://pytorch.org/)
- [Stockfish](https://stockfishchess.org/)