code: def keep_retrain(
      nkeep,
      X_train,
      y_train,
      X_test,
      y_test,
      attr_test,
      model_generator,
      metric,
      trained_model,
      random_state,
  ):
      """The model is retrained for each test sample with the non-important features set to a constant.
  
      If you want to know how important a set of features is you can ask how the model would be
      different if only those features had existed. To determine this we can mask the other features
      across the entire training and test datasets, then retrain the model. If we apply compare the
      output of this retrained model to the original model we can see the effect produced by only
      knowning the important features. Since for individualized explanation methods each test sample
      has a different set of most important features we need to retrain the model for every test sample
      to get the change in model performance when a specified fraction of the most important features
      are retained.
      """
  
      warnings.warn(
          "The retrain based measures can incorrectly evaluate models in some cases!"
      )
  
      # see if we match the last cached call
      global _keep_cache
      args = (X_train, y_train, X_test, y_test, model_generator, metric)
      cache_match = False
      if "args" in _keep_cache:
          if all(
              a is b for a, b in zip(_keep_cache["args"], args)
          ) and np.all(_keep_cache["attr_test"] == attr_test):
              cache_match = True
  
      X_train, X_test = to_array(X_train, X_test)
  
      # how many features to mask
      assert X_train.shape[1] == X_test.shape[1]
  
      # this is the model we will retrain many times
      model_masked = model_generator()
  
      # keep nkeep top features and re-train the model for each test explanation
      X_train_tmp = np.zeros(X_train.shape)
      X_test_tmp = np.zeros(X_test.shape)
      yp_masked_test = np.zeros(y_test.shape)
      tie_breaking_noise = const_rand(X_train.shape[1]) * 1e-6
      last_nkeep = _keep_cache.get("nkeep", None)
      last_yp_masked_test = _keep_cache.get("yp_masked_test", None)
      for i in tqdm(
          range(len(y_test)), "Retraining for the 'keep' metric"
      ):
          if cache_match and last_nkeep[i] == nkeep[i]:
              yp_masked_test[i] = last_yp_masked_test[i]
          elif nkeep[i] == attr_test.shape[1]:
              yp_masked_test[i] = trained_model.predict(
                  X_test[i : i + 1]
              )[0]
          else:
              # mask out the most important features for this test instance
              X_train_tmp[:] = X_train
              X_test_tmp[:] = X_test
              ordering = np.argsort(
                  -attr_test[i, :] + tie_breaking_noise
              )
              X_train_tmp[:, ordering[nkeep[i] :]] = X_train[
                  :, ordering[nkeep[i] :]
              ].mean()
              X_test_tmp[i, ordering[nkeep[i] :]] = X_train[
                  :, ordering[nkeep[i] :]
              ].mean()
  
              # retrain the model and make a prediction
              model_masked.fit(X_train_tmp, y_train)
              yp_masked_test[i] = model_masked.predict(
                  X_test_tmp[i : i + 1]
              )[0]
  
      # save our results so the next call to us can be faster when there is redundancy
      _keep_cache["nkeep"] = nkeep
      _keep_cache["yp_masked_test"] = yp_masked_test
      _keep_cache["attr_test"] = attr_test
      _keep_cache["args"] = args
  
      return metric(y_test, yp_masked_test)
  
file_path: shap/shap/benchmark/measures.py
imports: import warnings
  import numpy
  import pandas
  import sklearn.utils
  from tqdm.auto import tqdm
label_desc: Use image node_id 6 for calling a global function with example usage: keep_retrain(nkeep, X_train, y_train, X_test, y_test, attr_test, model_generator, metric, trained_model, random_state) and returns: metric