Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions robustness_experiment_box/database/epsilon_value_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
class EpsilonValueResult:
"""
A dataclass defining the verification result of a single verification.

This class is designed for traditional deterministic verification approaches
where we search for specific epsilon values. For probabilistic certification
(like randomized smoothing), use ProbabilisticCertificationResult directly.

For traditional verification:
- epsilon: The certified epsilon value
- smallest_sat_value: The smallest epsilon where SAT was found
"""

verification_context: VerificationContext
Expand All @@ -22,11 +30,10 @@ def to_dict(self) -> dict:
Returns:
dict: The dictionary representation of the EpsilonValueResult.
"""
ret = dict(
return dict(
**self.verification_context.get_dict_for_epsilon_result(),
epsilon_value=self.epsilon,
smallest_sat_value=self.smallest_sat_value,
total_time=self.time,
verifier=self.verifier,
)
return ret
70 changes: 70 additions & 0 deletions robustness_experiment_box/database/verification_result.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from dataclasses import dataclass
from enum import Enum


Expand All @@ -10,3 +11,72 @@ class VerificationResult(str, Enum):
SAT = "SAT"
TIMEOUT = "TIMEOUT"
ERROR = "ERR"


@dataclass
class ProbabilisticCertificationResult:
"""
Result class for probabilistic certification methods like randomized smoothing.

This provides certified robustness guarantees obtained through Monte Carlo sampling
with Gaussian noise, following the approach of Cohen et al. (2019).

Note: Unlike traditional verification, probabilistic certification provides
a certified radius rather than binary SAT/UNSAT/TIMEOUT/ERROR results. The certified radius
may be 0 if confidence is insufficient (ABSTAIN in Cohen et al.).

Attributes:
predicted_class: The class predicted by the smoothed classifier
certified_radius: The L2 radius within which the prediction is guaranteed to be constant
confidence: The statistical confidence level (1 - alpha)
n0: Number of samples used for initial prediction
n: Number of samples used for certification
sigma: Noise level used for smoothing
certification_time: Time taken for the certification process
"""

predicted_class: int
certified_radius: float
confidence: float # 1 - alpha
n0: int
n: int
sigma: float
certification_time: float

def to_dict(self) -> dict:
"""
Convert the probabilistic certification result to a dictionary.

Returns:
Dictionary representation of the result
"""
return {
"predicted_class": self.predicted_class,
"certified_radius": self.certified_radius,
"confidence": self.confidence,
"n0": self.n0,
"n": self.n,
"sigma": self.sigma,
"certification_time": self.certification_time,
}

@classmethod
def from_dict(cls, data: dict) -> "ProbabilisticCertificationResult":
"""
Create a ProbabilisticCertificationResult from a dictionary.

Args:
data: Dictionary containing the result data

Returns:
ProbabilisticCertificationResult instance
"""
return cls(
predicted_class=data["predicted_class"],
certified_radius=data["certified_radius"],
confidence=data["confidence"],
n0=data["n0"],
n=data["n"],
sigma=data["sigma"],
certification_time=data["certification_time"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
"""
Randomized Smoothing Estimator for VERONA.

This estimator provides direct computation of certified radii using randomized smoothing,
eliminating the need for binary search over epsilon values. It works with the
RandomizedSmoothingModule to provide probabilistic robustness guarantees.

This approach is more efficient than binary search for probabilistic certification
since it directly computes the certified radius rather than searching for boundaries.
"""

import logging

from robustness_experiment_box.database.epsilon_value_result import EpsilonValueResult
from robustness_experiment_box.database.verification_context import VerificationContext
from robustness_experiment_box.database.verification_result import ProbabilisticCertificationResult
from robustness_experiment_box.epsilon_value_estimator.epsilon_value_estimator import EpsilonValueEstimator
from robustness_experiment_box.verification_module.randomized_smoothing_module import RandomizedSmoothingModule

logger = logging.getLogger(__name__)


class RandomizedSmoothingEstimator(EpsilonValueEstimator):
"""
Estimator for probabilistic robustness using randomized smoothing.

This estimator directly computes certified radii using Monte Carlo sampling
rather than performing binary search over epsilon values. It is
designed to work with the RandomizedSmoothingModule.

Args:
smoothing_module: The randomized smoothing verification module
n0: Number of samples for initial prediction
n: Number of samples for certification
alpha: Confidence level (failure probability)
batch_size: Batch size for sampling
"""

def __init__(
self,
smoothing_module: RandomizedSmoothingModule,
n0: int = 100,
n: int = 100000,
alpha: float = 0.001,
batch_size: int = 1000
):
# Pass empty epsilon list since we don't use binary search
super().__init__([], smoothing_module)

self.smoothing_module = smoothing_module
self.n0 = n0
self.n = n
self.alpha = alpha
self.batch_size = batch_size

def compute_epsilon_value(self, verification_context: VerificationContext) -> EpsilonValueResult:
"""
Compute the certified epsilon value using randomized smoothing.

This method performs direct computation of the certified radius.

Args:
verification_context: The verification context

Returns:
EpsilonValueResult with the certified radius as epsilon value
"""
# Perform probabilistic verification
probabilistic_result = self.smoothing_module.verify_probabilistic(
verification_context=verification_context,
n0=self.n0,
n=self.n,
alpha=self.alpha,
sigma=self.smoothing_module.sigma,
batch_size=self.batch_size
)

# Convert to traditional EpsilonValueResult format
# Use certified_radius as the epsilon value for compatibility
epsilon_value_result = EpsilonValueResult(
verification_context=verification_context,
epsilon=probabilistic_result.certified_radius,
smallest_sat_value=probabilistic_result.certified_radius,
time=probabilistic_result.certification_time,
verifier=self.smoothing_module.name
)

logger.info(
f"Randomized smoothing result: predicted_class={probabilistic_result.predicted_class}, "
f"certified_radius={probabilistic_result.certified_radius:.4f}, "
f"confidence={probabilistic_result.confidence:.4f}, "
f"time={probabilistic_result.certification_time:.2f}s"
)

return epsilon_value_result

def get_probabilistic_result(self, verification_context: VerificationContext) -> ProbabilisticCertificationResult:
"""
Get the full probabilistic certification result.

This method provides access to the complete probabilistic result
including predicted class and confidence information.

Args:
verification_context: The verification context

Returns:
Probabilistic certification result
"""
return self.smoothing_module.verify_probabilistic(
verification_context=verification_context,
n0=self.n0,
n=self.n,
alpha=self.alpha,
sigma=self.smoothing_module.sigma,
batch_size=self.batch_size
)
Loading
Loading