Bayesian online change point detection for streaming numeric data
moon fmt
moon info
moon check --deny-warn
moon test --deny-warn
moon run cmd
moon run cmd/evaluatemoon bench --release --deny-warnlet model = @shift.GaussianModel::new(0.0, 1.0, 0.25).unwrap()
let config = @shift.Config::new(0.04, 128, model).unwrap()
let detector = @shift.Detector::new(config)
for update in detector.replay([0.0, 0.2, -0.1, 0.0, 5.1, 4.9]).unwrap() {
println(update.change_probability())
}| 模块 | 内容 |
|---|---|
| Detector / GaussianModel | 连续值 BOCPD、快照恢复、批量重放 |
| PoissonDetector / PoissonModel | 计数流 BOCPD |
| EventGate | 概率阈值、最小段长与冷却窗口组成的事件门控 |
| NumericSeries / TimedSeries | 输入验证、滚动统计、时间序列规则性检查 |
| threshold_points / evaluate_hazards | 阈值和 hazard 网格评估 |
| evaluate_ewma / evaluate_cusum | 与 EWMA、CUSUM 基线对照 |
| diagnose_trace / audit_series | 后验轨迹诊断、输入质量检查 |
| gaussian_segments / poisson_segments | 固定种子的合成实验数据 |
let result = @shift.execute_plan(
@shift.default_experiment_plan(),
@shift.NumericScenario::mean_shift(),
@shift.GaussianModel::new(0.0, 1.0, 0.05).unwrap(),
).unwrap()
println(result.summary())pub struct BaselineExperiment {
detector : String
scenario : String
threshold : Double
score : Score
alerts : Int
}pub struct Boundary {
step : Int
}pub struct ChangeEvent {
step : Int
observation : Double
probability : Double
prior_run_length : Int
}pub struct Config {
hazard : Double
hazard_log : Double
survival_log : Double
max_run_length : Int
model : GaussianModel
}fn Config::new(hazard : Double, max_run_length : Int, model : GaussianModel) -> Result[Config, DetectError]pub struct CountExperiment {
scenario : String
threshold : Double
score : Score
maximum_probability : Double
}pub struct CountUpdate {
step : Int
count : Int
change_probability : Double
most_likely_run_length : Int
posterior_rate : Double
}pub struct CurvePoint {
threshold : Double
recall : Double
precision : Double
false_positive_rate : Double
}pub struct CusumConfig {
reference_mean : Double
slack : Double
threshold : Double
}fn CusumConfig::new(reference_mean : Double, slack : Double, threshold : Double) -> Result[CusumConfig, DetectError]pub struct CusumUpdate {
step : Int
positive : Double
negative : Double
drift : Bool
}pub enum DetectError {
InvalidHazard
InvalidVariance
InvalidPriorStrength
InvalidRunLengthLimit
NonFiniteObservation
}pub struct DetectedSegment {
start_step : Int
end_step : Int
size : Int
mean_observation : Double
mean_change_probability : Double
}pub enum DetectorKind {
Bocpd
Ewma
Cusum
}pub struct EventPolicy {
probability_threshold : Double
minimum_run_length : Int
cooldown : Int
}fn EventPolicy::new(probability_threshold : Double, minimum_run_length : Int, cooldown : Int) -> Result[EventPolicy, DetectError]pub struct EwmaConfig {
alpha : Double
z_threshold : Double
warmup : Int
}fn EwmaConfig::new(alpha : Double, z_threshold : Double, warmup : Int) -> Result[EwmaConfig, DetectError]pub struct EwmaDetector {
config : EwmaConfig
step : Int
mean : Double
variance : Double
initialized : Bool
}fn EwmaDetector::replay(self : EwmaDetector, values : Array[Double]) -> Result[Array[EwmaUpdate], DetectError]pub struct EwmaUpdate {
step : Int
value : Double
mean : Double
variance : Double
z : Double
drift : Bool
}pub struct ExperimentPlan {
name : String
hazard : Double
max_run_length : Int
threshold : Double
tolerance : Int
seed : Int
}fn ExperimentPlan::new(name : String, hazard : Double, max_run_length : Int, threshold : Double, tolerance : Int, seed : Int) -> Result[ExperimentPlan, DetectError]pub struct GaussianModel {
prior_mean : Double
prior_strength : Double
observation_variance : Double
}fn GaussianModel::new(prior_mean : Double, prior_strength : Double, observation_variance : Double) -> Result[GaussianModel, DetectError]pub struct HazardPoint {
hazard : Double
best_threshold : Double
best_score : Score
maximum_probability : Double
}pub struct NumericExperiment {
scenario : String
hazard : Double
threshold : Double
score : Score
trace : TraceSummary
}fn NumericSeries::moving_means(self : NumericSeries, width : Int) -> Result[Array[Double], DetectError]fn NumericSeries::moving_ranges(self : NumericSeries, width : Int) -> Result[Array[Double], DetectError]fn NumericSeries::split(self : NumericSeries, width : Int) -> Result[Array[NumericSeries], DetectError]fn NumericSeries::subseries(self : NumericSeries, start : Int, finish : Int) -> Result[NumericSeries, DetectError]pub struct OnlineStats {
count : Int
average : Double
sum_of_squares : Double
minimum_value : Double?
maximum_value : Double?
}pub struct ParkMiller {
state : Int
}pub struct PlanResult {
plan : ExperimentPlan
experiment : NumericExperiment
diagnostics : TraceDiagnostics
predictions : Array[Boundary]
}pub struct PoissonConfig {
hazard : Double
hazard_log : Double
survival_log : Double
max_run_length : Int
model : PoissonModel
}fn PoissonConfig::new(hazard : Double, max_run_length : Int, model : PoissonModel) -> Result[PoissonConfig, DetectError]pub struct PoissonDetector {
config : PoissonConfig
step : Int
log_posterior : Array[Double]
totals : Array[Int]
observations : Array[Int]
}fn PoissonDetector::replay(self : PoissonDetector, values : Array[Int]) -> Result[Array[CountUpdate], DetectError]pub struct PoissonModel {
prior_shape : Double
prior_rate : Double
}fn PoissonModel::new(prior_shape : Double, prior_rate : Double) -> Result[PoissonModel, DetectError]pub struct Quality {
values : Int
non_finite : Int
minimum : Double?
maximum : Double?
monotonic_increasing : Bool
}pub struct ReproducibilityRecord {
project : String
scenario : String
observation_count : Int
boundary_count : Int
plan : String
}pub struct RunLengthAudit {
observed_steps : Int
retained_states : Int
truncation_ratio : Double
}pub struct RunningMoments {
count : Int
mean_value : Double
m2 : Double
m3 : Double
m4 : Double
}pub struct Score {
true_positives : Int
false_positives : Int
false_negatives : Int
mean_delay : Double
}pub struct SegmentSpec {
length : Int
level : Double
}pub struct SeriesAudit {
length : Int
finite_values : Int
non_finite_values : Int
repeated_adjacent_values : Int
increasing_steps : Int
decreasing_steps : Int
zero_steps : Int
minimum : Double?
maximum : Double?
}pub struct TimedValue {
time : Int
value : Double
}pub struct TraceDiagnostics {
steps : Int
mean_change_probability : Double
maximum_change_probability : Double
maximum_change_step : Int
shortest_map_run_length : Int
longest_map_run_length : Int
mean_posterior_mean : Double
}fn TraceDiagnostics::is_spiky(self : TraceDiagnostics, threshold : Double) -> Result[Bool, DetectError]pub struct TraceSummary {
points : Int
event_count : Int
mean_change_probability : Double
maximum_change_probability : Double
maximum_step : Int
final_run_length : Int
}pub struct Update {
step : Int
observation : Double
change_probability : Double
most_likely_run_length : Int
posterior_mean : Double
retained_run_lengths : Int
}pub struct Window {
capacity : Int
storage : Array[Double]
start : Int
length : Int
sum : Double
sum_squares : Double
}fn add_normal_noise(series : NumericSeries, scale : Double, seed : Int) -> Result[NumericSeries, DetectError]fn audit_run_length_capacity(updates : Array[Update], max_run_length : Int) -> Result[RunLengthAudit, DetectError]fn boundary_delays(truth : Array[Boundary], predicted : Array[Boundary], tolerance : Int) -> Result[Array[BoundaryDelay], DetectError]fn clip_series(series : NumericSeries, lower : Double, upper : Double) -> Result[NumericSeries, DetectError]fn compare_default_detectors(scenario : NumericScenario, model : GaussianModel, tolerance : Int) -> Result[Array[ComparisonRow], DetectError]fn contamination_mask(length : Int, probability : Double, seed : Int) -> Result[Array[Bool], DetectError]fn detected_segments(updates : Array[Update], boundaries : Array[Boundary]) -> Result[Array[DetectedSegment], DetectError]fn evaluate_count(scenario : CountScenario, model : PoissonModel, hazard : Double, max_run_length : Int, threshold : Double, tolerance : Int) -> Result[CountExperiment, DetectError]fn evaluate_cusum(scenario : NumericScenario, config : CusumConfig, tolerance : Int) -> Result[BaselineExperiment, DetectError]fn evaluate_ewma(scenario : NumericScenario, config : EwmaConfig, tolerance : Int) -> Result[BaselineExperiment, DetectError]fn evaluate_hazards(scenario : NumericScenario, model : GaussianModel, hazards : Array[Double], max_run_length : Int, thresholds : Array[Double], tolerance : Int) -> Result[Array[HazardPoint], DetectError]fn evaluate_numeric(scenario : NumericScenario, model : GaussianModel, hazard : Double, max_run_length : Int, threshold : Double, tolerance : Int) -> Result[NumericExperiment, DetectError]fn execute_default_plans(scenario : NumericScenario, model : GaussianModel) -> Result[Array[PlanResult], DetectError]fn execute_grid(plans : Array[ExperimentPlan], scenario : NumericScenario, model : GaussianModel) -> Result[Array[PlanResult], DetectError]fn execute_plan(plan : ExperimentPlan, scenario : NumericScenario, model : GaussianModel) -> Result[PlanResult, DetectError]fn experiment_csv_header() -> Stringfn format_probability_histogram(histogram : ProbabilityHistogram, width : Int) -> Result[String, DetectError]fn gaussian_segments(specs : Array[SegmentSpec], scale : Double, seed : Int) -> Result[NumericSeries, DetectError]fn inject_spikes(series : NumericSeries, positions : Array[Int], amount : Double) -> Result[NumericSeries, DetectError]fn normal_noise(length : Int, center : Double, scale : Double, seed : Int) -> Result[Array[Double], DetectError]fn piecewise_constant(lengths : Array[Int], means : Array[Double], half_width : Double, seed : Int) -> Result[Array[Double], DetectError]fn plan_grid(hazards : Array[Double], run_lengths : Array[Int], thresholds : Array[Double], tolerance : Int, seed : Int) -> Result[Array[ExperimentPlan], DetectError]fn point_at_precision(points : Array[ThresholdPoint], minimum_precision : Double) -> Result[ThresholdPoint, DetectError]fn poisson_segments(lengths : Array[Int], rates : Array[Double], seed : Int) -> Result[Array[Int], DetectError]fn predicted_boundaries(updates : Array[Update], threshold : Double) -> Result[Array[Boundary], DetectError]fn probability_histogram(updates : Array[Update], bins : Int) -> Result[ProbabilityHistogram, DetectError]fn reproducibility_record(scenario : NumericScenario, plan : ExperimentPlan) -> ReproducibilityRecordfn roc_curve(points : Array[ThresholdPoint], negatives : Int) -> Result[Array[CurvePoint], DetectError]fn segment_boundaries_from_updates(updates : Array[Update], threshold : Double, cooldown : Int) -> Result[Array[Boundary], DetectError]fn sinusoid(length : Int, center : Double, amplitude : Double, period : Double) -> Result[NumericSeries, DetectError]fn sweep_cusum(scenario : NumericScenario, reference_mean : Double, slacks : Array[Double], thresholds : Array[Double], tolerance : Int) -> Result[Array[BaselineExperiment], DetectError]fn sweep_ewma(scenario : NumericScenario, alphas : Array[Double], z_thresholds : Array[Double], warmup : Int, tolerance : Int) -> Result[Array[BaselineExperiment], DetectError]fn sweep_thresholds(scenario : NumericScenario, model : GaussianModel, hazard : Double, max_run_length : Int, thresholds : Array[Double], tolerance : Int) -> Result[Array[NumericExperiment], DetectError]fn threshold_grid(start : Double, finish : Double, count : Int) -> Result[Array[Double], DetectError]fn threshold_points(updates : Array[Update], truth : Array[Boundary], thresholds : Array[Double], tolerance : Int) -> Result[Array[ThresholdPoint], DetectError]fn trapezoid_area(horizontal : Array[Double], vertical : Array[Double]) -> Result[Double, DetectError]fn uniform_noise(length : Int, lower : Double, upper : Double, seed : Int) -> Result[Array[Double], DetectError]fn winsorize(values : Array[Double], lower_probability : Double, upper_probability : Double) -> Result[Array[Double], DetectError]Install
Download zipBayesian online change point detection for streaming numeric data