|
|
|
@ -1,11 +1,56 @@
|
|
|
|
|
#[derive(Debug, Clone)] |
|
|
|
|
|
|
|
|
|
use std::{fmt, sync::Arc}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use parking_lot::Mutex; |
|
|
|
|
use serde_json; |
|
|
|
|
use serde::{Serialize, Deserialize}; |
|
|
|
|
|
|
|
|
|
use linfa::prelude::*; |
|
|
|
|
|
|
|
|
|
use linfa; |
|
|
|
|
use linfa_svm::{error::Result, Svm}; |
|
|
|
|
|
|
|
|
|
use ndarray::{Array, ArrayView, Axis}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)] |
|
|
|
|
pub struct LearningResults { |
|
|
|
|
// model: Vec<f64>,
|
|
|
|
|
model: Arc<Mutex<Svm<f64, bool>>>, |
|
|
|
|
patterns: Vec<Vec<f64>>, |
|
|
|
|
anti_patterns: Vec<Vec<f64>>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const CORR_THRESHOLD: f64 = 0.95; |
|
|
|
|
// impl Clone for LearningResults {
|
|
|
|
|
// fn clone(&self) -> Self {
|
|
|
|
|
// // TODO: it's a hack
|
|
|
|
|
// // https://github.com/rust-ml/linfa/issues/174
|
|
|
|
|
// let model_str = serde_json::to_string(&self.model).unwrap();
|
|
|
|
|
// let model = serde_json::from_str(&model_str).unwrap();
|
|
|
|
|
// return LearningResults {
|
|
|
|
|
// model,
|
|
|
|
|
// patterns: self.patterns.clone(),
|
|
|
|
|
// anti_patterns: self.anti_patterns.clone()
|
|
|
|
|
// };
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
impl fmt::Debug for LearningResults { |
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
|
|
|
|
f.debug_struct("Point") |
|
|
|
|
.field("{:?}", &self.patterns) |
|
|
|
|
.field("{:?}", &self.anti_patterns) |
|
|
|
|
.finish() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const FEATURES_SIZE: usize = 6; |
|
|
|
|
|
|
|
|
|
type Features = [f64; FEATURES_SIZE]; |
|
|
|
|
|
|
|
|
|
const SCORE_THRESHOLD: f64 = 0.95; |
|
|
|
|
|
|
|
|
|
#[derive(Clone)] |
|
|
|
|
pub struct PatternDetector { |
|
|
|
@ -34,21 +79,65 @@ impl PatternDetector {
|
|
|
|
|
let mut patterns = Vec::<Vec<f64>>::new(); |
|
|
|
|
let mut anti_patterns = Vec::<Vec<f64>>::new(); |
|
|
|
|
|
|
|
|
|
// TODO: implement actual learning
|
|
|
|
|
|
|
|
|
|
let mut records = Array::zeros((0, FEATURES_SIZE)); |
|
|
|
|
let mut targets_raw = Vec::<bool>::new(); |
|
|
|
|
|
|
|
|
|
for r in reads { |
|
|
|
|
let xs: Vec<f64> = r.iter().map(|e| e.1).map(nan_to_zero).collect(); |
|
|
|
|
let fs = PatternDetector::get_features(&xs); |
|
|
|
|
|
|
|
|
|
records.push_row(ArrayView::from(&fs)).unwrap(); |
|
|
|
|
|
|
|
|
|
targets_raw.push(true); |
|
|
|
|
patterns.push(xs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for r in anti_reads { |
|
|
|
|
let xs: Vec<f64> = r.iter().map(|e| e.1).map(nan_to_zero).collect(); |
|
|
|
|
let fs = PatternDetector::get_features(&xs); |
|
|
|
|
records.push_row(ArrayView::from(&fs)).unwrap(); |
|
|
|
|
targets_raw.push(false); |
|
|
|
|
anti_patterns.push(xs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let targets = Array::from_vec(targets_raw); |
|
|
|
|
|
|
|
|
|
// println!("{:?}", records);
|
|
|
|
|
// println!("{:?}", targets);
|
|
|
|
|
|
|
|
|
|
let train = linfa::Dataset::new(records, targets); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The 'view' describes what set of data is drawn
|
|
|
|
|
// let v = ContinuousView::new()
|
|
|
|
|
// .add(s1)
|
|
|
|
|
// // .add(s2)
|
|
|
|
|
// .x_range(-500., 100.)
|
|
|
|
|
// .y_range(-200., 600.)
|
|
|
|
|
// .x_label("Some varying variable")
|
|
|
|
|
// .y_label("The response of something");
|
|
|
|
|
|
|
|
|
|
// Page::single(&v).save("scatter.svg").unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// let model = stat.iter().map(|(c, v)| v / *c as f64).collect();
|
|
|
|
|
|
|
|
|
|
let model = Svm::<_, bool>::params() |
|
|
|
|
.pos_neg_weights(50000., 5000.) |
|
|
|
|
.gaussian_kernel(80.0) |
|
|
|
|
.fit(&train).unwrap(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// let prediction = model.predict(Array::from_vec(vec![
|
|
|
|
|
// 715.3122807017543, 761.1228070175438, 745.0, 56.135764727158595, 0.0, 0.0
|
|
|
|
|
// ]));
|
|
|
|
|
|
|
|
|
|
// println!("pridiction: {}", prediction );
|
|
|
|
|
|
|
|
|
|
LearningResults { |
|
|
|
|
model: Arc::new(Mutex::new(model)), |
|
|
|
|
patterns, |
|
|
|
|
anti_patterns, |
|
|
|
|
} |
|
|
|
@ -57,12 +146,9 @@ impl PatternDetector {
|
|
|
|
|
// TODO: get iterator instead of vector
|
|
|
|
|
pub fn detect(&self, ts: &Vec<(u64, f64)>) -> Vec<(u64, u64)> { |
|
|
|
|
let mut results = Vec::new(); |
|
|
|
|
// let mut i = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let pt = &self.learning_results.patterns; |
|
|
|
|
let apt = &self.learning_results.anti_patterns; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for i in 0..ts.len() { |
|
|
|
|
|
|
|
|
@ -97,7 +183,21 @@ impl PatternDetector {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if pattern_match_score > anti_pattern_match_score && pattern_match_score >= CORR_THRESHOLD { |
|
|
|
|
{
|
|
|
|
|
let mut backet = Vec::<f64>::new(); |
|
|
|
|
for j in 0..pattern_match_len { |
|
|
|
|
backet.push(nan_to_zero(ts[i + j].1)); |
|
|
|
|
} |
|
|
|
|
let fs = PatternDetector::get_features(&backet); |
|
|
|
|
let detected = self.learning_results.model.lock().predict(Array::from_vec(fs.to_vec())); |
|
|
|
|
if detected { |
|
|
|
|
pattern_match_score += 0.1; |
|
|
|
|
} else { |
|
|
|
|
anti_pattern_match_score += 0.1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if pattern_match_score > anti_pattern_match_score && pattern_match_score >= SCORE_THRESHOLD { |
|
|
|
|
results.push((ts[i].0, ts[i + pattern_match_len - 1].0)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -148,4 +248,39 @@ impl PatternDetector {
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn get_features(xs: &Vec<f64>) -> Features { |
|
|
|
|
let mut min = f64::MAX; |
|
|
|
|
let mut max = f64::MIN; |
|
|
|
|
let mut sum = 0f64; |
|
|
|
|
|
|
|
|
|
for x in xs { |
|
|
|
|
min = min.min(*x); |
|
|
|
|
max = max.max(*x); |
|
|
|
|
sum += x; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let mean = sum / xs.len() as f64; |
|
|
|
|
|
|
|
|
|
sum = 0f64; |
|
|
|
|
|
|
|
|
|
for x in xs { |
|
|
|
|
sum += (x - mean) * (x - mean); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let sd = sum.sqrt(); |
|
|
|
|
|
|
|
|
|
// TODO: add autocorrelation
|
|
|
|
|
// TODO: add FFT
|
|
|
|
|
|
|
|
|
|
return [ |
|
|
|
|
min, |
|
|
|
|
max,
|
|
|
|
|
mean, |
|
|
|
|
sd, |
|
|
|
|
0f64,0f64, |
|
|
|
|
//0f64,0f64,0f64, 0f64
|
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|