使用 Estimator 實(shí)現(xiàn) Boosting Tree 模型
在學(xué)習(xí) TensorFlow 的過(guò)程之中,最好的方式是結(jié)合示例來(lái)進(jìn)行學(xué)習(xí),并且加以相應(yīng)的訓(xùn)練。因此這節(jié)課我們就來(lái)學(xué)習(xí)一下 Estimator 模型的一個(gè)經(jīng)典示例:Boosting Tree 模型,也被稱(chēng)作提升樹(shù)模型。
在這節(jié)課程之中,我們會(huì)學(xué)習(xí)什么是 Boosting Tree ,它的一些簡(jiǎn)單的工作原理,同時(shí)學(xué)習(xí)如何使用 Estimator 來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Boosting Tree 模型。
1. 什么是 Boosting
首先,Boosting 是機(jī)器學(xué)習(xí)中的集成學(xué)習(xí)的一種。
那么什么是集成學(xué)習(xí)呢?簡(jiǎn)單來(lái)說(shuō),集成學(xué)習(xí)就是使用多個(gè)模型來(lái)一同學(xué)習(xí),最后在每個(gè)模型都得到預(yù)測(cè)結(jié)果后再經(jīng)過(guò)進(jìn)一步的集成處理得到最終預(yù)測(cè)結(jié)果的一種學(xué)習(xí)方法。值得注意的是,不同的集成學(xué)習(xí)方法有著不同的集成方法,常見(jiàn)的包括 Bagging、Boosting 等集成方法。
下面我們可以簡(jiǎn)單的了解一下這兩種集成方法(我們的重點(diǎn)在集成,因此省略掉了相應(yīng)的采樣工作)。
- Bagging 集成方法:這種集成方法的思想比較簡(jiǎn)單,在每個(gè)模型都得到一個(gè)結(jié)果之后,我們會(huì)采用一種更加民主的方式進(jìn)行:
- 對(duì)于回歸問(wèn)題,我們使用的是取均值操作;
- 對(duì)于分類(lèi)問(wèn)題,我們采用的是投票方法,也就是選取出現(xiàn)次數(shù)最多的那個(gè)。
- 在 Bagging 之中,每個(gè)模型的重要性是相同的。
- Boosting 集成方法:這種集成方法就是我們這節(jié)課要采用的,相對(duì)復(fù)雜一些:
- 我們首先采用加法線(xiàn)性組合對(duì)各個(gè)模型進(jìn)行處理;
- 然后我們得到每個(gè)模型的錯(cuò)誤率;
- 最后對(duì)于錯(cuò)誤率小的模型,我們會(huì)減少它的權(quán)重(話(huà)語(yǔ)權(quán)),反而提升一些錯(cuò)誤率高的模型的權(quán)重(話(huà)語(yǔ)權(quán))。
- 在 Boosting 之中,每個(gè)模型的重要性是不同的。
既然了解了什么是 Boosting 方法,那么我們便要簡(jiǎn)單學(xué)習(xí)一下提升樹(shù)的基礎(chǔ)模型:決策樹(shù)。
2. 什么是決策樹(shù)(Tree)
決策樹(shù)其實(shí)很簡(jiǎn)單,我們?nèi)粘I钪杏玫降睦臃浅6啵e個(gè)簡(jiǎn)單的分類(lèi)的例子:
我中午餓了,要去吃飯,學(xué)校里面一共有兩個(gè)餐廳,而我一共有4個(gè)選擇:
- A餐廳:價(jià)格貴;
- B餐廳:價(jià)格便宜;
- 吃泡面:不用出宿舍,前提是宿舍售賣(mài)機(jī)有賣(mài);
- 點(diǎn)外賣(mài):不用出宿舍。
那么,我們的決策樹(shù)就如下圖所示:如果我想出門(mén)而且有錢(qián),我就去 A 餐廳;如果我想出門(mén)但是卻錢(qián)不多,那么我就去 B 餐廳;倘若我不想出宿舍而剛剛好宿舍有賣(mài)泡面,我就可以直接吃泡面;到那時(shí)如果沒(méi)有泡面的話(huà),我就只能點(diǎn)外賣(mài)。
這只是一個(gè)簡(jiǎn)單的理解,而具體的優(yōu)化的細(xì)節(jié)涉及到許多的數(shù)學(xué)原理,這里就不過(guò)多解釋了。
3. 如何在 TensorFlow 的 Estimator 之中使用提升樹(shù)
既然我們了解了 Boosting ,也知道了 Tree ,那么接下來(lái)就是了解如何在 Estimator 之中使用Boosting Tree。在這節(jié)課之中,我們依然使用泰坦尼克數(shù)據(jù)集為示例來(lái)進(jìn)行演示,這是我們接觸過(guò)的一個(gè)二分類(lèi)問(wèn)題。
其實(shí)在 Estimator 之中,已經(jīng)包含一個(gè)內(nèi)置的 API 來(lái)向我們提供一個(gè)提升樹(shù)分類(lèi)器,剛剛好符合我們對(duì)數(shù)據(jù)分類(lèi)的要求。
tf.estimator.BoostedTreesClassifier()
通過(guò)該API我們可以直接構(gòu)造一個(gè)用于分類(lèi)的提升樹(shù)。
4. 具體的實(shí)現(xiàn)細(xì)節(jié)
首先我們和之前一樣,進(jìn)行數(shù)據(jù)的獲?。?/p>
import numpy as np
import pandas as pd
import tensorflow as tf
x_train = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/train.csv')
x_test = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/eval.csv')
y_train = x_train.pop('survived')
y_test = x_test.pop('survived')
然后我們要定義連序列以及離散列:
categories = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck', 'embark_town', 'alone']
numeric = ['age', 'fare']
然后我們就要定義特征列了:
def one_hot_cat_column(feature_name, vocab):
return tf.feature_column.indicator_column(tf.feature_column.categorical_column_with_vocabulary_list(feature_name, vocab))
feature_columns = []
for feature_name in categories:
feature_columns.append(one_hot_cat_column(feature_name, x_train[feature_name].unique()))
for feature_name in numeric:
feature_columns.append(tf.feature_column.numeric_column(feature_name,dtype=tf.float32))
在第一個(gè) one_hot_cat_column 函數(shù)之中,我們對(duì)于特征列進(jìn)行了獨(dú)熱編碼。并且我們對(duì)于離散列與連續(xù)列進(jìn)行了不同的處理。
然后我們定義輸入函數(shù),這里我們?nèi)匀欢x了兩個(gè)輸入函數(shù),一個(gè)為訓(xùn)練使用,另一個(gè)為測(cè)試使用:
def train_input_fn(x, y):
dataset = tf.data.Dataset.from_tensor_slices((dict(x), y))
dataset = dataset.shuffle(len(y_train)).repeat().batch(32)
return dataset
def test_input_fn(x, y):
dataset = tf.data.Dataset.from_tensor_slices((dict(x), y)).batch(32)
return dataset
train_input = lambda: train_input_fn(x_train, y_train)
test_input = lambda: test_input_fn(x_test, y_eval)
在這之后,我們便需要定義我們的提升樹(shù)模型了:
estimator = tf.estimator.BoostedTreesClassifier(feature_columns, n_batches_per_layer=len(y_train) // 32)
這里的第一個(gè)參數(shù) feature_columns 就是特征列,這個(gè)很好理解;關(guān)鍵是第二個(gè)參數(shù),大家要記住的是, n_batches_per_layer 這個(gè)參數(shù)需要是樣本的數(shù)量與批次大小的商,因?yàn)檫@里我們的批次大小為 32 ,因此我們?cè)O(shè)置其為 (y_train) // 32 。
最后便是模型的訓(xùn)練了:
estimator.train(train_input, max_steps=100)
result = estimator.evaluate(test_input)
print(pd.Series(result))
于是我們可以的得到輸出:
accuracy 0.787879
accuracy_baseline 0.625000
auc 0.835384
auc_precision_recall 0.825271
average_loss 0.554901
label/mean 0.375000
loss 0.552625
precision 0.747126
prediction/mean 0.454899
recall 0.656566
global_step 100.000000
dtype: float64
于是我們可以得到了我們訓(xùn)練結(jié)果: 78% 的準(zhǔn)確率。
為了做對(duì)比,大家可以采用一個(gè)簡(jiǎn)單的線(xiàn)性分類(lèi)器來(lái)做對(duì)比,也就是:
tf.estimator.LinearClassifier(feature_columns)
通過(guò)對(duì)比,大家就可以看到集成學(xué)習(xí)的優(yōu)勢(shì)。
5. 小結(jié)
在這節(jié)課之中,我們學(xué)習(xí)了什么是集成學(xué)習(xí)以及集成學(xué)習(xí)的兩種常用的集成方法。同時(shí)我們也了解了什么是決策樹(shù)。最后我們?cè)趯?shí)踐中學(xué)習(xí)了如何使用 Estimator 來(lái)實(shí)現(xiàn)一個(gè)提升樹(shù)模型。