天池項目總結,特征工程了解一下!
業(yè)界廣泛流傳著這樣一句話:“數(shù)據(jù)和特征決定了機器學習的上限,而模型和算法只是逼近這個上限而已”,由此可見特征工程在機器學習中的重要性,今天我們將通過《阿里云天池大賽賽題解析——機器學習篇》中的【天貓用戶重復購買預測】案例來深入解析特征工程在實際商業(yè)場景中的應用。

學習前須知
(1)本文特征工程講解部分參考自圖書《阿里云天池大賽賽題解析——機器學習篇》中的第二個賽題:天貓用戶重復購買預測。
(2)本文相關數(shù)據(jù)可以在阿里云天池競賽平臺下載,數(shù)據(jù)地址:
https://tianchi.aliyun.com/competition/entrance/231576/information

一? 數(shù)據(jù)集介紹
按照上面方法下載好數(shù)據(jù)集后,我們來看看具體數(shù)據(jù)含義。

test_format1.csv和train_format1.csv里分別存放著測試數(shù)據(jù)和訓練數(shù)據(jù),測試數(shù)據(jù)集最后一個字段為prob,表示測試結果,訓練數(shù)據(jù)集最后一個字段為label,訓練數(shù)據(jù)各字段信息如下圖所示:

訓練數(shù)據(jù)集
user_log_format1.csv里存放著用戶行為日志,字段信息如下圖所示:

用戶行為日志數(shù)據(jù)
user_info_format1.csv里存放著用戶行基本信息,字段信息如下圖所示:

用戶基本信息數(shù)據(jù)
二? 特征構造
本賽題基于天貓電商數(shù)據(jù),主要關心用戶、店鋪和商家這三個實體,所以特征構造上也以用戶、店鋪和商家為核心,可以分為以下幾部分:
用戶-店鋪特征構造
店鋪特征構造
對店鋪特征選取可以使用,如 Numpy 的 corrcoef(x,y)函數(shù)計算相關系數(shù),保留相關系數(shù)小于0.9 的特征組合,具體內容如圖 2-3。

商家特征選取

用戶特征構造

用戶購買商品特征構造

利用時間提取特征
總結以上內容,特征主要基于基礎特征、用戶特征、店鋪特征、用戶+店鋪四個方面,如下圖所示:

特征總結
三? 特征提取
首先我們導入需要的工具包,進行數(shù)據(jù)分析和特征提取。
import numpy as npimport pandas as pdimport matplotlib.pyplot as plt import seaborn as snsfrom scipy import statsimport gcfrom collections import Counter import copyimport warnings warnings.filterwarnings("ignore")%matplotlib inline
接下來我們將按以下步驟進行特征提取。

特征提取步驟
1? 讀取數(shù)據(jù)
直接調用Pandas的read_csv函數(shù)讀取訓練集和測試集及用戶信息、用戶日志數(shù)據(jù)。
test_data = pd.read_csv('./data_format1/test_format1.csv') train_data = pd.read_csv('./data_format1/train_format1.csv')user_info = pd.read_csv('./data_format1/user_info_format1.csv')user_log = pd.read_csv('./data_format1/user_log_format1.csv')
2? 數(shù)據(jù)預處理
對數(shù)據(jù)內存進行壓縮:
def reduce_mem_usage(df, verbose=True):start_mem = df.memory_usage().sum() / 1024**2numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']for col in df.columns: col_type = df[col].dtypes if col_type in numerics:c_min = df[col].min()c_max = df[col].max()if str(col_type)[:3] == 'int':if c_min > np.iinfo(np.int8).min and c_max < np.iinfo( np.int8).max:df[col] = df[col].astype(np.int8)elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:df[col] = df[col].astype(np.int16)elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo( np.int32).max:df[col] = df[col].astype(np.int32)elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:df[col] = df[col].astype(np.int64)else:if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:df[col] = df[col].astype(np.float16)elif c_min > np.finfo(np.float32).min and c_max < np.finfo( np.float32).max:df[col] = df[col].astype(np.float32)else:df[col] = df[col].astype(np.float64)end_mem = df.memory_usage().sum() / 1024**2print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
all_data = train_data.append(test_data)all_data = all_data.merge(user_info,on=['user_id'],how='left')del train_data, test_data, user_infogc.collect()
# 用戶日志數(shù)據(jù)按時間排序user_log = user_log.sort_values(['user_id', 'time_stamp'])# 合并用戶日志數(shù)據(jù)各字段,新字段名為item_idlist_join_func = lambda x: " ".join([str(i) for i in x])agg_dict = {'item_id': list_join_func,'cat_id': list_join_func,'seller_id': list_join_func,'brand_id': list_join_func,'time_stamp': list_join_func,'action_type': list_join_func}rename_dict = {'item_id': 'item_path','cat_id': 'cat_path','seller_id': 'seller_path','brand_id': 'brand_path','time_stamp': 'time_stamp_path','action_type': 'action_type_path'}def merge_list(df_ID, join_columns, df_data, agg_dict, rename_dict):df_data = df_data.groupby(join_columns).agg(agg_dict).reset_index().rename(columns=rename_dict)df_ID = df_ID.merge(df_data, on=join_columns, how="left")return df_IDall_data = merge_list(all_data, 'user_id', user_log, agg_dict, rename_dict)del user_loggc.collect()
def cnt_(x):try:return len(x.split(' '))except:return -1def nunique_(x):try:return len(set(x.split(' ')))except:return -1def max_(x):try:return np.max([float(i) for i in x.split(' ')])except:return -1def min_(x):try:return np.min([float(i) for i in x.split(' ')])except:return -1def std_(x):try:return np.std([float(i) for i in x.split(' ')])except:return -1def most_n(x, n):try:return Counter(x.split(' ')).most_common(n)[n-1][0]except:return -1def most_n_cnt(x, n):try:return Counter(x.split(' ')).most_common(n)[n-1][1]except:return -1
def user_cnt(df_data, single_col, name):df_data[name] = df_data[single_col].apply(cnt_)return df_datadef user_nunique(df_data, single_col, name):df_data[name] = df_data[single_col].apply(nunique_)return df_datadef user_max(df_data, single_col, name):df_data[name] = df_data[single_col].apply(max_)return df_datadef user_min(df_data, single_col, name):df_data[name] = df_data[single_col].apply(min_)return df_datadef user_std(df_data, single_col, name):df_data[name] = df_data[single_col].apply(std_)return df_datadef user_most_n(df_data, single_col, name, n=1):func = lambda x: most_n(x, n)df_data[name] = df_data[single_col].apply(func)return df_datadef user_most_n_cnt(df_data, single_col, name, n=1):func = lambda x: most_n_cnt(x, n)df_data[name] = df_data[single_col].apply(func)return df_data
# 取2000條數(shù)據(jù)舉例all_data_test = all_data.head(2000)# 總次數(shù)all_data_test = user_cnt(all_data_test, 'seller_path', 'user_cnt')# 不同店鋪個數(shù)all_data_test = user_nunique(all_data_test, 'seller_path', 'seller_nunique ')# 不同品類個數(shù)all_data_test = user_nunique(all_data_test, 'cat_path', 'cat_nunique')# 不同品牌個數(shù)all_data_test = user_nunique(all_data_test, 'brand_path','brand_nunique')# 不同商品個數(shù)all_data_test = user_nunique(all_data_test, 'item_path', 'item_nunique')# 活躍天數(shù)all_data_test = user_nunique(all_data_test, 'time_stamp_path','time_stamp _nunique')# 不同用戶行為種數(shù)all_data_test = user_nunique(all_data_test, 'action_type_path','action_ty pe_nunique')
# 用戶最喜歡的店鋪all_data_test = user_most_n(all_data_test, 'seller_path', 'seller_most_1', n=1)# 最喜歡的類目all_data_test = user_most_n(all_data_test, 'cat_path', 'cat_most_1', n=1)# 最喜歡的品牌all_data_test = user_most_n(all_data_test, 'brand_path', 'brand_most_1', n= 1)# 最常見的行為動作all_data_test = user_most_n(all_data_test, 'action_type_path', 'action_type _1', n=1)
from sklearn.feature_extraction.text import CountVectorizerfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.feature_extraction.text import ENGLISH_STOP_WORDSfrom scipy import sparsetfidfVec = TfidfVectorizer(stop_words=ENGLISH_STOP_WORDS,ngram_range=(1, 1),max_features=100)columns_list = ['seller_path']for i, col in enumerate(columns_list):tfidfVec.fit(all_data_test[col])data_ = tfidfVec.transform(all_data_test[col])if i == 0:data_cat = data_else:data_cat = sparse.hstack((data_cat, data_))
import gensimmodel = gensim.models.Word2Vec(all_data_test['seller_path'].apply(lambda x: x.split(' ')),size=100,window=5,min_count=5,workers=4)def mean_w2v_(x, model, size=100):try:i = 0for word in x.split(' '):if word in model.wv.vocab:i += 1if i == 1:vec = np.zeros(size)vec += model.wv[word]return vec / iexcept:return np.zeros(size)def get_mean_w2v(df_data, columns, model, size):data_array = []for index, row in df_data.iterrows():w2v = mean_w2v_(row[columns], model, size)data_array.append(w2v)return pd.DataFrame(data_array)df_embeeding = get_mean_w2v(all_data_test, 'seller_path', model, 100)df_embeeding.columns = ['embeeding_' + str(i) for i in df_embeeding.columns]
# 1、使用 5 折交叉驗證from sklearn.model_selection import StratifiedKFold, KFoldfolds = 5seed = 1kf = KFold(n_splits=5, shuffle=True, random_state=0)# 2、選擇 lgb 和 xgb 分類模型作為基模型clf_list = [lgb_clf, xgb_clf]clf_list_col = ['lgb_clf', 'xgb_clf']# 3、獲取 Stacking 特征clf_list = clf_listcolumn_list = []train_data_list=[]test_data_list=[]for clf in clf_list:??train_data,test_data,clf_name=clf(x_train,?y_train,?x_valid,?kf,?label_?split=None)??????train_data_list.append(train_data)??????test_data_list.append(test_data)train_stacking?=?np.concatenate(train_data_list,?axis=1)test_stacking?=?np.concatenate(test_data_list,?axis=1)
valid_0's multi_logloss: 0.240875Training until validation scores don't improve for 100 rounds.valid_0's multi_logloss: 0.240675train-mlogloss:0.123211 eval-mlogloss:0.226966Best iteration:train-mlogloss:0.172219 eval-mlogloss:0.218029xgb now score is: [2.4208301225770263, 2.2433633135072886, 2.51909203146584 34, 2.4902898448798805, 2.5797977298125625]xgb_score_list: [2.4208301225770263, 2.2433633135072886, 2.5190920314658434, 2.4902898448798805, 2.5797977298125625]xgb_score_mean: 2.4506746084485203???
