當前位置:
首頁 > 新聞 > Kaggle 商品定價預測最優方案出爐,如何從兩千多支隊伍中脫穎而出?

Kaggle 商品定價預測最優方案出爐,如何從兩千多支隊伍中脫穎而出?

雷鋒網 AI 研習社按:為了自動為商品定價,日本著名的社區電子商務服務提供商 Mercari 在 Kaggle 上舉辦了「Mercari Price Suggestion Challenge」大賽,旨在利用商品的名稱、類型、描述等文本信息為賣家提供定價建議。

Kaggle 商品定價預測最優方案出爐,如何從兩千多支隊伍中脫穎而出?

上面的兩件毛衣,一件價值 335 美元,另一件價值 9.99 美元。對於我們人類來說,想要通過上面的描述為毛衣定價簡直可以說是「不可能完成的任務」!有了自然語言處理這個利器,它是否能幫助我們解決這個問題呢?該比賽圍繞這個問題展開。雷鋒網將比賽具體細節以及冠軍方案編譯整理如下:

比賽簡介

本比賽分為兩個階段,在這個比賽的第一階段中,選手被要求提交代碼解決這個問題,並且代碼需要在 Kaggle 比賽的伺服器上用一個小時以內的時間生成答案。而在下一階段中,選手被要求不能修改第一階段使用過的代碼。更為嚴苛的是,在這個階段,數據規模增長到了第一階段的 5 倍!這對項目代碼的魯棒性提出了很高的要求。本比賽採用均方根誤差(RMSLE)作為評價選手提交的模型性能的標準,具體來說,均方根誤差可以由如下圖所示的方法計算得到:

其中,? 是 RMSLE 的值,n 是在公開或者私密的數據集中觀察的樣本點的個數,pi 是我們預測的商品價格,ai 是商品實際的價格,log(x) 是 x 的自然對數。

數據集

本比賽使用的數據由 train.tsv 和 test.tsv 兩個數據文件組成,數據文件中的內容由 tab 符分隔開來,每個文件包含以下欄位:

  • train_id 和 test_id:條目的編號

  • name:商品名稱

  • item_condition_id:賣家提供的商品的狀態

  • category_name:商品的類別

  • brand-name:品牌名稱

  • price:商品曾經的售價,這也是我們的預測目標

  • shipping:運費

  • item_description :對商品的文字描述

本次比賽獎池巨大,主辦方一共提供了 10 萬美金的獎金,吸引到 2384 支參賽隊伍。Pawel 和 Konstantin 兩位選手在分別提出了性能十分優秀的模型後,決定雙劍合璧,取長補短。他們合併而成的隊伍獲得了本次比賽的大獎。下面讓我們看看他們拔得頭籌的方案吧!

Pawel 在組隊之前的解決方案(RMSLE 大約為 0.3950)

在與 Konstantin 組隊之前,Pawel 曾經設計了一個十分複雜的模型,該模型由三部分組成:

1. 針對每個類別的商品建立一個模型:Pawel 首先針對每個類別建立了 3 級的嶺回歸模型。這個 3 級模型可以看作基數 2 加上如「項目_條件_編號」這樣形式的偏移。這個模型訓練起來十分快,在 20 分鐘內取得了 0.4050 的預測準確率。

2. 殘差模型 MLP:在 1 中提到的模型的基礎上,Pawel 接著在稀疏的輸入數據上訓練了一個神經網路模型。這個網路設計損失函數的總體目標是讓預測值和真實數據之間的差別盡量小。這個模型的設計方法可以被視作強分類器的集成學習。

3. 殘差模型 LGBM 模型:想法和 2 一樣。

儘管為每個類別建立一個模型的想法似乎很棒,但是實際上並非如此!訓練這樣一個模型看起來很 cool,但是它會使每個模型的性能不能被充分發揮出來。我們可以這樣想,神經網路是不能被訓練去理解類別、描述、標籤之間的交互信息的,這是一個錯誤的假設。我們的實驗說明了,一個調試好的神經網路能夠學習到它想要學到的知識。

Konstantin 在組隊之前的解決方案(RMSLE 大約為0.3920)

在合併之前他建立了兩個模型:

1. 利用 TensorFlow 實現了一個稀疏的 MLP 模型。這個模型並沒有非常複雜的數據特徵,與公開的方案相比,僅僅改變了特徵的數量,並且使用嶺回歸的 eli5 解釋機製做了單詞化切片的處理。這樣依次訓練了 3 個模型。

2. 在 Keras 框架下實現了一維卷積組成的卷積神經網路,這與在其它的很多方案中的情況相類似。模型本身的性能並不是非常優秀,但是它和 MLP 模型差別十分大,所以這個模型在集成學習框架中起到很好的效果。

融合

在組隊的時候,Konstantin 排名第一,Pawel 排名第二。為了能夠很好地繼承各自模型的優點,並不能盲目地將兩個解決方案拼湊起來,需要融合兩個人的思路,創造出新的解決方案。

要讓這個新的模型在滿足各種約束的條件下正常工作是一件富有挑戰性的事。對他們來說,訓練時間並不是一個大麻煩,他們將更多的精力放在了籌集資金上,來購買硬體設備以便同時訓練 4 個神經網路。

他們花了 2 個星期做出了一個兩人都贊成的解決方案。結果表明,兩個不同的預處理方案產生了許多解決方案需要的變數,這使得很容易地將準確率提升了百分之 1,這是一個很大的突破。

最後,他們一共使用了 3 個數據集,並且在每個數據集上建立了 4 個模型。他們嘗試著通過以下方式建立更多樣化的模型:

1. 不同的分詞方式,帶詞幹的和不帶詞幹的

2. Countvectorizer 向量化技術/Tfidfvectorizer 向量化技術

構建系統

如果不將解決方案分解到各個模塊中,想要管理整個項目十分困難。他們針對自己的代碼創造構造系統。最終,他們使用這個系統寫出了解決方案的 python 程序包。代碼有些奇怪,偽代碼看起來是這樣的:


ENCODED_FILES = {some base64 encoded characters}

DECODE_FILES

INSTALL THE MERCARI PACKAGE

RUN MAIN FUNCTIONS

值得注意的是,按順序執行這 3 個程序十分重要。這是因為 python 很有可能在執行了某些操作之後並不會清理內存,尤其是在數據預處理過程中。

數據預處理

有一些簡單的數據處理技巧十分有效:

1. 基於名字字元的 N 元模型:儘管不能完全明白其背後的技術原理,但是使用基於項目名稱字元串的 N 元模型(N-gram)能夠有效地提升預測的 RMSLE。可能是因為這樣得到了相對更稠密的數據特徵。

2. 詞根化演算法:使用了標準的 PorterStemmer 分詞演算法。

3. 數值向量化:諸如「10 data 5 scientists」這樣的數據描述是一個重要的錯誤來源,這樣的數據描述往往被直觀地向量化表示為(data=10, scientists=5)。他們僅僅在一個數據集中應用了這種向量化方法,並且使總體的 RMSLE 得分提升了 0.001。但他們沒有更多的時間去驗證這個想法。

4. 文本鏈接技術:為了減小直接將文本鏈接起來後的文本域的數據維度,他們測試了改變名字(name)、項目描述(item_description)、種類(category)、品牌(barnd)等參數之後的模型效果。通過這個步驟,RMSLE 得分提升了 0.37xx。

除此之外,一些自認為很棒的特徵工程技術並不十分奏效。在這裡,簡單舉幾個例子:

1. 抽取諸如「for [Name]」這樣的數據特徵:他們注意到,很多數據項目僅僅出現在某些人的數據中。他們不能確定這究竟意味著什麼,但它似乎很重要,可以創建一個特徵類別。他們利用 nltk 工具創建了一個品名列表,並且通過 AhoCorasick 演算法搜索相似的字元串。

2. 他們注意到,在商品的描述中有一些由於換行引起的問題。只要有人在描述中使用換行符,就會連接這樣的單詞。

3. 拼寫檢查

使用神經網路做特徵提取就好比「好吧!我猜我能在這裡用你做特徵工程,你能提升 0.0003 的 RMSLE 得分」(意在說明神經網路是一個黑盒技術)

模型

Pawel 發現,當建立了一個經過精心調試之後的稀疏多層感知機(MLP)模型後,如果在不同的數據集上訓練相同的模型會比在相同的數據集上訓練不同的模型整體上得到更加多樣化的結果。因此,他們決定堅持做出一個「精品」模型,這也確實簡化了解決方案。

最基本的模型是一個有著稀疏輸入的多層前饋神經網路,這個模型貌似平凡無奇,但令人意外的是,它確實很有效。他們認為,這個模型之所以性能優秀的一個原因可能是,它比其它的方法都要更高效。具體而言,數據集十分大的,所以模型必須能夠處理大量的數據,並且能夠捕獲特徵之間的相互作用。在相同時間內,一個一維卷積神經網路只能訓練 4 個嵌入了 32 個節點的計算核心,他們的模型卻能夠訓練 4 個有 256 個隱含節點的多層感知機模型。

細心學習進度調優是十分關鍵的:最重要的是,他們在每一輪迭代之後都將批處理數據的規模擴大到之前的兩倍。這使得他們的模型在每一輪迭代之後都能夠被訓練地更快,這也讓模型最終獲得了更好的性能。除了讓批處理數據的規模加倍,他們還降低了學習率。

之前所做的這些工作讓他們的模型在第二次迭代之後,在模型驗證過程中獲得了最高的 RMSLE 分數。之後,在第三次迭代之後,就出現了過擬合的情況。這樣的情況讓模型的整體性能更好。

和之前的方案(https://www.kaggle.com/lopuhin/mercari-golf-0-3875-cv-in-75-loc-1900-s)相比,他們在以下的幾個方面進行了調整:

1. 使用了模型的變體:第一個是通過 Huber loss 作為損失函數訓練的,這樣做可以使得模型對於數據中的離群點不那麼敏感;另外一個是把這個任務當作了一個分類問題而非回歸問題。

對於這個回歸問題,他們將所有的價格分配到 64 個區間內,並且為最終的分類預測制訂了一個靈活的目標:他們首先計算了每個區間的中心之間的 L2 範數,之後對其應用 softmax 函數,這個 softmax 函數帶有更高的 softmax 溫度參數 T(溫度參數 T 是一個超參數)。當 T 很大時,所有的激活值對應的激活概率趨近於相同(激活概率差異性較小),而當 T 很低時,不同的激活值對應的激活概率差異也就越大。由於過擬合得到了緩解,這個分類模型本身能夠獲得更高的 RMSLE 分數,也使得預測的多樣性更強。

2. 在每個數據集上,對於 4 個模型中的 2 個,他們在訓練和預測的過程中將所有的非零值設置為了 1,從而對於輸入數據進行了二值化處理(離散化成 0 和 1)。這有點類似於得到一個通過二值的 CountVectorizer 技術產生的額外的數據集,而不是用 TFIDF 技術產生的數據大小沒有約束的數據集。這個想法很贊!他們也試著通過其它非零的閾值進行二值化處理,但是這些做法都沒有帶來很大的性能提升。

3. 他們僅僅在第一層中使用了 L2 正則化項,這也將模型性能提升了一點點。他們發現,在 TensorFlow 環境下編寫的模型使用 PRELU 作為激勵函數時,會比使用 RELU 激勵函數時取得更好的效果。

這個比賽除了對模型的理論構建有很高的要求,對於數據集的大小也有著非常嚴格的限制,讓訓練過程變得更加高效十分重要。擴大第一個隱藏層的節點數目很有可能提升預測的準確率得分。除了對數據集進行預處理,他們還訓練了 12 個模型。最終,他們成功地在 200K 的數據上訓練了 12 個有著 256 個隱藏節點的模型。以下是具體的實施方案:

1. TensorFlow 可以使用多個計算核心,但這並不是讓模型性能線性增長,特別是對於稀疏的數據作為輸入的模型。因此更好的解決方案是,每個模型使用一個計算核心,並行訓練模型。具體而言,他們通過「OMP_NUM_THREADS=1」指令將 TensorFlow 環境下每個計算核心上的線程數設置為 1。接著,他們使用 TensorFlow 的配置變數,通過非正式的「use_per_session_treads=1」指令,允許 TensorFlow 使用多個核心線程。這就意味著不需要啟動多個進程,還能使用更少的內存。

2. 結果表明 MXNet 框架能夠在 CPU 上實現一個更高效的稀疏 MLP 模型。這是因為 MXNet 支持稀疏更新(當然,TensorFlow 也許支持,但是他們在這裡沒有使用 TensorFlow 的這個功能)。Pawel 寫了一個 MXNet 版本,並且將速度提升了兩倍。之後他們添加了 TensorFlow 模型提取出的所有特徵,使它性能更好。一個值得注意的問題是,MXNet 的執行引擎不是線程安全的,如果你嘗試使用線程來做並行計算,最終只能得到一個可用的計算核心,或者引發段錯誤(Segfault)。因此,他們不得不轉而使用多進程計算。由於 MXNet 生成了大量的副本,並且使用了太多內存,他們也需要編寫自己的數據生成器。我們還有一個版本,將數據放入共享內存中,但磁碟空間不足,所以也不得不放棄這個版本。

總的來說,MXNet 解決方案的速度更快,在不犧牲速度的條件下,允許使用較小的初始批處理數據規模。但使用了更大的內存,因此看起來不那麼可靠。在最後,他們使用同樣的數據集提交了兩個版本。一個使用 MXNet(0.37758 private LB / 0.37665 public),另一個使用 TensorFlow(0.38006 private / 0.37920 public)。

最後,他們獲得了 12 組預測結果,需要將其融合。平均之後效果會很好,調整混合權重更好。因此,他們使用了 1% 的數據集進行驗證(其中 5% 來自本地),並且使用 Lasso 模型調整權重。Lasso 模型使用了 L1 正則化。

除此之外,他們將一些效果較差的模型列舉如下:

1. 混合專家模型(MoE):這裡有一篇很棒的論文(https://arxiv.org/abs/1701.06538),這篇文章描述在使用相同的計算資源時,如何訓練一個模型得到更大的容量。但是很不幸,最終結果表明,TensorFlow 對一些操作缺乏稀疏支持。

2. 他們嘗試加入一些外部的混合模型,例如:在同樣的架構中將 FM 和 MLP 模型合併,並且在 MLP 的輸出中添加一個線性回歸的 skip 層。這些最終都會收斂到一個簡單的 MLP 模型。

只有使用更大的 MLP 網路才能提高模型性能,但是由於比賽限制,顯然不能這麼做。只有添加更多的數據/特性時,模型才會得到改進。

比賽地址:https://www.kaggle.com/c/mercari-price-suggestion-challenge

方案地址:https://www.kaggle.com/c/mercari-price-suggestion-challenge/discussion/50256

雷鋒網編譯整理。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 雷鋒網 的精彩文章:

從被拒絕100次到被5.5億美元收購,AI公司Kensho如何蛻變華爾街之狼?
CES發布會後,拜騰CEO畢福康詳解超級大屏、電池方案與自動駕駛進展 |CES 2018

TAG:雷鋒網 |