XGBoost與神經(jīng)網(wǎng)絡(luò)誰(shuí)更牛倒慧?

XGBoost是Kaggle上的比賽神器按摘,近些年在kaggle或天池比賽上時(shí)常能斬獲大獎(jiǎng),不過(guò)這樣的歷史正在改變迫靖!最近幾年神經(jīng)網(wǎng)絡(luò)的優(yōu)勢(shì)開始從非結(jié)構(gòu)數(shù)據(jù)向結(jié)構(gòu)數(shù)據(jù)延伸院峡,而且在一些Kaggle比賽中取得非常不錯(cuò)的成績(jī)。

XGBoost很牛系宜,不過(guò)更牛的應(yīng)該是NN! 這章我們通過(guò)一個(gè)實(shí)例來(lái)說(shuō)明照激,本實(shí)例基于相同數(shù)據(jù),使用XGBoost和神經(jīng)網(wǎng)絡(luò)(NN)對(duì)類別數(shù)據(jù)轉(zhuǎn)換為數(shù)字盹牧。XGBoost是屬于Tree Model俩垃,故是否使用One-hot影響不大(通過(guò)測(cè)試,確實(shí)如此汰寓,相反口柳,如果轉(zhuǎn)換為one-hot將大大增加內(nèi)存開銷),所以使用xgboost的數(shù)據(jù)轉(zhuǎn)換為數(shù)字后有滑,沒(méi)有再轉(zhuǎn)換為one-hot編碼跃闹。對(duì)神經(jīng)網(wǎng)絡(luò)(NN)而言,是否把數(shù)據(jù)轉(zhuǎn)換為One-hot毛好,影響比較大望艺,所以使用NN的模型數(shù)據(jù)已轉(zhuǎn)換為One-hot。

兩種算法測(cè)試結(jié)果為表2-1肌访。

表2-1

訓(xùn)練及測(cè)試數(shù)據(jù)沒(méi)有打亂找默,其中測(cè)試數(shù)據(jù)是最新原數(shù)據(jù)的10%。

2.1 XGBoost簡(jiǎn)介

2.1.1概述

XGBoost的全稱是eXtreme Gradient Boosting吼驶,由很多CART(Classification And Regression Tree)樹集成惩激,其中CART是對(duì)分類決策樹和回歸決策樹的總稱。

分類決策樹一般使用信息增益蟹演、信息增益率风钻、基尼系數(shù)來(lái)選擇特征的依據(jù)。CART回歸樹是假設(shè)樹為二叉樹酒请,通過(guò)不斷將特征進(jìn)行分裂魄咕。比如當(dāng)前樹結(jié)點(diǎn)是基于第j個(gè)特征值進(jìn)行分裂的哮兰,設(shè)該特征值小于s的樣本劃分為左子樹,大于s的樣本劃分為右子樹喝滞。因此,當(dāng)我們?yōu)榱饲蠼庾顑?yōu)的切分特征j和最優(yōu)的切分點(diǎn)s做盅,就轉(zhuǎn)化為求解這么一個(gè)目標(biāo)函數(shù)窘哈。

只要遍歷所有特征的的所有切分點(diǎn),就能找到最優(yōu)的切分特征和切分點(diǎn)图筹。最終得到一棵回歸樹。

2.1.2 主要原理

XGBoost本質(zhì)上還是一個(gè)GBDT(Gradient Boosting Decision Tree)让腹,但為力爭(zhēng)把速度和效率發(fā)揮到極致远剩,所以叫X (Extreme) GBoosted。GBDT的原理就是所有弱分類器的結(jié)果相加等于預(yù)測(cè)值骇窍,然后下一個(gè)弱分類器去擬合誤差函數(shù)對(duì)預(yù)測(cè)值的梯度(或殘差)(這個(gè)梯度/殘差就是預(yù)測(cè)值與真實(shí)值之間的誤差)瓜晤。一個(gè)弱分類器如何去擬合誤差函數(shù)殘差?

舉一個(gè)非常簡(jiǎn)單的例子腹纳,比如我今年30歲了痢掠,但計(jì)算機(jī)或者模型GBDT并不知道我今年多少歲,那GBDT咋辦呢嘲恍?

(1)它會(huì)在第一個(gè)弱分類器(或第一棵樹中)隨便用一個(gè)年齡比如20歲來(lái)擬合志群,然后發(fā)現(xiàn)誤差有10歲;

(2)在第二棵樹中蛔钙,用6歲去擬合剩下的損失,發(fā)現(xiàn)差距還有4歲荠医;

(3)在第三棵樹中用3歲擬合剩下的差距吁脱,發(fā)現(xiàn)差距只有1歲了;

(4)在第四課樹中用1歲擬合剩下的殘差彬向,完美兼贡。

最終,四棵樹的結(jié)論加起來(lái)娃胆,就是真實(shí)年齡30歲遍希。實(shí)際工程中GBDT是計(jì)算負(fù)梯度,用負(fù)梯度近似殘差里烦。

注意凿蒜,為何GBDT可以用用負(fù)梯度近似殘差呢?

回歸任務(wù)下州泊,GBDT 在每一輪的迭代時(shí)對(duì)每個(gè)樣本都會(huì)有一個(gè)預(yù)測(cè)值,此時(shí)的損失函數(shù)為均方差損失函數(shù),表達(dá)式如下:

那此時(shí)的負(fù)梯度是這樣計(jì)算的演训,具體表達(dá)式如下:

所以,當(dāng)損失函數(shù)選用均方損失函數(shù)是時(shí)乌奇,每一次擬合的值就是(真實(shí)值 - 當(dāng)前模型預(yù)測(cè)的值)礁苗,即殘差。此時(shí)的變量是疏叨,即“當(dāng)前預(yù)測(cè)模型的值”蚤蔓,也就是對(duì)它求負(fù)梯度秀又。

更多詳細(xì)內(nèi)容可參考:https://blog.csdn.net/v_july_v/article/details/81410574

2.1.3 主要優(yōu)點(diǎn)

(1)目標(biāo)表達(dá)式:

XGBoost優(yōu)化了GBDT的目標(biāo)函數(shù)。一方面昏苏,在GBDT的基礎(chǔ)上加入了正則項(xiàng)洼专,包括葉子節(jié)點(diǎn)的個(gè)數(shù)和每個(gè)葉子節(jié)點(diǎn)輸出的L2模的平方和壶熏,正則項(xiàng)可以控制樹的復(fù)雜度,讓模型傾向于學(xué)習(xí)簡(jiǎn)單的模型帽哑,防止過(guò)擬合妻枕;另外屡谐,XGBoost還支持線性分類器,傳統(tǒng)的GBDT是以CART算法作為基學(xué)習(xí)器饵撑。

(2)使用Shrinkage:

對(duì)每棵樹的預(yù)測(cè)結(jié)果采用了shrinkage滑潘,相當(dāng)于學(xué)習(xí)率,降低模型對(duì)單顆樹的依賴粹舵,提升模型的泛化能力。

(3)采用列采樣:

XGBoost借助了隨機(jī)森林的優(yōu)點(diǎn)稠茂,采用了列采樣诱担,進(jìn)一步防止過(guò)擬合,加速訓(xùn)練過(guò)程摇邦,而傳統(tǒng)的GBDT則沒(méi)有列采樣施籍。

(4)優(yōu)化方法:

XGBoost對(duì)損失函數(shù)的展開采用了一階梯度和二階梯度丑慎,而傳統(tǒng)的GBDT只采用了一階梯度。

(5)增益計(jì)算:

對(duì)分裂依據(jù)進(jìn)行了優(yōu)化腻异。不同于CART算法捂掰,XGBoost采用了新的基于一階導(dǎo)數(shù)和二階導(dǎo)數(shù)的統(tǒng)計(jì)信息作為樹的結(jié)構(gòu)分?jǐn)?shù),采用分列前的結(jié)構(gòu)與分裂后的結(jié)構(gòu)得分的增益作為分裂依據(jù)姐帚,選擇增益最大的特征值作為分裂點(diǎn)罐旗,替代了回歸樹的誤差平方和九秀。

(6)最佳增益節(jié)點(diǎn)查找:

XGBoost在尋找最佳分離點(diǎn)的方式上采用了近似算法鼓蜒,基于權(quán)重的分位數(shù)劃分方式(權(quán)重為二階梯度)娇豫。主要是對(duì)特征取值進(jìn)行分桶冯痢,然后基于桶的值計(jì)算增益浦楣。

(7)預(yù)排序椒振。

在尋找最佳增益節(jié)點(diǎn)時(shí),將所有數(shù)據(jù)放入內(nèi)存進(jìn)行計(jì)算夹供,得到預(yù)排序結(jié)果哮洽,然后在計(jì)算分裂增益的時(shí)候直接調(diào)用。

(8)缺失值處理

對(duì)于特征的值有缺失的樣本匪凉,Xgboost可以自動(dòng)學(xué)習(xí)出他的分裂方向再层。Xgboost內(nèi)置處理缺失值的規(guī)則聂受。

(9)支持并行。

眾所周知碗旅,Boosting算法是順序處理的扛芽,也是說(shuō)Boosting不是一種串行的結(jié)構(gòu)嗎?怎么并行的茫孔?注意XGBoost的并行不是tree粒度的并行馍悟。XGBoost也是一次迭代完才能進(jìn)行下一次迭代的(第t次迭代的代價(jià)函數(shù)里包含)锣咒。XGBoost的并行式在特征粒度上的,也就是說(shuō)每一顆樹的構(gòu)造都依賴于前一顆樹绽左。

2.1.4 XGBoost的模型參數(shù)

XGBoost使用字典的方式存儲(chǔ)參數(shù)戏蔑,主要參數(shù)有如下這些:


params = {

? ? 'booster':'gbtree',

? ? 'objective':'multi:softmax',? # 多分類問(wèn)題

? ? 'num_class':10,? # 類別數(shù)总棵,與multi softmax并用

? ? 'gamma':0.1,? ? # 用于控制是否后剪枝的參數(shù)彻舰,越大越保守刃唤,一般0.1 0.2的樣子

? ? 'max_depth':12,? # 構(gòu)建樹的深度,越大越容易過(guò)擬合

? ? 'lambda':2,? # 控制模型復(fù)雜度的權(quán)重值的L2 正則化項(xiàng)參數(shù)笼裳,參數(shù)越大,模型越不容 易過(guò)擬合

? ? 'subsample':0.7, # 隨機(jī)采樣訓(xùn)練樣本

? ? 'colsample_bytree':3,# 這個(gè)參數(shù)默認(rèn)為1拜轨,是每個(gè)葉子里面h的和至少是多少

? ? ? # 對(duì)于正負(fù)樣本不均衡時(shí)的0-1分類而言,假設(shè)h在0.01附近法牲, ? #min_child_weight為1意味著葉子節(jié)點(diǎn)中最少需要包含100個(gè)樣本拒垃。 #這個(gè)參數(shù)非常影響結(jié)果,控制葉子節(jié)點(diǎn)中二階導(dǎo)的和的最小值谤牡,該 #參數(shù)值越小,越容易過(guò)擬合套么。

? ? 'silent':0,? # 設(shè)置成1 則沒(méi)有運(yùn)行信息輸入胚泌,最好是設(shè)置成0

? ? 'eta':0.007,? # 如同學(xué)習(xí)率

? ? 'seed':1000,

? ? 'nthread':7,? #CPU線程數(shù)

? ? #'eval_metric':'auc'

}


安裝XGBoost建議使用conda命令玷室。如:conda install py-xgboost=0.90

2.2 NN簡(jiǎn)介

使用的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示

圖2-2 神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)

本實(shí)例使用的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)比較簡(jiǎn)單箩兽,共4層汗贫,除輸入、輸出層外摊唇,中間是兩個(gè)全連接層。輸入層1183個(gè)節(jié)點(diǎn),這個(gè)正好是特征轉(zhuǎn)換為one-hot后的元素個(gè)數(shù)幢踏,第1個(gè)隱含層的節(jié)點(diǎn)是1000,激活函數(shù)為relu许师,第2個(gè)隱含層的節(jié)點(diǎn)數(shù)為500房蝉,激活函數(shù)為relu,輸出層1個(gè)節(jié)點(diǎn)微渠,激活函數(shù)為sigmoid搭幻。

2.3 數(shù)據(jù)集簡(jiǎn)介

這里使用德國(guó)Rossmann超市2013、2014逞盆、2015三年的銷售數(shù)據(jù),具體數(shù)據(jù)文件包括:

train.csv-包括銷售在內(nèi)的歷史數(shù)據(jù)

test.csv-測(cè)試數(shù)據(jù)(不包括銷售)

store.csv-有關(guān)商店的補(bǔ)充信息

這些數(shù)據(jù)可從這里下載:https://www.kaggle.com/c/rossmann-store-sales/data

1桌肴、train.csv-包括銷售在內(nèi)的歷史數(shù)據(jù),共有9列彪置,每列的含義如下:

date(日期):代表存儲(chǔ)期

DayOfWeek(星期幾):7表示周日耀盗,6表示周六以此類推

store(商店):每個(gè)商店的唯一ID

sale(銷售):特定日期的營(yíng)業(yè)額(這是您的預(yù)期)

customer(客戶):特定日期的客戶數(shù)量

open(開):為對(duì)存儲(chǔ)是否被打開的指示:0 =關(guān)閉,1 =開

promo(促銷):表示商店當(dāng)天是否在進(jìn)行促銷

StateHoliday(州假日):通常扫尺,除州外襟交,所有商店都在州法定假日關(guān)閉形纺。請(qǐng)注意挪捕,所有學(xué)校在公共假日和周末都關(guān)閉鉴嗤。a =公共假期,b =復(fù)活節(jié)假期坯认,c =圣誕節(jié)恩伺,0 =無(wú)

SchoolHoliday(學(xué)校假日):指示(商店,日期)是否受到公立學(xué)校關(guān)閉的影響

(1)導(dǎo)入數(shù)據(jù)


import pandas as pd

import numpy as np

store = pd.read_csv(r".\data\rossmann\store.csv")

train = pd.read_csv(r".\data\rossmann\train.csv",index_col = "Date",parse_dates = ['Date'],low_memory=False)

test = pd.read_csv(r".\data\rossmann\test.csv",index_col = "Date",parse_dates = ['Date'],low_memory=False)


(2)查看前5行數(shù)據(jù)。

(3)查看是否有空值


#查看是否有空值

train.isnull().sum()


Store 0

DayOfWeek 0

Sales 0

Customers 0

Open 0

Promo 0

StateHoliday 0

SchoolHoliday 0

dtype: int64

(4)查看各特征的不同值


#查看各字段的不同值

train['Year'] = train.index.year

print("共有幾年的數(shù)據(jù):",train['Year'].unique())

print("共有幾種促銷方法:",train['Promo'].unique())


共有幾年的數(shù)據(jù): [2015 2014 2013]

共有幾種促銷方法: [1 0]

2烂完、store.csv數(shù)據(jù)集簡(jiǎn)介

StoreType- 區(qū)分4種不同的商店模型:a,b储耐,c,d

Assortment分類 -描述分類級(jí)別:a =基本,b =額外,c =擴(kuò)展

CompetitionDistance-距離最近的競(jìng)爭(zhēng)對(duì)手商店的距離(以米為單位)

CompetitionOpenSince [Month / Year] -給出最近的競(jìng)爭(zhēng)對(duì)手開放的大概年份和月份。

Promo促銷 -表示商店當(dāng)天是否在進(jìn)行促銷

Promo2 -Promo2是某些商店的連續(xù)和連續(xù)促銷:0 =商店不參與,1 =商店正在參與

Promo2Since [年/周] -描述商店開始參與Promo2的年份和日歷周。

PromoInterval-描述啟動(dòng)Promo2的連續(xù)間隔翔忽,并指定重新開始促銷的月份旨别。例如儿捧,“ Feb,May旧找,Aug,Nov”表示該商店的每一輪始于該年任何一年的2月,5月驼壶,8月,11月

2.4使用Xgboost算法實(shí)例

2.4.1 讀取數(shù)據(jù)

(1)導(dǎo)入模塊


import pickle

import csv

#屏蔽警告信息

import warnings

warnings.filterwarnings('ignore')


(2)定義數(shù)據(jù)預(yù)處理函數(shù)


#把csv文件轉(zhuǎn)換為字典

def csv2dicts(csvfile):

? ? data = []

? ? keys = []

? ? for row_index, row in enumerate(csvfile):

? ? ? ? #把第一行標(biāo)題打印出來(lái)

? ? ? ? if row_index == 0:

? ? ? ? ? ? keys = row

? ? ? ? ? ? print(row)

? ? ? ? ? ? continue

? ? ? ? # if row_index % 10000 == 0:

? ? ? ? #? ? print(row_index)

? ? ? ? data.append({key: value for key, value in zip(keys, row)})

? ? return data

#如果值為空高蜂,則用'0'填充

def set_nan_as_string(data, replace_str='0'):

? ? for i, x in enumerate(data):

? ? ? ? for key, value in x.items():

? ? ? ? ? ? if value == '':

? ? ? ? ? ? ? ? x[key] = replace_str

? ? ? ? data[i] = x


(3)讀取數(shù)據(jù)


train_data = "train.csv"

store_data = "store.csv"

store_states = 'store_states.csv'

#讀取數(shù)據(jù)

with open(train_data) as csvfile:

? ? data = csv.reader(csvfile, delimiter=',')

? ? with open('train_data.pickle', 'wb') as f:

? ? ? ? data = csv2dicts(data)

? ? ? ? #頭尾倒過(guò)來(lái)

? ? ? ? data = data[::-1]

? ? ? ? #序列化聪黎,把數(shù)據(jù)保存到文件中

? ? ? ? pickle.dump(data, f, -1)

? ? ? ? print(data[:3])


2.4.2 預(yù)處理數(shù)據(jù)

(1)導(dǎo)入模塊


import pickle

from datetime import datetime

from sklearn import preprocessing

import numpy as np

import random

random.seed(42)


(2)讀取處理后的文件


with open('train_data.pickle', 'rb') as f:

? ? train_data = pickle.load(f)

? ? num_records = len(train_data)

with open('store_data.pickle', 'rb') as f:

? ? store_data = pickle.load(f)


(3)定義預(yù)處理store數(shù)據(jù)函數(shù)


#對(duì)時(shí)間特征進(jìn)行拆分和轉(zhuǎn)換,是是否促銷promo等特征轉(zhuǎn)換為整數(shù)

def feature_list(record):

? ? dt = datetime.strptime(record['Date'], '%Y-%m-%d')

? ? store_index = int(record['Store'])

? ? year = dt.year

? ? month = dt.month

? ? day = dt.day

? ? day_of_week = int(record['DayOfWeek'])

? ? try:

? ? ? ? store_open = int(record['Open'])

? ? except:

? ? ? ? store_open = 1

? ? promo = int(record['Promo'])

? ? #同時(shí)返回state對(duì)應(yīng)的簡(jiǎn)稱

? ? return [store_open,

? ? ? ? ? ? store_index,

? ? ? ? ? ? day_of_week,

? ? ? ? ? ? promo,

? ? ? ? ? ? year,

? ? ? ? ? ? month,

? ? ? ? ? ? day,

? ? ? ? ? ? store_data[store_index - 1]['State']

? ? ? ? ? ? ]


(4)生成訓(xùn)練數(shù)據(jù)

train_data_X = []

train_data_y = []

for record in train_data:

? ? if record['Sales'] != '0' and record['Open'] != '':

? ? ? ? fl = feature_list(record)

? ? ? ? train_data_X.append(fl)

? ? ? ? train_data_y.append(int(record['Sales']))

print("Number of train datapoints: ", len(train_data_y))

print(min(train_data_y), max(train_data_y))

2.4.3 保存預(yù)處理數(shù)據(jù)

(1)把各類別特征轉(zhuǎn)換為整數(shù)备恤,并保存為pickle文件

full_X = train_data_X

full_X = np.array(full_X)

train_data_X = np.array(train_data_X)

les = []

#對(duì)每列進(jìn)行處理稿饰,先把類別轉(zhuǎn)換為數(shù)值,然后轉(zhuǎn)換為獨(dú)熱編碼

for i in range(train_data_X.shape[1]):

? ? le = preprocessing.LabelEncoder()

? ? le.fit(full_X[:, i])

? ? les.append(le)

? ? train_data_X[:, i] = le.transform(train_data_X[:, i])

with open('les.pickle', 'wb') as f:

? ? pickle.dump(les, f, -1)

train_data_X = train_data_X.astype(int)

train_data_y = np.array(train_data_y)

#保存數(shù)據(jù)到feature_train_data.pickle文件

with open('feature_train_data.pickle', 'wb') as f:

? ? pickle.dump((train_data_X, train_data_y), f, -1)

? ? print(train_data_X[0], train_data_y[0])

2.4.4 采樣生成訓(xùn)練與測(cè)試數(shù)據(jù)

(1)讀取數(shù)據(jù)


train_ratio = 0.9

f = open('feature_train_data.pickle', 'rb')

(X, y) = pickle.load(f)

num_records = len(X)

train_size = int(train_ratio * num_records)


(2)生成訓(xùn)練與測(cè)試集


X_train = X[:train_size]

X_val = X[train_size:]

y_train = y[:train_size]

y_val = y[train_size:]


(3)定義采樣函數(shù)


def sample(X, y, n):

? ? '''random samples'''

? ? num_row = X.shape[0]

? ? indices = numpy.random.randint(num_row, size=n)

? ? return X[indices, :], y[indices]


(4)采樣數(shù)據(jù)

X_train, y_train = sample(X_train, y_train, 200000) # Simulate data sparsity

print("Number of samples used for training: " + str(y_train.shape[0]))

2.4.5 構(gòu)建模型

(1)導(dǎo)入模塊


import tensorflow as tf

import numpy

numpy.random.seed(123)

from sklearn import linear_model

from sklearn.ensemble import RandomForestRegressor

from sklearn.svm import SVR

from sklearn.preprocessing import StandardScaler

import xgboost as xgb

from sklearn import neighbors

from sklearn.preprocessing import Normalizer

from tensorflow.keras.models import Sequential

from tensorflow.keras.models import Model as KerasModel

from tensorflow.keras.layers import Input, Dense, Activation, Reshape,Flatten

from tensorflow.keras.layers import Concatenate

from tensorflow.keras.layers import Embedding

from tensorflow.keras.callbacks import ModelCheckpoint


(2)構(gòu)建xgboost模型


class Model(object):

? ? def evaluate(self, X_val, y_val):

? ? ? ? assert(min(y_val) > 0)

? ? ? ? guessed_sales = self.guess(X_val)

? ? ? ? relative_err = numpy.absolute((y_val - guessed_sales) / y_val)

? ? ? ? result = numpy.sum(relative_err) / len(y_val)

? ? ? ? return result

class XGBoost(Model):

? ? def __init__(self, X_train, y_train, X_val, y_val):

? ? ? ? super().__init__()

? ? ? ? dtrain = xgb.DMatrix(X_train, label=numpy.log(y_train))

? ? ? ? evallist = [(dtrain, 'train')]

? ? ? ? param = {'nthread': -1,

? ? ? ? ? ? ? ? 'max_depth': 7,

? ? ? ? ? ? ? ? 'eta': 0.02,

? ? ? ? ? ? ? ? 'silent': 1,

? ? ? ? ? ? ? ? 'objective': 'reg:linear',

? ? ? ? ? ? ? ? 'colsample_bytree': 0.7,

? ? ? ? ? ? ? ? 'subsample': 0.7}

? ? ? ? num_round = 3000

? ? ? ? self.bst = xgb.train(param, dtrain, num_round, evallist)

? ? ? ? print("Result on validation data: ", self.evaluate(X_val, y_val))

? ? def guess(self, feature):

? ? ? ? dtest = xgb.DMatrix(feature)

? ? ? ? return numpy.exp(self.bst.predict(dtest))


2.4.6 訓(xùn)練模型

models = []

print("Fitting XGBoost...")

models.append(XGBoost(X_train, y_train, X_val, y_val))

運(yùn)行結(jié)果如下:

[2980] train-rmse:0.148366

[2981] train-rmse:0.148347

[2982] train-rmse:0.148314

[2983] train-rmse:0.148277

[2984] train-rmse:0.148238

[2985] train-rmse:0.148221

[2986] train-rmse:0.148218

[2987] train-rmse:0.148187

[2988] train-rmse:0.148182

[2989] train-rmse:0.148155

[2990] train-rmse:0.148113

[2991] train-rmse:0.148113

[2992] train-rmse:0.148067

[2993] train-rmse:0.148066

[2994] train-rmse:0.148064

[2995] train-rmse:0.148062

[2996] train-rmse:0.148048

[2997] train-rmse:0.148046

[2998] train-rmse:0.148046

[2999] train-rmse:0.148041

Result on validation data: 0.14628885960491078


2.5 使用NN算法實(shí)例

2.5.1 預(yù)處理數(shù)據(jù)

導(dǎo)入數(shù)據(jù)露泊、對(duì)數(shù)據(jù)進(jìn)行預(yù)處理喉镰,這些與2.4小節(jié)中的2.4.1、2.4.2一樣滤淳,接下來(lái)對(duì)個(gè)特征先轉(zhuǎn)換為數(shù)字梧喷,然后轉(zhuǎn)換為one-hot編碼砌左,并保存脖咐。

(1)把數(shù)據(jù)轉(zhuǎn)換為one-hot編碼


encoded_x = None

full_X = train_data_X

full_X = np.array(full_X)

train_data_X = np.array(train_data_X)

for i in range(train_data_X.shape[1]):

? ? label_encoder = preprocessing.LabelEncoder()

? ? feature = label_encoder.fit_transform(train_data_X[:,i])

? ? feature = feature.reshape(train_data_X.shape[0], 1)

? ? onehot_encoder = preprocessing.OneHotEncoder(sparse=False)

? ? feature = onehot_encoder.fit_transform(feature)

? ? if encoded_x is None:

? ? ? ? encoded_x = feature

? ? else:

? ? ? ? encoded_x = np.concatenate((encoded_x,feature),axis=1)

print("X shape: : ", encoded_x.shape)


(2)保存數(shù)據(jù)


train_data_X =encoded_x.astype(int)

train_data_y = np.array(train_data_y)

#保存數(shù)據(jù)到feature_train_data.pickle文件

with open('feature_train_data.pickle', 'wb') as f:

? ? pickle.dump((train_data_X, train_data_y), f, -1)

? ? print(train_data_X[0], train_data_y[0])


2.5.2 生成訓(xùn)練數(shù)據(jù)

(1)讀取數(shù)據(jù)

train_ratio = 0.9

f = open('feature_train_data.pickle', 'rb')

(X, y) = pickle.load(f)

num_records = len(X)

train_size = int(train_ratio * num_records)

(2)生成訓(xùn)練數(shù)據(jù)

X_train = X[:train_size]

X_val = X[train_size:]

y_train = y[:train_size]

y_val = y[train_size:]

(3)定義采樣函數(shù)


def sample(X, y, n):

? ? '''random samples'''

? ? num_row = X.shape[0]

? ? indices = numpy.random.randint(num_row, size=n)

? ? return X[indices, :], y[indices]


(4)通過(guò)采樣生成訓(xùn)練數(shù)據(jù)


X_train, y_train = sample(X_train, y_train, 200000) # Simulate data sparsity

print("Number of samples used for training: " + str(y_train.shape[0]))


2.5.3 構(gòu)建神經(jīng)網(wǎng)絡(luò)模型

(1)導(dǎo)入模塊


import tensorflow as tf

import numpy

numpy.random.seed(123)

from sklearn import linear_model

from sklearn.ensemble import RandomForestRegressor

from sklearn.svm import SVR

from sklearn.preprocessing import StandardScaler

import xgboost as xgb

from sklearn import neighbors

from sklearn.preprocessing import Normalizer

from tensorflow.keras.models import Sequential

from tensorflow.keras.models import Model as KerasModel

from tensorflow.keras.layers import Input, Dense, Activation, Reshape,Flatten

from tensorflow.keras.layers import Concatenate

from tensorflow.keras.layers import Embedding

from tensorflow.keras.callbacks import ModelCheckpoint


(2)定義Model類?


class Model(object):

? ? def evaluate(self, X_val, y_val):

? ? ? ? assert(min(y_val) > 0)

? ? ? ? guessed_sales = self.guess(X_val)

? ? ? ? relative_err = numpy.absolute((y_val - guessed_sales) / y_val)

? ? ? ? result = numpy.sum(relative_err) / len(y_val)

? ? ? ? return result


(3)構(gòu)建神經(jīng)網(wǎng)絡(luò)


class NN(Model):

? ? def __init__(self, X_train, y_train, X_val, y_val):

? ? ? ? super().__init__()

? ? ? ? self.epochs = 10

? ? ? ? self.checkpointer = ModelCheckpoint(filepath="best_model_weights.hdf5", verbose=1, save_best_only=True)

? ? ? ? self.max_log_y = max(numpy.max(numpy.log(y_train)), numpy.max(numpy.log(y_val)))

? ? ? ? self.__build_keras_model()

? ? ? ? self.fit(X_train, y_train, X_val, y_val)

? ? def __build_keras_model(self):

? ? ? ? self.model = Sequential()

? ? ? ? self.model.add(Dense(1000, kernel_initializer="uniform", input_dim=1183))

? ? ? ? #self.model.add(Dense(1000, kernel_initializer="uniform", input_dim=8))

? ? ? ? self.model.add(Activation('relu'))

? ? ? ? self.model.add(Dense(500, kernel_initializer="uniform"))

? ? ? ? self.model.add(Activation('relu'))

? ? ? ? self.model.add(Dense(1))

? ? ? ? self.model.add(Activation('sigmoid'))

? ? ? ? self.model.compile(loss='mean_absolute_error', optimizer='adam')

? ? def _val_for_fit(self, val):

? ? ? ? val = numpy.log(val) / self.max_log_y

? ? ? ? return val

? ? def _val_for_pred(self, val):

? ? ? ? return numpy.exp(val * self.max_log_y)

? ? def fit(self, X_train, y_train, X_val, y_val):

? ? ? ? self.model.fit(X_train, self._val_for_fit(y_train),

? ? ? ? ? ? ? ? ? ? ? validation_data=(X_val, self._val_for_fit(y_val)),

? ? ? ? ? ? ? ? ? ? ? epochs=self.epochs, batch_size=128,

? ? ? ? ? ? ? ? ? ? ? # callbacks=[self.checkpointer],

? ? ? ? ? ? ? ? ? ? ? )

? ? ? ? # self.model.load_weights('best_model_weights.hdf5')

? ? ? ? print("Result on validation data: ", self.evaluate(X_val, y_val))

? ? def guess(self, features):

? ? ? ? result = self.model.predict(features).flatten()

? ? ? ? return self._val_for_pred(result)


2.5.4 訓(xùn)練模型


models = []

print("Fitting NN...")

for i in range(1):

? ? models.append(NN(X_train, y_train, X_val, y_val))


運(yùn)行結(jié)果:

Fitting NN...

Train on 200000 samples, validate on 84434 samples

Epoch 1/10

200000/200000 [==============================] - 12s 60us/sample - loss: 0.0121 - val_loss: 0.0142

Epoch 2/10

200000/200000 [==============================] - 11s 54us/sample - loss: 0.0080 - val_loss: 0.0104

Epoch 3/10

200000/200000 [==============================] - 11s 53us/sample - loss: 0.0071 - val_loss: 0.0100

Epoch 4/10

200000/200000 [==============================] - 11s 54us/sample - loss: 0.0064 - val_loss: 0.0099

Epoch 5/10

200000/200000 [==============================] - 11s 54us/sample - loss: 0.0059 - val_loss: 0.0098

Epoch 6/10

200000/200000 [==============================] - 11s 54us/sample - loss: 0.0055 - val_loss: 0.0103

Epoch 7/10

200000/200000 [==============================] - 11s 55us/sample - loss: 0.0051 - val_loss: 0.0100

Epoch 8/10

200000/200000 [==============================] - 11s 54us/sample - loss: 0.0047 - val_loss: 0.0099

Epoch 9/10

200000/200000 [==============================] - 11s 53us/sample - loss: 0.0045 - val_loss: 0.0102

Epoch 10/10

200000/200000 [==============================] - 11s 54us/sample - loss: 0.0042 - val_loss: 0.0100

Result on validation data: 0.10825838109273625

接下來(lái)將用更多實(shí)例,從多個(gè)角度比較NN與傳統(tǒng)ML的比較汇歹,帶EE(Entity Embedding)的NN與不帶NN的比較屁擅,帶EE的傳統(tǒng)ML與不帶EE的傳統(tǒng)ML,以及EE在ML的頂級(jí)應(yīng)用(如推薦算法、預(yù)測(cè)等問(wèn)題上的使用)产弹。

EE就像一座橋梁派歌,把結(jié)構(gòu)化數(shù)據(jù)與NN(或深度學(xué)習(xí)算法)連接在一起弯囊,大大發(fā)揮了NN在處理結(jié)構(gòu)化數(shù)據(jù)方面的潛能(即NN強(qiáng)大的學(xué)習(xí)能力),深度學(xué)習(xí)將徹底改變傳統(tǒng)機(jī)器學(xué)習(xí)胶果。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匾嘱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子早抠,更是在濱河造成了極大的恐慌霎烙,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蕊连,死亡現(xiàn)場(chǎng)離奇詭異悬垃,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)甘苍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門尝蠕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事》茉纾” “怎么了犬庇?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)更耻。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么序矩? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮跋破,結(jié)果婚禮上簸淀,老公的妹妹穿的比我還像新娘。我一直安慰自己毒返,他們只是感情好租幕,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拧簸,像睡著了一般劲绪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盆赤,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天贾富,我揣著相機(jī)與錄音,去河邊找鬼牺六。 笑死颤枪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淑际。 我是一名探鬼主播畏纲,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼扇住,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了盗胀?” 一聲冷哼從身側(cè)響起艘蹋,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎票灰,沒(méi)想到半個(gè)月后簿训,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡米间,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年强品,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屈糊。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡的榛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出逻锐,到底是詐尸還是另有隱情夫晌,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布昧诱,位于F島的核電站晓淀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盏档。R本人自食惡果不足惜凶掰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜈亩。 院中可真熱鬧懦窘,春花似錦、人聲如沸稚配。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)道川。三九已至午衰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間冒萄,已是汗流浹背臊岸。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宦言,地道東北人扇单。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓商模,卻偏偏與公主長(zhǎng)得像奠旺,于是被迫代替她去往敵國(guó)和親蜘澜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容