ML (Training)
naive_bayes_training()¶
Demonstrates the naive_bayes_training function. This is the core FHE circuit logic used by FHENaiveBayesTrainer to calculate feature counts and class priors directly on encrypted data.
In [ ]:
Copied!
from concrete import fhe
from concrete_fhe_toolkit.ml.training import naive_bayes_training
compiler = fhe.Compiler(naive_bayes_training, {'X_train': 'encrypted', 'y_train_one_hot': 'encrypted'})
inputset = [([[1, 0]], [[1, 0]])]
circuit = compiler.compile(inputset)
expected = naive_bayes_training(*inputset[0])
result = circuit.encrypt_run_decrypt(*inputset[0])
import numpy as np
np.testing.assert_array_equal(result[0], expected[0])
np.testing.assert_array_equal(result[1], expected[1])
print('naive_bayes_training compiled and executed successfully!')
from concrete import fhe
from concrete_fhe_toolkit.ml.training import naive_bayes_training
compiler = fhe.Compiler(naive_bayes_training, {'X_train': 'encrypted', 'y_train_one_hot': 'encrypted'})
inputset = [([[1, 0]], [[1, 0]])]
circuit = compiler.compile(inputset)
expected = naive_bayes_training(*inputset[0])
result = circuit.encrypt_run_decrypt(*inputset[0])
import numpy as np
np.testing.assert_array_equal(result[0], expected[0])
np.testing.assert_array_equal(result[1], expected[1])
print('naive_bayes_training compiled and executed successfully!')
make_raw_naive_bayes_training()¶
Tests the function.
This cell verifies the make_raw_naive_bayes_training function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
In [ ]:
Copied!
from concrete import fhe
from concrete_fhe_toolkit.ml.training import make_raw_naive_bayes_training
fn = make_raw_naive_bayes_training(thresholds=[1, 1])
def test_make_raw_naive_bayes_training_enc(X_train_raw, y_train_one_hot):
import numpy as np
res = fn(X_train_raw, y_train_one_hot)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_make_raw_naive_bayes_training_enc, {'X_train_raw': 'encrypted', 'y_train_one_hot': 'encrypted'})
inputset = [([[1, 0]], [[1, 0]])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = fn(*inp)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "make_raw_naive_bayes_training: all inputs were skipped — test is broken"
print(f"make_raw_naive_bayes_training tests passed! ({_successes}/{len(inputset)})")
from concrete import fhe
from concrete_fhe_toolkit.ml.training import make_raw_naive_bayes_training
fn = make_raw_naive_bayes_training(thresholds=[1, 1])
def test_make_raw_naive_bayes_training_enc(X_train_raw, y_train_one_hot):
import numpy as np
res = fn(X_train_raw, y_train_one_hot)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_make_raw_naive_bayes_training_enc, {'X_train_raw': 'encrypted', 'y_train_one_hot': 'encrypted'})
inputset = [([[1, 0]], [[1, 0]])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = fn(*inp)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "make_raw_naive_bayes_training: all inputs were skipped — test is broken"
print(f"make_raw_naive_bayes_training tests passed! ({_successes}/{len(inputset)})")