計算廣告學(二)
本系列文章主要參考劉鵬老師的計算廣告學課程
-------------------------------------------------------------------------------------------------------------------
線上廣告的核心計算問題和挑戰
廣告中的計算問題可以概括為下面的公式(Find the best match between a given user u, in a given context c, and a suitable ad a)。下面公式中a表示Sponsor(advertiser),c表示媒體(context),u代表受眾(user)。公式的含義是:給定user,給定context,選擇一組ad,使得ROI最高。ROI對於不同的產品形態是不同的,後面會再討論。i是impression,注意這裡優化的是一組impressions,即要優化的是impression整體的ROI,而不僅僅是一次的ROI。
這個計算問題是一個比較複雜的問題。從優化角度看它會涉及:1. 特徵提取:個人理解是受眾定向,即把u和c打上標籤的過程,這是重要的一步。2. 微觀優化,對一次展示進行優化,得到最好的廣告,最關鍵的技術是CTR預測。3. 巨集觀優化:因為線上廣告是使用者,媒體,廣告商三方博弈,所以競價市場機制的設計非常重要,如果它設計的不好,那影響是巨大的。4. 受限優化:無論是品牌廣告還是效果廣告,都有質和量兩個方面的需求,對品牌廣告來講,大部分情況下,量比質更重要,比如寶潔,它要投一個campaign, reach大量人群,如果廣告僅是點選率比較低,那寶潔可能是可以接受的,但如果預計要reach 20萬人,但最後只reach了10萬人,那它是不能接受的。但對於效果廣告來說,質一般要重要一點,但是量還是重要的。受限優化要解決的就是在量一定的情況下,怎麼來優化質,線上分配就是這個問題。5. 強化學習:如何知道在新的廣告主或新的使用者群預測它的點選率,很直覺的想法是嘗試,分配一定的流量給廣告,看是男性使用者點選率高還是女性。但是在嘗試的過程中會損失一部分收入,因為不是按最優策略出廣告的了。嘗試的過程即探索,使用探索的結果即利用。6. 個性化重定向:會深入的使用推薦技術。
從系統角度來會涉及:1. 候選查詢:要使用實時索引技術,使廣告能很快地進入索引,很快指兩個方面,新的廣告要能儘快上線,廣告預算用完的廣告要儘快下線。2. 特徵儲存:線上高併發要用到一些No-Sql技術。3. 離線學習:很多時候要用到Hadoop。4. 線上學習:一些比較快的反饋,比如得到使用者上一個搜尋詞,要用到流計算技術。5. 交易市場:要用到實時競價。
線上廣告計算的主要挑戰有:
大規模(Scale)
因為計算廣告要處理的是廣告主,使用者,媒體三者的資料,所以資料量非常大,百萬量級的頁面(沒有搜尋要處理的十億級量大)和十億量級的使用者,需要被分析處理。線投放系統中的高併發挑戰 (例: Rightmedia每天處理百億次廣告交易,它會向多個DSP去請求,即每天要進行千億次的請求),響應速度在常見的web應用中可能是最高的,廣告系統對Latency有嚴格要求 (例: ad exchange要求DSP競價在100ms內返回,在 100ms內DSP要做完所有的Target,CTR預測,選出合理的廣告返回),對於廣告效果本身,Latency也是很重要的,廣告晚展示100ms,效果就比較明顯的變差了。
動態性(Dynamics)
從建模的廣度講動態性是很重要的。比如一個使用者想買一雙運動鞋,他可能會去電商網站搜尋,但這種興趣在購完後可能就會消失。所以需要所建立的模型支援快速變化,比如涉及到CTR預測,那麼模型引數是否能快變,特徵是否能快速改變都是有挑戰的。
豐富的查詢資訊 (Rich query)
在搜尋中只需要使用者所鍵入的關鍵詞外,不再需要更多的資訊就可以產生比較好的結果了。而在廣告中,則需要多方面的資訊,使用者的資訊,上下文的資訊,使用者的短期行為等等。搜尋中查詢一般是一到四個關鍵詞,而如果把廣告看成是搜尋問題,那它的查詢條件有幾十上百個之多。
探索與發現 (Explore & exploit)
使用者反饋資料侷限於在以往投放中出現過的(a, u, c)組合,需要主動探索未觀察到的領域,以提高模型正確性
搜尋,廣告與推薦的比較
搜尋 |
搜尋廣告 |
顯示廣告 |
推薦 |
|
首要準則 |
相關性 |
投資回報率(ROI) |
使用者興趣 |
|
其他需求 |
各垂直領域 獨立定義 |
質量,安全性(Safety) |
多樣性(diversity), 新鮮度(freshness) |
|
索引規模 |
~十億級 |
~百萬級--千萬級 |
~百萬級 |
~百萬級--億級 |
個性化 |
較少的個性化需求 |
~億級使用者規模上的個性化 |
||
檢索訊號 |
較為集中 |
較為豐富 |
||
Downstream 優化 |
不適用` |
適用 |
廣告明顯比搜尋容易部分的是不需要複雜的爬蟲技術和PageRank。而它比搜尋困難的地方是它需要建模的資料量比搜尋要大。搜尋,廣告與推薦三者的主要區別在於它們的準則不同,搜尋主要是針對相關性,廣告主要針對ROI。舉例來講,比如搜尋美聯行,那麼對於搜尋來講,必須將美聯行放到結果首位,否則就不合理。但對於廣告來講,如果美聯行代理公司的廣告點選率高於美聯行本身,因為針對的是ROI,所以它可以將美聯行代理排在前面,而不需要將authority的美聯行排在前面。
一些文章中把推薦(recommendation)和個性化(personalization)視為同義詞,但個人認為兩者還是有所不同,個人認為個性化是推薦的一個準則,但推薦還有其它準則,比如多樣性,新鮮度,三者結合,才會有很好的效果。比如一個從不關心軍事的使用者,但如果因釣魚島問題而進行戰爭時,對於這種非常重要的新聞時,推薦應該將這種新聞推薦給這個使用者。
推薦和廣告比較大的區別是:推薦進行的是同質化的推薦,比如在買商品的時候推薦商品,在看新聞的時候推薦其它新聞。另外推薦還有優化流(downstream)的概念,比如使用者在看新聞時,會根據推薦跳到另一個新聞頁面,而在這個新聞頁面上可以繼續推薦,優化流是指優化整個根據推薦看新聞過程的點選率。而對於廣告來講,推薦出的廣告點選後,就跳到目標頁面了,就不可能有優化downstream的機會了。
計算廣告學-廣告基本知識-ROI分解
任何一個線上廣告系統,都面臨ROI的問題,對於Invest,我們先不考慮,因為對於流量有多種方式可以買回,也無法優化(當然在RTB的時候是可以優化的)。Return是主要優化的方向,Return=點選率 * 每次點選創造的價值。比如:點選率是10%,每次點選帶來的收益是5元,則每次點選的收益是10% * 5=0.5元。計算廣告學裡有兩個很重要的概念,1. 點選率(CTR),點選率是使用者(u),廣告(a),上下文(c)三者的函式,點選價值是使用者(u)和廣告(a)的函式,可以認為與上下文(c)無關,因為使用者已經跳到商品所在的頁面了。2. eCPM,點選率與點選價值之積是eCPM(expect CPM),它是非常重要的一個值。Return是每次eCPM的累加值。
Inverstment公式中的#x * CPX,如果是CPM就是總展示次數#x,乘上每次展示所付費用,如果是CPC就是乘上每次點選所付費用。Return公式中T表示的是點選次數。
不同的分解對應不同的市場形態。CPM市場:是固定的eCPM,由媒體和代理商結算,是由代理商自己估算展示的價值,風險是在Demand方,這種方式對媒體有利。這種方式對品牌廣告有一定優勢,因為品牌廣告受到廣告影響是一個長期的過程,很難估算ROI。美國品牌廣告一般採用CPM結算,而中國一般採用按天包段。CPC市場:它是將ROI分成點選率和點選價值,廣告系統負責估計點選率,而廣告主負責估計點選價值。廣告主只需要告訴廣告系統一次點選的價值是多少。
線上廣告系統
下圖是廣告系統的一個概念圖,請大家不要誤解成是實際的架構圖。
搭建一個廣告系統有以下幾個重要組成部分:1. 高併發的投送系統,即線上的AdServer,它通過請求中的user和context資訊來決定展示哪些ads。它的特點是高併發,要做到10ms級別的實時決策,百億次/天的廣告投放系統。2. 受眾定向平臺,它進行離線的資料探勘分析,一般要用到Hadoop。比如進行點選率預測的分析。3. 資料高速公路,它是聯絡線上與離線的部分,它比較簡單,可以用開源工具實現,它的作用是準實時地將日誌推送到其它平臺上,目的一是快速地反饋到線上系統中,二是給BI人員快速看結果。它還可能收集其它平臺的日誌,比如搜尋廣告會收集搜尋日誌。4. 流式計算平臺,它是比Hadoop快的一個準實時分析平臺,它要實現的功能:反作弊,計價,實時索引。
常用廣告系統開源工具
是否可以用開源工具快速地搭建廣告系統?可以肯定的說,基本是可以的。很多重要的模組,如上章所講的architecture裡的模組很多都可以藉助開源工具實現。
在實際的廣告系統中我們會用到很多的開源工具。下面我將分別講述幾個開源開具。基本上所有的大的廣告系統公司都要使用Hadoop平臺,除了google。Hadoop是廣告平臺中建模的基礎,Hadoop有很多子專案,有的子專案與Hadoop有密切的聯絡,有的子專案僅是在Hadoop框架體系下深挖出來的一些Idea。簡單介紹一下,Hadoop現在核心的專案只剩下來兩個,HDFS和MapReduce,以前Hadoop有很多子專案,中間兩列以前都是Hadoop的子專案,但很多現在都已經獨立出來,成為頂級專案了。Hadoop本身是一個大資料的儲存和計算的平臺。
圖中的工具可以分為兩類,一類是離線的資料處理,另一類是線上的資料處理。離線的資料處理,常用的是HBase,它是基於Hadoop的列儲存資料庫,並不是關係型資料庫,是NoSql型資料庫。和HBase功能相似的資料庫有很多,比如google的BigTable,和HBase對應的HyperTable,HyperTable是c語言寫的工具,效率比HBase高一些,還有Facebook開源的Cassandra。它們都是解決大資料上半結構化儲存的問題,在實際的系統中都可能會用到。
oozie是把Hadoop上的流程控制工具,比如我們每天的日誌處理,要等日誌收到後,進行各種分析,比如有的進行CTR預測,有的進行Audience Targeting,有的交由BI系統,它們這些分析之間可能有一些依賴關係。Hadoop提供了一個管理這些依賴的工具就是oozie,oozie可以認為是比較底層的,可以用API開發的一個framework,我個人感覺是很不好用,也沒看到有多少用人這個工具,但它在設計上比較完善。
Hadoop上有兩個很重要的指令碼語言,Pig和Hive。它們的作用有些相似,功能都是希望將Hadoop上的非結構化的資料,可以用sql語言的方式來訪問和加工。這樣在拉一些簡單的資料報表時,就不用寫MapReduce程式去得到資料,只用寫pig或hive的指令碼。Pig和Hive的區別是:如果你的資料是用分隔符分好的資料,你就可以寫Pig指令碼直接訪問了,所以用起來比較直接方便。而Hive需要預先加工,建立類似於Index的資料才可以操作。所以Pig更接近於程式設計師的習慣,Hive更適合做BI的習慣。
Mahout是一個在Hadoop上用Map/Reduce做資料探勘,機器學習的工具,我個人感覺除了幾個演算法外,其它的演算法並不太好用。但這也是機器學習演算法的本質決定的,機器學習演算法需要根據資料和實際情況做調整,加工,所以如果不瞭解內部實現,調整模型比較麻煩。
線上部分,最常用的是ZooKeeper,ZooKeeper是分散式環境下解決一致性問題的開源解決方案,它對應的是更有名的Google的Chubby。ZooKeeper和Chubby的理論基礎不完全一致。Chubby是嚴格按照Paxos演算法來實現的,Paxos是Lamport是提出的解決分散式環境下的一致性問題的一個完備的演算法,而ZooKeeper是這個演算法的簡化版,它把Paxos簡化成兩段式提交後實現的一個版本,無法在理論上證明它是正確的,但實踐中沒有問題,這個是我們在做線上服務中經常要用到的一個工具。
Avro知道的人可能並不多,因為並不常用它,常用的是Facebook的Thrift,它解決的是分散式環境裡的跨語言通訊的問題,非常好用,而Avro僅是Hadoop的作者實現的一個代替產品,Google的ProtoBuffer也是類似的工具。
S4類比於更常用的Twitter的Storm,是我們上章Architecture裡的流式計算平臺,進行日誌快速處理反饋的一個計算平臺。S4是最早Yahoo!用於搜尋廣告系統分析目的而開發的,Storm是為了滿足Twitter上一些快速的計算任務,比如快速計算Fans數,Repost數。兩種有一定不同,S4主要優化的是吞吐量,它完全不用磁碟,而Storm還要用到少量的磁碟操作,因為它要保證資料的一致性,保證每一條資料至少被處理一次,但它不保證僅被處理一次。
Chuhwa對應的是Facebook的Scribe,它是上章Architecture裡提到的Data Highway,它是分散式的日誌收集工具,一個廣告系統有很多的廣告投放引擎,這些投放引擎,Data Highway準實時地把多個伺服器的日誌準實時地都收集到一起,準實時地投到Hadoop或是Storm上,現在還有一個常用的是Flume。
Elephant-Bird是一個有意思的小工具,它是配合Pig使用的,如果我們的系統中大量使用Thrift或是ProtoBuffer,它的結構都是序列化的,二進位制的,你用Pig無法直接訪問,Twitter為了解決這個問題提供了Elephant-Bird工具,使用Elephant-Bird後,Pig就可以直接訪問序列化的資料了。
圖中有陰影的表示是我個人感覺好用的工具,但僅代表我個人觀點。在這裡我也想介紹一點我個人對開源社群的一些看法,現在開源社群已經和若干年前已經完全不同,現在不再是一個質量不能保證,內容比較蕪雜的環境了。原因是有很多大公司在不遺餘力地在支援開源專案,比較典型的是Twitter,Yahoo!,Facebook。我們認為開源工具可選的原因是這些工具是在Twitter,Facebook這種資料量上進行驗證的,而其它公司很難有真實的環境去測試這種大規模資料的,比如Facebook在測試Scribe的時候,資料達到過每秒10T,所以開源工具的質量和可靠性非常高。
跨語言服務搭建工具
在搭建一個廣告系統的時候,遇到的第一個問題可能就是多模組的語言不統一,Facebook在這方面是比較開放的,它提供了一個工具Thrift,它允許工程師各自喜歡或是習慣的語言去開發,Thift就是一個跨語言服務快速搭建的工具。它的使用方法非常簡單,第一步是用struct定義語言無關的通訊資料結構,用IDL語言描述,比如下面的KV,它有兩個欄位一個是32位int型別的key,一個是string型別的value。Thrift會將IDL語言的定義轉為你所需要的語言(比如c語言)的定義。
struct KV
{
1:optional i32 key=10;
2:optional string value=“x”
}
搭建服務也是在IDL檔案裡寫,比如KVCache是存KV pair的一個服務,它有幾個介面,set,get和delete,這些定義都是語言無關的,你根據定義實現自己的邏輯。
service KVCache
{
void set(1:i32 key, 2:string value);
string get(1:32 key); void delete(1:i32 key);
}
如果不是進行特殊的協議層優化,Thrift就可以滿足需求了。並且它能實現結構和介面的向後相容(backward compatible),型別的工具有Hadoop的Avro和google的ProtoBuffer。
合約廣告系統
直接媒體購買
合約廣告英文是Agreement-based Advertising,它是一種基於合約(Agreement)的商業模式,大家會看到它與後面的Network和Exchange有相當大的不同,我們當前最主要的是把合約廣告要解決的問題理解清楚,具體的技術可以再理解。
傳統的廣告媒體購買方式是稱之為直接媒體購買方式(Direct Media Buy),它是一種簡單的購買方式,比如一個雜誌可能有幾個廣告位,比如封二頁,封底頁,廣告主可以直接購買這些廣告位,這種方式沒有任何的技術元素。在這種方式的運作中,Supply有一個廣告排期系統,廣告排期系統比較簡單,用於對購買了的廣告位,以及相應的時間的廣告排期。不提供受眾定向,它在展示時將廣告素材直接插入頁面,這樣廣告作為靜態資源載入,它的response time就會比較短,這樣使用者看到廣告也越早,效果也就也越好。這種方式的代表公司是4A。需求方,即廣告代理商要做的是兩件事情:1. 幫助廣告商策劃和執行排期,2. 用經驗和人工滿足廣告商的質和量的需求。比如寶馬公司今年要reach多少使用者,通過什麼要的媒體reach,4A公司就會幫寶馬公司把創意做好,並分析在哪些媒體,哪些位置上投放廣告,能達到效果。因為沒有技術元素,所以都是要依賴經驗和人工的方式來完成的。但令人驚訝的是,中國很多品牌廣告仍然是以為種方式進行的。
擔保式投送與廣告投放
線上廣告的一種主流做法是擔保式投送(Guaranteed Delivery, GD),這種方法與廣告位的直接購買不同的是:從媒體角度是它賣的不是廣告位,還是廣告位上的流量。從Yahoo!來看,它的邏輯是這樣的:最早開放出一個廣告位,每隔一段時間會提高這個廣告位的售價,但漲到一定的售價後,就很難再漲了,它就將廣告位的流量拆開,比如分為男性使用者流量和女性使用者流量,比如一個廣告位整體出售可能價值1萬元,但男性使用者流量可能最高能賣7000元,女性使用者流量假設價值6000元,那麼總售價是13000,比整體出售的售價10000元的收益要高。為什麼說它還是一個合約機制呢?是因為廣告主和媒體所籤的協議中還有明確的量的需求,我們在討論品牌廣告和效果廣告時提到過,量(Quantity)和質(Quality)是廣告主的兩個根本需求,這兩個需求是固有的,只是可能側重點有時候會不同。在GD廣告中,量是在合約中明確寫明的,比如合約中如果寫了要對加州男性的使用者進行100萬次的展示,如果沒有完成這100萬次的展示,是需要廣告平臺根據所未完成的量進行較多的賠償。
GD是一個量優先於質的銷售方式,後面所講的AdNetwork和AdExchange是質優先於量的銷售方式,競價系統的方式不同於GD,比如廣告出0.5元買加州男性的使用者流量,系統只會把當你的出價在所有競爭對手中是最高的時候,才分配給你,所以沒有辦法保證提供給你的流量。GD廣告多采用千次展示付費(CPM)方式結算,多是品牌廣告主使用GD,廣告主的數量不多,Yahoo!也僅有1000~2000的廣告主,但這些廣告主的所籤的都是大訂單,它是合約廣告最主要的市場形狀。
不同於前面所提到的靜態插入頁面的方式,GD廣告是在廣告投放機(Ad server)上決策展示某個廣告。受眾定向,CTR預測,流量預測是GD廣告投放機的基礎。GD系統往往希望幫助廣告商做一些優化,比如有的廣告商買了加州男性使用者,有的廣告商買的財經型別使用者,比如一個使用者是加州男性財經使用者,這個使用者在訪問時,Ad server會決定這次展示出什麼廣告。Ad Server的準則是希望把每個使用者在滿足多個合約的時候投給合適的廣告商,以使得每個廣告商的效果最好,這裡相比AdNetwork有一個難點是GD必須滿足合約裡簽定的給廣告主的流量 。
下圖是合約廣告投放系統的主要模組,前面的圖是按競價廣告系統的圖來畫的,所以它來描述合約廣告系統是很不合適,所以大家就拿它略做參考。
它有retrieval部分,retrieval部分是各個系統都存在的。ranking的部分,它可能不是真正的ranking,有可能是做CTR預測。上圖沒有畫出來的部分是Hadoop上的forecasting,它對實際的GD系統非常重要,它會與Online Allocation模板配合。反作弊和計價這是必須有的模組。而Real Time Index概念就不同了,合約廣告系統中,它是用來對流量實時反饋。算廣告學-合約廣告系統-線上分配問題
線上分配(Online Allocation)問題
線上分配問題
前面提到過廣告是三方博弈,使用者,廣告主,媒體之間的博弈,而推薦系統是使用者與媒體的博弈。它們之間的區別其一是廣告主通媒體reach使用者是有量的需求的,推薦系統是自己把內容推給使用者,不見得有明顯的量的需求。廣告的量的需求體現在兩個方面,一種是我前面提到的GD廣告系統,有量的下限的需求,或者說有固定流量的需求,二是Non- Guaranteed delivery,即非合約方式,它有一種上限的限制,它受到廣告預算的受限。所以線上分配問題的核心是:在量的某種型別的限制下,完成對質的優化。
我下面列出的是google的做法,可以將線上分配問題看成是二部圖匹配的問題,二部圖一邊是廣告結點,另一邊是線上到達的頁面和使用者。
注意廣告中的a, u, c三個要素都在這出現了。將context和user根據audience targeting分成不同的segment,每一個segment是要分配給不同的合約,要分配多少的比例,這就是allocation的問題。廣告的分配與通用的二部圖匹配有什麼不同呢?因為廣告是一個實時系統,不能離線地計算匹配問題。實時的線上分配問題在理論界和工程界都進行了大量的探討,產生了大量的演算法,讀者沒有必要把這些演算法都理解清楚,重要的是深刻理解線上分配的問題,並結合自己的問題設計自己的演算法。
因為有量的限制,它是一個constrained optimization(受限優化)的問題,最早google提出的是AdWords Problem。
簡單解釋一下,先看目標函式,bia是把一次展示(Impression,i)分給一個(Ad, a)產生的收益(bid * ctr, b,即ecpm),xia是指一次展示(impression, i)是否分給了一個廣告(Ad, a),這個值只能為0或是1,因為一次展示只能或是分配給一個廣告,或是沒分配。sum(i, a)也就是整個系統的收益,max sum(i,a)即是優化的核心問題:如何最大化整個系統的收益。它的限制是:對每個廣告商來講,有一個budget,每個廣告商所消耗的資金應該小於他的budget,即式中Ba。
後來研究者把這個問題推廣到display problem,display problem中有很多CPM的campaign,它希望優化的是每一個CPM的效果。
效果即是它收穫到的點選量,點選量的計算方法為把所有的展示的Xia乘上點選率起來就是點選量。優化目標有兩個constrain,一個是稱之為Demand Constrain,它是指每一個廣告商來講,他需要Ca次展示,那麼媒體提供的展示數應該小於等於Ca,注意這裡是NGD的問題,廣告系統提供的展示次數可以小於需求的量,另一個Constrain是Supply Constrain,是對於任何展示,xia加起來小於等於1,可以小於是因為這次廣告也可以不分配給任何廣告,它可以交給下游的其它變現手段。上面所講的就是Allocation描述成Constrained Optimization的形式。需要注意的是大家不要糾結於到底是Display problem還是Adwords problem,因為這些問題在框架上看都是一樣的,都是linear programming的問題。
Maximally Representative allocation(MRA)是另一個準則,它反映了定向廣告的一些本質的市場需求。比如一個廣告主買了加州的使用者的流量,那個廣告主實際有一個隱含的需求,他希望得到的是按自然分佈的加州的使用者流量。即比如不能全給廣告主男性使用者的流量。如果我們僅按上面的公式進行優化,會有一定的問題,比如一個廣告主出高價買走了所有加州女性的使用者,那其它廣告主得到的流量就只能是男性使用者的流量了,雖然流量還是符合使用者的要求,這也就不符合廣告主的本源商業需求了。所以MRA會在Objective上做一些加工,使它既優化量,又在一定程度上接近流量在一定程式上接近人群的真實分佈。
拉格朗日方法
拉格朗日方式是在解受限優化中比較通用的一種方法。原問題是由下面幾個部分組成:一個目標函式f(x),一組小於0的不等式Constrain g(x),一組等於0的Constrain h(x)。(注:大於0的,可以加負號把它變成小於0的)。
這裡只對拉格朗日做簡單的介紹,先用原問題構造拉格朗日函式,拉格朗日是x, lamda, mu的函式。它是把g(x)和h(x)分別加上lamda和mu係數放到原問題後面。
拉格朗日會產生一個對偶函式,對偶函式是對L求它的下确界(或者說最小值),對x求最小值,就將x消掉。
對偶問題是在lamda和mu上求它的最小值。
這個方法的幾何意義是比較清楚的,下圖來自於wiki。
目標函式是f(x,y)的最小值,它的等高線是圖中的兩個圈f(x,y)=d1和f(x,y)=d2,Constrain是g(x,y)=c。思考一下即可以得出,要滿足g(x,y)=c的約束,f(x,y)最小值一定是在曲線與等高線相切的位置,找相切的問題就是找下确界,一般用導數等於0的方式找。
在凸優化情形下KKT條件是一定滿足的,而非凸優化也可能會滿足KKT條件。
線上隨機分配演算法
如前面所講,把原問題中的Supply Constrain和Demand Constrain用拉格朗日方法得到一個對偶問題,對每一個a產生一個Betaa,對每一個i產生一個zi,去解這樣一個對偶問題,Betaa和zi就對應Supply Constrain和Demand Constrain。
具體的演算法步驟如下:
1 對每個a, 初始化對偶變數βa為0
2 當展示i線上到達時, 將其分配給a’以最大化μia – βa
3 令xia’= 1. 如果a’已經得到Ca’次展示, 令i為使得此值最小的展示, 令xia’= 0
4 在對偶問題中, 令zi=μia’-βa’ , 並按照一定規則更新βa’ , 不同更新規則對應了不同的演算法
通過這種方式,它構造出一種線上隨機分配的演算法,對每個at初始化對偶變數Beta為0,我們可以認為Betaa的物理意義是這個廣告a已經收穫的點選量,比如要優化一個廣告商的點選數,他已經收穫的Impression裡有多少點選。當每次展示i到達時,要分配某個廣告a的物理意義是很直接的,分配的準則是這次展示i對廣告a的點選率減去它收穫的平均點選率Betaa,選擇差值最大的a,意義就是選擇這次展示會給廣告最大提升的廣告。問題的關鍵是每一步如何去更新Betaa,不同的Betaa對應了不同的線上分配演算法,這些演算法研究關注點是:線上分配的演算法與離線分配的演算法相比,線上分配的演算法不要比離線分配的演算法差的太遠,儘可能接近,離線分配演算法是指將一天的展示收集後批量分析的方式。
Betaa更新策略
策略 |
演算法 |
有效性 |
Greedy |
對每個a, βa是分配給a的前Ca個高權重展示中最低的權重, 也即a接受一個新的展示需要拋棄的權重 |
1/2 competitive |
Uniform Weighting |
對每個a, βa是分配給a的前Ca個高權重展示的權重的算術平均. 如果分配給a的展示少於Ca個, βa是這些展示總權重與Ca的比. |
1/2 competitive |
Exponential Weighting |
對每個a, βa是分配給a的前Ca個高權重展示的權重的指數加權。即:設μ1≤ μ2≤ …≤ μCa,則: |
當Ca對每個a 都充分大時為(1 ? 1/e) competitive |
請大家對上面演算法的公式不必太認真,因為這些討論主要是理論的討論。它們主要是解決對流量沒有任何先驗知識的情況下,通過一定的策略,可以達到最優的程度,但這和真實的問題差別比較大,因為實際情況中,我們一定對流量是有一定的預知能力的,比如,流量有會有多少,男性使用者比例如何等等。前面的討論是在沒有流量預測做指導的情況下的處理,而實際中是一定有流量預測做指導的。另一方面,最重要的一點,線上決策時是要避免儲存xia,前面的討論中,廣告主a需要Ca次展示,哪些展示分配給了廣告主a都要儲存下來,這樣空間複雜度很高,這種方法似乎實現不了,只是理論性的討論。
流量預測指導下的GD線上分配
下面要講的演算法是High Water Mark演算法,是Yahoo!實際系統中用的方法,它分兩個階段,離線計劃階段和線上分配階段。
離線計劃:
l 令每個人群維度組合k的剩餘supply(rk)等於預測量(sk):rk = sk。
l 對於每個合約j,按照分配優先順序對每個a:
l 解下式得到其serving rate αa:
如果無解,則令αa=1。
l 對Γ(a)中的每個k, 令rk = rk – min{rk, skαa}
線上階段:
l 對線上到來的某個impression, A = {a1, a2, …, a|A|}為按照分配優先順序排序的所有滿足要求的廣告
l 按照A中的每個廣告的serving rate隨機分配其展示機會。
這種演算法的好處是各個它是一個概率的演算法,各個ad server之間可以沒有通訊,每個廣告只需要儲存αa,而前面的演算法每一個Impression到達都要更新βa,換言之,serving是有狀態的,每次impression都要改變狀態。線上有很多ad server,要同步它們的狀態是比較麻煩的。而HWM因為它是離線分析的,所以它需要儘快更新alphaa,在幾個小時更新alphaa。HWM在演算法角度上不如前面的演算法完美,它是一個簡化的版本,但它在工程中比較實用。
Yahoo! GD廣告
Yahoo! Advertising Solutions首要執行的是GD廣告,GD市場廣告主資料為幾千,年收入為Boillion量級。GD無法分配的流量轉接到NGD(non-guaranteed delivery,即Rightmedia exchange)。
它是通過compact allocation plan完成線上決策,提供下列受眾定向:地域,人口屬性,行為(較為粗淺,常用的僅有幾十個分類)。合約式銷售中,品牌廣告主對曝光往往有獨佔要求,這與競價廣告系統完全不同,比如京東,在投品牌廣告的時候,合約裡會簽定不能出類似的電商廣告,比如蘇寧易購的廣告。
Hadoop
Hadoop 概況
Hadoop 由 Apache Software Foundation 公司於 2005 年秋天作為 Lucene的子專案 Nutch的一部分正式引入。它受到最先由 Google Lab 開發的 Map/Reduce 和 Google File System(GFS) 的啟發。Yahoo! 是最主要原始碼貢獻者, 貢獻了大約80%的程式碼,Powerset寫的HBase, Facebook 寫的Hive都是Hadoop上很重要的子專案。Hadoop的使用異常廣泛,凡是涉及大資料處理的網際網路公司幾乎都使用Hadoop,已知為接近150家的大型組織實際使用: Yahoo!, Amazon, EBay, AOL, Google, IBM, Facebook, Twitter, Baidu, Alibaba, Tencent。在這裡可以看到一些使用Hadoop的公司。
Hadoop目標可以概括為:可擴充套件性: Petabytes (1015 Bytes) 級別的資料量, 數千個節點,經濟性: 利用商品級(commodity)硬體完成海量資料儲存和計算,可靠性: 在大規模叢集上提供應用級別的可靠性。
Hadoop包含兩個部分:
1、HDFS
HDFS即Hadoop Distributed File System(Hadoop分散式檔案系統),HDFS具有高容錯性,並且可以被部署在低價的硬體裝置之上。HDFS很適合那些有大資料集的應用,並且提供了對資料讀寫的高吞吐率。HDFS是一個master/slave的結構,就通常的部署來說,在master上只執行一個Namenode,而在每一個slave上執行一個Datanode。
HDFS支援傳統的層次檔案組織結構,同現有的一些檔案系統在操作上很類似,比如你可以建立和刪除一個檔案,把一個檔案從一個目錄移到另一個目錄,重新命名等等操作。Namenode管理著整個分散式檔案系統,對檔案系統的操作(如建立、刪除檔案和資料夾)都是通過Namenode來控制。
HDFS的結構圖中可以看出,Namenode,Datanode,Client之間的通訊都是建立在TCP/IP的基礎之上的。當Client要執行一個寫入的操作的時候,命令不是馬上就傳送到Namenode,Client首先在本機上臨時資料夾中快取這些資料,當臨時資料夾中的資料塊達到了設定的Block的值(預設是64M)時,Client便會通知Namenode,Namenode便響應Client的RPC請求,將檔名插入檔案系統層次中並且在Datanode中找到一塊存放該資料的block,同時將該Datanode及對應的資料塊資訊告訴Client,Client便這些本地臨時資料夾中的資料塊寫入指定的資料節點。
HDFS採取了副本策略,其目的是為了提高系統的可靠性,可用性。HDFS的副本放置策略是三個副本,一個放在本節點上,一個放在同一機架中的另一個節點上,還有一個副本放在另一個不同的機架中的一個節點上。
2、MapReduce
有另一種分散式計算框架MPI,它在很多的問題上實現起來比Map/Reduce更方便,比如帶迭代的機器學習的模型,但是個人還是要提倡Map/Reduce。原因是Map/Reduce模型中Map之間是相互獨立的,因為相互獨立,使得系統的可靠性大大提高了。比如一個任務需要1000個結點共同完成,在MPI中需要這1000個結點協同來完成這個任務,結點間可能有通訊,資料交換。如果你有一個結點發生問題,整個任務就會失敗,當然你也可能有一些容錯的處理可以讓任務繼續算。但在海量資料情況下,比如你需要四位數的伺服器運算一個任務,而你的機器是普通的伺服器(commodity server),一個機器失敗的概率是非常高的,這也就是Map/Reduce在處理海量資料情況下更適合的原因。在後面談到LDA等Topic Model運算的時候,個人認為Map/Reduce不一定是最適合的,因為文件級的運算稱不上是海量資料,最多是大量資料運算,它的量級是百萬級左右,是否要用Map/Reduce的模型,值得探討。但是使用者級別的資料,是億的量級,用Map/Reduce比較適合。
它是用排程計算代替排程,在處理資料時,是將程式複製到目標機器上,而不是拷貝資料到目標計算機器上。
計算流程非常類似於簡單的Unix pipe,上次給出一個Unix pipe方式和Map/Reduce統計單詞的功能的比較:
Pipe: cat input | grep | sort | uniq -c > output
M/R: Input | map | shuffle & sort | reduce | output
Hadoop支援多樣的程式設計介面:
Java native map/reduce – 可以操作M/R各細節
Streaming – 利用標準輸入輸出模擬以上pipeline
Pig –只關注資料邏輯,無須考慮M/R實現
這裡提供一個示例,幫助您理解M/R。假設輸入域是 one small step for man0, one giant leap for mankind。在這個域上執行 Map 函式將得出以下的鍵/值對列表:
(one,1) (small,1) (step,1) (for,1) (man,1) (one,1) (giant,1) (leap,1) (for,1) (mankind,1)
如果對這個鍵/值對列表應用 Reduce 函式,將得到以下一組鍵/值對:
(one,2) (small,1) (step,1) (for,2) (man,1)(giant,1) (leap,1) (mankind,1)
結果是對輸入域中的單詞進行計數。
常用統計模型
後面討論的幾種方法會用到機器學習演算法,機器學習的演算法有很多分類,其中有統計機器學習演算法,統計機器學習在Hadoop上僅僅實現其邏輯是比較簡單的。常用的統計模型可以大致歸為下面兩個類別:
指數族分佈
大多工程上的實用分佈都是指數族分佈,指數族分佈的形式比較簡單:
它是引數和自變數的引數做內積,這個內積就是thetaTu(x)。指數族分佈是由最大熵的原則推匯出來的,即在最大熵的假設下,滿足一定條件的分佈可以證明出是指數族的分佈。指數族分佈函式包括:Gaussian multinomial, maximum entroy。
指數族分佈在工程中大量使用是因為它有一個比較好的性質,這個性質可以批核為最大似然(Maximum likelihook, ML)估計可以通過充分統計量(sufficient statistics)連結到資料(注:摘自《Pattern Recognition》),要解模型的引數,即對theta做最大似然估計,實際上可以用充分統計量來解最大似然估計:
充分估計量大小是與模型的引數的空間複雜度成正比,和資料沒有關係。換言之,在你的資料上計算出充分統計量後,最就可以將資料丟棄了,只用充分統計量。比如求高斯分佈的均值和方差,只需要求出樣本的與樣本平方和。
指數族的混合分佈
它不能通過計算得到充分統計量後將資料丟棄,但它在工程中使用的更多。比如有Mixture of Gaussians,Hidden Markov Model,Probability Latent Semantic Analysis(pLSI).
雖然概率模型有很多,但個人認為解決問題的思路卻很相似。即如果問題本身可以描述成一種分佈,比如某種指數族分佈,那麼就使用該種指數族分佈。比如點選率的問題,它的最值總是0或1,那麼它就可以描述成Bi-nomial分佈,再比如明顯的鐘型分佈,我們可以用高斯分佈。如果分佈本身比較複雜,無法用單一的指數族分佈描述,我們可以將多個分佈疊加來描述。基本上常用的技術就這兩種。
Map/Reduce統計學習流程
Map的過程是收集充分統計量,充分統計量的形式是u(x),它是指數族函式變換函式的均值。所以我們只需要得到u(x)的累加值,對高斯分佈來講,即得到樣本之和,和樣本平方和。Reduce即根據最大似然公式解出theta。即在在mapper中僅僅生成比較緊湊的統計量, 其大小正比於模型引數量, 與資料量無關。在圖中還有一個反饋的過程,是因為是EM演算法,EM是模擬指數族分佈解的過程,它本質上還是用u(x)解模型中的引數,但它不是充分統計量所以它解完之後還要把引數再帶回去,進行迭代。我們前面提到的所有的模型,比如高斯分佈,pLSI等等都可以用這個框架去解。
大家瞭解了這個框架後,可以先估計一個統計模型,然後先用這個框架試一下,如果它的確是這個統計模型,那麼就用這個模型解就可以了。但如果資料並不滿足服從該統計模型,那麼我們只能回退到使用梯度族的方法去解,梯度族的方法也很簡單,因為我們往往假設樣本間有獨立性,我們可以在每個樣本上計算梯度,累加後得到總體的梯度,Map就是在每個樣本上收集梯度,在Reduce上把它們加起來,然後按梯度下降,更新模型,再進行迭代。
Map/Reduce 基本統計模型訓練
Mapper template <class TModel> class CTrainMapper : public CFeature, public IDataNnalyzer{ protected: TModel * pModel; public: /// Comsume a data record \author Peng Liu virtual bool consume(const CRecord & record){ CFeature::consume(record); pModel -> accumulate(*this, 1.0f); return true; } /// Produced statistics (or modified data in case needed) \author Peng Liu virtual bool produce(CRecord & record){ static bool first = true; pModel -> produce(record); if (record.getField("STAT") != NULL){ record.rmvField("PARAM") return true; } return false; }; } |
Reducer template <class TModel> class CTrainReducer : public IDataAnalyzer{ protected: TModel * pModel; public: /// Comsume a data record \author Peng Liu virtual bool consume(const CRecord & record) {return pModel -> consume(record);} /// Try to update model after all input data finish \author Peng Liu virtual void finish() {pModel -> update();} /// Produced model \author Peng Liu virtual bool produce(CRecord & record){ pModel -> produce(record); if (record.getField("STAT") != NULL){ record.rmvField("STAT"); return true; } return false; } }; |
示例: Gaussian模型訓練
Map階段所要計算的充分統計量為:
,Reduce階段要計算的模型引數為:
void CGaussDiag::accumulate(CFeature & x, float occ) { size_t dim = getFeaDim(); assert(x.size() == dim); accumOcc(occ); for (size_t d = 0; d < dim; d ++) { stats[ d] += occ * x[d]; stats[dim + d] += occ * x[d] * x[d]; } } |
void CGaussDiag::update() { size_t dim = getFeaDim(); for (size_t d = 0; d < dim; d ++) { float X = stats[d], float X2 = stats[dim + d]; params[ d] = X / occ(); params[dim + d] = occ() / (X2 - X * X / occ()); } } |
Hadoop上的工作流引擎-oozie
先說明一下,個人感覺oozie並不好用。
Oozie的功能是連線多個Map/Reduce Job,完成複雜的資料處理的工作流引擎,它可以很方便定製資料流之間的依賴關係,一個Job可以依賴三種條件:資料,時間,其它Job。比如它可以指定一個Job在某些資料到達後開始,可以指定固定時間Job開始執行,還可以指定在其它Job執行完成後開始。
前面說它不好用是因為它的定義很麻煩,它使用hPDL(一種XML流程語言)來定義DAG(有向無環圖)工作流:
<start to='ingestor'/>
<action name='ingestor'> … <ok to=“proc"/> <error to="fail"/> </action>
<fork name=“proc">
<path start=“proc1"/> <path start=" proc2"/> </fork>
<action name=‘proc1’> … <ok to="completed"/> <error to="fail"/> </action>
<action name='proc2'> … <ok to="completed"/> <error to="fail"/> </action>
<join name="completed" to="end"/>
<kill name="fail"> <message>Java failed, error message… </kill>
<end name='end'/>
並且oozie目前不支援Iteration,因為它是DAG。如果大家要用工作流引擎,可以推薦另一個工具是Linkin開發的Azkaban,它其實和Hadoop沒什麼關係,它是處理Linux環境下的Job的關係,所以它非常輕量級,也有一個比較方便的圖形化介面去檢視。Oozie是深度的與Hadoop結合,在通過API訪問上,可能是有優勢的,但簡單的使用上又顯得太重了。
介紹工作流引擎的原因是它在廣告系統中是很重要的,因為廣告系統的Hadoop上運行了很多工,比如Audience Targeting,Click Model,Forecasting(流量預測),這些任務需要一個完善的排程機制,否則在執行環境中會非常混亂,資料的失敗,Job的失敗很難處理。工作流引擎會使整個系統更容易控制。