Class: Rubythinking::Quap

Inherits:
Object
  • Object
show all
Defined in:
lib/rubythinking/quap.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(formulas:, data:, start: nil) ⇒ Quap

Returns a new instance of Quap.



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/rubythinking/quap.rb', line 15

def initialize(formulas:, data:, start: nil)
  @formulas = formulas
  @data = data
  @start = start
  @estimated = false
  @coef = nil
  @vcov = nil
  
  validate_formulas!
  validate_data!
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



13
14
15
# File 'lib/rubythinking/quap.rb', line 13

def data
  @data
end

#formulasObject (readonly)

Returns the value of attribute formulas.



13
14
15
# File 'lib/rubythinking/quap.rb', line 13

def formulas
  @formulas
end

#startObject (readonly)

Returns the value of attribute start.



13
14
15
# File 'lib/rubythinking/quap.rb', line 13

def start
  @start
end

Instance Method Details

#aicObject



104
105
106
107
# File 'lib/rubythinking/quap.rb', line 104

def aic
  check_estimated!
  -2 * loglik + 2 * npar
end

#coefObject



50
51
52
53
# File 'lib/rubythinking/quap.rb', line 50

def coef
  check_estimated!
  @coef
end

#estimateObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/rubythinking/quap.rb', line 31

def estimate
  # Get initial parameter values
  param_names = parameters
  initial_values = get_initial_values(param_names)
  
  # Optimize log-likelihood using Nelder-Mead
  result = nelder_mead_optimize(initial_values, param_names)
  
  # Store results
  @coef = param_names.zip(result[:x]).to_h
  @log_likelihood = -result[:fval]  # Convert from negative log-likelihood
  
  # Calculate variance-covariance matrix using numerical Hessian
  @vcov = calculate_vcov(result[:x], param_names)
  
  @estimated = true
  self
end

#estimated?Boolean

Returns:



27
28
29
# File 'lib/rubythinking/quap.rb', line 27

def estimated?
  @estimated
end

#loglikObject



94
95
96
97
# File 'lib/rubythinking/quap.rb', line 94

def loglik
  check_estimated!
  @log_likelihood
end

#nparObject



99
100
101
102
# File 'lib/rubythinking/quap.rb', line 99

def npar
  check_estimated!
  @coef.length
end

#samples(n: 1000, seed: nil) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/rubythinking/quap.rb', line 82

def samples(n: 1000, seed: nil)
  check_estimated!
  srand(seed) if seed
  
  result = {}
  @coef.each_with_index do |(param, value), i|
    variance = @vcov[i, i]
    result[param] = Distributions::Normal.samples(n, value, Math.sqrt(variance))
  end
  result
end

#seObject



60
61
62
63
64
65
# File 'lib/rubythinking/quap.rb', line 60

def se
  check_estimated!
  diagonal = @vcov.each(:diagonal).to_a
  param_names = @coef.keys
  param_names.zip(diagonal.map { |v| Math.sqrt(v) }).to_h
end

#summaryObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rubythinking/quap.rb', line 67

def summary
  check_estimated!
  
  lines = []
  lines << "Quadratic approximation"
  lines << ""
  lines << "Parameter estimates:"
  @coef.each do |param, value|
    stderr = se[param]
    lines << "  #{param}: #{value} (SE: #{stderr})"
  end
  
  lines.join("\n")
end

#vcovObject



55
56
57
58
# File 'lib/rubythinking/quap.rb', line 55

def vcov
  check_estimated!
  @vcov
end