天池大赛, Storm
http://antkillerfarm.github.io
簡介
天池大數據競賽是由阿里巴巴集團主辦,面向全球科研工作者的高端算法競賽。官網:
https://tianchi.shuju.aliyun.com/
和它類似的比賽,最著名的當屬國外的kaggle大賽。其官網:
https://www.kaggle.com/
但是,kaggle官網在國外,國內無論注冊還是登錄,都比較麻煩。
還有KDD挑戰賽:
http://www.kdd.org/kdd-cup
這是ACM主辦的年度數據競賽。
我之前雖然參加了其中的“廣東航空大數據創新大賽——機場客流量的時空分布預測”(2016.9~2016.11),然而由于首次參賽,各項準備和工具都不純熟,仰仗隊友給力,最終獲得了第318名。
注意:手機登錄天池網站的時候,瀏覽器必須選擇手機模式,否則無論賬號密碼正確與否,都無法正常登錄。
口碑商家客流量預測
概況
本次“口碑商家客流量預測”大賽由螞蟻金融服務集團,IJCAI 2017,阿里云主辦。
IJCAI是International Joint Conferences on Artificial Intelligence Organization的縮寫,屬于人工智能領域頂級會議之一。
比賽的內容和數據參見:
https://tianchi.shuju.aliyun.com/competition/introduction.htm?spm=5176.100066.333.4.0eh92S&raceId=231591
數據分析工具
主辦方提供了大約2G的原始數據。這個數據量采用Hadoop+Spark無疑是大才小用了。但是,數據庫尤其是SQL語言,在數據的整理和初步分析中的地位是無可替代的。因此,這里我選擇了MySql數據庫。
機器學習庫的語言有兩個選擇:R或python。考慮到以后研究tensorflow的需要,我選擇了python語言,這個相對來說更通用、更熟悉一些。
數據的預處理
將官方提供的csv數據導入數據庫。這里全部使用SQL語言。
1.根據官方提供的數據格式建立table。
2.使用load語句導入csv文件。
數據的初步分析
這里首先對user_pay和user_view兩張表進行粗粒度的統計。比如,統計兩表中最熱的10家店鋪的類型。
這里發現一個有趣的事實:用戶瀏覽數量最多的是火鍋店,前10家中占到了9家,而用戶購買最多的卻是快餐店和便利店。
這實際上暗合《機器學習(十四)》中提到的顯式反饋和隱式反饋的區別。
因為隱式反饋的數據有效性(這里指單位數據中包含的有效信息的數量,也可稱作信息豐度)不如顯式反饋,所以通常需要有多出1到2個數量級的隱式反饋數據,才能得到足夠的信息以輔助預測顯式反饋。
而官方的數據正好相反,隱式反饋數據的數量只有顯式反饋的十分之一,且并不包含待預測時間段的數據。因此,user_view實際上是沒什么用的數據。
select count(distinct user_id) from user_pay;
select count(*) from user_pay;
其次,對用戶行為進行分析。誠如論壇某網友指出的,這批數據平均下來一個用戶還不到4條交易記錄(19583949個用戶,69674110條交易記錄),這都能找出規律,那就不是人而是神了。
針對這樣的分析,為了便于計算,我們新建了shopcount表用于存放店鋪的客流數據,而忽略客流本身的其他信息(這里主要是user_id)。
新建shopcount表之后,計算效率得到極大的提升,原來從user_pay中查詢一個店鋪的客流信息需要2分鐘左右的時間,而現在不到1秒鐘。
數據建模初步
上圖是其中一家店鋪的客流數據。從直觀上來看,這樣的波形十分類似信號處理領域中的:一個低頻信號疊加一個高頻信號。
因此,該數據的模型可定義為:
f=flow+fhigh(1)
其中,fhigh表示高頻信號。通過測量兩個波峰的間隔,不出意料的,這個時間間隔是一周。這與人們的日常常識也是吻合的。
flow表示低頻信號,也就是每周平均客流量的長期變化函數。
數據清洗
對于圖中數據波形不規則的地方,稍加留意就可以發現:不規則的數據主要出現在節日,尤其是春節、五一和國慶。而待預測的時間段不在重大節日期間。因此,需要將上述時段的數據排除在統計之外。
數據建模進階
公式1需要進一步細化為可執行的算法。考慮到一周的客流數據是離散數據,因此fhigh擬合的一種最簡單的方法就是:
1.統計每周一的數據,計算周一的均值D1。
2.按照第1步的方法,統計周二、周三、……、周日的均值D2,…,D7。
3.令
D=D1+?+D77
則fhigh的離散采樣為:
{WD1D,…,WD7D}(2)
其中W表示基數,它的值由flow來確定。
我們可以從另一個角度來觀察公式2。如果把客流分為固定客流和變化客流的話,則客流模型也可寫作:
f=ffix+falter
如果將周最小客流值Dmin定義為ffix的值的話(假設1),可以觀察到DminD的值,并不隨D的大小變化而有顯著改變。也就是說平均客流的一定比例轉化為了固定客流。假定這個轉化比例不變(假設2),則可推出公式2的結論。
flow(也就是公式2中的W)就沒有那么規律了,這里我做了如下嘗試:
Method 1
令W=W(?1)=W(0)=W(1)。待預測時間段為2周,我們將其中的第1周的客流均值記作W(0),第2周的記作W(1)。其他的可以此類推。
這種方法的Loss為0.085647。
Method 2
Method 1相當于是flow在W(?1)處進行常數展開。為了更精確的描述函數,我們亦可考慮進行一次項展開。即:
W(0)=W(?1)+W′(?1),W(1)=W(0)+W′(?1)
W′(?1)原則上可以用W(?1)?W(?2)獲得,但是由于數據的短期波動性較大,這樣求得的斜率穩定性很差,不適合用于預測。
可以對W使用FIR濾波和IIR濾波,然后用濾波值計算,以獲得穩定的斜率。
Method 2的最終結果并不理想,無論是沿著梯度方向,還是相反方向都得不到更好的結果。但是針對W的FIR濾波和IIR濾波取得了較好的結果。
最終Loss為0.08500277。
天氣因素
論壇上有網友提供了相關的天氣數據。經過我的分析,惡劣天氣的確會減少客流量,這也與常識相符。
然而,待預測時段(2016.11.1~2016.11.14)正好是我國氣候最好的時段,北方秋高氣爽,但又不太冷,南方的雨季和臺風季也基本結束。因此,天氣因素注定不會有多少發揮的空間。
模型的繼續改進
Method 2中的濾波,主要針對的是某些店鋪在預測時段之前流量的大起大落。在取得較好的結果之后,促使我思考另一個問題。
我在分析之初就發現,使用10月31日的值作為W值的效果,沒有使用之前一周的均值作為W的效果好。那么是否使用更長時間的均值,效果會更好呢?
首先,使用IIR均值或者超過3周以上的FIR均值的情況可以排除,歷史效應畢竟是歷史效應,不可能一年前的數據和最近的數據影響力相等。
經過實踐,我發現:
W(0)=W(?1)+W(?2)+W(?3)22
的效果要優于三周均值和一周均值,這即體現了歷史數據的意義,也兼顧了近期數據的重要程度。
修改之后,Loss為0.08331434。
雙十一效應
待預測時段雖然沒有國家法定節日,但有雙十一節,這個在年輕人群中有一定的知名度。而年輕人群也是使用口碑的熱點人群。因此,需要對11.11的客流數據,進行一定程度的加成處理。
加成5%的結果的Loss為0.08298507。
加成15%的結果的Loss為0.08309067。
最終,加成9%的結果的Loss為0.08289156。
對于fhigh改進的思路
雙十一效應的成功,使我打算嘗試進一步改進fhigh。
嘗試使用最近3周的數據,估算D值。結果Loss為0.09959968。
當然這個結果完全在我意料之中,一般來說,D值還是IIR濾波值比較準。
刷榜的終結
采用類似雙十一效應的刷榜方式,實際上還可以進一步提高結果,最終我的成績定格在0.8137。但是,這種方式顯然不是我想要的,我不想再這樣在沒有理論依據的情況下,單純用湊數字的方式提高成績,于是我的參賽之旅也就終結于此了(2.21)。況且這種方式也有其極限,我估計其極限最多也就是0.809。想獲得更好的成績,一定要有其他更好的思路才行。
比賽結果及代碼
最終結果:第1賽季排名:91 第2賽季排名:166
源代碼:
https://github.com/antkillerfarm/antkillerfarm_crazy/blob/master/python/ml/tc/tc0215.py
創建數據庫的SQL語句:
https://github.com/antkillerfarm/antkillerfarm_crazy/blob/master/helloworld/mysql/tc.sql
導入數據的SQL語句:
https://github.com/antkillerfarm/antkillerfarm_crazy/blob/master/helloworld/mysql/import.sql
其他相關中間結果表的SQL語句:
https://github.com/antkillerfarm/antkillerfarm_crazy/blob/master/helloworld/mysql/tc_view.sql
Storm
Storm是一個大數據領域的實時計算框架。
官網:
http://storm.apache.org/
教程:
http://storm.apache.org/releases/current/Tutorial.html
http://blog.csdn.net/rzhzhz/article/details/8788137
http://ifeve.com/getting-started-with-stom-index/
http://blog.csdn.net/NB_vol_1/article/details/46287077
http://www.open-open.com/lib/view/open1374979211233.html
示例
這里使用源代碼中自帶的示例。
1.下載源代碼。
2.mvn clean install -DskipTests=true
3.進入examples/storm-starter目錄:
mvn compile exec:java -Dstorm.topology=org.apache.storm.starter.ExclamationTopology
Trident
Trident是在storm基礎上,一個以realtime計算為目標的高度抽象。它在提供處理大吞吐量數據能力的同時,也提供了低延時分布式查詢和有狀態流式處理的能力。
教程:
http://storm.apache.org/releases/current/Trident-tutorial.html
http://blog.csdn.net/derekjiang/article/details/9126185
Storm vs Spark
http://blog.csdn.net/iefreer/article/details/32715153
問題匯總
http://blog.sina.com.cn/s/blog_8c243ea30101k0k1.html
集群部署
Storm的本地模式,無須hadoop生態圈軟件的支持,自己就能運行。但它的集群部署依賴Zookeeper和YARN。
1.配置YARN和Zookeeper,并啟動相關服務進程。
2.配置Storm
https://storm.apache.org/releases/current/Setting-up-a-Storm-cluster.html
3.啟動Nimbus和Supervisor
Nimbus和Supervisor都是Storm服務進程,前者運行在Master上,而后者運行在Node上。這里的Master和Node,可以和Zookeeper或YARN設置的不同。
Nimbus的作用是將運行的jar分發到各Node去執行。
雖然bin/storm nimbus可以啟動nimbus,然而這種方法啟動的是前臺進程,一旦退出終端,進程就會被殺死。可用如下方法解決之:
start-stop-daemon --start --background --exec /root/apache-storm-1.0.2/bin/storm nimbus
總結
以上是生活随笔為你收集整理的天池大赛, Storm的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Transifex与GTK文档翻译, L
- 下一篇: Kettle, Solr