Trang chủ‎ > ‎IT‎ > ‎Data Science - Python‎ > ‎

Introduction to Boosted Trees

XGBoost is short for “Extreme Gradient Boosting”, where the term “Gradient Boosting” is proposed in the paper Greedy Function Approximation: A Gradient Boosting Machine, by Friedman. XGBoost is based on this original model. This is a tutorial on gradient boosted trees, and most of the content is based on these slides by the author of xgboost.

The GBM (boosted trees) has been around for really a while, and there are a lot of materials on the topic. This tutorial tries to explain boosted trees in a self-contained and principled way using the elements of supervised learning. We think this explanation is cleaner, more formal, and motivates the variant used in xgboost.

Elements of Supervised Learning

XGBoost is used for supervised learning problems, where we use the training data (with multiple features) xixito predict a target variable yiyi. Before we dive into trees, let us start by reviewing the basic elements in supervised learning.

Model and Parameters

The model in supervised learning usually refers to the mathematical structure of how to make the prediction yiyigiven xixi. For example, a common model is a linear model, where the prediction is given by y^i=jθjxijy^i=∑jθjxij, a linear combination of weighted input features. The prediction value can have different interpretations, depending on the task, i.e., regression or classification. For example, it can be logistic transformed to get the probability of positive class in logistic regression, and it can also be used as a ranking score when we want to rank the outputs.

The parameters are the undetermined part that we need to learn from data. In linear regression problems, the parameters are the coefficients θθ. Usually we will use θθ to denote the parameters (there are many parameters in a model, our definition here is sloppy).

Objective Function : Training Loss + Regularization

Based on different understandings of yiyi we can have different problems, such as regression, classification, ordering, etc. We need to find a way to find the best parameters given the training data. In order to do so, we need to define a so-called objective function, to measure the performance of the model given a certain set of parameters.

A very important fact about objective functions is they must always contain two parts: training loss and regularization.

Obj(Θ)=L(θ)+Ω(Θ)Obj(Θ)=L(θ)+Ω(Θ)

where LL is the training loss function, and ΩΩ is the regularization term. The training loss measures how predictive our model is on training data. For example, a commonly used training loss is mean squared error.

L(θ)=i(yiy^i)2L(θ)=∑i(yi−y^i)2

Another commonly used loss function is logistic loss for logistic regression

L(θ)=i[yiln(1+ey^i)+(1yi)ln(1+ey^i)]L(θ)=∑i[yiln⁡(1+e−y^i)+(1−yi)ln⁡(1+ey^i)]

The regularization term is what people usually forget to add. The regularization term controls the complexity of the model, which helps us to avoid overfitting. This sounds a bit abstract, so let us consider the following problem in the following picture. You are asked to fit visually a step function given the input data points on the upper left corner of the image. Which solution among the three do you think is the best fit?

The correct answer is marked in red. Please consider if this visually seems a reasonable fit to you. The general principle is we want both a simple and predictive model. The tradeoff between the two is also referred as bias-variance tradeoff in machine learning.

Why introduce the general principle?

The elements introduced above form the basic elements of supervised learning, and they are naturally the building blocks of machine learning toolkits. For example, you should be able to describe the differences and commonalities between boosted trees and random forests. Understanding the process in a formalized way also helps us to understand the objective that we are learning and the reason behind the heuristics such as pruning and smoothing.

Tree Ensemble

Now that we have introduced the elements of supervised learning, let us get started with real trees. To begin with, let us first learn about the model of xgboost: tree ensembles. The tree ensemble model is a set of classification and regression trees (CART). Here’s a simple example of a CART that classifies whether someone will like computer games.

We classify the members of a family into different leaves, and assign them the score on the corresponding leaf. A CART is a bit different from decision trees, where the leaf only contains decision values. In CART, a real score is associated with each of the leaves, which gives us richer interpretations that go beyond classification. This also makes the unified optimization step easier, as we will see in a later part of this tutorial.

Usually, a single tree is not strong enough to be used in practice. What is actually used is the so-called tree ensemble model, which sums the prediction of multiple trees together.

Here is an example of a tree ensemble of two trees. The prediction scores of each individual tree are summed up to get the final score. If you look at the example, an important fact is that the two trees try to complementeach other.  Mathematically, we can write our model in the form

y^i=k=1Kfk(xi),fkFy^i=∑k=1Kfk(xi),fk∈F

where KK is the number of trees, ff is a function in the functional space FF, and FF is the set of all possible CARTs. Therefore our objective to optimize can be written as

obj(θ)=inl(yi,y^i)+k=1KΩ(fk)obj(θ)=∑inl(yi,y^i)+∑k=1KΩ(fk)

Now here comes the question, what is the model for random forests? It is exactly tree ensembles! So random forests and boosted trees are not different in terms of model, the difference is how we train them. This means if you write a predictive service of tree ensembles, you only need to write one of them and they should directly work for both random forests and boosted trees. One example of why elements of supervised learning rock.

Tree Boosting

After introducing the model, let us begin with the real training part. How should we learn the trees? The answer is, as is always for all supervised learning models: define an objective function, and optimize it!

Assume we have the following objective function (remember it always needs to contain training loss and regularization)

obj=i=1nl(yi,y^(t)i)+i=1tΩ(fi)obj=∑i=1nl(yi,y^i(t))+∑i=1tΩ(fi)

First thing we want to ask is what are the parameters of trees? You can find that what we need to learn are those functions fifi, with each containing the structure of the tree and the leaf scores. This is much harder than traditional optimization problem where you can take the gradient and go. It is not easy to train all the trees at once. Instead, we use an additive strategy: fix what we have learned, and add one new tree at a time. We write the prediction value at step tt as y^(t)iy^i(t), so we have

y^(0)iy^(1)iy^(2)iy^(t)i=0=f1(xi)=y^(0)i+f1(xi)=f1(xi)+f2(xi)=y^(1)i+f2(xi)=k=1tfk(xi)=y^(t1)i+ft(xi)y^i(0)=0y^i(1)=f1(xi)=y^i(0)+f1(xi)y^i(2)=f1(xi)+f2(xi)=y^i(1)+f2(xi)…y^i(t)=∑k=1tfk(xi)=y^i(t−1)+ft(xi)

It remains to ask, which tree do we want at each step? A natural thing is to add the one that optimizes our objective.

obj(t)=i=1nl(yi,y^(t)i)+i=1tΩ(fi)=i=1nl(yi,y^(t1)i+ft(xi))+Ω(ft)+constantobj(t)=∑i=1nl(yi,y^i(t))+∑i=1tΩ(fi)=∑i=1nl(yi,y^i(t−1)+ft(xi))+Ω(ft)+constant

If we consider using MSE as our loss function, it becomes the following form.

obj(t)=i=1n(yi(y^(t1)i+ft(xi)))2+i=1tΩ(fi)=i=1n[2(y^(t1)iyi)ft(xi)+ft(xi)2]+Ω(ft)+constantobj(t)=∑i=1n(yi−(y^i(t−1)+ft(xi)))2+∑i=1tΩ(fi)=∑i=1n[2(y^i(t−1)−yi)ft(xi)+ft(xi)2]+Ω(ft)+constant

The form of MSE is friendly, with a first order term (usually called the residual) and a quadratic term. For other losses of interest (for example, logistic loss), it is not so easy to get such a nice form. So in the general case, we take the Taylor expansion of the loss function up to the second order

where the gigi and hihi are defined as

gihi=y^(t1)il(yi,y^(t1)i)=2y^(t1)il(yi,y^(t1)i)gi=∂y^i(t−1)l(yi,y^i(t−1))hi=∂y^i(t−1)2l(yi,y^i(t−1))

After we remove all the constants, the specific objective at step tt becomes

This becomes our optimization goal for the new tree. One important advantage of this definition is that it only depends on gigi and hihi. This is how xgboost can support custom loss functions. We can optimize every loss function, including logistic regression and weighted logistic regression, using exactly the same solver that takes gigi and hihi as input!

Model Complexity

We have introduced the training step, but wait, there is one important thing, the regularization! We need to define the complexity of the tree Ω(f)Ω(f). In order to do so, let us first refine the definition of the tree f(x)f(x) as

ft(x)=wq(x),wRT,q:Rd{1,2,,T}.ft(x)=wq(x),w∈RT,q:Rd→{1,2,⋯,T}.

Here ww is the vector of scores on leaves, qq is a function assigning each data point to the corresponding leaf, andTT is the number of leaves. In XGBoost, we define the complexity as

Ω(f)=γT+12λj=1Tw2jΩ(f)=γT+12λ∑j=1Twj2

Of course there is more than one way to define the complexity, but this specific one works well in practice. The regularization is one part most tree packages treat less carefully, or simply ignore. This was because the traditional treatment of tree learning only emphasized improving impurity, while the complexity control was left to heuristics. By defining it formally, we can get a better idea of what we are learning, and yes it works well in practice.

The Structure Score

Here is the magical part of the derivation. After reformalizing the tree model, we can write the objective value with the tt-th tree as:

Obj(t)i=1n[giwq(xi)+12hiw2q(xi)]+γT+12λj=1Tw2j=j=1T[(iIjgi)wj+12(iIjhi+λ)w2j]+γTObj(t)≈∑i=1n[giwq(xi)+12hiwq(xi)2]+γT+12λ∑j=1Twj2=∑j=1T[(∑i∈Ijgi)wj+12(∑i∈Ijhi+λ)wj2]+γT

where Ij={i|q(xi)=j}Ij={i|q(xi)=j} is the set of indices of data points assigned to the jj-th leaf. Notice that in the second line we have changed the index of the summation because all the data points on the same leaf get the same score. We could further compress the expression by defining Gj=iIjgiGj=∑i∈Ijgi and Hj=iIjhiHj=∑i∈Ijhi:

obj(t)=j=1T[Gjwj+12(Hj+λ)w2j]+γTobj(t)=∑j=1T[Gjwj+12(Hj+λ)wj2]+γT

In this equation wjwj are independent with respect to each other, the form Gjwj+12(Hj+λ)w2jGjwj+12(Hj+λ)wj2 is quadratic and the best wjwj for a given structure q(x)q(x) and the best objective reduction we can get is:

wj=GjHj+λobj=12j=1TG2jHj+λ+γTwj∗=−GjHj+λobj∗=−12∑j=1TGj2Hj+λ+γT

The last equation measures how good a tree structure q(x)q(x) is.

If all this sounds a bit complicated, let’s take a look at the picture, and see how the scores can be calculated. Basically, for a given tree structure, we push the statistics gigi and hihi to the leaves they belong to, sum the statistics together, and use the formula to calculate how good the tree is. This score is like the impurity measure in a decision tree, except that it also takes the model complexity into account.

Learn the tree structure

Now that we have a way to measure how good a tree is, ideally we would enumerate all possible trees and pick the best one. In practice this is intractable, so we will try to optimize one level of the tree at a time. Specifically we try to split a leaf into two leaves, and the score it gains is

Gain=12[G2LHL+λ+G2RHR+λ(GL+GR)2HL+HR+λ]γGain=12[GL2HL+λ+GR2HR+λ−(GL+GR)2HL+HR+λ]−γ

This formula can be decomposed as 1) the score on the new left leaf 2) the score on the new right leaf 3) The score on the original leaf 4) regularization on the additional leaf. We can see an important fact here: if the gain is smaller than γγ, we would do better not to add that branch. This is exactly the pruning techniques in tree based models! By using the principles of supervised learning, we can naturally come up with the reason these techniques work :)

For real valued data, we usually want to search for an optimal split. To efficiently do so, we place all the instances in sorted order, like the following picture.

A left to right scan is sufficient to calculate the structure score of all possible split solutions, and we can find the best split efficiently.

Final words on XGBoost

Now that you understand what boosted trees are, you may ask, where is the introduction on XGBoost? XGBoost is exactly a tool motivated by the formal principle introduced in this tutorial! More importantly, it is developed with both deep consideration in terms of systems optimization and principles in machine learning. The goal of this library is to push the extreme of the computation limits of machines to provide a scalableportable and accurate library. Make sure you try it out, and most importantly, contribute your piece of wisdom (code, examples, tutorials) to the community!