interactions = data_raw["category"]+"_"+data_raw["country"] baseline_data = baseline_data.assign(category_country = label_encoder.fit_transform(interactions))
上面的第一句代碼就是我們interaction的部分,第二句是講interaction事後的數據label encoding而且加入到我們的數據集裏面,簡單明瞭。上面是將原始數據中的category 和 country鏈接在一塊兒從而造成一個新的feature 2.2 numerical transforming。這是什麼意思呢,對於有些numerical data的columns,他們的數據分佈是很不均勻的,或者說他們的數值太大或者過小,有的時候不適合我們的數據的訓練,可能會出現vanishing gradient或者gradient explode的狀況。具體啥叫vanishing gradient和gradient exploding,我們在後面的內容在慢慢解釋。暫時只須要知道這是個很麻煩的事情就行了,會致使我們訓練的模型不那麼牛逼就好了。那麼我們經過什麼方法解決呢?這裏主要經過一些常見的數學的方式來解決,例如用log 或者 sqrt等等方式。我們能夠經過下面的代碼來簡單的展現一下html
np.sqrt(baseline_data['goal']) np.log(baseline_data['goal'])
從上面我們能夠看出,這裏我們主要仍是經過numpy裏面提供的API進行處理的,很是簡單,簡單跟1同樣,好了這裏就說到這了。 對了,忘記一個事兒,就是numerical transforming在tree-based模型中沒有什麼卵用的,由於tree-based的全部模型都是scale invariant的,就是tree-based模型都是不care數據的大小分佈的。 2.3 rolling。這個就比較高級一點啦(相比前兩種方式),首先我們先要明白rolling的概念,其實rolling就是至關於在我們的數據(series)上面卡上一個fixed-size的小window,而後對於這個window覆蓋的數據進行一些簡單的計算,例如:counting,mean,sum等等。若是你們仍是以爲不懂,我把它的官方連接貼在這裏,你們本身去看看,裏面還有不少實例:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.rolling.html#pandas.Series.rolling 。那麼我先寫一個簡單的小例子給你們參考一下哈api
launched = pd.Series(data_raw.index,data_raw.launched,name="count_7_days").sort_index() count_7_days = launched.rolling('7d').count() count_7_days.index = launched.values
count_7_days = count_7_days.reindex(data_raw.index)
我先簡單解釋一下上面代碼的意思哈,第一句是讓時間做爲這個series的index,第二句rolling是計算最近7天的的數量,第三第四句是講數據還原到以前的index的順序,房間從新join到原來的數據集中。那麼rolling這種方式通常在什麼狀況下用呢?通常在你的數據有datetime的時候,或者前面數據會影響到後面的結果的時候,你們能夠考慮一下下,可是這個是不必定的,仍是須要你們有必定的creativity的。例如上面的例子就是統計最近7天一共上傳的APP的數量,來判斷某一個APP是否被下載的應用場景。通常狀況下,最近上傳的APP數量太多,被下載的機率就越低,因此他們仍是有必定關聯關係的。因此我generate一個新的feature仍是有必定道理的。 2.4 Time delta。從這個命名中我們能夠知道,這個跟time確定有關係,這個你們猜的很對。time delta也是有必定隨機性的,有時須要有時也不須要,也是要根據實際的數據的特性來決定的,甚至是根據工程師本身來決定的,跟上面的rolling有點類似。爲了方便解釋這其中的細節,我也是直接來一個例子而後慢慢解釋app
def time_since_last_project_same_category(series): return series.diff().dt.total_seconds()/3600 df = data_raw[['category','launched']].sort_values('launched') group_category = df.groupby('category') timedeltas = group_category.transform(time_since_last_project_same_category) timedeltas = timedeltas.fillna(timedeltas.mean()).reindex(baseline_data.index)
上面前兩行是一個計算相鄰datatime之間的相差多少個小時,第三行建立一個按照排序好的launched time爲index的dataframe, 第四行是按照category的條件來group前面建立的df, 第五行是計算group裏面相鄰數據之間的time delta,而且返回一個series, 第六行是填充這些空數據,而且按照原始數據的方式index從新排序方便加入到原始數據。流程就這樣結束了。上面的場景是計算同一個category相鄰app上傳的時間差,這個其實也是會影響到我們的APP是否被下載的因素。因此這個也是我們的一個creativity,實際狀況中變幻無窮,必定要根據實際狀況來定,不能爲了裝逼而裝逼,必定要根據實際的業務須要,不然拔苗助長。 好了,其實關於feature generation還有不少種方式,例若有些事計算兩個columns之間的差值,取模等等,這裏沒有統一的標準,惟一的捷徑和key就是我們必定得理解我們每個columns和dataset的實際業務的意思,不然再牛逼的generation也拯救不了你。下面我們進入到這一章的最後一節feature selection吧。dom
from sklearn.feature_selection import SelectKBest, f_classif selector = SelectKBest(score_func = f_classif, k = 5) train,valid,test = get_data_splits(baseline_data, 0.1) feature_cols = train.columns.drop("outcome") X_new = selector.fit_transform(train[feature_cols],train["outcome"] )
#get back to the features we kept
features = pd.DataFrame(selector.inverse_transform(X_new), index = train.index, columns = feature_cols)
#drop the columns that the values are all 0s
feature_cols_final = features.columns[features.var()!=0]
features_final = features[feature_cols_final]機器學習
從上面的代碼我們能夠看出來,首先得從sklearn.feature_selection這個模塊中引進SelectKBest和f_classif兩個子模塊;第二步就是建立一個Selector實例對象,這個selector最終返回多少個features是經過我們的參數K來控制的,selector的最終選擇哪些features也是經過f_classif這個函數來控制的;最後就是這個selector的transform了,將features和target做爲參數分別傳遞給他,他會自動搞定,而且返回K個features, 而後再將numpy array返回到dataframe的格式。這種方式的只能計算出每個feature和target的linear dependency,並不能一次性包括全部的features進行關聯性計算。 3.2 L1 Regression。L1 Regression能夠直接包括全部的features一次性的計算這個columns和target的關聯性。關聯性越強,數值越大。它不須要制定最後返回多少個features,它是根據L1的結果自動幫助我們features。可是它的運行速度要遠遠慢於上面k-classif的方法,但是好處就是通常狀況下L1 Regression的運行結果要好於K-classif, 但也不必定澳,只能說大部分狀況是這樣的。函數
from sklearn.linear_model import LogisticRegression from sklearn.feature_selection import SelectFromModel train,valid,test = get_data_splits(baseline_data, 0.1) X, y = train[train.columns.drop("outcome")], train["outcome"] logistic_model = LogisticRegression(C=1, penalty="l1", random_state=7).fit(X,y) selector = SelectFromModel(logistic_model,prefit=True) X_new = selector.transform(X) features = pd.DataFrame(selector.inverse_transform(X_new),index = train.index, columns = feature_cols) feature_cols_final = features.columns[features.var()!=0]
總結:上面就是通常的的特徵工程的feature selection和feature generation的通常方法,我們上面講了不少種的方式,實際狀況中具體選擇哪種仍是要根據實際狀況,必定不要死讀書。feature generation通常就是interaction,numerical generation,rolling和time delta四種方式。feature selection通常用到的技術手段就是就是f-classif和L1 regression幾種方式。學習