code: def _get_prediction_feature_weights(lgb, X, n_targets):
      
      if n_targets == 2:
          n_targets = 1
      dump = lgb.booster_.dump_model()
      tree_info = dump['tree_info']
      _compute_node_values(tree_info)
      pred_leafs = lgb.booster_.predict(X, pred_leaf=True).reshape(-1, n_targets)
      tree_info = np.array(tree_info).reshape(-1, n_targets)
      assert pred_leafs.shape == tree_info.shape
  
      res = []
      for target in range(n_targets):
          feature_weights = defaultdict(float)  # type: DefaultDict[Optional[str], float]
          for info, leaf_id in zip(tree_info[:, target], pred_leafs[:, target]):
              leaf_index, split_index = _get_leaf_split_indices(
                  info['tree_structure']
              )
              bias, path = _get_decision_path(leaf_index, split_index, leaf_id)
              feature_weights[None] += bias
              for feat, value in path:
                  feature_weights[feat] += value
          res.append(dict(feature_weights))
      return res
docs: Return a list of {feat_id: value} dicts with feature weights, 
      following ideas from  http://blog.datadive.net/interpreting-random-forests/