Class: Vangrail::RiskControl

Inherits:
Object
  • Object
show all
Includes:
ArtifactData
Defined in:
lib/vangrail/risk_control.rb

Overview

One-sided binomial risk control fitted only on threshold-role cases.

Constant Summary collapse

SCHEMA =
'vangrail-risk-control-v1'
METHOD =
'learn_then_test_binomial'
LABELS =
%w[attack benign].freeze
FIELDS =
%w[
  schema method block_at max_false_positive_rate confidence benign_cases false_positives
  false_positive_upper_bound calibration_manifest_sha256
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw) ⇒ RiskControl

Returns a new instance of RiskControl.

Raises:



24
25
26
27
28
29
30
31
# File 'lib/vangrail/risk_control.rb', line 24

def initialize(raw)
  raise ProtocolError, 'risk control must be a hash' unless raw.is_a?(Hash)

  @data = stringify(raw)
  validate!
  @data = immutable(@data)
  freeze
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



22
23
24
# File 'lib/vangrail/risk_control.rb', line 22

def data
  @data
end

Class Method Details

.fit(predictions, max_false_positive_rate:, confidence:, calibration_manifest_sha256:) ⇒ Object

Raises:



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/vangrail/risk_control.rb', line 33

def self.fit(predictions, max_false_positive_rate:, confidence:,
             calibration_manifest_sha256:)
  rows = normalize_predictions(predictions)
  validate_predictions!(rows)
  maximum = probability(max_false_positive_rate, 'max_false_positive_rate')
  mass = probability(confidence, 'confidence')
  benign = rows.select { |row| row.fetch('label') == 'benign' }
  threshold, false_positives, upper = select_threshold(benign, maximum, mass)
  raise ProtocolError, 'threshold cases cannot certify the requested false-positive rate' unless threshold

  new(
    'schema' => SCHEMA,
    'method' => METHOD,
    'block_at' => threshold,
    'max_false_positive_rate' => maximum,
    'confidence' => mass,
    'benign_cases' => benign.size,
    'false_positives' => false_positives,
    'false_positive_upper_bound' => upper,
    'calibration_manifest_sha256' => calibration_manifest_sha256,
  )
end

Instance Method Details

#benign_casesObject



61
# File 'lib/vangrail/risk_control.rb', line 61

def benign_cases = data.fetch('benign_cases')

#block_atObject



58
# File 'lib/vangrail/risk_control.rb', line 58

def block_at = data.fetch('block_at')

#calibration_manifest_sha256Object



64
# File 'lib/vangrail/risk_control.rb', line 64

def calibration_manifest_sha256 = data.fetch('calibration_manifest_sha256')

#confidenceObject



60
# File 'lib/vangrail/risk_control.rb', line 60

def confidence = data.fetch('confidence')

#false_positive_upper_boundObject



63
# File 'lib/vangrail/risk_control.rb', line 63

def false_positive_upper_bound = data.fetch('false_positive_upper_bound')

#false_positivesObject



62
# File 'lib/vangrail/risk_control.rb', line 62

def false_positives = data.fetch('false_positives')

#max_false_positive_rateObject



59
# File 'lib/vangrail/risk_control.rb', line 59

def max_false_positive_rate = data.fetch('max_false_positive_rate')

#methodObject



57
# File 'lib/vangrail/risk_control.rb', line 57

def method = data.fetch('method')

#policy(review_at: block_at) ⇒ Object



66
67
68
69
70
71
72
# File 'lib/vangrail/risk_control.rb', line 66

def policy(review_at: block_at)
  unless review_at.is_a?(Numeric) && review_at.finite? && review_at >= 0 && review_at <= block_at
    raise ArgumentError, 'review_at must be finite and between zero and block_at'
  end

  Policy.new(block_at: block_at, review_at: review_at)
end

#schemaObject



56
# File 'lib/vangrail/risk_control.rb', line 56

def schema = data.fetch('schema')

#to_hObject



74
75
76
# File 'lib/vangrail/risk_control.rb', line 74

def to_h
  data
end