lazyqsar 0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lazyqsar/__init__.py +7 -0
- lazyqsar/binary/__init__.py +0 -0
- lazyqsar/binary/classic.py +70 -0
- lazyqsar/binary/eosembedding.py +87 -0
- lazyqsar/binary/maccs.py +70 -0
- lazyqsar/binary/mordred.py +70 -0
- lazyqsar/binary/morgan.py +87 -0
- lazyqsar/binary/rdkit.py +70 -0
- lazyqsar/descriptors/__init__.py +0 -0
- lazyqsar/descriptors/descriptors.py +541 -0
- lazyqsar/regression/__init__.py +0 -0
- lazyqsar/regression/eosembedding.py +68 -0
- lazyqsar/regression/morgan.py +69 -0
- lazyqsar-0.4.dist-info/LICENSE +674 -0
- lazyqsar-0.4.dist-info/METADATA +144 -0
- lazyqsar-0.4.dist-info/RECORD +18 -0
- lazyqsar-0.4.dist-info/WHEEL +5 -0
- lazyqsar-0.4.dist-info/top_level.txt +1 -0
lazyqsar/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from .binary.morgan import MorganBinaryClassifier
|
|
2
|
+
from .binary.mordred import MordredBinaryClassifier
|
|
3
|
+
from .binary.classic import ClassicBinaryClassifier
|
|
4
|
+
from .binary.rdkit import RdkitBinaryClassifier
|
|
5
|
+
from .binary.eosembedding import ErsiliaBinaryClassifier
|
|
6
|
+
from .regression.morgan import MorganRegressor
|
|
7
|
+
from .regression.eosembedding import ErsiliaRegressor
|
|
File without changes
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from flaml import AutoML
|
|
2
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import joblib
|
|
6
|
+
|
|
7
|
+
import shap
|
|
8
|
+
|
|
9
|
+
from ..descriptors.descriptors import ClassicDescriptor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ClassicBinaryClassifier(object):
|
|
13
|
+
|
|
14
|
+
def __init__(self, automl=True, time_budget_sec=20, estimator_list=None):
|
|
15
|
+
self.time_budget_sec=time_budget_sec
|
|
16
|
+
self.estimator_list=estimator_list
|
|
17
|
+
self.model = None
|
|
18
|
+
self.explainer = None
|
|
19
|
+
self._automl = automl
|
|
20
|
+
self.descriptor = ClassicDescriptor()
|
|
21
|
+
|
|
22
|
+
def fit_automl(self, smiles, y):
|
|
23
|
+
model = AutoML(task="classification", time_budget=self.time_budget_sec)
|
|
24
|
+
X = self.descriptor.fit(smiles)
|
|
25
|
+
y = np.array(y)
|
|
26
|
+
model.fit(X, y, time_budget=self.time_budget_sec, estimator_list=self.estimator_list)
|
|
27
|
+
self._n_pos = int(np.sum(y))
|
|
28
|
+
self._n_neg = len(y) - self._n_pos
|
|
29
|
+
self._auroc = 1-model.best_loss
|
|
30
|
+
self.meta = {
|
|
31
|
+
"n_pos": self._n_pos,
|
|
32
|
+
"n_neg": self._n_neg,
|
|
33
|
+
"auroc": self._auroc
|
|
34
|
+
}
|
|
35
|
+
self.model = model.model.estimator
|
|
36
|
+
self.model.fit(X, y)
|
|
37
|
+
|
|
38
|
+
def fit_default(self, smiles, y):
|
|
39
|
+
model = RandomForestClassifier()
|
|
40
|
+
X = self.descriptor.fit(smiles)
|
|
41
|
+
y = np.array(y)
|
|
42
|
+
model.fit(X, y)
|
|
43
|
+
self.model = model
|
|
44
|
+
|
|
45
|
+
def fit(self, smiles, y):
|
|
46
|
+
if self._automl:
|
|
47
|
+
self.fit_automl(smiles, y)
|
|
48
|
+
else:
|
|
49
|
+
self.fit_default(smiles, y)
|
|
50
|
+
|
|
51
|
+
def predict(self, smiles):
|
|
52
|
+
X = self.descriptor.transform(smiles)
|
|
53
|
+
return self.model.predict(X)
|
|
54
|
+
|
|
55
|
+
def predict_proba(self, smiles):
|
|
56
|
+
X = self.descriptor.transform(smiles)
|
|
57
|
+
return self.model.predict_proba(X)
|
|
58
|
+
|
|
59
|
+
def explain(self, smiles):
|
|
60
|
+
X = self.descriptor.transform(smiles)
|
|
61
|
+
if self.explainer is None:
|
|
62
|
+
self.explainer = shap.Explainer(self.model)
|
|
63
|
+
shap_values = self.explainer(X, check_additivity=False)
|
|
64
|
+
return shap_values
|
|
65
|
+
|
|
66
|
+
def save(self, path):
|
|
67
|
+
joblib.dump(self, path)
|
|
68
|
+
|
|
69
|
+
def load(self, path):
|
|
70
|
+
return joblib.load(path)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from flaml import AutoML
|
|
2
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
3
|
+
from sklearn.decomposition import PCA
|
|
4
|
+
|
|
5
|
+
import shap
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import joblib
|
|
9
|
+
|
|
10
|
+
from ..descriptors.descriptors import ErsiliaEmbedding
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ErsiliaBinaryClassifier(object):
|
|
14
|
+
|
|
15
|
+
def __init__(self, automl=True, reduced=False, time_budget_sec=20, estimator_list=None):
|
|
16
|
+
self.time_budget_sec=time_budget_sec
|
|
17
|
+
self.estimator_list=estimator_list
|
|
18
|
+
self.model = None
|
|
19
|
+
self.reducer=None
|
|
20
|
+
self.explainer = None
|
|
21
|
+
self._automl = automl
|
|
22
|
+
self._reduced = reduced
|
|
23
|
+
self.descriptor = ErsiliaEmbedding()
|
|
24
|
+
|
|
25
|
+
def fit_automl(self, smiles, y):
|
|
26
|
+
model = AutoML(task="classification", time_budget=self.time_budget_sec)
|
|
27
|
+
X = np.array(self.descriptor.transform(smiles))
|
|
28
|
+
y = np.array(y)
|
|
29
|
+
if self._reduced:
|
|
30
|
+
self.reducer = PCA(n_components=100)
|
|
31
|
+
self.reducer.fit(X)
|
|
32
|
+
X = self.reducer.transform(X)
|
|
33
|
+
model.fit(X, y, time_budget=self.time_budget_sec, estimator_list=self.estimator_list)
|
|
34
|
+
self._n_pos = int(np.sum(y))
|
|
35
|
+
self._n_neg = len(y) - self._n_pos
|
|
36
|
+
self._auroc = 1-model.best_loss
|
|
37
|
+
self.meta = {
|
|
38
|
+
"n_pos": self._n_pos,
|
|
39
|
+
"n_neg": self._n_neg,
|
|
40
|
+
"auroc": self._auroc
|
|
41
|
+
}
|
|
42
|
+
self.model = model.model.estimator
|
|
43
|
+
self.model.fit(X, y)
|
|
44
|
+
|
|
45
|
+
def fit_default(self, smiles, y):
|
|
46
|
+
model = RandomForestClassifier()
|
|
47
|
+
X = np.array(self.descriptor.transform(smiles))
|
|
48
|
+
y = np.array(y)
|
|
49
|
+
if self._reduced:
|
|
50
|
+
self.reducer = PCA(n_components=100)
|
|
51
|
+
self.reducer.fit(X)
|
|
52
|
+
X = self.reducer.transform(X)
|
|
53
|
+
model.fit(X, y)
|
|
54
|
+
self.model = model
|
|
55
|
+
|
|
56
|
+
def fit(self, smiles, y):
|
|
57
|
+
if self._automl:
|
|
58
|
+
self.fit_automl(smiles, y)
|
|
59
|
+
else:
|
|
60
|
+
self.fit_default(smiles, y)
|
|
61
|
+
|
|
62
|
+
def explain(self, smiles):
|
|
63
|
+
X = self.descriptor.transform(smiles)
|
|
64
|
+
if self._reduced:
|
|
65
|
+
X = self.reducer.transform(X)
|
|
66
|
+
if self.explainer is None:
|
|
67
|
+
self.explainer = shap.Explainer(self.model)
|
|
68
|
+
shap_values = self.explainer(X, check_additivity=False)
|
|
69
|
+
return shap_values
|
|
70
|
+
|
|
71
|
+
def predict(self, smiles):
|
|
72
|
+
X = np.array(self.descriptor.transform(smiles))
|
|
73
|
+
if self._reduced:
|
|
74
|
+
X = self.reducer.transform(X)
|
|
75
|
+
return self.model.predict(X)
|
|
76
|
+
|
|
77
|
+
def predict_proba(self, smiles):
|
|
78
|
+
X = np.array(self.descriptor.transform(smiles))
|
|
79
|
+
if self._reduced:
|
|
80
|
+
X = self.reducer.transform(X)
|
|
81
|
+
return self.model.predict_proba(X)
|
|
82
|
+
|
|
83
|
+
def save(self, path):
|
|
84
|
+
joblib.dump(self, path)
|
|
85
|
+
|
|
86
|
+
def load(self, path):
|
|
87
|
+
return joblib.load(path)
|
lazyqsar/binary/maccs.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from flaml import AutoML
|
|
2
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import joblib
|
|
6
|
+
|
|
7
|
+
import shap
|
|
8
|
+
|
|
9
|
+
from ..descriptors.descriptors import MaccsDescriptor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MaccsBinaryClassifier(object):
|
|
13
|
+
|
|
14
|
+
def __init__(self, automl=True, time_budget_sec=20, estimator_list=None):
|
|
15
|
+
self.time_budget_sec=time_budget_sec
|
|
16
|
+
self.estimator_list=estimator_list
|
|
17
|
+
self.model = None
|
|
18
|
+
self.explainer = None
|
|
19
|
+
self._automl = automl
|
|
20
|
+
self.descriptor = MaccsDescriptor()
|
|
21
|
+
|
|
22
|
+
def fit_automl(self, smiles, y):
|
|
23
|
+
model = AutoML(task="classification", time_budget=self.time_budget_sec)
|
|
24
|
+
X = np.array(self.descriptor.fit(smiles))
|
|
25
|
+
y = np.array(y)
|
|
26
|
+
model.fit(X, y, time_budget=self.time_budget_sec, estimator_list=self.estimator_list)
|
|
27
|
+
self._n_pos = int(np.sum(y))
|
|
28
|
+
self._n_neg = len(y) - self._n_pos
|
|
29
|
+
self._auroc = 1-model.best_loss
|
|
30
|
+
self.meta = {
|
|
31
|
+
"n_pos": self._n_pos,
|
|
32
|
+
"n_neg": self._n_neg,
|
|
33
|
+
"auroc": self._auroc
|
|
34
|
+
}
|
|
35
|
+
self.model = model.model.estimator
|
|
36
|
+
self.model.fit(X, y)
|
|
37
|
+
|
|
38
|
+
def fit_default(self, smiles, y):
|
|
39
|
+
model = RandomForestClassifier()
|
|
40
|
+
X = np.array(self.descriptor.fit(smiles))
|
|
41
|
+
y = np.array(y)
|
|
42
|
+
model.fit(X, y)
|
|
43
|
+
self.model = model
|
|
44
|
+
|
|
45
|
+
def fit(self, smiles, y):
|
|
46
|
+
if self._automl:
|
|
47
|
+
self.fit_automl(smiles, y)
|
|
48
|
+
else:
|
|
49
|
+
self.fit_default(smiles, y)
|
|
50
|
+
|
|
51
|
+
def predict(self, smiles):
|
|
52
|
+
X = np.array(self.descriptor.transform(smiles))
|
|
53
|
+
return self.model.predict(X)
|
|
54
|
+
|
|
55
|
+
def predict_proba(self, smiles):
|
|
56
|
+
X = np.array(self.descriptor.transform(smiles))
|
|
57
|
+
return self.model.predict_proba(X)
|
|
58
|
+
|
|
59
|
+
def explain(self, smiles):
|
|
60
|
+
X = self.descriptor.transform(smiles)
|
|
61
|
+
if self.explainer is None:
|
|
62
|
+
self.explainer = shap.Explainer(self.model)
|
|
63
|
+
shap_values = self.explainer(X, check_additivity=False)
|
|
64
|
+
return shap_values
|
|
65
|
+
|
|
66
|
+
def save(self, path):
|
|
67
|
+
joblib.dump(self, path)
|
|
68
|
+
|
|
69
|
+
def load(self, path):
|
|
70
|
+
return joblib.load(path)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from flaml import AutoML
|
|
2
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import joblib
|
|
6
|
+
|
|
7
|
+
import shap
|
|
8
|
+
|
|
9
|
+
from ..descriptors.descriptors import MordredDescriptor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MordredBinaryClassifier(object):
|
|
13
|
+
|
|
14
|
+
def __init__(self, automl=True, time_budget_sec=20, estimator_list=None):
|
|
15
|
+
self.time_budget_sec=time_budget_sec
|
|
16
|
+
self.estimator_list=estimator_list
|
|
17
|
+
self.model = None
|
|
18
|
+
self.explainer = None
|
|
19
|
+
self._automl = automl
|
|
20
|
+
self.descriptor = MordredDescriptor()
|
|
21
|
+
|
|
22
|
+
def fit_automl(self, smiles, y):
|
|
23
|
+
model = AutoML(task="classification", time_budget=self.time_budget_sec)
|
|
24
|
+
X = self.descriptor.fit(smiles)
|
|
25
|
+
y = np.array(y)
|
|
26
|
+
model.fit(X, y, time_budget=self.time_budget_sec, estimator_list=self.estimator_list)
|
|
27
|
+
self._n_pos = int(np.sum(y))
|
|
28
|
+
self._n_neg = len(y) - self._n_pos
|
|
29
|
+
self._auroc = 1-model.best_loss
|
|
30
|
+
self.meta = {
|
|
31
|
+
"n_pos": self._n_pos,
|
|
32
|
+
"n_neg": self._n_neg,
|
|
33
|
+
"auroc": self._auroc
|
|
34
|
+
}
|
|
35
|
+
self.model = model.model.estimator
|
|
36
|
+
self.model.fit(X, y)
|
|
37
|
+
|
|
38
|
+
def fit_default(self, smiles, y):
|
|
39
|
+
model = RandomForestClassifier()
|
|
40
|
+
X = self.descriptor.fit(smiles)
|
|
41
|
+
y = np.array(y)
|
|
42
|
+
model.fit(X, y)
|
|
43
|
+
self.model = model
|
|
44
|
+
|
|
45
|
+
def fit(self, smiles, y):
|
|
46
|
+
if self._automl:
|
|
47
|
+
self.fit_automl(smiles, y)
|
|
48
|
+
else:
|
|
49
|
+
self.fit_default(smiles, y)
|
|
50
|
+
|
|
51
|
+
def predict(self, smiles):
|
|
52
|
+
X = self.descriptor.transform(smiles)
|
|
53
|
+
return self.model.predict(X)
|
|
54
|
+
|
|
55
|
+
def predict_proba(self, smiles):
|
|
56
|
+
X = self.descriptor.transform(smiles)
|
|
57
|
+
return self.model.predict_proba(X)
|
|
58
|
+
|
|
59
|
+
def explain(self, smiles):
|
|
60
|
+
X = self.descriptor.transform(smiles)
|
|
61
|
+
if self.explainer is None:
|
|
62
|
+
self.explainer = shap.Explainer(self.model)
|
|
63
|
+
shap_values = self.explainer(X, check_additivity=False)
|
|
64
|
+
return shap_values
|
|
65
|
+
|
|
66
|
+
def save(self, path):
|
|
67
|
+
joblib.dump(self, path)
|
|
68
|
+
|
|
69
|
+
def load(self, path):
|
|
70
|
+
return joblib.load(path)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from flaml import AutoML
|
|
2
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
3
|
+
from sklearn.decomposition import PCA
|
|
4
|
+
|
|
5
|
+
import shap
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import joblib
|
|
9
|
+
|
|
10
|
+
from ..descriptors.descriptors import MorganDescriptor
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MorganBinaryClassifier(object):
|
|
14
|
+
|
|
15
|
+
def __init__(self, automl=True, reduced=False, time_budget_sec=20, estimator_list=None):
|
|
16
|
+
self.time_budget_sec=time_budget_sec
|
|
17
|
+
self.estimator_list=estimator_list
|
|
18
|
+
self.model = None
|
|
19
|
+
self.reducer = None
|
|
20
|
+
self.explainer = None
|
|
21
|
+
self._automl = automl
|
|
22
|
+
self._reduced =reduced
|
|
23
|
+
self.descriptor = MorganDescriptor()
|
|
24
|
+
|
|
25
|
+
def fit_automl(self, smiles, y):
|
|
26
|
+
model = AutoML(task="classification", time_budget=self.time_budget_sec)
|
|
27
|
+
X = np.array(self.descriptor.fit(smiles))
|
|
28
|
+
y = np.array(y)
|
|
29
|
+
if self._reduced:
|
|
30
|
+
self.reducer = PCA(n_components=100)
|
|
31
|
+
self.reducer.fit(X)
|
|
32
|
+
X = self.reducer.transform(X)
|
|
33
|
+
model.fit(X, y, time_budget=self.time_budget_sec, estimator_list=self.estimator_list)
|
|
34
|
+
self._n_pos = int(np.sum(y))
|
|
35
|
+
self._n_neg = len(y) - self._n_pos
|
|
36
|
+
self._auroc = 1-model.best_loss
|
|
37
|
+
self.meta = {
|
|
38
|
+
"n_pos": self._n_pos,
|
|
39
|
+
"n_neg": self._n_neg,
|
|
40
|
+
"auroc": self._auroc
|
|
41
|
+
}
|
|
42
|
+
self.model = model.model.estimator
|
|
43
|
+
self.model.fit(X, y)
|
|
44
|
+
|
|
45
|
+
def fit_default(self, smiles, y):
|
|
46
|
+
model = RandomForestClassifier()
|
|
47
|
+
X = np.array(self.descriptor.fit(smiles))
|
|
48
|
+
if self._reduced:
|
|
49
|
+
self.reducer = PCA(n_components=100)
|
|
50
|
+
self.reducer.fit(X)
|
|
51
|
+
X = self.reducer.transform(X)
|
|
52
|
+
y = np.array(y)
|
|
53
|
+
model.fit(X, y)
|
|
54
|
+
self.model = model
|
|
55
|
+
|
|
56
|
+
def fit(self, smiles, y):
|
|
57
|
+
if self._automl:
|
|
58
|
+
self.fit_automl(smiles, y)
|
|
59
|
+
else:
|
|
60
|
+
self.fit_default(smiles, y)
|
|
61
|
+
|
|
62
|
+
def explain(self, smiles):
|
|
63
|
+
X = self.descriptor.transform(smiles)
|
|
64
|
+
if self._reduced:
|
|
65
|
+
X = self.reducer.transform(X)
|
|
66
|
+
if self.explainer is None:
|
|
67
|
+
self.explainer = shap.Explainer(self.model)
|
|
68
|
+
shap_values = self.explainer(X, check_additivity=False)
|
|
69
|
+
return shap_values
|
|
70
|
+
|
|
71
|
+
def predict(self, smiles):
|
|
72
|
+
X = np.array(self.descriptor.transform(smiles))
|
|
73
|
+
if self._reduced:
|
|
74
|
+
X = self.reducer.transform(X)
|
|
75
|
+
return self.model.predict(X)
|
|
76
|
+
|
|
77
|
+
def predict_proba(self, smiles):
|
|
78
|
+
X = np.array(self.descriptor.transform(smiles))
|
|
79
|
+
if self._reduced:
|
|
80
|
+
X = self.reducer.transform(X)
|
|
81
|
+
return self.model.predict_proba(X)
|
|
82
|
+
|
|
83
|
+
def save(self, path):
|
|
84
|
+
joblib.dump(self, path)
|
|
85
|
+
|
|
86
|
+
def load(self, path):
|
|
87
|
+
return joblib.load(path)
|
lazyqsar/binary/rdkit.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from flaml import AutoML
|
|
2
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import joblib
|
|
6
|
+
|
|
7
|
+
import shap
|
|
8
|
+
|
|
9
|
+
from ..descriptors.descriptors import RdkitDescriptor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RdkitBinaryClassifier(object):
|
|
13
|
+
|
|
14
|
+
def __init__(self, automl=True, time_budget_sec=20, estimator_list=None):
|
|
15
|
+
self.time_budget_sec=time_budget_sec
|
|
16
|
+
self.estimator_list=estimator_list
|
|
17
|
+
self.model = None
|
|
18
|
+
self.explainer = None
|
|
19
|
+
self._automl = automl
|
|
20
|
+
self.descriptor = RdkitDescriptor()
|
|
21
|
+
|
|
22
|
+
def fit_automl(self, smiles, y):
|
|
23
|
+
model = AutoML(task="classification", time_budget=self.time_budget_sec)
|
|
24
|
+
X = self.descriptor.fit(smiles)
|
|
25
|
+
y = np.array(y)
|
|
26
|
+
model.fit(X, y, time_budget=self.time_budget_sec, estimator_list=self.estimator_list)
|
|
27
|
+
self._n_pos = int(np.sum(y))
|
|
28
|
+
self._n_neg = len(y) - self._n_pos
|
|
29
|
+
self._auroc = 1-model.best_loss
|
|
30
|
+
self.meta = {
|
|
31
|
+
"n_pos": self._n_pos,
|
|
32
|
+
"n_neg": self._n_neg,
|
|
33
|
+
"auroc": self._auroc
|
|
34
|
+
}
|
|
35
|
+
self.model = model.model.estimator
|
|
36
|
+
self.model.fit(X, y)
|
|
37
|
+
|
|
38
|
+
def fit_default(self, smiles, y):
|
|
39
|
+
model = RandomForestClassifier()
|
|
40
|
+
X = self.descriptor.fit(smiles)
|
|
41
|
+
y = np.array(y)
|
|
42
|
+
model.fit(X, y)
|
|
43
|
+
self.model = model
|
|
44
|
+
|
|
45
|
+
def fit(self, smiles, y):
|
|
46
|
+
if self._automl:
|
|
47
|
+
self.fit_automl(smiles, y)
|
|
48
|
+
else:
|
|
49
|
+
self.fit_default(smiles, y)
|
|
50
|
+
|
|
51
|
+
def predict(self, smiles):
|
|
52
|
+
X = self.descriptor.transform(smiles)
|
|
53
|
+
return self.model.predict(X)
|
|
54
|
+
|
|
55
|
+
def predict_proba(self, smiles):
|
|
56
|
+
X = self.descriptor.transform(smiles)
|
|
57
|
+
return self.model.predict_proba(X)
|
|
58
|
+
|
|
59
|
+
def explain(self, smiles):
|
|
60
|
+
X = self.descriptor.transform(smiles)
|
|
61
|
+
if self.explainer is None:
|
|
62
|
+
self.explainer = shap.Explainer(self.model)
|
|
63
|
+
shap_values = self.explainer(X, check_additivity=False)
|
|
64
|
+
return shap_values
|
|
65
|
+
|
|
66
|
+
def save(self, path):
|
|
67
|
+
joblib.dump(self, path)
|
|
68
|
+
|
|
69
|
+
def load(self, path):
|
|
70
|
+
return joblib.load(path)
|
|
File without changes
|