-
-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Anomaly detection/combined scorer #1995
Conversation
31be8fa
to
bbccf33
Compare
9a50bc9
to
62f6a83
Compare
prophet_timestamps = np.array([None] * n_predictions) | ||
prophet_ys = np.array([None] * n_predictions) | ||
prophet_yhats = np.array([None] * n_predictions) | ||
prophet_yhat_lowers = np.array([None] * n_predictions) | ||
prophet_yhat_uppers = np.array([None] * n_predictions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
performance nit: would it be better to use np.full(n_predictions, None)
? This would just create the array directly rather than performing a conversion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think this was something you added? I just changed the values to None instead of 0.0 as 0.0 can affect scores.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you're right I did add these to pass down the prophet related info. Was reviewing the _hydrate_alert
function prior to this so was thinking of potential optimizations. I can add this as a followup PR if needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is fine, I can make the changes. It is a minor one.
forecast_len = algo_config.prophet_forecast_len * (60 // config.time_period) | ||
ts_internal = convert_external_ts_to_internal(timeseries) | ||
prophet_df = prophet_detector.predict( | ||
ts_internal.timestamps, | ||
ts_internal.values, | ||
forecast_len, | ||
config.time_period, | ||
config.sensitivity, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
qq: Could we use the cached predictions in the db rather than re-running predict here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and/or does forecast_len need to be > 0 in this case? Since specifically we just want the prophet predictions for what we currently have (history) and are not storing the future predictions in this function. I assume this would make this function slightly faster?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is called from both store_data and batch_predict calls. In the store_data path, the result from here is stored in DB. Agreed that the we do not need to predict for the batch_detection path but then that API is not being used actively in prod at this time. So I would not put it high on the list.
raise ServerError("No flags and scores from MP scorer") | ||
|
||
if prophet_df is None or prophet_df.empty: | ||
# logger.warning("The prophet_df is None or empty, skipping prophet scoring") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this log should still be included
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will cause a bunch of warnings in the case of combo_detect at present, where a batch detection is followed by a bunch of stream detection calls. I will be adding this back once I update that in a followup pr.
): | ||
return prophet_flag | ||
|
||
if (direction == "up" and y >= yhat_upper) or (direction == "down" and y <= yhat_lower): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this just be strictly greater/less than? I noticed thats what it was in the original LocationDetectors too. Probably doesn't make a large difference otherwise though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't make any noticeable difference.
if pd.to_datetime(timestamp) in prophet_map["flag"]: | ||
found += 1 | ||
pd_dt = pd.to_datetime(timestamp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it would be faster to convert the entire timestamp array to pd datetimes first then iterate over the converted values rather than converting each element within the loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For batch detection we are looking up at most 96 timestamps and for streaming we are looking up 1 timestamp. The prediction data can be up to 2688 long. So I do not think updating the entire DataFrame will be more efficient.
and prophet_flag == "anomaly_higher_confidence" | ||
): | ||
flags.append("anomaly_higher_confidence") | ||
elif prophet_score >= 2.0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed this threshold was >= 5.0 on the data-analysis notebook (I can't select the exact lines of code but if you cmd + f merge_prophet_mp_results
its in that function). Is there a reason this was dropped to 2.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't that part of your recommendation from your experiments for that one timeseries with an extended flatline at 0? Or am I misremembering it? Regardless, all my experiments in these past few days that we evaluated together and with Tillman has been using 2.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I think my investigation for that was prior to us fixing the stream logic for the scoring. Since 2.0 seems to work then LGTM and we can adjust later if needed
# todo: publish metrics for found/total | ||
# if debug: | ||
# print(f"found {found} out of {len(timestamps)}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nits: Should this just be added now as a log.info()? Also extra debug comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I'm actively working on this. I enabled this log and noticed that there is a difference in how timestamps are treated by the code that retrieves data from DB, resulting in stream computations not finding the datapoint. Am trouble shooting it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW it may be the discrepancy in the timestamps stored in DB (seconds) vs the pd timestamps which I believe defaults to 'ns': https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html
ad_config: AnomalyDetectionConfig, | ||
) -> FlagsAndScores: | ||
|
||
# todo: return prophet thresholds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
qq: I assume adding this would be a followup PR to support the UI changes for the confidence interval?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
@@ -376,7 +376,6 @@ def ready_check(app_config: AppConfig = injected): | |||
from seer.inference_models import models_loading_status | |||
|
|||
status = models_loading_status() | |||
logger.info(f"Model loading status: {status}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was causing a log entry to be published every second, increasing the noise in logs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just asked jenn/rohan about this. It isnt used for autofix, but may be helpful for grouping?
Would it make more sense to push this log to a few lines below within the if statements (FAILED/DONE checks on lines 384-387)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think there is much value in this log. Let me know if it is helpful for grouping.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just reviewed the entire file this log can probably just be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! No structural changes just had a couple of nits and questions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good
aa95433
to
540a511
Compare
…e LowVarianceScorer to MPLowVarianceScorer
23b9384
to
8b85677
Compare
No description provided.