|
@@ -8,6 +8,7 @@ import os.path
|
8
|
8
|
import pickle
|
9
|
9
|
from keras import layers
|
10
|
10
|
from optparse import OptionParser
|
|
11
|
+import copy
|
11
|
12
|
|
12
|
13
|
|
13
|
14
|
parser = OptionParser()
|
|
@@ -32,7 +33,7 @@ for i in range(NumberOfFailures+1):
|
32
|
33
|
datafiles.append([])
|
33
|
34
|
|
34
|
35
|
# Next set of ddata corresponds to Freezer, SP=-26
|
35
|
|
-datafiles[0]=['2024-08-07_5_','2024-08-08_5_']
|
|
36
|
+datafiles[0]=['2024-08-07_5_','2024-08-08_5_','2025-01-25_5_','2025-01-26_5_']
|
36
|
37
|
datafiles[1]=['2024-12-11_5_', '2024-12-12_5_','2024-12-13_5_','2024-12-14_5_','2024-12-15_5_']
|
37
|
38
|
datafiles[2]=['2024-12-18_5_','2024-12-19_5_']
|
38
|
39
|
datafiles[3]=['2024-12-21_5_','2024-12-22_5_','2024-12-23_5_','2024-12-24_5_','2024-12-25_5_','2024-12-26_5_']
|
|
@@ -44,7 +45,7 @@ datafiles[4]=['2024-12-28_5_','2024-12-29_5_','2024-12-30_5_','2024-12-31_5_','2
|
44
|
45
|
# Seems to be incoropored in new tests
|
45
|
46
|
|
46
|
47
|
features=['r1 s1','r1 s4','r1 s5','pa1 apiii']
|
47
|
|
-features=['r1 s1','r1 s2','r1 s3','r1 s4','r1 s5','r1 s6','r1 s7','r1 s8','r1 s9','r1 s10','r2 s1','r2 s2','r2 s3','r2 s4','r2 s5','r2 s6','r2 s7','r2 s8','r2 s9','pa1 apiii','tc s1','tc s2']
|
|
48
|
+#features=['r1 s1','r1 s2','r1 s3','r1 s4','r1 s5','r1 s6','r1 s7','r1 s8','r1 s9','r1 s10','r2 s1','r2 s2','r2 s3','r2 s4','r2 s5','r2 s6','r2 s7','r2 s8','r2 s9','pa1 apiii','tc s1','tc s2']
|
48
|
49
|
|
49
|
50
|
#features=['r2 s2', 'tc s1','r1 s10','r1 s6','r2 s8']
|
50
|
51
|
|
|
@@ -116,15 +117,16 @@ def plotData():
|
116
|
117
|
#axes[1].legend()
|
117
|
118
|
#axes[0].set_ylabel(features[0])
|
118
|
119
|
#axes[1].set_ylabel(features[1])
|
119
|
|
- #plt.show()
|
|
120
|
+ plt.show()
|
120
|
121
|
|
121
|
122
|
#plotData()
|
|
123
|
+#exit(0)
|
122
|
124
|
|
123
|
125
|
|
124
|
126
|
NumFilters=64
|
125
|
127
|
KernelSize=7
|
126
|
|
-DropOut=0.1
|
127
|
|
-ThresholdFactor=1.7
|
|
128
|
+DropOut=0.2
|
|
129
|
+ThresholdFactor=0.9
|
128
|
130
|
TIME_STEPS = 48 # This is a trade off among better performance (high) and better response delay (low)
|
129
|
131
|
def create_sequences(values, time_steps=TIME_STEPS):
|
130
|
132
|
output = []
|
|
@@ -191,6 +193,7 @@ else:
|
191
|
193
|
x_train_pred=model.predict(x_train[0])
|
192
|
194
|
train_mae_loss=np.mean(np.abs(x_train_pred - x_train[0]), axis=1)
|
193
|
195
|
threshold=np.max(train_mae_loss,axis=0)
|
|
196
|
+thresholdOrig=copy.deepcopy(threshold)
|
194
|
197
|
|
195
|
198
|
print("Threshold : ",threshold)
|
196
|
199
|
threshold=threshold*ThresholdFactor
|
|
@@ -199,7 +202,8 @@ threshold=threshold*ThresholdFactor
|
199
|
202
|
|
200
|
203
|
# 1st scenario. Detect only anomaly. Later, we will classiffy it
|
201
|
204
|
# Test data= testnormal + testfail1 + testtail2 + testfail3 + testfail4 + testnormal
|
202
|
|
-d=np.vstack((dataTestNorm[0],dataTestNorm[1],dataTestNorm[2],dataTestNorm[3],dataTestNorm[4],dataTestNorm[0]))
|
|
205
|
+#d=np.vstack((dataTestNorm[0],dataTestNorm[1],dataTestNorm[2],dataTestNorm[3],dataTestNorm[4],dataTestNorm[0]))
|
|
206
|
+d=np.vstack((dataTestNorm[0],dataTestNorm[1],dataTestNorm[2],dataTestNorm[3],dataTestNorm[4]))
|
203
|
207
|
|
204
|
208
|
x_test = create_sequences(d)
|
205
|
209
|
x_test_pred = model.predict(x_test)
|
|
@@ -215,7 +219,8 @@ for i in range(1,NumberOfFailures+1):
|
215
|
219
|
testRanges.append([r,rnext] )
|
216
|
220
|
r=rnext
|
217
|
221
|
|
218
|
|
-testRanges.append([r, x_test.shape[0]+TIME_STEPS ])
|
|
222
|
+# Drop the last TIME_STEPS for plotting
|
|
223
|
+testRanges[NumberOfFailures][1]=testRanges[NumberOfFailures][1]-TIME_STEPS
|
219
|
224
|
|
220
|
225
|
|
221
|
226
|
def AtLeastOneTrue(x):
|
|
@@ -239,51 +244,54 @@ for i in range(anomalies.shape[0]):
|
239
|
244
|
colorline=['violet','lightcoral','cyan','lime','grey']
|
240
|
245
|
colordot=['darkviolet','red','blue','green','black']
|
241
|
246
|
|
242
|
|
-featuresToPlot=['r1 s1','r1 s2','r1 s3','pa1 apiii']
|
243
|
|
-#featuresToPlot=features
|
|
247
|
+#featuresToPlot=['r1 s1','r1 s2','r1 s3','pa1 apiii']
|
|
248
|
+featuresToPlot=features
|
244
|
249
|
|
245
|
250
|
indexesToPlot=[]
|
246
|
251
|
for i in featuresToPlot:
|
247
|
252
|
indexesToPlot.append(features.index(i))
|
248
|
253
|
|
249
|
|
-def plotData2():
|
|
254
|
+def plotData3():
|
250
|
255
|
NumFeaturesToPlot=len(indexesToPlot)
|
|
256
|
+ plt.rcParams.update({'font.size': 16})
|
251
|
257
|
fig, axes = plt.subplots(
|
252
|
|
- nrows=NumFeaturesToPlot, ncols=1, figsize=(25, 20), dpi=80, facecolor="w", edgecolor="k",sharex=True
|
|
258
|
+ nrows=NumFeaturesToPlot, ncols=1, figsize=(15, 10), dpi=80, facecolor="w", edgecolor="k",sharex=True
|
253
|
259
|
)
|
254
|
260
|
for i in range(NumFeaturesToPlot):
|
255
|
261
|
init=0
|
256
|
|
- end=len(x_train[0])
|
257
|
|
- axes[i].plot(range(init,end),x_train[0][:,0,indexesToPlot[i]],label="normal train")
|
258
|
|
- init=end
|
259
|
|
- end+=testRanges[0][1]
|
260
|
|
- axes[i].plot(range(init,end),x_test[testRanges[0][0]:testRanges[0][1],0,indexesToPlot[i]],label="normal test")
|
|
262
|
+ end=testRanges[0][1]
|
|
263
|
+ axes[i].plot(range(init,end),x_test[testRanges[0][0]:testRanges[0][1],0,indexesToPlot[i]],label="No fail")
|
261
|
264
|
init=end
|
262
|
265
|
end+=(testRanges[1][1]-testRanges[1][0])
|
263
|
266
|
for j in range(1,NumberOfFailures+1):
|
264
|
267
|
axes[i].plot(range(init,end),x_test[testRanges[j][0]:testRanges[j][1],0,indexesToPlot[i]],label="fail type "+str(j), color=colorline[j-1])
|
265
|
|
- init=end
|
266
|
|
- end+=(testRanges[j+1][1]-testRanges[j+1][0])
|
267
|
|
- # Shift TIME_STEPS because detection is performed at the end of time serie
|
268
|
|
- trail=np.hstack((x_test[:,0,indexesToPlot[i]], x_test[-1:,1:TIME_STEPS,indexesToPlot[i]].reshape(TIME_STEPS-1)))
|
269
|
|
- axes[i].plot(len(x_train[0])+np.array(anomalous_data_indices)+TIME_STEPS,trail[np.array(anomalous_data_indices)+TIME_STEPS],color='grey',marker='.',linewidth=0,label="abnormal detection" )
|
270
|
|
-
|
271
|
|
- init=end-(testRanges[NumberOfFailures+1][1]-testRanges[NumberOfFailures+1][0])
|
272
|
|
- end=init+(testRanges[0][1]-testRanges[0][0])
|
273
|
|
- axes[i].plot(range(init,end),x_test[testRanges[0][0]:testRanges[0][1],0,indexesToPlot[i]],color='orange')
|
|
268
|
+ if j<NumberOfFailures:
|
|
269
|
+ init=end
|
|
270
|
+ end+=(testRanges[j+1][1]-testRanges[j+1][0])
|
|
271
|
+ x=[]
|
|
272
|
+ y=[]
|
|
273
|
+ for k in anomalous_data_indices:
|
|
274
|
+ if (k+TIME_STEPS)<x_test.shape[0]:
|
|
275
|
+ x.append(k+TIME_STEPS)
|
|
276
|
+ y.append(x_test[k+TIME_STEPS,0,indexesToPlot[i]])
|
|
277
|
+ axes[i].plot(x,y ,color='grey',marker='.',linewidth=0,label="fail detection" )
|
274
|
278
|
|
275
|
279
|
if i==0:
|
276
|
|
- axes[i].legend(bbox_to_anchor=(1, 0.5))
|
|
280
|
+ axes[i].legend(bbox_to_anchor=(0.9, 0.4))
|
277
|
281
|
axes[i].set_ylabel(features[indexesToPlot[i]])
|
278
|
282
|
axes[i].grid()
|
|
283
|
+ axes[NumFeaturesToPlot-1].set_xlabel("Sample number")
|
279
|
284
|
plt.show()
|
280
|
285
|
|
281
|
286
|
|
282
|
287
|
def anomalyMetric(testList): # first of list is non failure data
|
283
|
288
|
# FP, TP: false/true positive
|
284
|
289
|
# TN, FN: true/false negative
|
285
|
|
- # Sensitivity: probab failure detection if data is fail: TP/(TP+FN)
|
|
290
|
+ # Sensitivity (recall): probab failure detection if data is fail: TP/(TP+FN)
|
286
|
291
|
# Specificity: true negative ratio given data is OK: TN/(TN+FP)
|
|
292
|
+ # Accuracy: Rate of correct predictions: (TN+TP)/(TN+TP+FP+FN)
|
|
293
|
+ # Precision: Rate of positive results: TP/(TP+FP)
|
|
294
|
+ # F-score: predictive performance measure: 2*Precision*Sensitity/(Precision+Sensitity)
|
287
|
295
|
|
288
|
296
|
x_test = create_sequences(testList[0])
|
289
|
297
|
x_test_pred = model.predict(x_test)
|
|
@@ -298,6 +306,8 @@ def anomalyMetric(testList): # first of list is non failure data
|
298
|
306
|
count=0
|
299
|
307
|
TP=np.zeros((NumberOfFailures))
|
300
|
308
|
FN=np.zeros((NumberOfFailures))
|
|
309
|
+ Sensitivity=np.zeros((NumberOfFailures))
|
|
310
|
+ Precision=np.zeros((NumberOfFailures))
|
301
|
311
|
for i in range(1,len(testList)):
|
302
|
312
|
x_test = create_sequences(testList[i])
|
303
|
313
|
x_test_pred = model.predict(x_test)
|
|
@@ -309,13 +319,50 @@ def anomalyMetric(testList): # first of list is non failure data
|
309
|
319
|
count+=1
|
310
|
320
|
TP[i-1] = count
|
311
|
321
|
FN[i-1] = anomalies.shape[0]-count
|
312
|
|
- Sensitivity=TP.sum()/(TP.sum()+FN.sum())
|
313
|
|
- Specifity=TN/(TN+FP)
|
|
322
|
+ Sensitivity[i-1]=TP[i-1]/(TP[i-1]+FN[i-1])
|
|
323
|
+ Precision[i-1]=TP[i-1]/(TP[i-1]+FP)
|
|
324
|
+
|
|
325
|
+ GlobalSensitivity=TP.sum()/(TP.sum()+FN.sum())
|
|
326
|
+ Specificity=TN/(TN+FP)
|
|
327
|
+ Accuracy=(TN+TP.sum())/(TN+TP.sum()+FP+FN.sum())
|
|
328
|
+ GlobalPrecision=TP.sum()/(TP.sum()+FP)
|
|
329
|
+ FScore= 2*GlobalPrecision*GlobalSensitivity/(GlobalPrecision+GlobalSensitivity)
|
|
330
|
+
|
314
|
331
|
print("Sensitivity: ",Sensitivity)
|
315
|
|
- print("Specifity: ",Specifity)
|
|
332
|
+ print("Global Sensitivity: ",GlobalSensitivity)
|
|
333
|
+ print("Precision: ",Precision)
|
|
334
|
+ print("Global Precision: ",GlobalPrecision)
|
|
335
|
+ print("Specifity: ",Specificity)
|
|
336
|
+ print("Accuracy: ",Accuracy)
|
|
337
|
+ print("FScore: ",FScore)
|
316
|
338
|
print("FP: ",FP)
|
317
|
|
- return Sensitivity+Specifity
|
|
339
|
+ #return Sensitivity+Specifity
|
|
340
|
+ return FScore
|
318
|
341
|
|
319
|
342
|
anomalyMetric([dataTestNorm[0],dataTestNorm[1],dataTestNorm[2],dataTestNorm[3],dataTestNorm[4]])
|
320
|
|
-plotData2()
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+def plotFScore():
|
|
346
|
+ global threshold
|
|
347
|
+ res=[]
|
|
348
|
+ # plots FSCroe as a function of Threshold Factor
|
|
349
|
+ tf=0.3
|
|
350
|
+ while tf<1.5:
|
|
351
|
+ threshold=thresholdOrig*tf
|
|
352
|
+ r=anomalyMetric([dataTestNorm[0],dataTestNorm[1],dataTestNorm[2],dataTestNorm[3],dataTestNorm[4]])
|
|
353
|
+ res.append([tf,r])
|
|
354
|
+ tf+=0.05
|
|
355
|
+
|
|
356
|
+ print(res)
|
|
357
|
+ ar=np.array((res))
|
|
358
|
+ plt.rcParams.update({'font.size': 16})
|
|
359
|
+ fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(14, 10), dpi=80, facecolor="w", edgecolor="k")
|
|
360
|
+ axes.plot(ar[:,0],ar[:,1],label="normal train",linewidth=4)
|
|
361
|
+ axes.set_xlabel("Threshold factor")
|
|
362
|
+ axes.set_ylabel("F-Score")
|
|
363
|
+ plt.grid()
|
|
364
|
+ plt.show()
|
|
365
|
+
|
|
366
|
+#plotFScore()
|
|
367
|
+plotData3()
|
321
|
368
|
|