AtthalaricNero commited on
Commit
d969e8f
·
1 Parent(s): 0da1da8

feat(controller): implement binary and classification prediction methods with error handling

Browse files
Files changed (2) hide show
  1. controller.py +136 -4
  2. requirements.txt +2 -1
controller.py CHANGED
@@ -4,22 +4,154 @@ from utils import (
4
  convert_cyclical_to_original,
5
  create_timestamp_from_predictions,
6
  prepare_prediction_data,
 
 
 
 
 
7
  )
8
 
 
9
 
10
  class Controller:
11
  def __init__(self):
12
  self.__database = Database()
13
  self.__sensor = self.__database.get_sensor_readings()
14
  self.__model = Model()
15
-
 
 
 
 
 
 
 
 
 
 
 
 
16
  # Binary method
17
  def predict_binary(self):
18
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  # Classification Method
21
  def predict_classification(self):
22
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  # Time series method
25
  def predict_time_series(self):
@@ -44,7 +176,7 @@ class Controller:
44
 
45
  if X_sequence is None:
46
  return {"success": False, "error": "Failed to prepare prediction data."}
47
-
48
  scaled_prediction = self.__model.model_lstm.predict(X_sequence, verbose=0)
49
 
50
  prediction = self.__model.scaler_y.inverse_transform(scaled_prediction)
 
4
  convert_cyclical_to_original,
5
  create_timestamp_from_predictions,
6
  prepare_prediction_data,
7
+ prepare_sensor_data_for_anomaly,
8
+ calculate_risk_score,
9
+ get_risk_level,
10
+ get_failure_severity,
11
+ get_failure_type_name,
12
  )
13
 
14
+ from datetime import datetime
15
 
16
  class Controller:
17
  def __init__(self):
18
  self.__database = Database()
19
  self.__sensor = self.__database.get_sensor_readings()
20
  self.__model = Model()
21
+
22
+ def _get_hardcoded_error_sensor(self):
23
+ """Hardcoded sensor data yang pasti error untuk testing"""
24
+ return {
25
+ "id": 9999,
26
+ "air_temp": 298.9,
27
+ "process_temp": 309.1,
28
+ "rotational_speed": 2861,
29
+ "torque": 4.6,
30
+ "tool_wear": 143,
31
+ "timestamp": datetime.now(),
32
+ "created_at": datetime.now()
33
+ }
34
  # Binary method
35
  def predict_binary(self):
36
+ if self.__sensor is None:
37
+ return {
38
+ "success": False,
39
+ "error": "No sensor data available from database.",
40
+ }
41
+
42
+ if (
43
+ self.__model.model_binary is None
44
+ or self.__model.preprocessor_anomaly is None
45
+ ):
46
+ return {
47
+ "success": False,
48
+ "error": "Binary model or preprocessor not loaded.",
49
+ }
50
+
51
+ X_scaled = prepare_sensor_data_for_anomaly(
52
+ self.__sensor, self.__model.preprocessor_anomaly
53
+ )
54
+
55
+ if X_scaled is None:
56
+ return {"success": False, "error": "Failed to prepare sensor data."}
57
+
58
+ if hasattr(self.__model.model_binary, "predict_proba"):
59
+ probabilities = self.__model.model_binary.predict_proba(X_scaled)[0]
60
+ confidence_normal = float(probabilities[0])
61
+ confidence_error = float(probabilities[1])
62
+
63
+ is_error = int(confidence_error > 0.5)
64
+ confidence = confidence_error if is_error else confidence_normal
65
+ else:
66
+ prediction = self.__model.model_binary.predict(X_scaled)
67
+ is_error = int(prediction[0])
68
+ confidence = 1.0 if is_error else 0.0
69
+
70
+ risk_score = confidence * 100 if is_error else (1 - confidence) * 100
71
+
72
+ result = {
73
+ "success": True,
74
+ "failure_predicted": bool(is_error),
75
+ "confidence": float(f"{confidence}"),
76
+ "risk_score": float(f"{risk_score}"),
77
+ "sensor_data": {
78
+ "air_temp": self.__sensor.get("air_temp"),
79
+ "process_temp": self.__sensor.get("process_temp"),
80
+ "rotational_speed": self.__sensor.get("rotational_speed"),
81
+ "torque": self.__sensor.get("torque"),
82
+ "tool_wear": self.__sensor.get("tool_wear"),
83
+ },
84
+ }
85
+
86
+ if is_error:
87
+ multiclass_result = self.predict_classification()
88
+ if multiclass_result.get("success"):
89
+ result["failure_analysis"] = {
90
+ "failure_type": multiclass_result.get("failure_type"),
91
+ "confidence": multiclass_result.get("confidence"),
92
+ "risk_level": multiclass_result.get("risk_level"),
93
+ "risk_score": multiclass_result.get("risk_score"),
94
+ "all_probabilities": multiclass_result.get("all_probabilities"),
95
+ }
96
+ else:
97
+ result["failure_analysis"] = {
98
+ "failure_type": "No Failure",
99
+ "risk_level": "Very Low",
100
+ }
101
+
102
+ return result
103
 
104
  # Classification Method
105
  def predict_classification(self):
106
+ if self.__sensor is None:
107
+ return {
108
+ "success": False,
109
+ "error": "No sensor data available from database.",
110
+ }
111
+
112
+ if (
113
+ self.__model.model_multiclass is None
114
+ or self.__model.preprocessor_anomaly is None
115
+ ):
116
+ return {"success": False, "error": "Model or scalers not loaded."}
117
+
118
+ X_scaled = prepare_sensor_data_for_anomaly(
119
+ self.__sensor, self.__model.preprocessor_anomaly
120
+ )
121
+
122
+ if X_scaled is None:
123
+ return {"success": False, "error": "Failed to prepare sensor data."}
124
+
125
+ prediction = self.__model.model_multiclass.predict(X_scaled)
126
+
127
+ if hasattr(self.__model.model_multiclass, "predict_proba"):
128
+ probabilities = self.__model.model_multiclass.predict_proba(X_scaled)[0]
129
+ failure_index = int(probabilities.argmax())
130
+ confidence = float(probabilities[failure_index])
131
+
132
+ all_probs = {
133
+ get_failure_type_name(i): float(prob)
134
+ for i, prob in enumerate(probabilities)
135
+ }
136
+ else:
137
+ failure_index = int(prediction[0])
138
+ confidence = 1.0
139
+ all_probs = None
140
+
141
+ failure_type = get_failure_type_name(failure_index)
142
+
143
+ severity = get_failure_severity(failure_index)
144
+ risk_score = calculate_risk_score(confidence, severity)
145
+ risk_level = get_risk_level(risk_score)
146
+
147
+ return {
148
+ "success": True,
149
+ "failure_type": failure_type,
150
+ "confidence": float(f"{confidence}"),
151
+ "risk_score": float(f"{risk_score}"),
152
+ "risk_level": risk_level,
153
+ "all_probabilities": all_probs,
154
+ }
155
 
156
  # Time series method
157
  def predict_time_series(self):
 
176
 
177
  if X_sequence is None:
178
  return {"success": False, "error": "Failed to prepare prediction data."}
179
+
180
  scaled_prediction = self.__model.model_lstm.predict(X_sequence, verbose=0)
181
 
182
  prediction = self.__model.scaler_y.inverse_transform(scaled_prediction)
requirements.txt CHANGED
@@ -6,4 +6,5 @@ joblib
6
  keras
7
  numpy
8
  pandas
9
- scikit-learn
 
 
6
  keras
7
  numpy
8
  pandas
9
+ scikit-learn
10
+ xgboost