4bac6e0156221d37e9fd69c3b2ad33742738ad05
[ric-app/ad.git] / src / ad_model.py
1 # ==================================================================================
2 #  Copyright (c) 2020 HCL Technologies Limited.
3 #
4 #  Licensed under the Apache License, Version 2.0 (the "License");
5 #  you may not use this file except in compliance with the License.
6 #  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #  Unless required by applicable law or agreed to in writing, software
11 #  distributed under the License is distributed on an "AS IS" BASIS,
12 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 #  See the License for the specific language governing permissions and
14 #  limitations under the License.
15 # ==================================================================================
16
17 import joblib
18 from mdclogpy import Logger
19
20 logger = Logger(name=__name__)
21
22
23 class modelling(object):
24     r""" Filter dataframe based on paramters that were used to train model
25     use transormer to transform the data
26     load model and predict the label(normal/anomalous)
27
28     Parameters:
29     data:DataFrame
30     """
31
32     def __init__(self, data=None):
33         self.data = data
34         self.load_model()
35         self.load_param()
36         self.load_scale()
37
38     def load_model(self):
39         try:
40             with open('src/model', 'rb') as f:
41                 self.model = joblib.load(f)
42         except FileNotFoundError:
43             logger.error("Model Does not exsist")
44
45     def load_param(self):
46         try:
47             with open('src/num_params', 'rb') as f:
48                 self.num = joblib.load(f)
49
50         except FileNotFoundError:
51             logger.error("Parameter file does not exsist")
52
53     def load_scale(self):
54         try:
55             with open('src/scale', 'rb') as f:
56                 self.scale = joblib.load(f)
57         except FileNotFoundError:
58             logger.error("Scale file does not exsist")
59
60     def transformation(self):
61         self.data = self.scale.transform(self.data)
62
63     def predict(self, df):
64         """ Load the saved model and return predicted result.
65         Parameters
66         .........
67         name:str
68             name of model
69
70         Return
71         ......
72         pred:int
73             predict label on a given sample
74
75         """
76         self.data = df.loc[:, self.num]
77         self.transformation()
78         pred = self.model.predict(self.data)
79         pred = [1 if p == -1 else 0 for p in pred]
80         return pred
81
82
83 class CAUSE(object):
84     r""""Rule basd method to find degradation type of anomalous sample
85
86     Attributes:
87     normal:DataFrame
88         Dataframe that contains only normal sample
89     """
90
91     def __init__(self):
92         self.normal = None
93
94     def cause(self, df, db, threshold):
95         """ Filter normal data for a particular ue-id to compare with a given sample
96             Compare with normal data to find and return degradaton type
97         """
98         sample = df.copy()
99         sample.index = range(len(sample))
100         for i in range(len(sample)):
101             if sample.iloc[i]['Anomaly'] == 1:
102                 query = """select * from {} where "{}" = \'{}\' and time<now() and time>now()-20s""".format(db.meas, db.ue, sample.iloc[i][db.ue])
103                 normal = db.query(query)
104                 if normal:
105                     normal = normal[db.meas][[db.thpt, db.rsrp, db.rsrq]]
106                     deg = self.find(sample.loc[i, :], normal.max(), db, threshold)
107                     if deg:
108                         sample.loc[i, 'Degradation'] = deg
109                         if 'Throughput' in deg and ('RSRP' in deg or 'RSRQ' in deg):
110                             sample.loc[i, 'Anomaly'] = 2
111                     else:
112                         sample.loc[i, 'Anomaly'] = 0
113         return sample[['Anomaly', 'Degradation']].values.tolist()
114
115     def find(self, row, l, db, threshold):
116         """ store if a particular parameter is below threshold and return """
117         deg = []
118         if row[db.thpt] < l[db.thpt]*(100 - threshold)*0.01:
119             deg.append('Throughput')
120         if row[db.rsrp] < l[db.rsrp]-15:
121             deg.append('RSRP')
122         if row[db.rsrq] < l[db.rsrq]-10:
123             deg.append('RSRQ')
124         if len(deg) == 0:
125             deg = False
126         else:
127             deg = ' '.join(deg)
128         return deg