docs: def _trees_feature_weights(clf, X, feature_names, num_targets):
      """ Return feature weights for a tree or a tree ensemble.
      """
      feature_weights = np.zeros([len(feature_names), num_targets])
      if hasattr(clf, 'tree_'):
          _update_tree_feature_weights(X, feature_names, clf, feature_weights)
      else:
          if isinstance(clf, (
                  GradientBoostingClassifier, GradientBoostingRegressor)):
              weight = clf.learning_rate
          else:
              weight = 1. / len(clf.estimators_)
          for _clfs in clf.estimators_:
              _update = partial(_update_tree_feature_weights, X, feature_names)
              if isinstance(_clfs, np.ndarray):
                  if len(_clfs) == 1:
                      _update(_clfs[0], feature_weights)
                  else:
                      for idx, _clf in enumerate(_clfs):
                          _update(_clf, feature_weights[:, idx])
              else:
                  _update(_clfs, feature_weights)
          feature_weights *= weight
          if hasattr(clf, 'init_'):
              feature_weights[feature_names.bias_idx] += clf.init_.predict(X)[0]
      return feature_weights