Return feature weights for a tree or a tree ensemble.

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