Spaces:
Sleeping
Sleeping
Create model/anomaly_detector.py
Browse files- model/anomaly_detector.py +41 -0
model/anomaly_detector.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
from sklearn.ensemble import IsolationForest
|
| 3 |
+
from utils.preprocessing import extract_features
|
| 4 |
+
|
| 5 |
+
# A placeholder Isolation Forest model
|
| 6 |
+
# In production, load a pre-trained model using joblib or pickle
|
| 7 |
+
model = IsolationForest(contamination=0.2, random_state=42)
|
| 8 |
+
|
| 9 |
+
# Example training data (you should replace with real preprocessed dataset)
|
| 10 |
+
example_training_data = np.array([
|
| 11 |
+
[5, 0, 30, 0],
|
| 12 |
+
[10, 1, 50, 1],
|
| 13 |
+
[2, 4, 10, 3],
|
| 14 |
+
[8, 0, 45, 0],
|
| 15 |
+
[3, 5, 12, 2]
|
| 16 |
+
])
|
| 17 |
+
model.fit(example_training_data)
|
| 18 |
+
|
| 19 |
+
def detect_anomaly(agent_data):
|
| 20 |
+
features = extract_features(agent_data)
|
| 21 |
+
prediction = model.predict([features])[0] # -1 for anomaly
|
| 22 |
+
flagged = prediction == -1
|
| 23 |
+
|
| 24 |
+
reason = ""
|
| 25 |
+
if flagged:
|
| 26 |
+
if agent_data["missed_visits"] >= 5:
|
| 27 |
+
reason = "Missed appointments spike"
|
| 28 |
+
elif agent_data["weekly_calls"] < 4:
|
| 29 |
+
reason = "Low call frequency"
|
| 30 |
+
elif agent_data["lead_drop_rate"] > 0.6:
|
| 31 |
+
reason = "High lead drop rate"
|
| 32 |
+
else:
|
| 33 |
+
reason = "Unusual activity pattern"
|
| 34 |
+
|
| 35 |
+
return {
|
| 36 |
+
"agent_id": agent_data.get("agent_id", "unknown"),
|
| 37 |
+
"weekly_calls": agent_data["weekly_calls"],
|
| 38 |
+
"missed_visits": agent_data["missed_visits"],
|
| 39 |
+
"flagged": flagged,
|
| 40 |
+
"reason": reason if flagged else "Normal behavior"
|
| 41 |
+
}
|