Files
2026-07-13 13:22:34 +08:00

52 lines
2.5 KiB
Python

import pickle
import shap
from shap._serializable import Deserializer, Serializable, Serializer
class _PatchedKernelExplainer(shap.KernelExplainer):
def save(self, out_file, model_saver=None, masker_saver=None):
"""
This patched `save` method fix `KernelExplainer.save`.
Issues in original `KernelExplainer.save`:
- It saves model by calling model.save, but shap.utils._legacy.Model has no save method
- It tries to save "masker", but there's no "masker" in KernelExplainer
- It does not save "KernelExplainer.data" attribute, the attribute is required when
loading back
Note: `model_saver` and `masker_saver` are meaningless argument for `KernelExplainer.save`,
the model in "KernelExplainer" is an instance of `shap.utils._legacy.Model`
(it wraps the predict function), we can only use pickle to dump it.
and no `masker` for KernelExplainer so `masker_saver` is meaningless.
but I preserve the 2 argument for overridden API compatibility.
"""
pickle.dump(type(self), out_file)
with Serializer(out_file, "shap.Explainer", version=0) as s:
s.save("model", self.model)
s.save("link", self.link)
s.save("data", self.data)
@classmethod
def load(cls, in_file, model_loader=None, masker_loader=None, instantiate=True):
"""
This patched `load` method fix `KernelExplainer.load`.
Issues in original KernelExplainer.load:
- Use mismatched model loader to load model
- Try to load non-existent "masker" attribute
- Does not load "data" attribute and then cause calling " KernelExplainer"
constructor lack of "data" argument.
Note: `model_loader` and `masker_loader` are meaningless argument for
`KernelExplainer.save`, because the `model` object is saved by pickle dump,
we must use pickle load to load it.
and no `masker` for KernelExplainer so `masker_loader` is meaningless.
but I preserve the 2 argument for overridden API compatibility.
"""
if instantiate:
return cls._instantiated_load(in_file, model_loader=None, masker_loader=None)
kwargs = Serializable.load(in_file, instantiate=False)
with Deserializer(in_file, "shap.Explainer", min_version=0, max_version=0) as s:
kwargs["model"] = s.load("model")
kwargs["link"] = s.load("link")
kwargs["data"] = s.load("data")
return kwargs