2.2. Local Linear Explanations
This functionality build the Local Linear Explanations (LLEs) used in the ReVel’s paper.
|
Abstract class for Local Linear Explanations. |
|
LIME is a Local Linear Explanation method, proposed in [RSG16]. |
|
SHAP is a Local Linear Explanation method, proposed in [LL17]. |
|
RANDOM is a comparative Local Linear Explanation method. |
-
class ReVel.LLEs.LLE(perturbation: Perturbation = None, max_examples: int = 1000, **kwargs)
View Source Code
class LLE(object): ''' Abstract class for Local Linear Explanations. A Local Linear explanation is defined by a regression model and a perturbation strategy of the input. This perturbation strategy defines the neighbourhood construction. Parameters ---------- perturbation: Perturbation Perturbation class with the strategy used to construct the neighbourhood. max_examples: int Maximum number of examples to be used in the regression. ''' def __init__(self,perturbation:Perturbation=None,max_examples:int = 1000,**kwargs): self.max_examples = max_examples self.perturbation = perturbation def generate_neighbour(self,n_features:int)->np.ndarray: ''' Abstract method for generating a neighbour. Parameters ---------- n_features: int Number of features to be considered Returns ------- np.array A neighbour of the instance. ''' raise NotImplementedError("Subclass must implement abstract method") def regression(self,instance,model_forward, segments, examples)->LinearRegression: ''' Abstract method for regression. Parameters ---------- instance: Instance to be explained. model_forward: black-box model to explain the instance. It must accept an object similar to instance and return a prediction. segments: Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension. examples: Examples to be used in the regression. Returns ------- sklearn.linear_model.LinearRegression The explanation proposed by the method. ''' raise NotImplementedError("Subclass must implement abstract method") def kernel(self,V)->np.ndarray: ''' Abstract method for kernel. This function is used to weight the neighbour respect to the distance to the original instance. Parameters ---------- V: float Distance to the original instance. Returns ------- np.array Weight of the neighbour. ''' raise NotImplementedError("Subclass must implement abstract method") def perturb(self,img,neutral,segments,indexes)->np.ndarray: ''' Abstract method for perturbation. This function is used to perturb the original instance to generate a neighbour. It is a wrapper for the perturbation object which has the strategy to generate the neighbour. Parameters ---------- img: Original instance. neutral: Neutral instance. segments: Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension. indexes: Indexes of the features to be perturbed. Returns ------- np.array The perturbed instance obtained by removing the features of the indexes on the img and adding the features of the indexes on the neutral. Dims (H,W,C). ''' return self.perturbation.perturbation(img,neutral,segments,indexes) def __call__(self,model_forward,instance)->LinearRegression: ''' Abstract method for calling the LLE. This function is used to generate the LLE. This function propose the segmentation of the instance by the perturbation object. Parameters ---------- model_forward: black-box model forward method. It must accept an object similar to instance and return a prediction. instance: Instance to be explained. Returns ------- sklearn.linear_model.LinearRegression The explanation proposed by the LLE. ''' if np.array(instance).shape[0] == 3: segments = self.perturbation.segmentation_fn(np.array(instance).swapaxes(0,1).swapaxes(1,2)) else: segments = self.perturbation.segmentation_fn(np.array(instance)) return self.explain_instance(instance,model_forward,segments=segments) def explain_instance(self,instance,model_forward,segments)->LinearRegression: ''' Method for explaining an instance. This function is used to generate the LLE. Parameters ---------- model_forward: black-box model forward method. It must accept an object similar to instance and return a prediction. instance: Instance to be explained. segments: Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension. Returns ------- sklearn.linear_model.LinearRegression The explanation proposed by the method. ''' examples = [] n_features = len(np.unique(segments)) while len(examples) < self.max_examples: lista = self.generate_neighbour(n_features) inside = False for j, cluster in enumerate(examples): same_shape = cluster.shape[0] == lista.shape[0] if same_shape: equal = np.all(cluster == lista) if equal: inside = True break if not inside and len(lista) > 0: examples.append(lista) examples = np.array(examples,dtype=object) return self.regression(instance,model_forward,segments,examples) Abstract class for Local Linear Explanations.
A Local Linear explanation is defined by a regression model and a perturbation strategy of the input. This perturbation strategy defines the neighbourhood construction.
- Parameters:
perturbation (Perturbation) – Perturbation class with the strategy used to construct the neighbourhood.
max_examples (int) – Maximum number of examples to be used in the regression.
-
explain_instance(instance, model_forward, segments) LinearRegression
View Source Code
def explain_instance(self,instance,model_forward,segments)->LinearRegression: ''' Method for explaining an instance. This function is used to generate the LLE. Parameters ---------- model_forward: black-box model forward method. It must accept an object similar to instance and return a prediction. instance: Instance to be explained. segments: Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension. Returns ------- sklearn.linear_model.LinearRegression The explanation proposed by the method. ''' examples = [] n_features = len(np.unique(segments)) while len(examples) < self.max_examples: lista = self.generate_neighbour(n_features) inside = False for j, cluster in enumerate(examples): same_shape = cluster.shape[0] == lista.shape[0] if same_shape: equal = np.all(cluster == lista) if equal: inside = True break if not inside and len(lista) > 0: examples.append(lista) examples = np.array(examples,dtype=object) return self.regression(instance,model_forward,segments,examples) Method for explaining an instance. This function is used to generate the LLE.
- Parameters:
model_forward – black-box model forward method. It must accept an object similar to instance and return a prediction.
instance – Instance to be explained.
segments – Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension.
- Returns:
The explanation proposed by the method.
- Return type:
sklearn.linear_model.LinearRegression
-
generate_neighbour(n_features: int) ndarray
View Source Code
def generate_neighbour(self,n_features:int)->np.ndarray: ''' Abstract method for generating a neighbour. Parameters ---------- n_features: int Number of features to be considered Returns ------- np.array A neighbour of the instance. ''' raise NotImplementedError("Subclass must implement abstract method") Abstract method for generating a neighbour.
- Parameters:
n_features (int) – Number of features to be considered
- Returns:
A neighbour of the instance.
- Return type:
np.array
-
kernel(V) ndarray
View Source Code
def kernel(self,V)->np.ndarray: ''' Abstract method for kernel. This function is used to weight the neighbour respect to the distance to the original instance. Parameters ---------- V: float Distance to the original instance. Returns ------- np.array Weight of the neighbour. ''' raise NotImplementedError("Subclass must implement abstract method") Abstract method for kernel. This function is used to weight the neighbour respect to the distance to the original instance.
- Parameters:
V (float) – Distance to the original instance.
- Returns:
Weight of the neighbour.
- Return type:
np.array
-
perturb(img, neutral, segments, indexes) ndarray
View Source Code
def perturb(self,img,neutral,segments,indexes)->np.ndarray: ''' Abstract method for perturbation. This function is used to perturb the original instance to generate a neighbour. It is a wrapper for the perturbation object which has the strategy to generate the neighbour. Parameters ---------- img: Original instance. neutral: Neutral instance. segments: Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension. indexes: Indexes of the features to be perturbed. Returns ------- np.array The perturbed instance obtained by removing the features of the indexes on the img and adding the features of the indexes on the neutral. Dims (H,W,C). ''' return self.perturbation.perturbation(img,neutral,segments,indexes) Abstract method for perturbation. This function is used to perturb the original instance to generate a neighbour. It is a wrapper for the perturbation object which has the strategy to generate the neighbour.
- Parameters:
img – Original instance.
neutral – Neutral instance.
segments – Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension.
indexes – Indexes of the features to be perturbed.
- Returns:
The perturbed instance obtained by removing the features of the indexes on the img and adding the features of the indexes on the neutral. Dims (H,W,C).
- Return type:
np.array
-
regression(instance, model_forward, segments, examples) LinearRegression
View Source Code
def regression(self,instance,model_forward, segments, examples)->LinearRegression: ''' Abstract method for regression. Parameters ---------- instance: Instance to be explained. model_forward: black-box model to explain the instance. It must accept an object similar to instance and return a prediction. segments: Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension. examples: Examples to be used in the regression. Returns ------- sklearn.linear_model.LinearRegression The explanation proposed by the method. ''' raise NotImplementedError("Subclass must implement abstract method") Abstract method for regression.
- Parameters:
instance – Instance to be explained.
model_forward – black-box model to explain the instance. It must accept an object similar to instance and return a prediction.
segments – Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension.
examples – Examples to be used in the regression.
- Returns:
The explanation proposed by the method.
- Return type:
sklearn.linear_model.LinearRegression
-
class ReVel.LLEs.LIME(sigma: int = 3, **kwargs)
View Source Code
class LIME(LLE): ''' LIME is a Local Linear Explanation method, proposed in :cite:`lime`. Parameters ---------- sigma: int Sigma parameter of the kernel. It controls the size of the neighbourhood in terms of how weighted the examples are. ''' def __init__(self,sigma:int=3,**kwargs): self.sigma = sigma super().__init__(**kwargs) def generate_neighbour(self,n_features:int)->np.ndarray: ''' Generate a neighbour of the instance. The neighbour generation is done over the feature space. The generation of the neighbour is done randomly but each neighbour is generated with a probability proportional to their weight on the LIME regressor. Parameters ---------- n_features: int Number of features to be considered. It is needed to generate the neighbour of size n_features. Returns ------- np.array A neighbour of the instance of size n_features. ''' p = np.random.random() w = int(self.sigma*np.sqrt(-np.log(p))) lista = np.array([i for i in range(n_features)]) np.random.shuffle(lista) lista = lista[:min(w,len(lista))] return lista def kernel(self, V)->np.ndarray: r''' Kernel function for the LIME regressor. It is calculated by the following formula :math:`K(V) = e^{-\dfrac{||1_{N}-V||^2}{ \sigma^2} }` where :math:`1_{N}` is the vector of ones of size N and :math:`d` is the vector of the vector of features. Parameters ---------- V: np.array Vector of features of the neighbour. The :math:`V_{i}` must be 1 if the feature is present in the neighbour and 0 if it is not. Returns ------- np.array Weight of the neighbour. ''' distance = np.linalg.norm((1-V),axis=-1)/self.sigma return np.exp(distance) def regression(self, instance, model_forward, segments, examples)->Ridge: ''' Regression method for the LIME method. It is a ridge regression with the kernel function defined by LIME method. Parameters ---------- instance: Instance to be explained. model_forward: Black-box model to explain the instance. It must accept an object similar to instance and return a prediction. segments: Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension. examples: Examples to be used in the regression. They must be generated in the feature space. Returns ------- sklearn.linear_model.Ridge The explanation proposed by the method ''' logits = [] n_pixels = [] n_features = len(np.unique(segments)) if len(examples) > self.max_examples: examples = np.random.choice(examples,self.max_examples,replace=False) examples,weights = np.unique(np.array([tuple(e) for e in examples ],dtype=object),return_counts=True) for example in tqdm.tqdm(examples): perturbacion = self.perturbation.perturbation(instance,self.perturbation.fn_neutral_image(instance),segments,example) logit = model_forward(perturbacion).to("cpu").detach().numpy()[0] logits.append(np.copy(logit)) oclusion_pixels = np.any([i == segments for i in example],axis=0) n_pixels.append(np.copy(oclusion_pixels)) #indices = [(i,j) for i in range(len(logits)) for j in range(i+1,len(logits))] X_Vector = np.array([[0.0 if k in examples[i] else 1.0 for k in range(n_features)] for i in range(len(examples))]) Y_logits = logits regressor_logits = Ridge(fit_intercept=True) X_Vector,Y_logits = np.array(X_Vector),np.array(Y_logits) regressor_logits.fit(X_Vector,Y_logits,sample_weight= self.kernel(X_Vector)) return regressor_logits LIME is a Local Linear Explanation method, proposed in [RSG16].
- Parameters:
sigma (int) – Sigma parameter of the kernel. It controls the size of the neighbourhood in terms of how weighted the examples are.
-
generate_neighbour(n_features: int) ndarray
View Source Code
def generate_neighbour(self,n_features:int)->np.ndarray: ''' Generate a neighbour of the instance. The neighbour generation is done over the feature space. The generation of the neighbour is done randomly but each neighbour is generated with a probability proportional to their weight on the LIME regressor. Parameters ---------- n_features: int Number of features to be considered. It is needed to generate the neighbour of size n_features. Returns ------- np.array A neighbour of the instance of size n_features. ''' p = np.random.random() w = int(self.sigma*np.sqrt(-np.log(p))) lista = np.array([i for i in range(n_features)]) np.random.shuffle(lista) lista = lista[:min(w,len(lista))] return lista Generate a neighbour of the instance. The neighbour generation is done over the feature space. The generation of the neighbour is done randomly but each neighbour is generated with a probability proportional to their weight on the LIME regressor.
- Parameters:
n_features (int) – Number of features to be considered. It is needed to generate the neighbour of size n_features.
- Returns:
A neighbour of the instance of size n_features.
- Return type:
np.array
-
kernel(V) ndarray
View Source Code
def kernel(self, V)->np.ndarray: r''' Kernel function for the LIME regressor. It is calculated by the following formula :math:`K(V) = e^{-\dfrac{||1_{N}-V||^2}{ \sigma^2} }` where :math:`1_{N}` is the vector of ones of size N and :math:`d` is the vector of the vector of features. Parameters ---------- V: np.array Vector of features of the neighbour. The :math:`V_{i}` must be 1 if the feature is present in the neighbour and 0 if it is not. Returns ------- np.array Weight of the neighbour. ''' distance = np.linalg.norm((1-V),axis=-1)/self.sigma return np.exp(distance) Kernel function for the LIME regressor. It is calculated by the following formula
\(K(V) = e^{-\dfrac{||1_{N}-V||^2}{ \sigma^2} }\)
where \(1_{N}\) is the vector of ones of size N and \(d\) is the vector of the vector of features.
- Parameters:
V (np.array) – Vector of features of the neighbour. The \(V_{i}\) must be 1 if the feature is present in the neighbour and 0 if it is not.
- Returns:
Weight of the neighbour.
- Return type:
np.array
-
regression(instance, model_forward, segments, examples) Ridge
View Source Code
def regression(self, instance, model_forward, segments, examples)->Ridge: ''' Regression method for the LIME method. It is a ridge regression with the kernel function defined by LIME method. Parameters ---------- instance: Instance to be explained. model_forward: Black-box model to explain the instance. It must accept an object similar to instance and return a prediction. segments: Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension. examples: Examples to be used in the regression. They must be generated in the feature space. Returns ------- sklearn.linear_model.Ridge The explanation proposed by the method ''' logits = [] n_pixels = [] n_features = len(np.unique(segments)) if len(examples) > self.max_examples: examples = np.random.choice(examples,self.max_examples,replace=False) examples,weights = np.unique(np.array([tuple(e) for e in examples ],dtype=object),return_counts=True) for example in tqdm.tqdm(examples): perturbacion = self.perturbation.perturbation(instance,self.perturbation.fn_neutral_image(instance),segments,example) logit = model_forward(perturbacion).to("cpu").detach().numpy()[0] logits.append(np.copy(logit)) oclusion_pixels = np.any([i == segments for i in example],axis=0) n_pixels.append(np.copy(oclusion_pixels)) #indices = [(i,j) for i in range(len(logits)) for j in range(i+1,len(logits))] X_Vector = np.array([[0.0 if k in examples[i] else 1.0 for k in range(n_features)] for i in range(len(examples))]) Y_logits = logits regressor_logits = Ridge(fit_intercept=True) X_Vector,Y_logits = np.array(X_Vector),np.array(Y_logits) regressor_logits.fit(X_Vector,Y_logits,sample_weight= self.kernel(X_Vector)) return regressor_logits Regression method for the LIME method. It is a ridge regression with the kernel function defined by LIME method.
- Parameters:
instance – Instance to be explained.
model_forward – Black-box model to explain the instance. It must accept an object similar to instance and return a prediction.
segments – Segments on which the instance is divided into features. It must have the same shape as instance except for the last dimension.
examples – Examples to be used in the regression. They must be generated in the feature space.
- Returns:
The explanation proposed by the method
- Return type:
sklearn.linear_model.Ridge
-
class ReVel.LLEs.SHAP(sigma=0.5, **kwargs)
View Source Code
class SHAP(LLE): ''' SHAP is a Local Linear Explanation method, proposed in :cite:`shap`. We also develop a variation of the SHAP method, called Loacal-SHAP, where we don't consider the neighbours with less than half the features. Parameters ---------- sigma : float The sigma parameter define if the method is local or global. If sigma is greater than 0.5, the method is local. If sigma is less than 0.5, the method is global. The default value is 0.5. ''' def __init__(self,sigma=0.5, **kwargs): self.local = (sigma > 0.5) super().__init__(**kwargs) def generate_neighbour(self,n_features:int)->np.ndarray: ''' Generate a neighbour of the instance. The neighbour generation is done over the feature space. The generation of the neighbour is done randomly but each neighbour is generated with a probability proportional to their weight on the SHAP regressor. If the method is global, the neighbour is generated with 50% probability to have less than half the features and 50% probability to have more than half the features. If the method is local, the neighbour is generated with more than half the features. Parameters ---------- n_features: int Number of features to be considered. It is needed to generate the neighbour of size n_features. Returns ------- list A neighbour of the instance of size n_features. ''' w = np.random.random() w = max(w,(4*n_features+4)/(n_features*n_features)+0.00001) if not self.local: if np.random.random() < 0.5: choosed = int((n_features - np.sqrt(n_features*n_features - 4*(n_features-1)/w))/2) else: choosed = int((n_features + np.sqrt(n_features*n_features - 4*(n_features-1)/w))/2) else: choosed = int((n_features - np.sqrt(n_features*n_features - 4*(n_features-1)/w))/2) lista = np.array([i for i in range(n_features)]) np.random.shuffle(lista) lista = lista[:choosed] return lista def kernel(self, V,n_features:int)->np.ndarray: r''' The kernel function is used to weight the examples. For each example V, the asociated weight is computed as :math:`w = \dfrac{N-1}{|k|(N-\sum_{i=1}^{N}V_i){N\choose{|k|}}}` where :math:`|k|=\sum_{i=1}^{N}V_i`, that is, the number of features in the example. where :math:`N` is the number of features. Note that V is a vector of size with 0 and 1 values so the sum of V is the number of features that are not ocluded. Parameters ---------- V: numpy.ndarray Vector of size N with 0 and 1 values. n_features: int Number of features. Returns ------- float Weight associated to the feature vetor V. ''' w = (n_features-1)/((n_features-np.sum(V,axis=-1))*np.sum(V,axis=-1)) Mchoosez = scipy.special.comb(n_features,np.sum(V,axis=-1),exact=False) w = w / Mchoosez return w def regression(self, instance, model_forward, segments, examples)->Ridge: ''' Regression method for the SHAP method. It is a ridge regression with the weights computed using the kernel function. Parameters ---------- instance: numpy.ndarray Instance to be explained. model_forward: Black-box model to explain the instance. It must accept an object similar to instance and return a prediction. segments: numpy.ndarray Segments of the instance. examples: numpy.ndarray Examples over the feature space over which the regression is performed. Those examples must be the neighbours over the feature space of the instance. Returns ------- sklearn.linear_model.Ridge The explanation proposed by the method. ''' logits = [] n_pixels = [] n_features = len(np.unique(segments)) if len(examples) > self.max_examples: examples = np.random.choice(examples,self.max_examples,replace=False) examples,weights = np.unique(np.array([tuple(e) for e in examples ],dtype=object),return_counts=True) for example in tqdm.tqdm(examples): perturbacion = self.perturbation.perturbation(instance,self.perturbation.fn_neutral_image(instance),segments,example) logit = model_forward(perturbacion).to("cpu").detach().numpy()[0] logits.append(np.copy(logit)) oclusion_pixels = np.any([i == segments for i in example],axis=0) n_pixels.append(np.copy(oclusion_pixels)) X_Vector = np.array([[0.0 if k in examples[i] else 1.0 for k in range(n_features)] for i in range(len(examples))]) Y_logits = logits regressor_logits = Ridge(fit_intercept=True) X_Vector,Y_logits = np.array(X_Vector),np.array(Y_logits) regressor_logits.fit(X_Vector,Y_logits,sample_weight= self.kernel(X_Vector,n_features=n_features)) return regressor_logits SHAP is a Local Linear Explanation method, proposed in [LL17]. We also develop a variation of the SHAP method, called Loacal-SHAP, where we don’t consider the neighbours with less than half the features.
- Parameters:
sigma (float) – The sigma parameter define if the method is local or global. If sigma is greater than 0.5, the method is local. If sigma is less than 0.5, the method is global. The default value is 0.5.
-
generate_neighbour(n_features: int) ndarray
View Source Code
def generate_neighbour(self,n_features:int)->np.ndarray: ''' Generate a neighbour of the instance. The neighbour generation is done over the feature space. The generation of the neighbour is done randomly but each neighbour is generated with a probability proportional to their weight on the SHAP regressor. If the method is global, the neighbour is generated with 50% probability to have less than half the features and 50% probability to have more than half the features. If the method is local, the neighbour is generated with more than half the features. Parameters ---------- n_features: int Number of features to be considered. It is needed to generate the neighbour of size n_features. Returns ------- list A neighbour of the instance of size n_features. ''' w = np.random.random() w = max(w,(4*n_features+4)/(n_features*n_features)+0.00001) if not self.local: if np.random.random() < 0.5: choosed = int((n_features - np.sqrt(n_features*n_features - 4*(n_features-1)/w))/2) else: choosed = int((n_features + np.sqrt(n_features*n_features - 4*(n_features-1)/w))/2) else: choosed = int((n_features - np.sqrt(n_features*n_features - 4*(n_features-1)/w))/2) lista = np.array([i for i in range(n_features)]) np.random.shuffle(lista) lista = lista[:choosed] return lista Generate a neighbour of the instance. The neighbour generation is done over the feature space. The generation of the neighbour is done randomly but each neighbour is generated with a probability proportional to their weight on the SHAP regressor.
If the method is global, the neighbour is generated with 50% probability to have less than half the features and 50% probability to have more than half the features. If the method is local, the neighbour is generated with more than half the features.
- Parameters:
n_features (int) – Number of features to be considered. It is needed to generate the neighbour of size n_features.
- Returns:
A neighbour of the instance of size n_features.
- Return type:
list
-
kernel(V, n_features: int) ndarray
View Source Code
def kernel(self, V,n_features:int)->np.ndarray: r''' The kernel function is used to weight the examples. For each example V, the asociated weight is computed as :math:`w = \dfrac{N-1}{|k|(N-\sum_{i=1}^{N}V_i){N\choose{|k|}}}` where :math:`|k|=\sum_{i=1}^{N}V_i`, that is, the number of features in the example. where :math:`N` is the number of features. Note that V is a vector of size with 0 and 1 values so the sum of V is the number of features that are not ocluded. Parameters ---------- V: numpy.ndarray Vector of size N with 0 and 1 values. n_features: int Number of features. Returns ------- float Weight associated to the feature vetor V. ''' w = (n_features-1)/((n_features-np.sum(V,axis=-1))*np.sum(V,axis=-1)) Mchoosez = scipy.special.comb(n_features,np.sum(V,axis=-1),exact=False) w = w / Mchoosez return w The kernel function is used to weight the examples. For each example V, the asociated weight is computed as
\(w = \dfrac{N-1}{|k|(N-\sum_{i=1}^{N}V_i){N\choose{|k|}}}\)
where \(|k|=\sum_{i=1}^{N}V_i\), that is, the number of features in the example.
where \(N\) is the number of features. Note that V is a vector of size with 0 and 1 values so the sum of V is the number of features that are not ocluded.
- Parameters:
V (numpy.ndarray) – Vector of size N with 0 and 1 values.
n_features (int) – Number of features.
- Returns:
Weight associated to the feature vetor V.
- Return type:
float
-
regression(instance, model_forward, segments, examples) Ridge
View Source Code
def regression(self, instance, model_forward, segments, examples)->Ridge: ''' Regression method for the SHAP method. It is a ridge regression with the weights computed using the kernel function. Parameters ---------- instance: numpy.ndarray Instance to be explained. model_forward: Black-box model to explain the instance. It must accept an object similar to instance and return a prediction. segments: numpy.ndarray Segments of the instance. examples: numpy.ndarray Examples over the feature space over which the regression is performed. Those examples must be the neighbours over the feature space of the instance. Returns ------- sklearn.linear_model.Ridge The explanation proposed by the method. ''' logits = [] n_pixels = [] n_features = len(np.unique(segments)) if len(examples) > self.max_examples: examples = np.random.choice(examples,self.max_examples,replace=False) examples,weights = np.unique(np.array([tuple(e) for e in examples ],dtype=object),return_counts=True) for example in tqdm.tqdm(examples): perturbacion = self.perturbation.perturbation(instance,self.perturbation.fn_neutral_image(instance),segments,example) logit = model_forward(perturbacion).to("cpu").detach().numpy()[0] logits.append(np.copy(logit)) oclusion_pixels = np.any([i == segments for i in example],axis=0) n_pixels.append(np.copy(oclusion_pixels)) X_Vector = np.array([[0.0 if k in examples[i] else 1.0 for k in range(n_features)] for i in range(len(examples))]) Y_logits = logits regressor_logits = Ridge(fit_intercept=True) X_Vector,Y_logits = np.array(X_Vector),np.array(Y_logits) regressor_logits.fit(X_Vector,Y_logits,sample_weight= self.kernel(X_Vector,n_features=n_features)) return regressor_logits Regression method for the SHAP method. It is a ridge regression with the weights computed using the kernel function.
- Parameters:
instance (numpy.ndarray) – Instance to be explained.
model_forward – Black-box model to explain the instance. It must accept an object similar to instance and return a prediction.
segments (numpy.ndarray) – Segments of the instance.
examples (numpy.ndarray) – Examples over the feature space over which the regression is performed. Those examples must be the neighbours over the feature space of the instance.
- Returns:
The explanation proposed by the method.
- Return type:
sklearn.linear_model.Ridge
-
class ReVel.LLEs.RANDOM(**kwargs)
View Source Code
class RANDOM(LLE): ''' RANDOM is a comparative Local Linear Explanation method. This method is not based on any algorithm. It is just a random method to compare with the behaviour of the other methods. ''' def __init__(self,**kwargs): super().__init__(**kwargs) def generate_neighbour(self,n_features:int)->np.ndarray: ''' Generate a neighbour of the instance. The neighbour is actually not used in the method, but it is needed to be compatible with the LLE class. ''' p = np.random.random() lista = np.array([i for i in range(n_features)]) np.random.shuffle(lista) lista = lista[:p*len(lista)] return lista def kernel(self, V)->np.ndarray: ''' The kernel is not used in the method, but it is needed to be compatible with the LLE class. Parameters ---------- V : numpy.ndarray The feature vector of an instance. Returns ------- The same feature vector. It is not used in the method. ''' return V def regression(self, instance, model_forward, segments, examples)->Ridge: ''' This regression method just returns a scikit-learn Ridge regression model with random weights generated by np.random.rand(). Parameters ---------- instance : numpy.ndarray The feature vector of an instance. Used to calculate the dimensionality of the output. model_forward : numpy.ndarray The feature vector of the instance. Used to calculate the dimensionality of the output. segments : numpy.ndarray The feature vector of the instance. Used to calculate the number of segments of the instance. examples : numpy.ndarray The feature vector of the instance. Not used in the method. Returns ------- sklearn.linear_model.Ridge The explanation proposed by the method. ''' n_segments = len(np.unique(segments)) out = model_forward(instance).detach().numpy() regressor_logits = Ridge(fit_intercept=True) regressor_logits.coef_ = np.random.rand(out.shape[1],n_segments) regressor_logits.intercept_ = np.random.rand(out.shape[1]) return regressor_logits RANDOM is a comparative Local Linear Explanation method. This method is not based on any algorithm. It is just a random method to compare with the behaviour of the other methods.
-
generate_neighbour(n_features: int) ndarray
View Source Code
def generate_neighbour(self,n_features:int)->np.ndarray: ''' Generate a neighbour of the instance. The neighbour is actually not used in the method, but it is needed to be compatible with the LLE class. ''' p = np.random.random() lista = np.array([i for i in range(n_features)]) np.random.shuffle(lista) lista = lista[:p*len(lista)] return lista Generate a neighbour of the instance. The neighbour is actually not used in the method, but it is needed to be compatible with the LLE class.
-
kernel(V) ndarray
View Source Code
def kernel(self, V)->np.ndarray: ''' The kernel is not used in the method, but it is needed to be compatible with the LLE class. Parameters ---------- V : numpy.ndarray The feature vector of an instance. Returns ------- The same feature vector. It is not used in the method. ''' return V The kernel is not used in the method, but it is needed to be compatible with the LLE class.
- Parameters:
V (numpy.ndarray) – The feature vector of an instance.
- Return type:
The same feature vector. It is not used in the method.
-
regression(instance, model_forward, segments, examples) Ridge
View Source Code
def regression(self, instance, model_forward, segments, examples)->Ridge: ''' This regression method just returns a scikit-learn Ridge regression model with random weights generated by np.random.rand(). Parameters ---------- instance : numpy.ndarray The feature vector of an instance. Used to calculate the dimensionality of the output. model_forward : numpy.ndarray The feature vector of the instance. Used to calculate the dimensionality of the output. segments : numpy.ndarray The feature vector of the instance. Used to calculate the number of segments of the instance. examples : numpy.ndarray The feature vector of the instance. Not used in the method. Returns ------- sklearn.linear_model.Ridge The explanation proposed by the method. ''' n_segments = len(np.unique(segments)) out = model_forward(instance).detach().numpy() regressor_logits = Ridge(fit_intercept=True) regressor_logits.coef_ = np.random.rand(out.shape[1],n_segments) regressor_logits.intercept_ = np.random.rand(out.shape[1]) return regressor_logits This regression method just returns a scikit-learn Ridge regression model with random weights generated by np.random.rand().
- Parameters:
instance (numpy.ndarray) – The feature vector of an instance. Used to calculate the dimensionality of the output.
model_forward (numpy.ndarray) – The feature vector of the instance. Used to calculate the dimensionality of the output.
segments (numpy.ndarray) – The feature vector of the instance. Used to calculate the number of segments of the instance.
examples (numpy.ndarray) – The feature vector of the instance. Not used in the method.
- Returns:
The explanation proposed by the method.
- Return type:
sklearn.linear_model.Ridge
-
generate_neighbour(n_features: int) ndarray