歷時兩個月的比賽終於結束了,最終以第32名的成績告終,在此和大家分享下解決問題的思路。
從初賽到複賽,有走過彎路,也有突然靈光一現的時刻。一路走來,對數據各種把玩,分析了各種可能的情況,儘可能得挖掘數據中潛在的信息來構建更爲準確的模型。
本文無法涵蓋所有的分析歷程,但是會涉及解決問題的主要思路以及部分代碼,詳細的代碼見Github頁面
競賽詳細信息參見比賽官方網站
1. 問題描述
機場擁有巨大的旅客吞吐量,與巨大的人員流動相對應的則是巨大的服務壓力。安防、安檢、突發事件應急、值機、行李追蹤等機場服務都希望能夠預測未來的旅客吞吐量,並據此提前調配人力物力,更好的爲旅客服務。本次大賽以廣州白雲機場真實的客流數據爲基礎,每天數萬離港旅客在機場留下百萬級的數據記錄。希望參賽隊伍通過數據算法來構建客流量預測模型。
2. 數據概覽
提供的數據:
Table |
---|
連接WIFI AP (Access Point)的人數表 airport_gz_wifi_ap |
安檢旅客過關人數表 airport_gz_security_check |
旅客進入-離開機場的行程表 airport_gz_departure |
航班排班表airport_gz_flights [比賽一段時間後才提供] |
機場登機口區域表 airport_gz_gates [比賽一段時間後才提供] |
機場WIFI接入點座標表 airport_gz_wifi_coor [複賽提供的] |
例如airport_gz_wifi_ap 表數據概覽:
wifi_ap_tag | passenger_count | time_stamp |
---|---|---|
E1-1A-1 | 15 | 2016-09-10-18-55-04 |
E1-1A-2 | 15 | 2016-09-10-18-55-04 |
E1-1A-3 | 38 | 2016-09-10-18-55-04 |
E1-1A-4 | 19 | 2016-09-10-18-55-04 |
提交表格案例:
passenger_count | wifi_ap_tag | slice10min |
---|---|---|
1.1 | E1-1A-1 | 2016-09-14-15-0 |
2.2 | E1-1A-1 | 2016-09-14-15-1 |
3.3 | E1-1A-1 | 2016-09-14-15-2 |
4.4 | E1-1A-1 | 2016-09-14-15-3 |
5.5 | E1-1A-1 | 2016-09-14-15-4 |
3. 初賽
3.1初賽數據描述
初賽提供了2016-10-09至2016-09-25的數據
3.2初賽問題描述
選手需要預測未來三小時(9月25日15:00:00到18:00)的時間窗口裏,機場內每個WIFI AP點每10分鐘內的平均設備連接數量
3.3初賽解決方案
簡要概括:均值加趨勢
數據預處理:
提供的表格中時間數據都是精確到秒,而所提交的結果要求是每10分鐘的平均情況,所以我們首先需要將數據按照每十分鐘的間隔彙總起來(詳細代碼見Github)
此處提供兩種方案:
以airport_gz_wifi_ap表爲例截取time_stamp的部分字符串,然後按照截取的time_stamp和wifi_ap_tag進行aggregate
t = t0[:15] # 例如將t0 = 2016-09-10-18-55-04截取爲t = 2016-09-10-18-5
將數據按照時間排序,然後抽出每十分鐘的數據進行處理後整合,這個方式可能會比較麻煩,但是這個方式有他的優勢,我們只需調整一個參數,便能讓數據按照任意的時間間隔進行統計,便於以後複用函數
此處附加Python處理時間格式的一些函數
我們可以直接使用pandas中的參數解析時間數據
# Normal
df =pd.read_csv(path, parse_dates=['column name'])
# Special
dateparse = lambdax: pd.datetime.strptime(x, '%Y-%m-%d %H:%M:%S')
df =pd.read_csv(path, parse_dates=['column name'], date_parser=dateparse)
當然也可以自己寫函數處理
import pandas as pd
def ReturnTimeElement(Date):
return [int(t) for t in Date.split('-')]
def TransToTime(TimeElement):
return pd.datetime(*(TimeElement))
def GetTime(Date):
TimeElement = ReturnTimeElement(Date)
Time = TransToTime(TimeElement)
return Time
T = '2016-10-19-9-47-00'
>>> GetTime(T)
datetime.datetime(2016, 10, 19, 9, 47)
處理後可以得到如下數據,命名爲WIFITAPTag_Mean_All
PassengerCountMean | Time | WIFIAPTag |
---|---|---|
16.2 | 2016/9/10 19:00 | E1-1A-1 |
19.7 | 2016/9/10 19:10 | E1-1A-1 |
19.7 | 2016/9/10 19:20 | E1-1A-1 |
20.5 | 2016/9/10 19:30 | E1-1A-1 |
20.5 | 2016/9/10 19:40 | E1-1A-1 |
24.8 | 2016/9/10 19:50 | E1-1A-1 |
問題分析:
對於這個預測問題有以下關鍵兩點:
- 機場每天的排班表基本穩定,用戶在機場內的行走模式也基本穩定
- 時間序列具有一定程度的連續性,下午三點至六點的情況會一定程度延續此前幾小時的情況
基於以上兩點想法,就得到了兩個基本模型:均值模型
和時間序列模型
比賽初期只提供了前三個表格,所以開始就注重分析了這幾個表格,例如從WIFIAPTag中可以提取出大概的位置信息和樓層信息,分組統計不同區域的WIFIAP是否有接近的模式,同時也可從安檢和出發表格中尋找一定的關聯等等。
但是經過分析發現,airport_gz_security_check及airport_gz_departure的數據雖然和airport_gz_wifi_ap的數據有一定的關聯,但是其本身存在較大的隨機因素,用隨機預測隨機存在太大的變數,不如只使用airport_gz_wifi_ap中的數據進行更穩定的預測(當然肯定也有隊伍能很好得從airport_gz_security_check及airport_gz_departure中提出很很棒的特徵)。後期提供的幾個表格由於數據質量問題,經分析後發現貢獻不是特別大,故也沒有進一步利用。
因而之後要說的均值模型
和時間序列模型
都基於WIFITAPTag_Mean_All表格的數據,並且是以WIFIAP爲對象, 每一個分開預測。
數據探索:
接下來讓我們對數據有一個大概的瞭解
def GetTimeSeries(WIFIAPTag):
'''
Get WIFIAPTag 's Time Series
'''
Tag_Data = WIFITAPTag_Mean_All[WIFITAPTag_Mean_All.WIFIAPTag == WIFIAPTag]
MinTime = min(Tag_Data.Time)
MaxTime = max(Tag_Data.Time)
DataTimeRange = pd.date_range(start = MinTime , end = MaxTime , freq = '10Min')
ts_0 = pd.Series([0]*len(DataTimeRange),index=DataTimeRange)
ts =pd.Series(Tag_Data.PassengerCountMean.values , index = Tag_Data.Time)
TS = ts_0+ts
TS = TS.fillna(0)
return TS
以上函數能提取出特定WIFIAP的時間序列數據,及每10分鐘的平均連接數
ts = GetTimeSeries('E1-1A-1<E1-1-01>')
ts
Out[7]:
2016-09-10 19:00:00 16.2
2016-09-10 19:10:00 19.7
2016-09-10 19:20:00 19.7
...
2016-09-25 14:30:00 11.1
2016-09-25 14:40:00 8.0
2016-09-25 14:50:00 10.9
dtype: float64
繪圖結果如下,可以看出每天還是有一定的規律,但是有異常的日子
ts.plot() |
---|
由於我們需要預測的是特定某幾個小時的數據,所以需要如下函數提取部分的時間序列
def Get_Part_of_TimeSeries(TS,TimeRange):
'''
Input [start_time,end_time]
'''
return TS[TimeRange[0]:TimeRange[1]]
均值模型
需要考慮之前每一天同一時間段的情況,所以有如下函數
def GenerateTs_0(Time):
timerange = pd.date_range(start = Time[0],end = Time[1] ,freq = '10Min')
ts = pd.Series(np.zeros(len(timerange)),index = timerange)
return ts
def TsList(WIFIAPTag,Time):
ts_list=[]
ts = GetTimeSeries(WIFIAPTag)
for i in range(1,15):
TimeRange = Time - timedelta(i)
ts_part = Get_Part_of_TimeSeries(ts,TimeRange)
if len(ts_part) == 0 or ts_part.isnull().any():
ts_list.append(GenerateTs_0(TimeRange))
else:
ts_list.append(ts_part)
return np.array(ts_list)
使用以上函數便可以得到如下結果,其中array的每一行是之前每天下午三點到下午6點的數據
Time = np.array([pd.datetime(2016,9,25,15,0,0),pd.datetime(2016,9,25,17,50,0)])
Time
Out[11]:
array([datetime.datetime(2016, 9, 25, 15, 0),
datetime.datetime(2016, 9, 25, 17, 50)], dtype=object)
ts_list = TsList('E1-1A-1<E1-1-01>',Time)
ts_list
Out[25]:
array([[ 1.5, 0.4, 1.8, ..., 15. , 15.9, 18.4],
[ 11. , 11.3, 13.4, ..., 6.3, 7.2, 9.4],
[ 7. , 5.5, 4.9, ..., 4.9, 4. , 6.4],
...,
[ 13.6, 16.4, 16.7, ..., 4.7, 3.9, 4.1],
[ 3.8, 4.2, 6. , ..., 10.2, 9.6, 19.4],
[ 5.2, 3.2, 4.2, ..., 5. , 4.5, 4.3]])
但是之前這麼多天必然有比較異常的日子,所以需要寫如下函數將異常的日子過濾掉,此處的過濾策略是:
對每天特定時間段的數據求均值與標準差,然後將均值與標準差落在10%分位數以下和90%分位數以上的日子去除
def TrueFalseListCombine(TFlist1,TFlist2):
return [l1 and l2 for l1,l2 in zip(TFlist1,TFlist2)]
def ExceptOutlier(ts_list):
Mean = pd.DataFrame([np.mean(i) for i in ts_list])
mean_low = Mean > Mean.quantile(0.1)
mean_up = Mean < Mean.quantile(0.9)
TF = TrueFalseListCombine(mean_low.values,mean_up.values)
mean_index = Mean[TF].index.values
Std = pd.DataFrame([np.std(i) for i in ts_list])
std_low = Std > Std.quantile(0.1)
std_up = Std < Std.quantile(0.9)
TF = TrueFalseListCombine(std_low.values,std_up.values)
std_index = Std[TF].index.values
valid_index = list(set(mean_index)&set(std_index))
return valid_index
例如對剛生成的ts_list處理得到
ExceptOutlier(ts_list)
Out[26]: [0, 1, 2, 3, 4, 6, 8, 9, 10, 12]
爲了更直觀我們使用如下函數繪圖
def DrawTsList(ts_list):
plt.plot(ts_list.T)
DrawTsList(ts_list) | DrawTsList(ts_list[ExceptOutlier(ts_list)]) |
---|---|
上圖左側爲所有日子的時間序列,右圖爲去除異常日子之後的時間序列,可以看出已經將特別異常的幾天去除了
均值模型:
每天的量值都存在一定的差異,直接將所有去除異常之後的日子取均值並不是特別好的策略,在此我們認爲,機場下午3點至6點的人流總量應當與當天這個時刻之前的人流量存在一定的關係,所以我們取了上午6點到下午3點這一時間段的數據作爲人流量值的參考。我們是有預測當天上午6點到下午3點的數據的,故可以依據此和之前去除異常後的多天該時間段的數據計算之前各天下午3點到下午6點數據的貢獻度。
基於以上思想,並做了一點小修改寫了如下兩個模型,兩個模型比較接近,但是在某些WIFIAP上其中一個會表現好很多,這使得我們之後利用誤差分析挑選模型時多一個候選模型。
def Ratio(L):
return np.array(L*1.0/sum(L))
def Imitate1(WIFIAPTag,TrainTime,PredictTime):
TrainTimeTsList = TsList(WIFIAPTag,TrainTime)
PredictTimeTsList = TsList(WIFIAPTag,PredictTime)
IndexWithoutOutlier = ExceptOutlier(PredictTimeTsList)
ValidTrainTimeTsList = TrainTimeTsList[IndexWithoutOutlier]
ValidPredictTimeTsList = PredictTimeTsList[IndexWithoutOutlier]
PredictDayTrainTs = Get_Part_of_TimeSeries(GetTimeSeries(WIFIAPTag),TrainTime)
if len(PredictDayTrainTs) == 0:
PredictTs = ValidPredictTimeTsList.mean(axis=0)
else:
MeanPredictDayTrainTs = PredictDayTrainTs.mean()
MeanValidTrainTimeTsList = ValidTrainTimeTsList.mean(axis=1)
RatioList = Ratio(MeanPredictDayTrainTs/MeanValidTrainTimeTsList)
PredictTs = np.dot(ValidPredictTimeTsList.T,RatioList)
PredictTimeRange = pd.date_range(start = PredictTime[0],end = PredictTime[1] ,freq = '10Min')
TS_Predict = pd.Series(PredictTs,index = PredictTimeRange)
return TS_Predict
def Imitate2(WIFIAPTag,TrainTime,PredictTime):
TrainTimeTsList = TsList(WIFIAPTag,TrainTime)
PredictTimeTsList = TsList(WIFIAPTag,PredictTime)
IndexWithoutOutlier = ExceptOutlier(PredictTimeTsList)
ValidTrainTimeTsList = TrainTimeTsList[IndexWithoutOutlier]
ValidPredictTimeTsList = PredictTimeTsList[IndexWithoutOutlier]
PredictDayTrainTs = Get_Part_of_TimeSeries(GetTimeSeries(WIFIAPTag),TrainTime)
if len(PredictDayTrainTs) == 0:
PredictTs = ValidPredictTimeTsList.mean(axis=0)
else:
MeanPredictDayTrainTs = PredictDayTrainTs.mean()
MeanValidTrainTimeTsList = ValidTrainTimeTsList.mean(axis=1)
RatioList = MeanPredictDayTrainTs/MeanValidTrainTimeTsList
PredictTs = np.dot(ValidPredictTimeTsList.T,RatioList) / len(RatioList)
PredictTimeRange = pd.date_range(start = PredictTime[0],end = PredictTime[1] ,freq = '10Min')
TS_Predict = pd.Series(PredictTs,index = PredictTimeRange)
return TS_Predict
時間序列模型:
如果只用上文提及的均值模型,很可能在3點那個時刻出現斷點的情況,比如前一時刻是15人,後10分鐘突然變成2人,考慮到人們在機場移動具有連續性的特徵,我們使用ARMA來對預測進行一定的修正,正所謂穩中求變,模型如下
def Do_ARMA(WIFIAPTag,TrainTime,PredictTime,p,q,Draw = False):
Tag_Time_Series = GetTimeSeries(WIFIAPTag)
ARMA_Time = [PredictTime[0]-timedelta(2),PredictTime[0] - timedelta(0,0,0,0,10,0)]
#ARMA_Time = [pd.datetime(2016,9,11,6,0,0),pd.datetime(2016,9,14,15,0,0)]
Tag_Time_Series = Get_Part_of_TimeSeries(Tag_Time_Series,ARMA_Time)
# ARMA model
from statsmodels.tsa.arima_model import ARMA
arma_mod = ARMA(Tag_Time_Series,(p,q)).fit()
Predict = arma_mod.predict(start=str(PredictTime[0]),end=str(PredictTime[1]))
if Draw == True:
plt.rc('figure', figsize=(12, 8))
plt.plot(arma_mod.fittedvalues,'r')
plt.plot(Tag_Time_Series)
plt.plot(Predict,'g-')
return Predict
試運行如下
Do_ARMA(‘E1-1A-1’,TrainTime,PredictTime,4,2,Draw=True) |
---|
模型整合:
現在我們有了三個基本模型,單單使用一個模型去預測所有的WIFIAP效果必然不好,每個WIFIAP都有自己最適合的模型,所以我們通過對前一週每天下午3點到6點的數據進行預測,計算每個WIFIAP在每個模型上的平均誤差,讓每個WIFIAP挑選誤差最小的那個模型進行預測。數據有缺失的情況,所有模型中包含了蠻多的異常處理部分。
代碼如下
def ErrorAnalysis(i,day):
Est_TrainTime = np.array([pd.datetime(2016,9,day,6,0,0),pd.datetime(2016,9,day,14,50,0)])
Est_PredictTime = np.array([pd.datetime(2016,9,day,15,0,0),pd.datetime(2016,9,day,17,50,0)])
y = Get_Part_of_TimeSeries(GetTimeSeries(WIFIAPTag_List[i]),Est_PredictTime)
prey0 =Imitate1(WIFIAPTag_List[i],Est_TrainTime,Est_PredictTime)
prey1 =Imitate2(WIFIAPTag_List[i],Est_TrainTime,Est_PredictTime)
def error(a,b):
return sum([n*n for n in (a-b)])
imitate1_error = error(prey0,y)
imitate2_error = error(prey1,y) # sometimes y is empty [expection]
if np.isnan(imitate1_error):
imitate1_error = 1
if np.isnan(imitate2_error):
imitate2_error = 1
try:
prey2=Do_ARMA(WIFIAPTag_List[i],Est_TrainTime,Est_PredictTime,4,2)
arma_error = error(prey2,y)
except:
arma_error = 10000000
if np.isnan(arma_error):
arma_error = 10000000
Error_list = [imitate1_error,imitate2_error,arma_error]
return Error_list
def GetRatio():
import time
Error_Analysis = []
for i in range(len(WIFIAPTag_List)):
t1 = time.time()
Error = np.array([0,0,0])
for j in range(1,8):
try:
e = ErrorAnalysis(i,25-j)
Error = np.c_[Error,e]
except:
print 'Error Com'
ratio = Ratio(1.0/Error.mean(axis=1))
Error_Analysis.append(ratio)
t2 = time.time()
print '===== Got '+str(i)+'th Ratio base on error analysis=====Cost '+str(t2-t1)+' Seconds==='
def Save_Obj(Obj,File_Name):
import pickle
File = File_Name + '.pkl'
output = open(File, 'wb')
pickle.dump(Obj, output)
output.close()
Ratio_Dict = dict(zip(WIFIAPTag_List,Error_Analysis))
Save_Obj(Ratio_Dict,'Ratio_Dict')
return Ratio_Dict
def Combine(WIFIAPTag,TrainTime,PredictTime,Ratio_Dict):
num = list(Ratio_Dict[WIFIAPTag]).index(Ratio_Dict[WIFIAPTag].max())
if num ==0:
Predict = Imitate1(WIFIAPTag,TrainTime,PredictTime)
if num ==1:
Predict = Imitate2(WIFIAPTag,TrainTime,PredictTime)
if num ==2:
try:
Predict = Do_ARMA(WIFIAPTag,TrainTime,PredictTime,4,2)
if np.isnan(Predict.values).any():
print 'Nan in ARMA'
Predict = Imitate2(WIFIAPTag,TrainTime,PredictTime)
except:
print 'ARMA Failed'
Predict = Imitate2(WIFIAPTag,TrainTime,PredictTime)
return Predict
爲了看下混合模型的效果,可以使用如下代碼
def Compare(i,day,Ratio_Dict):
Est_TrainTime = np.array([pd.datetime(2016,9,day,6,0,0),pd.datetime(2016,9,day,14,50,0)])
Est_PredictTime = np.array([pd.datetime(2016,9,day,15,0,0),pd.datetime(2016,9,day,17,50,0)])
y = Get_Part_of_TimeSeries(GetTimeSeries(WIFIAPTag_List[i]),Est_PredictTime)
prey0 =Imitate1(WIFIAPTag_List[i],Est_TrainTime,Est_PredictTime)
prey1 =Imitate2(WIFIAPTag_List[i],Est_TrainTime,Est_PredictTime)
prey2=Do_ARMA(WIFIAPTag_List[i],Est_TrainTime,Est_PredictTime,4,2)
prey3 = Combine(WIFIAPTag_List[i],Est_TrainTime,Est_PredictTime,Ratio_Dict)
y.plot()
prey0.plot()
prey1.plot()
prey2.plot()
prey3.plot()
plt.legend(['real','imitate1','imitate2','arma','combine'])
title = '2016-9-'+str(day)
plt.title(title)
Imitate1 佔優勢例子 | Imitate2 佔優勢例子 | Do_ARMA 佔優勢例子 |
---|---|---|
基於以上組件,便可以進行開心地預測了,結果保存爲airport_gz_passenger_predict.csv
def Predict(TrainTime,PredictTime,Ratio_Dict):
count=0
tag = WIFIAPTag_List[0]
Predict = Combine(tag,TrainTime,PredictTime,Ratio_Dict)
def TransTime(time):
date = str(time.date())
hour = time.hour
minute = time.minute
output = date + '-' + str(hour) + '-' + str(minute / 10)
return output
slice10min = [TransTime(time) for time in Predict.index]
passengerCount = Predict.values
WIFIAPTag = [tag]*len(Predict)
Predict_Result = pd.DataFrame({'passengerCount':passengerCount,'WIFIAPTag':WIFIAPTag,'slice10min':slice10min})
Predict_Result = Predict_Result[['passengerCount','WIFIAPTag','slice10min']]
for tag in WIFIAPTag_List[1:]:
Predict = Combine(tag,TrainTime,PredictTime,Ratio_Dict)
slice10min = [TransTime(time) for time in Predict.index]
passengerCount = Predict.values
WIFIAPTag = [tag]*len(Predict)
Predict_Result_Part = pd.DataFrame({'passengerCount':passengerCount,'WIFIAPTag':WIFIAPTag,'slice10min':slice10min})
Predict_Result_Part = Predict_Result_Part[['passengerCount','WIFIAPTag','slice10min']]
Predict_Result = pd.concat([Predict_Result,Predict_Result_Part])
count += 1
print count
Path_Result = './Data/airport_gz_passenger_predict.csv'
Predict_Result['passengerCount'] = np.nan_to_num(Predict_Result.passengerCount)
Save_DataFrame_csv(Predict_Result,Path_Result)
return Predict_Result
4. 複賽
4.1 複賽數據描述
複賽提供了2016-10-09至2016-11-10的數據
4.2複賽問題描述
選手需要預測未來兩整天(11月11日0點到12日23:59:59)的時間窗口裏,機場內每個WIFI AP點每10分鐘內的平均設備連接數量
4.2複賽解決方案
簡要概括:多層篩選加均值
基本思路:
複賽是對未來的兩個整天進行預測,基本思路與初賽相似,但是做了如下修改
- ARMA模型不再作爲一天之內連續性的調整策略,而是用於預測未來兩天整體量值的趨勢
- 修改了數據的篩選機制
由於複賽是在天池數加平臺進行,第一次接觸對於平臺並不是太熟悉,所以選擇在其機器學習平臺使用SQL節點編寫語句實現模型
解決方案:
首先在數據開發平臺讀取數據表
drop table if exists airport_gz_flights;
create table if not exists airport_gz_flights as
select * from odps_tc_257100_f673506e024.airport_gz_flights;
然後在機器學習平臺進行數據處理和模型搭建
讀入初始數據預覽如下
使用以下節點預處理數據(每個節點是一條SQL語句,將處理結果傳入下一節點)
使用瞭如下等語句(這些語句應該可以再精簡些,但是當初寫好了就沒再去修改了)
--tag_time(slice10min)_combine
select passenger_count , concat(wifi_ap_tag,'|',substr(time_stamp,1,15)) as tag_time
from airport_gz_wifi_ap;
--agg_tag_time
select avg(passenger_count) as mean_passenger_count , tag_time from ${t1}
group by tag_time;
--split_tag_time
select mean_passenger_count , split_part(tag_time, '|', 1) as tag , split_part(tag_time, '|', 2) as time_split from ${t1};
--split_date_time
select mean_passenger_count , tag , time_split , substr(time_split,1,10) as d , substr(time_split,12,15) as t from ${t1};
-- Add_Date_Column
select mean_passenger_count , tag ,d, to_date(d,'yyyy-mm-dd') as date_stamp ,t,time_split,c as day_avg from ${t1};
--get_date
select substr(time_stamp,1,10) as t , passenger_count from ${t1};
--date_mean
select avg(passenger_count) as c , t from ${t1} group by t;
得到如下結果
其中一個模型大概結構如下
節點確實有點多具體細節就不在此展開,此處簡要提一下複賽中的篩選策略:
首先計算所有日子全部節點每天的平均連接量,從而得到一個時間序列。如下圖所示
利用這個時間序列依據ARMA模型估計出之後兩天的量值,依據這量值建立一個區間,篩選出均值落在這個區間內的所有日子,然後對這些天的數據按照初賽的思路再進一步做異常篩選,此外還要進一步加大最近幾日的數據權重,依據這些想法建立模型。最後在某些步驟上做些小修改,共建立三個候選模型,依據初賽的思路進行誤差分析整合模型進行預測。
誤差分析的的結果大概如下,基於誤差值可以挑選使用哪個模型
5. 總結
比賽初期其實提取了很多特徵,然後使用一些機器學習算法去預測,但是效果卻強差人意,隨後結合實際問題思考,發現其實不一定要使用各種特徵,而且很多隨機因素對各個特徵的影響真的蠻大的。僅使用一些簡單的想法也能達到比較好的效果。
所以這次比賽後,想說的就是模型真的不是越複雜越好,也不一定要用各種現成的模型,結合實際問題背景去分析可能會比一直糾結各種特徵以及模型參數獲得更大的收益。