成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

基于PaddlePaddle的點擊率的深度學習方法嘗試

企業動態
前面在團隊內部分享點擊率相關的一些文章時,輸出了一篇常見計算廣告點擊率預估算法總結,看了一些廣告點擊率的文章,從最經典的Logistic Regression到Factorization Machined,FFM,FNN,PNN到今年的DeepFM,還有文章里面沒有講的gbdt+lr這類,一直想找時間實踐下

前言

前面在團隊內部分享點擊率相關的一些文章時,輸出了一篇常見計算廣告點擊率預估算法總結,看了一些廣告點擊率的文章,從最經典的Logistic Regression到Factorization Machined,FFM,FNN,PNN到今年的DeepFM,還有文章里面沒有講的gbdt+lr這類,一直想找時間實踐下,正好這次在學習paddle的時候在它的models目錄下看到了DeepFM的實現,因為之前對DeepFM有過比較詳細的描述,這里稍微復習一下:

DeepFM更有意思的地方是WDL和FM結合了,其實就是把PNN和WDL結合了,PNN即將FM用神經網絡的方式構造了一遍,作為wide的補充,原始的Wide and Deep,Wide的部分只是LR,構造線性關系,Deep部分建模更高階的關系,所以在Wide and Deep中還需要做一些特征的東西,如Cross Column的工作,而我們知道FM是可以建模二階關系達到Cross column的效果,DeepFM就是把FM和NN結合,無需再對特征做諸如Cross Column的工作了,這個是我感覺最吸引人的地方,其實FM的部分感覺就是PNN的一次描述,這里只描述下結構圖,PNN的部分前面都描述, FM部分:

Deep部分:

DeepFM相對于FNN、PNN,能夠利用其Deep部分建模更高階信息(二階以上),而相對于Wide and Deep能夠減少特征工程的部分工作,wide部分類似FM建模一、二階特征間關系, 算是NN和FM的一個更***的結合方向,另外不同的是如下圖,DeepFM的wide和deep部分共享embedding向量空間,wide和deep均可以更新embedding部分,雖說wide部分純是PNN的工作,但感覺還是蠻有意思的。

本文相關代碼部分都是來自于paddlepaddle/model, 我這里走一遍流程,學習下,另外想要了解算法原理的可以仔細再看看上面的文章,今天我們來paddlepaddle上做下實驗,來從代碼程度學習下DeepFM怎么實現的:

數據集說明

criteo Display Advertising Challenge,數據主要來criteolab一周的業務數據,用來預測用戶在訪問頁面時,是否會點擊某廣告。

wget --no-check-certificate https://s3-eu-west-1.amazonaws.com/criteo-labs/dac.tar.gz tar zxf dac.tar.gz rm -f dac.tar.gz  mkdir raw mv ./*.txt raw/ 

數據有點大, 大概4.26G,慢慢等吧,數據下載完成之后,解壓出train.csv,test.csv,其中訓練集45840617條樣本數,測試集45840617條樣本,數據量還是蠻大的。 數據主要有三部分組成:

  • label: 廣告是否被點擊;
  • 連續性特征: 1-13,為各維度下的統計信息,連續性特征;
  • 離散型特征:一些被脫敏處理的類目特征

Overview

整個項目主要由幾個部分組成:

數據處理

這里數據處理主要包括兩個部分:

  1. 連續值特征值處理:
  • 濾除統計次數95%以上的數據,這樣可以濾除大部分異值數據,這里的處理方式和以前我在1號店做相關工作時一致,代碼里面已經做了這部分工作,直接給出了這部分的特征閾值;
  • 歸一化處理,這里andnew ng的課程有張圖很明顯,表明不同的特征的值域范圍,會使得模型尋優走『之』字形,這樣會增加收斂的計算和時間;
  1. 離散特征值處理:
  • one-hot: 對應特征值映射到指定維度的只有一個值為1的稀疏變量;
  • embedding: 對應特征值映射到指定的特征維度上;

具體我們來研究下代碼:

class ContinuousFeatureGenerator:     """     Normalize the integer features to [0, 1] by min-max normalization     """      def __init__(self, num_feature):         self.num_feature = num_feature         self.min = [sys.maxint] * num_feature         self.max = [-sys.maxint] * num_feature      def build(self, datafile, continous_features):         with open(datafile, 'r') as f:             for line in f:                 features = line.rstrip('\n').split('\t')                 for i in range(0, self.num_feature):                     val = features[continous_features[i]]                     if val != '':                         val = int(val)                         if val > continous_clip[i]:                             val = continous_clip[i]                         self.min[i] = min(self.min[i], val)                         self.max[i] = max(self.max[i], val)      def gen(self, idx, val):         if val == '':             return 0.0         val = float(val)         return (val - self.min[idx]) / (self.max[idx] - self.min[idx]) 

連續特征是在1-13的位置,讀取文件,如果值大于對應維度的特征值的95%閾值,則該特征值置為該閾值,并計算特征維度的***、最小值,在gen時歸一化處理。

class CategoryDictGenerator:     """     Generate dictionary for each of the categorical features     """      def __init__(self, num_feature):         self.dicts = []         self.num_feature = num_feature         for i in range(0, num_feature):             self.dicts.append(collections.defaultdict(int))      def build(self, datafile, categorial_features, cutoff=0):         with open(datafile, 'r') as f:             for line in f:                 features = line.rstrip('\n').split('\t')                 for i in range(0, self.num_feature):                     if features[categorial_features[i]] != '':                         self.dicts[i][features[categorial_features[i]]] += 1         for i in range(0, self.num_feature):             self.dicts[i] = filter(lambda x: x[1] >= cutoff,                                 self.dicts[i].items())             self.dicts[i] = sorted(self.dicts[i], key=lambda x: (-x[1], x[0]))             vocabs, _ = list(zip(*self.dicts[i]))             self.dicts[i] = dict(zip(vocabs, range(1, len(vocabs) + 1)))             self.dicts[i]['<unk>'] = 0      def gen(self, idx, key):         if key not in self.dicts[idx]:             res = self.dicts[idx]['<unk>']         else:             res = self.dicts[idx][key]         return res      def dicts_sizes(self):         return map(len, self.dicts) 

類目特征的處理相對比較麻煩,需要遍歷,然后得到對應維度上所有出現值的所有情況,對打上對應id,為后續類目特征賦予id。這部分耗時好大,慢慢等吧,另外強烈希望paddlepaddle的小伙伴能在輸出處理期間打印下提示信息,算了,我之后有時間看看能不能提提pr。

經過上面的特征處理之后,訓練集的值變為:

reader

paddle里面reader的文件,自由度很高,自己可以寫生成器,然后使用batch的api,完成向網絡傳入batchsize大小的數據:

class Dataset:     def _reader_creator(self, path, is_infer):         def reader():             with open(path, 'r') as f:                 for line in f:                     features = line.rstrip('\n').split('\t')                     dense_feature = map(float, features[0].split(','))                     sparse_feature = map(int, features[1].split(','))                     if not is_infer:                         label = [float(features[2])]                         yield [dense_feature, sparse_feature                             ] + sparse_feature + [label]                     else:                         yield [dense_feature, sparse_feature] + sparse_feature          return reader      def train(self, path):         return self._reader_creator(path, False)      def test(self, path):         return self._reader_creator(path, False)      def infer(self, path):         return self._reader_creator(path, True) 

主要邏輯在兌入文件,然后yield對應的網絡數據的輸入格式

模型構造

模型構造,DeepFM在paddlepaddle里面比較簡單,因為有專門的fm層,這個據我所知在TensorFlow或MXNet里面沒有專門的fm層,但是值得注意的是,在paddlepaddle里面的fm層,只建模二階關系,需要再加入fc才是完整的fm,實現代碼如下:

def fm_layer(input, factor_size, fm_param_attr):     first_order = paddle.layer.fc(         input=input, size=1, act=paddle.activation.Linear())     second_order = paddle.layer.factorization_machine(         input=input,         factor_size=factor_size,         act=paddle.activation.Linear(),         param_attr=fm_param_attr)     out = paddle.layer.addto(         input=[first_order, second_order],         act=paddle.activation.Linear(),         bias_attr=False)     return out 

然后就是構造DeepFM,這里根據下面的代碼畫出前面的圖,除去數據處理的部分,就是DeepFM的網絡結構:

def DeepFM(factor_size, infer=False):     dense_input = paddle.layer.data(         name="dense_input",         type=paddle.data_type.dense_vector(dense_feature_dim))     sparse_input = paddle.layer.data(         name="sparse_input",         type=paddle.data_type.sparse_binary_vector(sparse_feature_dim))     sparse_input_ids = [         paddle.layer.data(             name="C" + str(i),             type=s(sparse_feature_dim))         for i in range(1, 27)     ]     dense_fm = fm_layer(         dense_input,         factor_size,         fm_param_attr=paddle.attr.Param(name="DenseFeatFactors"))     sparse_fm = fm_layer(         sparse_input,         factor_size,         fm_param_attr=paddle.attr.Param(name="SparseFeatFactors"))     def embedding_layer(input):         return paddle.layer.embedding(             input=input,             size=factor_size,             param_attr=paddle.attr.Param(name="SparseFeatFactors"))     sparse_embed_seq = map(embedding_layer, sparse_input_ids)     sparse_embed = paddle.layer.concat(sparse_embed_seq)      fc1 = paddle.layer.fc(         input=[sparse_embed, dense_input],         size=400,         act=paddle.activation.Relu())     fc2 = paddle.layer.fc(input=fc1, size=400, act=paddle.activation.Relu())     fc3 = paddle.layer.fc(input=fc2, size=400,            act=paddle.activation.Relu())      predict = paddle.layer.fc(         input=[dense_fm, sparse_fm, fc3],         size=1,         act=paddle.activation.Sigmoid())      if not infer:         label = paddle.layer.data(             name="label", type=paddle.data_type.dense_vector(1))         cost = paddle.layer.multi_binary_label_cross_entropy_cost(             input=predict, label=label)         paddle.evaluator.classification_error(             name="classification_error", input=predict, label=label)         paddle.evaluator.auc(name="auc", input=predict, label=label)          return cost     else:         return predict 

其中,主要包括三個部分,一個是多個fc組成的deep部分,第二個是sparse fm部分,然后是dense fm部分,如圖:

這里蠻簡單的,具體的api去查下文檔就可以了,這里稍微說明一下的是,sparse feature這塊有兩部分一塊是embedding的處理,這里是先生成對應的id,然后用id來做embedding,用作后面fc的輸出,然后sparse_input是onehot表示用來作為fm的輸出,fm來計算一階和二階隱變量關系。

模型訓練

數據量太大,單機上跑是沒有問題,可以正常運行成功,在我內部機器上,可以運行成功,但是有兩個問題:

  1. fm由于處理的特征為稀疏表示,而paddlepaddle在這塊的FM層的支持只有在cpu上,速度很慢,分析原因其實不是fm的速度的問題,因為deepfm有設計多個fc,應該是這里的速度影響, 在paddlepaddle github上有提一個issue,得知暫時paddlepaddle不能把部分放到gpu上面跑,給了一個解決方案把所有的sparse改成dense,發現在這里gpu顯存hold不住;
  2. 我的機器太渣,因為有開發任務不能長期占用;

所以綜上,我打算研究下在百度云上怎么通過k8s來布置paddlepaddle的分布式集群。

文檔cloud.baidu.com/doc/CCE

研究來研究去,***步加卡主了,不知道怎么回事,那個頁面就是出不來...出師未捷身先死,提了個issue: github.com/PaddlePaddle,等后面解決了再來更新分布式訓練的部分。

單機的訓練沒有什么大的問題,由上面所說,因為fm的sparse不支持gpu,所以很慢,拉的百度云上16核的機器,大概36s/100 batch,總共樣本4000多w,一個epoch預計4個小時,MMP,等吧,分布式的必要性就在這里。

另外有在paddlepaddle里面提一個issue:

github.com/PaddlePaddle,說把sparse轉成dense的話可以直接在gpu上跑起來,這個看起來不值得去嘗試,sparse整個維度還是挺高的,期待對sparse op 有更好的解決方案,更期待在能夠把單層單層的放在gpu,多設備一起跑,這方面,TensorFlow和MXNet要好太多。

這里我遇到一個問題,我使用paddle的docker鏡像的時候,可以很穩定的占用16個cpu的大部分計算力,但是我在云主機上自己裝的時候,cpu占用率很低,可能是和我環境配置有點問題,這個問題不大,之后為了不污染環境主要用docker來做相關的開發工作,所以這里問題不大。

cpu占有率有比較明顯的跳動,這里從主觀上比TensorFlow穩定性要差一些,不排除是sparse op的影響,印象中,TensorFlow cpu的占用率很穩定。


到發這篇文章位置,跑到17300個batch,基本能達到auc為0.8左右,loss為0.208左右。

預測

預測代碼和前一篇將paddle里面的demo一樣,只需要,重新定義一下網絡,然后綁定好模型訓練得到的參數,然后傳入數據即可完成inference,paddle,有專門的Inference接口,只要傳入output_layer,和訓練學習到的parameters,就可以很容易的新建一個模型的前向inference網絡。

def infer():     args = parse_args()     paddle.init(use_gpu=False, trainer_count=1)     model = DeepFM(args.factor_size, infer=True)     parameters = paddle.parameters.Parameters.from_tar(         gzip.open(args.model_gz_path, 'r'))     inferer = paddle.inference.Inference(         output_layer=model, parameters=parameters)     dataset = reader.Dataset()     infer_reader = paddle.batch(dataset.infer(args.data_path),  batch_size=1000)     with open(args.prediction_output_path, 'w') as out:         for id, batch in enumerate(infer_reader()):             res = inferer.infer(input=batch)             predictions = [x for x in itertools.chain.from_iterable(res)]             out.write('\n'.join(map(str, predictions)) + '\n') 

總結

照例總結一下,DeemFM是17年深度學習在點擊率預估、推薦這塊的新的方法,有點類似于deep and wide的思想,將傳統的fm來nn化,利用神經網絡強大的建模能力來挖掘數據中的有效信息,paddlepaddle在這塊有現成的deepfm模型,單機部署起來比較容易,分布式,這里我按照百度云上的教程還未成功,后續會持續關注。另外,因為最近在做大規模機器學習框架相關的工作,越發覺得別說成熟的,僅僅能夠work的框架就很不錯了,而比較好用的如現在的TensorFlow\MXNet,開發起來真的難上加難,以前光是做調包俠時沒有體驗,現在深入到這塊的工作時,才知道其中的難度,也從另一個角度開始審視現在的各種大規模機器學習框架,比如TensorFlow、MXNet,在深度學習的支持上,確實很棒,但是也有瓶頸,對于大規模海量的feature,尤其是sparse op的支持上,至少現在還未看到特別好的支持,就比如這里的FM,可能大家都會吐槽為啥這么慢,沒做框架之前,我也會吐槽,但是開始接觸了一些的時候,才知道FM,主要focus在sparse相關的數據對象,而這部分數據很難在gpu上完成比較高性能的計算,所以前面經過paddle的開發者解釋sparse相關的計算不支持gpu的時候,才感同身受,一個好的大規模機器學習框架必須要從不同目標來評價,如果需求是大規律數據,那穩定性、可擴展性是重點,如果是更多算法、模型的支持,可能現在的TensorFlow、MXNet才是標桿,多么希望現在大規模機器學習框架能夠多元化的發展,有深度學習支持力度大的,也有傳統算法上,把數據量、訓練規模、并行化加速并做到***的,這樣的發展才或許稱得上百花齊放,其實我們不需要太多不同長相的TensorFlow、MXNet錘子,有時候我們就需要把鐮刀而已,希望大規模機器學習框架的發展,不應該僅僅像TensorFlow、MXNet一樣,希望有一個專注把做大規模、大數據量、***并行化加速作為roadmap的新標桿,加油。

責任編輯:張燕妮 來源: 小石頭的碼瘋窩
相關推薦

2018-03-15 15:40:39

廣告點擊率PaddlePaddlTensorflow

2021-07-01 15:56:42

深度學習人工智能互聯網

2021-11-12 15:16:32

深度學習數據合成人工智能

2024-10-08 08:19:19

2011-06-20 15:55:14

SEO

2013-10-30 10:39:25

Banner

2017-05-23 14:00:26

機器學習編程技術計算模型

2016-11-22 19:54:56

點擊率預估推薦算法廣告

2017-05-08 23:02:56

敏捷學習GitHubissue

2016-12-28 15:19:22

大數據機器學習銷售預測

2009-09-28 10:40:28

.NET學習

2018-04-23 14:49:31

表征句子深度學習自然語言

2009-09-04 09:37:49

思科認證CCNA學習方法

2016-09-30 15:33:02

集成學習機器學習算法

2018-09-06 11:25:46

機器學習神經網絡人工智能

2015-07-28 15:41:06

機器學習算法數據挖掘

2011-07-10 15:07:37

2017-11-27 15:24:02

Linux學習方法優勢

2023-11-21 09:32:17

深度學習人工智能

2017-08-07 10:08:29

深度學習分類體系信息檢索
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品日韩 | 蜜桃视频在线观看免费视频网站www | 欧美日韩在线一区二区 | 日本欧美在线 | 国产精品一区二区免费 | 精品一区二区三区免费毛片 | 国产精品成人国产乱 | 欧美激情在线精品一区二区三区 | 欧美网址在线观看 | 男人的天堂在线视频 | 色就是色欧美 | 一区久久 | 99视频在线免费观看 | 久久国产视频网站 | 亚洲一二三区在线观看 | 天天天天操 | 日本一道本视频 | 亚洲品质自拍视频 | 日韩欧美精品在线播放 | 亚洲国产精品久久久久 | 精品国产伦一区二区三区观看体验 | www成年人视频 | 国产一区二区三区四区三区四 | 伊人网一区 | 国产黄色网址在线观看 | 91高清在线视频 | 久久久久久久久久久久久久久久久久久久 | www日本在线播放 | 国产午夜精品一区二区三区 | 久久久五月天 | 国产精品一区在线观看你懂的 | 免费精品久久久久久中文字幕 | 在线观看国产视频 | 中文字幕国产 | 欧美在线观看黄色 | 亚洲精品电影在线观看 | av天天干 | 狠狠ri| 久久久国产精品一区 | 中文字幕一区二区三区四区不卡 | 91日b|