skiftet_statistical 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +308 -8
  3. data/README.md +1416 -39
  4. data/lib/skiftet_statistical/additive_contrasts.rb +894 -0
  5. data/lib/skiftet_statistical/bandit/allocator.rb +477 -63
  6. data/lib/skiftet_statistical/bandit/checks.rb +128 -0
  7. data/lib/skiftet_statistical/bandit/decay.rb +86 -0
  8. data/lib/skiftet_statistical/bandit/draw.rb +179 -0
  9. data/lib/skiftet_statistical/bandit/normal_argmax.rb +209 -0
  10. data/lib/skiftet_statistical/bandit/pass.rb +94 -0
  11. data/lib/skiftet_statistical/bandit/posteriors.rb +497 -0
  12. data/lib/skiftet_statistical/bandit/prior.rb +264 -0
  13. data/lib/skiftet_statistical/bandit/probabilities.rb +929 -0
  14. data/lib/skiftet_statistical/bandit/ranking.rb +552 -0
  15. data/lib/skiftet_statistical/bandit/summary.rb +152 -0
  16. data/lib/skiftet_statistical/bandit/tallies.rb +297 -0
  17. data/lib/skiftet_statistical/bandit.rb +3 -3
  18. data/lib/skiftet_statistical/beta_argmax.rb +526 -0
  19. data/lib/skiftet_statistical/beta_function.rb +28 -1
  20. data/lib/skiftet_statistical/cholesky.rb +244 -0
  21. data/lib/skiftet_statistical/cusum.rb +183 -0
  22. data/lib/skiftet_statistical/descriptive.rb +3 -3
  23. data/lib/skiftet_statistical/gauss_legendre.rb +73 -0
  24. data/lib/skiftet_statistical/hierarchical_rates.rb +450 -0
  25. data/lib/skiftet_statistical/inputs.rb +214 -0
  26. data/lib/skiftet_statistical/linear_value.rb +364 -0
  27. data/lib/skiftet_statistical/numbers.rb +98 -0
  28. data/lib/skiftet_statistical/prequential.rb +206 -0
  29. data/lib/skiftet_statistical/shared_credit.rb +811 -0
  30. data/lib/skiftet_statistical/significance.rb +5 -6
  31. data/lib/skiftet_statistical/version.rb +1 -1
  32. data/lib/skiftet_statistical.rb +43 -4
  33. metadata +37 -11
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SkiftetStatistical
4
- # Frequentist significance testing for A/B experiments. Consolidates the
5
- # two-proportion z-test, Welch's t-test and the normal CDF that were previously
6
- # re-implemented (inconsistently) across mej.la's AbTestAnalyzer and skram.la's
7
- # CRM::AbTestAnalysis. One correct, exact (erf-based) normal CDF — no polynomial
8
- # approximations. Since 0.2 also the normal quantile, the chi-squared survival
9
- # and the sample-ratio check (f1's copies, one home).
4
+ # Frequentist significance testing for A/B experiments. One home for the
5
+ # two-proportion z-test, Welch's t-test and the normal CDF, which callers
6
+ # otherwise re-implement, often inconsistently. One correct, exact (erf-based)
7
+ # normal CDF — no polynomial approximations. Since 0.2 also the normal
8
+ # quantile, the chi-squared survival and the sample-ratio check.
10
9
  module Significance
11
10
  # normal_quantile bisects [-40, 40]: 0.5 * erfc(40 / sqrt(2)) underflows to 0.0,
12
11
  # so every p a Float can hold strictly inside (0, 1) has its z in there.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SkiftetStatistical
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "skiftet_statistical/version"
4
+ require_relative "skiftet_statistical/numbers"
4
5
  require_relative "skiftet_statistical/sampler"
5
6
  require_relative "skiftet_statistical/gamma"
6
7
  require_relative "skiftet_statistical/beta_function"
@@ -14,12 +15,32 @@ require_relative "skiftet_statistical/policies/thompson_sampling"
14
15
  require_relative "skiftet_statistical/policies/ucb1"
15
16
  require_relative "skiftet_statistical/policies/softmax"
16
17
  require_relative "skiftet_statistical/bandit"
18
+ require_relative "skiftet_statistical/bandit/checks"
19
+ require_relative "skiftet_statistical/bandit/tallies"
20
+ require_relative "skiftet_statistical/bandit/prior"
21
+ require_relative "skiftet_statistical/bandit/decay"
22
+ require_relative "skiftet_statistical/bandit/draw"
23
+ require_relative "skiftet_statistical/bandit/normal_argmax"
24
+ require_relative "skiftet_statistical/bandit/posteriors"
25
+ require_relative "skiftet_statistical/bandit/ranking"
26
+ require_relative "skiftet_statistical/bandit/summary"
27
+ require_relative "skiftet_statistical/bandit/probabilities"
28
+ require_relative "skiftet_statistical/bandit/pass"
17
29
  require_relative "skiftet_statistical/bandit/weighted_posterior"
18
30
  require_relative "skiftet_statistical/bandit/allocator"
19
31
  require_relative "skiftet_statistical/bandit/win_hold"
32
+ require_relative "skiftet_statistical/cholesky"
33
+ require_relative "skiftet_statistical/linear_value"
34
+ require_relative "skiftet_statistical/hierarchical_rates"
35
+ require_relative "skiftet_statistical/shared_credit"
36
+ require_relative "skiftet_statistical/gauss_legendre"
37
+ require_relative "skiftet_statistical/beta_argmax"
38
+ require_relative "skiftet_statistical/additive_contrasts"
39
+ require_relative "skiftet_statistical/prequential"
40
+ require_relative "skiftet_statistical/cusum"
20
41
 
21
- # Skiftet's shared statistics toolkit — a home for reusable, app-independent
22
- # statistical analysis code across the workspace.
42
+ # A dependency-free statistics toolkit: reusable, app-independent statistical
43
+ # analysis code, so the same test, interval or draw is written once.
23
44
  #
24
45
  # Modules:
25
46
  # - {Descriptive} — mean, variance, standard deviation, percentiles/median.
@@ -31,15 +52,33 @@ require_relative "skiftet_statistical/bandit/win_hold"
31
52
  # - {Sampler} — Gamma/Beta/Gaussian random sampling (RNG-injectable).
32
53
  # - {JointBeta} — joint Monte Carlo draws over Beta posteriors (P(best), loss).
33
54
  # - {Bandit} + {Policies} — multi-armed bandit (Thompson Sampling, epsilon-greedy,
34
- # UCB1, Softmax) for online explore/exploit decisions.
55
+ # UCB1, Softmax) for online explore/exploit decisions, kept as 0.3.0 wrote it.
56
+ # - {Bandit::Posteriors} — the generic bandit: a set of items with their views
57
+ # and yes/no or amount posteriors, ordered (`rank`) and picked (`pick`) by one
58
+ # rule from a key, given uniforms or an RNG, with the odds of what it draws
59
+ # (exact for a pick among up to EXACT_PICK_MAX contenders and for orders and
60
+ # positions over up to EXACT_ORDER_MAX free items with none barred from
61
+ # leading, otherwise a seeded Monte Carlo estimate with its standard error),
62
+ # and per-item summaries; its priors
63
+ # ({Bandit::Prior}), decay ({Bandit::Decay}) and keyed uniforms and draw by
64
+ # weight ({Bandit::Draw}) beside it, with {Bandit::NormalArgmax} and
65
+ # {Bandit::Pass}.
35
66
  # - {Bandit::Allocator}, {Bandit::WinHold}, {Bandit::WeightedPosterior} — an A/B
36
67
  # test's Thompson-sampling allocation with a floor, a step limit, an automatic
37
68
  # win and a hold on it.
69
+ # - {LinearValue}, {Cholesky}, {SharedCredit}, {HierarchicalRates},
70
+ # {AdditiveContrasts}, {BetaArgmax}, {GaussLegendre}, {Prequential}, {Cusum} —
71
+ # values of several parts, pooled estimates, the exact Beta argmax, the
72
+ # prequential score and a change test.
38
73
  #
39
- # bandit = SkiftetStatistical.bandit(arms: %w[facebook whatsapp x])
74
+ # bandit = SkiftetStatistical.bandit(arms: %w[a b c])
40
75
  # choice = bandit.select # which arm to play now
41
76
  # bandit.record(choice, 1) # observed a reward (e.g. a conversion)
42
77
  # bandit.best_arm # current best by empirical mean
78
+ #
79
+ # set = SkiftetStatistical::Bandit::Posteriors.yes_no({ "a" => { views: 40, outcomes: 8 },
80
+ # "b" => { views: 10, outcomes: 1 } })
81
+ # set.rank(key: %w[list visit-1], shuffle: 0.1).items # => the order that key draws, every time
43
82
  module SkiftetStatistical
44
83
  class Error < StandardError; end
45
84
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skiftet_statistical
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Skiftet
@@ -10,13 +10,18 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: |-
13
- A small, dependency-free toolkit for online decision-making under uncertainty:
14
- register arms, ask which to play, record rewards, and let a pluggable policy
15
- balance exploration and exploitation. Ships Thompson Sampling, epsilon-greedy,
16
- UCB1 and Softmax; state serialises to a plain Hash for persistence and every
17
- policy is deterministic under an injected RNG for testing.
18
- email:
19
- - joel@skram.la
13
+ Pure Ruby statistics for deciding under uncertainty. Descriptive statistics,
14
+ significance tests and distribution functions; Beta and Normal posteriors with
15
+ exact P(best), expected loss and credible intervals; an A/B allocator with
16
+ floors, fixed shares, an automatic win and a hold on it; estimators for values
17
+ of several parts, pooled contrasts, hierarchical rates and a change test; and
18
+ a generic Thompson-sampling bandit: a set of items with their views and
19
+ yes/no or amount outcomes, ranked or picked by one rule from a key, given
20
+ uniforms or an RNG, with the odds of what it draws: exact for a pick among
21
+ up to 20 contenders (EXACT_PICK_MAX) and for orders and positions over up to
22
+ 10 free items (EXACT_ORDER_MAX) with none barred from leading, otherwise a
23
+ seeded Monte Carlo estimate with its standard error. Every random input is
24
+ injected, so each answer can be reproduced.
20
25
  executables: []
21
26
  extensions: []
22
27
  extra_rdoc_files: []
@@ -25,21 +30,43 @@ files:
25
30
  - LICENSE.txt
26
31
  - README.md
27
32
  - lib/skiftet_statistical.rb
33
+ - lib/skiftet_statistical/additive_contrasts.rb
28
34
  - lib/skiftet_statistical/arm.rb
29
35
  - lib/skiftet_statistical/bandit.rb
30
36
  - lib/skiftet_statistical/bandit/allocator.rb
37
+ - lib/skiftet_statistical/bandit/checks.rb
38
+ - lib/skiftet_statistical/bandit/decay.rb
39
+ - lib/skiftet_statistical/bandit/draw.rb
40
+ - lib/skiftet_statistical/bandit/normal_argmax.rb
41
+ - lib/skiftet_statistical/bandit/pass.rb
42
+ - lib/skiftet_statistical/bandit/posteriors.rb
43
+ - lib/skiftet_statistical/bandit/prior.rb
44
+ - lib/skiftet_statistical/bandit/probabilities.rb
45
+ - lib/skiftet_statistical/bandit/ranking.rb
46
+ - lib/skiftet_statistical/bandit/summary.rb
47
+ - lib/skiftet_statistical/bandit/tallies.rb
31
48
  - lib/skiftet_statistical/bandit/weighted_posterior.rb
32
49
  - lib/skiftet_statistical/bandit/win_hold.rb
50
+ - lib/skiftet_statistical/beta_argmax.rb
33
51
  - lib/skiftet_statistical/beta_function.rb
52
+ - lib/skiftet_statistical/cholesky.rb
53
+ - lib/skiftet_statistical/cusum.rb
34
54
  - lib/skiftet_statistical/descriptive.rb
35
55
  - lib/skiftet_statistical/gamma.rb
56
+ - lib/skiftet_statistical/gauss_legendre.rb
57
+ - lib/skiftet_statistical/hierarchical_rates.rb
58
+ - lib/skiftet_statistical/inputs.rb
36
59
  - lib/skiftet_statistical/joint_beta.rb
60
+ - lib/skiftet_statistical/linear_value.rb
61
+ - lib/skiftet_statistical/numbers.rb
37
62
  - lib/skiftet_statistical/policies/base.rb
38
63
  - lib/skiftet_statistical/policies/epsilon_greedy.rb
39
64
  - lib/skiftet_statistical/policies/softmax.rb
40
65
  - lib/skiftet_statistical/policies/thompson_sampling.rb
41
66
  - lib/skiftet_statistical/policies/ucb1.rb
67
+ - lib/skiftet_statistical/prequential.rb
42
68
  - lib/skiftet_statistical/sampler.rb
69
+ - lib/skiftet_statistical/shared_credit.rb
43
70
  - lib/skiftet_statistical/significance.rb
44
71
  - lib/skiftet_statistical/version.rb
45
72
  homepage: https://github.com/Skiftet/skiftet_statistical
@@ -48,7 +75,6 @@ licenses:
48
75
  metadata:
49
76
  allowed_push_host: https://rubygems.org
50
77
  github_repo: https://github.com/Skiftet/skiftet_statistical
51
- homepage_uri: https://github.com/Skiftet/skiftet_statistical
52
78
  source_code_uri: https://github.com/Skiftet/skiftet_statistical
53
79
  changelog_uri: https://github.com/Skiftet/skiftet_statistical/blob/main/CHANGELOG.md
54
80
  rubygems_mfa_required: 'true'
@@ -68,6 +94,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
94
  requirements: []
69
95
  rubygems_version: 3.6.9
70
96
  specification_version: 4
71
- summary: Multi-armed bandit policies (Thompson Sampling, epsilon-greedy, UCB1, Softmax)
72
- for Ruby.
97
+ summary: 'A dependency-free statistics toolkit for Ruby: significance tests, Bayesian
98
+ A/B allocation and a Thompson-sampling bandit that picks and orders items.'
73
99
  test_files: []