Skip to content

Using winterfell for neural networks #375

@timk11

Description

@timk11

Hi team. I'm working on a project using winterfell in conjunction with a neural network trainer. My project repo is at https://github.com/timk11/zk-trainer and the main logic is in prover.rs. The aim is to train a small (publicly visible) neural network on a private dataset, and to use a zk-STARK to show that the training was authentic. Public inputs are hashes of the initial model and final model and a hash of the dataset. My questions are mainly about the trace table and constraint degree calculations.

Trace table - The trace table columns consist of flag, len_sample, hidden_size, learning_rate, dataset, expected, dataset_hash, wb_hash, and weights and biases. These are all one column each except for dataset (one sample per row, occupying len_sample columns, repeating for each epoch) and weights and biases (updated at each row except when flag == 1, variable number of columns). The update loop for each epoch is in lines 110-196.

Q1: Have I used the right approach here, including having the dataset in the trace table as a recurring matrix occupying several columns?

Constraint degrees - I've included two of these:

        let degrees = vec![
            TransitionConstraintDegree::new(5),
            TransitionConstraintDegree::new(30)
        ];

The first one is for the dataset hash. By my understanding rescue prime has degrees of 5, based on this answer.

The second one is for the hash of weights and biases. I've shown my working of the calculation in the image below. If I'm correct, the highest degree for weights should be 25, and then we add 5 for the rescue hash to make 30. Q2: Does this look right?

Image

I've added some debug print lines to produce the following output on testing:

---- tests::test_train_and_prove stdout ----
num_samples: 7, len_sample: 8, hidden_size: 12, num_columns: 136
flag: 0, frame.next()[4]: 1988944142759683713, dataset_hash: 1988944142759683713, frame.next()[5]: 13443926300744107950, w_b_hash: 13443926300744107950, frame.next()[-1]: 7666499316168129282, bias_o: 7666499316168129282, result: 0, 0
flag: 0, frame.next()[4]: 15758796173594749889, dataset_hash: 15758796173594749889, frame.next()[5]: 13251977776104907959, w_b_hash: 13251977776104907959, frame.next()[-1]: 3585489129564534949, bias_o: 3585489129564534949, result: 0, 0

This shows frame values nicely matching up with hashes as anticipated by these lines:

        result[0] = (frame.next()[4] - dataset_hash);
        result[1] = (frame.next()[5] - w_b_hash);

I've also shown output bias and the corresponding frame value as an additional check. This all repeats quite happily for 64 lines, at which point it ought to stop, but then this starts happening:

flag: 0, frame.next()[4]: 9080182147223831867, dataset_hash: 9080182147223831867, frame.next()[5]: 8973157242228625980, w_b_hash: 8973157242228625980, frame.next()[-1]: 16312796124388405370, bias_o: 16312796124388405370, result: 0, 0
flag: 18210199780982572190, frame.next()[4]: 1535783160212123500, dataset_hash: 17866269203665947714, frame.next()[5]: 11252226151124759407, w_b_hash: 5171612489511717358, frame.next()[-1]: 17544902386472247398, bias_o: 17150592172401078110, result: 2116258025960760107, 6080613661613042049
flag: 3727822874259453825, frame.next()[4]: 1709029980266899968, dataset_hash: 7099683142479157042, frame.next()[5]: 10269402497121169506, w_b_hash: 5995184084187237790, frame.next()[-1]: 11594520110464754199, bias_o: 4733675032304182569, result: 13056090907202327247, 4274218412933931716

From this point on none of the hashes match the frame values and flag is all over the place instead of just 0 or 1. This continues on for several hundred lines until ending in:

thread 'tests::test_train_and_prove' panicked at /home/timk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winter-prover-0.12.0/src/constraints/evaluation_table.rs:214:9:
assertion `left == right` failed: transition constraint degrees didn't match
expected: [252, 1827]
actual:   [2041, 2047]
  left: [252, 1827]
 right: [2041, 2047]

Q3: What could be going on here? Any pointers would be very gratefully received.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions