Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Build your own fly-based chess model

You will build a small chess model on top of a real fruit-fly connectome. The connectome and the pretrained FlyNet numbers stay fixed. The new piece is yours: a scorer that gives a number to each legal move.

By the end of this notebook, you will be able to:

  1. Load the published fly network and a set of real chess positions.

  2. Read one position, its legal moves, its Stockfish move, and the neuron activity.

  3. Choose training positions from a prepared pool, and leave the test positions out.

  4. Create a model, train it, and test it with helper functions.

  5. Change one setting, make a second model, and compare the two on the same test positions.

Playing a game in the other ChessFly notebook does not train anything. Training happens when you run the training cell in this notebook.

Stockfish top-move agreement is one narrow metric. It is not a complete chess-strength assessment.

The network files are downloaded in your browser from ChessFly. The first load is about 148 MB. This notebook has not been run on DataHub yet.

0. Warmup

In the cell below, answer this question: What would a computer need, besides a wiring diagram, before it could choose a chess move?

Add your response here:

1. Two places, one model

This lab uses two different programs.

In the browser. A published worker downloads the FlyWire connectome and the pretrained FlyNet weights. It runs the fly network on each chess position. For every position it returns 41,692 numbers. Those numbers are the readout neurons the pretrained decoder reads. The worker runs in ordinary browser JavaScript so those floats can be sent back. The game page can still use WebGPU.

In Python. Your cells receive that activity matrix. You choose a few of its columns, then train a small scorer. The scorer’s only choices are the legal moves of the board it is looking at. Python does not run the 15 million connections. If the browser has not sent the matrix, Python will say so instead of inventing activity.

The connectome, the signs of the connections, the encoder, the connection strengths, the gains, the shifts, and FlyNet’s decoder stay fixed. Train changes only the scorer you create.

2. Load the chess examples

The file data/lichess_lab.csv has 60 real positions from Lichess/chess-position-evaluations (CC0). stockfish_uci is the first move of the published Stockfish line. Each of those moves is legal on its own board.

The split column was assigned before any training, using row order only. Rows marked test are held out. Rows marked pool are the ones you may train on. This dataset has no game id, so positions from the same game could not be kept together. Details are in data/README.md.

Question

The test indexes are already chosen. Why should those rows stay out of the list you train on?

Add your response here:

3. Load the fly network, then let Python receive the activity

Run the next cell. A box appears. Press Load the real network and wait.

The browser downloads the connectome and the weights, then runs all 60 positions. When the transfer works, the status line says that Python received the activity matrix and prints its shape. Then run the cell after the box. That cell is the Python side of the handoff. If you run it too early, it stops and tells you the activity is not here yet.

When the status line says Python received the activity matrix, run the next cell.

You should see a shape (60, 41692) and the word finite. The 60 rows are the chess positions, in the same order as the table above. The 41,692 columns are the readout neurons.

Question

The activity sum is a total of neuron values. Which program computed the fly network: the browser, or this Python cell?

Add your response here:

4. Inspect one position

Pick a pool index. The default is 0. You can change it to another pool index from the table.

The cell prints the board, the Stockfish move, every legal move the scorer will be allowed to consider, and a short description of that row of activity. It does not print all 41,692 numbers.

Predict

Before any training, the scorer’s weights are zeros, so it picks the alphabetical baseline. For the position you just inspected, write that baseline move. After training, do you expect the model to match Stockfish on the test rows? Why or why not?

Add your response here:

5. Choose training examples

Edit the list below. Use indexes from the pool only. Index 4 is a test position, so it is not in the default list.

The check refuses test indexes. If you add one, the cell stops before any model is created.

Question

What should the helper do if a test index is placed in train_rows?

Add your response here:

6. Create a fresh model

n_features is how many readout neurons your scorer may use. The helper keeps the neurons whose activity varies the most on your training rows only. Test rows do not vote. The move itself is described by 33 fixed numbers: start file, start rank, end file, end rank, and a constant. Those numbers are not trained.

With n_features = 16, the new model has 16 × 33 = 528 trainable numbers, all starting at zero. This object is model_v1. A later model will be a different object.

You should see weight length 0.0000. If you asked for 16 features, you should see 528 trainable numbers.

7. Train your model

Edit learning_rate and n_rounds, then run the cell. This is the step that changes model_v1’s numbers. The connectome does not change.

A larger learning rate takes a bigger step. More rounds repeat the step. The lines below show the weight length before and after each round. If you change the settings and run the cell again, the new length should differ from a run with the old settings, because training continues from the current weights. Call reset_scorer(model_v1) first if you want to start again at zero.

You should see the weight length move away from zero. Training matches count only the rows in train_rows. They are not a test result.

8. Test

The test rows were not used to choose features or to fit. The table shows the alphabetical baseline, your model’s move, and the Stockfish move. Every model move should be legal on that board.

Read the training count and the test count separately. Matching the training rows does not show that the model will match the test rows.

Question

Your model may agree with Stockfish on several training rows. Does that agreement mean the model is a strong chess player? What does the sentence about the metric say?

Add your response here:

9. Make a second model by changing one setting

model_v2 is a new scorer. Creating it does not reset model_v1. The cell below changes one setting: n_features is 8 instead of 16. The training rows, learning rate, and number of rounds stay the same.

The comparison uses the same test positions for both models.

You should see two different parameter counts. model_v1’s weight length should be the same number before and after model_v2 trains.

Question

Reset cleared model_v2. What happened to the weights in model_v1?

Add your response here:

10. Optional: turn off connections in stored order

This section does not train a model. It changes the fly network inside the browser, then sends a new activity matrix to Python.

The button turns off the first 2,000,000 connections in stored order. That phrase means the first 2,000,000 entries of the published weight array. It is not a named brain region or a chosen circuit. Restore writes those same numbers back. The published website is not changed.

An activity sum adds the readout numbers. It is not a measure of intelligence or of chess performance. Your scorer’s weights stay whatever they are unless you call train_scorer again. Do not create a new scorer here if you want to keep the same features: a new scorer would choose neurons again.

Run the next cell, scroll back to the fly box, press the turn-off button, and wait until the status says Python received a new activity matrix. Then run the cell after that. The restore button puts the connections back and sends another matrix.

Question

Did the activity sum for index 0 change? Did model_v1’s weights change? What does an activity sum tell you, and what does it leave out?

Add your response here:

Sources

  • ChessFly model card and weights: huggingface.co/mlabonne/chessfly. The hosted files are loaded in the browser from mlabonne-chessfly.static.hf.space/data/.

  • The worker is fetched from that site and patched in memory so Python can receive readout floats. This repository does not copy the worker, the connectome, or the weight file. If the published program no longer contains the expected lines, the loader stops.

  • FlyWire public-release guidelines, CC BY-NC 4.0: flywire.ai/guidelines. The model card says those terms apply to anything derived from the graph. Activity is computed at runtime and is not saved here.

  • Positions: Lichess/chess-position-evaluations, CC0. The lab file is data/lichess_lab.csv. How it was sampled is in data/README.md.

  • Helper code: fly_scorer.py trains your scorer. fly_activity.py is the browser handoff.

  • Playing a game stays in ChessFly: a fruit-fly brain map that plays chess.