【零基础入门数据挖掘】-特征工程
?Datawhale?
作者:吳忠強(qiáng),Datawhale優(yōu)秀學(xué)習(xí)者
摘要:對(duì)于數(shù)據(jù)挖掘項(xiàng)目,本文將學(xué)習(xí)應(yīng)該從哪些角度做特征工程?從哪些角度做數(shù)據(jù)清洗,如何對(duì)特征進(jìn)行增刪,如何使用PCA降維技術(shù)等。
特征工程(Feature Engineering)對(duì)特征進(jìn)行進(jìn)一步分析,并對(duì)數(shù)據(jù)進(jìn)行處理。常見的特征工程包括:異常值處理、缺失值處理、數(shù)據(jù)分桶、特征處理、特征構(gòu)造、特征篩選及降維等。
數(shù)據(jù)及背景
https://tianchi.aliyun.com/competition/entrance/231784/information(阿里天池-零基礎(chǔ)入門數(shù)據(jù)挖掘)
異常值處理
常用的異常值處理操作包括BOX-COX轉(zhuǎn)換(處理有偏分布),箱線圖分析刪除異常值, 長尾截?cái)嗟确绞?#xff0c; 當(dāng)然這些操作一般都是處理數(shù)值型的數(shù)據(jù)。
BOX-COX轉(zhuǎn)換
關(guān)于box-cox轉(zhuǎn)換,一般是用于連續(xù)的變量不滿足正態(tài)的時(shí)候,在做線性回歸的過程中,一般線性模型假定:
其中ε滿足正態(tài)分布,但是利用實(shí)際數(shù)據(jù)建立回歸模型時(shí),個(gè)別變量的系數(shù)通不過。例如往往不可觀測(cè)的誤差 ε 可能是和預(yù)測(cè)變量相關(guān)的,不服從正態(tài)分布,于是給線性回歸的最小二乘估計(jì)系數(shù)的結(jié)果帶來誤差,為了使模型滿足線性性、獨(dú)立性、方差齊性以及正態(tài)性,需改變數(shù)據(jù)形式,故應(yīng)用BOX-COX轉(zhuǎn)換。具體詳情這里不做過多介紹,當(dāng)然還有很多轉(zhuǎn)換非正態(tài)數(shù)據(jù)分布的方式:
對(duì)數(shù)轉(zhuǎn)換: ? ?
平方根轉(zhuǎn)換:
倒數(shù)轉(zhuǎn)換:
平方根后取倒數(shù):
平方根后再取反正弦:
冪轉(zhuǎn)換:,
其中,參數(shù)
在一些情況下(P值<0.003)上述方法很難實(shí)現(xiàn)正態(tài)化處理,所以優(yōu)先使用BOX-COX轉(zhuǎn)換,但是當(dāng)P值>0.003時(shí)兩種方法均可,優(yōu)先考慮普通的平方變換。
BOX-COX的變換公式:
具體實(shí)現(xiàn):
箱線圖
接下來,介紹一下箱線圖篩選異常并進(jìn)行截尾。從上面的探索中發(fā)現(xiàn),某些數(shù)值型字段有異常點(diǎn),可以看一下power這個(gè)字段:
# power屬性是有異常點(diǎn)的 num_data.boxplot(['power'])結(jié)果如下:
所以,下面用箱線圖去捕獲異常,然后進(jìn)行截尾, 這里不用刪除,其原因?yàn)?#xff1a;
筆者已經(jīng)合并了訓(xùn)練集和測(cè)試集,若刪除的話,肯定會(huì)刪除測(cè)試集的數(shù)據(jù)
刪除有時(shí)候會(huì)改變數(shù)據(jù)的分布等
所以這里考慮使用截尾的方式:
"""這里包裝了一個(gè)異常值處理的代碼,可以隨便調(diào)用""" def outliers_proc(data, col_name, scale=3):"""用于截尾異常值, 默認(rèn)用box_plot(scale=3)進(jìn)行清洗param:data:接收pandas數(shù)據(jù)格式col_name: pandas列名scale: 尺度"""data_col = data[col_name]Q1 = data_col.quantile(0.25) # 0.25分位數(shù)Q3 = data_col.quantile(0.75) # 0,75分位數(shù)IQR = Q3 - Q1data_col[data_col < Q1 - (scale * IQR)] = Q1 - (scale * IQR)data_col[data_col > Q3 + (scale * IQR)] = Q3 + (scale * IQR)return data[col_name]num_data['power']?=?outliers_proc(num_data,?'power')再看一下數(shù)據(jù):
當(dāng)然,如果想刪除這些異常點(diǎn),可參考下列代碼:
def outliers_proc(data, col_name, scale=3):"""用于清洗異常值,默認(rèn)用 box_plot(scale=3)進(jìn)行清洗:param data: 接收 pandas 數(shù)據(jù)格式:param col_name: pandas 列名:param scale: 尺度:return:"""def box_plot_outliers(data_ser, box_scale):"""利用箱線圖去除異常值:param data_ser: 接收 pandas.Series 數(shù)據(jù)格式:param box_scale: 箱線圖尺度,:return:"""iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))val_low = data_ser.quantile(0.25) - iqrval_up = data_ser.quantile(0.75) + iqrrule_low = (data_ser < val_low)rule_up = (data_ser > val_up)return (rule_low, rule_up), (val_low, val_up)data_n = data.copy()data_series = data_n[col_name]rule, value = box_plot_outliers(data_series, box_scale=scale)index = np.arange(data_series.shape[0])[rule[0] | rule[1]]print("Delete number is: {}".format(len(index)))data_n = data_n.drop(index)data_n.reset_index(drop=True, inplace=True)print("Now column number is: {}".format(data_n.shape[0]))index_low = np.arange(data_series.shape[0])[rule[0]]outliers = data_series.iloc[index_low]print("Description of data less than the lower bound is:")print(pd.Series(outliers).describe())index_up = np.arange(data_series.shape[0])[rule[1]]outliers = data_series.iloc[index_up]print("Description of data larger than the upper bound is:")print(pd.Series(outliers).describe())fig, ax = plt.subplots(1, 2, figsize=(10, 7))sns.boxplot(y=data[col_name], data=data, palette="Set1", ax=ax[0])sns.boxplot(y=data_n[col_name], data=data_n, palette="Set1", ax=ax[1])return?data_n這個(gè)代碼是直接刪除數(shù)據(jù),這個(gè)如果要使用,不要對(duì)測(cè)試集用哈。下面看看power這個(gè)特征的分布也不錯(cuò)了,所以就沒再進(jìn)一步處理power,至于其他的數(shù)值型是不是需要截尾,需要自己決策。
缺失值處理
關(guān)于缺失值處理的方式, 有幾種情況:
不處理(這是針對(duì)xgboost等樹模型),有些模型有處理缺失的機(jī)制,所以可以不處理
如果缺失的太多,可以考慮刪除該列
插值補(bǔ)全(均值,中位數(shù),眾數(shù),建模預(yù)測(cè),多重插補(bǔ)等)
分箱處理,缺失值一個(gè)箱。
下面整理幾種填充值的方式:
# 刪除重復(fù)值 data.drop_duplicates() # dropna()可以直接刪除缺失樣本,但是有點(diǎn)不太好# 填充固定值 train_data.fillna(0, inplace=True) # 填充 0 data.fillna({0:1000, 1:100, 2:0, 4:5}) # 可以使用字典的形式為不用列設(shè)定不同的填充值train_data.fillna(train_data.mean(),inplace=True) # 填充均值 train_data.fillna(train_data.median(),inplace=True) # 填充中位數(shù) train_data.fillna(train_data.mode(),inplace=True) # 填充眾數(shù)train_data.fillna(method='pad', inplace=True) # 填充前一條數(shù)據(jù)的值,但是前一條也不一定有值 train_data.fillna(method='bfill', inplace=True) # 填充后一條數(shù)據(jù)的值,但是后一條也不一定有值"""插值法:用插值法擬合出缺失的數(shù)據(jù),然后進(jìn)行填充。""" for f in features: train_data[f] = train_data[f].interpolate()train_data.dropna(inplace=True)"""填充KNN數(shù)據(jù):先利用knn計(jì)算臨近的k個(gè)數(shù)據(jù),然后填充他們的均值""" from fancyimpute import KNN train_data_x = pd.DataFrame(KNN(k=6).fit_transform(train_data_x), columns=features)#?還可以填充模型預(yù)測(cè)的值,?這一個(gè)在我正在寫的數(shù)據(jù)競(jìng)賽修煉筆記的第三篇里面可以看到,并且超級(jí)精彩,還在寫再回到這個(gè)比賽中,在數(shù)據(jù)探索中已經(jīng)看到了缺失值的情況:
上圖可以看到缺失情況, 都是類別特征的缺失,notRepaired這個(gè)特征的缺失比較嚴(yán)重, 可以嘗試填充, 但目前關(guān)于類別缺失,感覺上面的方式都不太好,所以這個(gè)也是一個(gè)比較困難的地方,感覺用模型預(yù)測(cè)填充比較不錯(cuò)。但目前不做進(jìn)一步處理,因?yàn)楹竺娴臉淠P涂梢宰孕刑幚砣笔?。?dāng)然OneHot的時(shí)候,會(huì)把空值處理成全0的一種表示,類似于一種新類型了。
數(shù)據(jù)分桶
連續(xù)值經(jīng)常離散化或者分離成“箱子”進(jìn)行分析, 為什么要做數(shù)據(jù)分桶呢?
離散后稀疏向量內(nèi)積乘法運(yùn)算速度更快,計(jì)算結(jié)果也方便存儲(chǔ),容易擴(kuò)展;
離散后的特征對(duì)異常值更具魯棒性,如 age>30 為 1 否則為 0,對(duì)于年齡為 200 的也不會(huì)對(duì)模型造成很大的干擾;
LR 屬于廣義線性模型,表達(dá)能力有限,經(jīng)過離散化后,每個(gè)變量有單獨(dú)的權(quán)重,這相當(dāng)于引入了非線性,能夠提升模型的表達(dá)能力,加大擬合;
離散后特征可以進(jìn)行特征交叉,提升表達(dá)能力,由 M+N 個(gè)變量編程 M*N 個(gè)變量,進(jìn)一步引入非線形,提升了表達(dá)能力;
特征離散后模型更穩(wěn)定,如用戶年齡區(qū)間,不會(huì)因?yàn)橛脩裟挲g長了一歲就變化
當(dāng)然還有很多原因,LightGBM 在改進(jìn) XGBoost 時(shí)就增加了數(shù)據(jù)分桶,增強(qiáng)了模型的泛化性?,F(xiàn)在介紹數(shù)據(jù)分桶的方式:
等頻分桶
等距分桶
Best-KS分桶(類似利用基尼指數(shù)進(jìn)行二分類)
卡方分桶
最好將數(shù)據(jù)分桶的特征作為新一列的特征,不要把原來的數(shù)據(jù)給替換掉, 所以在這里通過分桶的方式做一個(gè)特征出來看看,以power為例:
"""下面以power為例進(jìn)行分桶, 當(dāng)然構(gòu)造一列新特征了""" bin = [i*10 for i in range(31)] num_data['power_bin'] = pd.cut(num_data['power'], bin, labels=False)當(dāng)然這里的新特征會(huì)有缺失。這里也放一個(gè)數(shù)據(jù)分桶的其他例子(遷移之用)
# 連續(xù)值經(jīng)常離散化或者分離成“箱子”進(jìn)行分析。 # 假設(shè)某項(xiàng)研究中一組人群的數(shù)據(jù),想將他們進(jìn)行分組,放入離散的年齡框中 ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32] # 如果按年齡分成18-25, 26-35, 36-60, 61以上的若干組,可以使用pandas中的cut bins = [18, 25, 35, 60, 100] # 定義箱子的邊 cats = pd.cut(ages, bins) print(cats) # 這是個(gè)categories對(duì)象 通過bin分成了四個(gè)區(qū)間, 然后返回每個(gè)年齡屬于哪個(gè)區(qū)間 # codes屬性 print(cats.codes) # 這里返回一個(gè)數(shù)組,指明每一個(gè)年齡屬于哪個(gè)區(qū)間 print(cats.categories) print(pd.value_counts(cats))???#?返回結(jié)果是每個(gè)區(qū)間年齡的個(gè)數(shù)# 與區(qū)間的數(shù)學(xué)符號(hào)一致, 小括號(hào)表示開放,中括號(hào)表示封閉, 可以通過right參數(shù)改變 print(pd.cut(ages,?bins,?right=False))# 可以通過labels自定義箱名或者區(qū)間名 group_names = ['Youth', 'YonngAdult', 'MiddleAged', 'Senior'] data = pd.cut(ages, bins, labels=group_names) print(data) print(pd.value_counts(data))# 如果將箱子的邊替代為箱子的個(gè)數(shù),pandas將根據(jù)數(shù)據(jù)中的最小值和最大值計(jì)算出等長的箱子 data2 = np.random.rand(20) print(pd.cut(data2, 4, precision=2)) # precision=2 將十進(jìn)制精度限制在2位# qcut是另一個(gè)分箱相關(guān)的函數(shù), 基于樣本分位數(shù)進(jìn)行分箱。取決于數(shù)據(jù)的分布,使用cut不會(huì)使每個(gè)箱子具有相同數(shù)據(jù)數(shù)量的數(shù)據(jù)點(diǎn),而qcut,使用 # 樣本的分位數(shù),可以獲得等長的箱 data3 = np.random.randn(1000) # 正太分布 cats = pd.qcut(data3, 4) print(pd.value_counts(cats))結(jié)果如下:
數(shù)據(jù)轉(zhuǎn)換
數(shù)據(jù)轉(zhuǎn)換的方式有:
數(shù)據(jù)歸一化(MinMaxScaler);
標(biāo)準(zhǔn)化(StandardScaler);
對(duì)數(shù)變換(log1p);
轉(zhuǎn)換數(shù)據(jù)類型(astype);
獨(dú)熱編碼(OneHotEncoder);
標(biāo)簽編碼(LabelEncoder);
修復(fù)偏斜特征(boxcox1p)等。
1. 數(shù)值特征歸一化, 因?yàn)檫@里數(shù)值的取值范圍相差很大
minmax = MinMaxScaler() num_data_minmax = minmax.fit_transform(num_data) num_data_minmax = pd.DataFrame(num_data_minmax, columns=num_data.columns, index=num_data.index)2. 類別特征獨(dú)熱一下
"""類別特征某些需要獨(dú)熱編碼一下""" hot_features = ['bodyType', 'fuelType', 'gearbox', 'notRepairedDamage'] cat_data_hot = pd.get_dummies(cat_data, columns=hot_features)3. 關(guān)于高勢(shì)集特征model,也就是類別中取值個(gè)數(shù)非常多的, 一般可以使用聚類的方式,然后獨(dú)熱,這里就采用了這種方式:
from scipy.cluster.hierarchy import linkage, dendrogram #from sklearn.cluster import AgglomerativeClustering from sklearn.cluster import KMeansac = KMeans(n_clusters=3) ac.fit(model_price_data)model_fea = ac.predict(model_price_data) plt.scatter(model_price_data[:,0], model_price_data[:,1], c=model_fea)cat_data_hot['model_fea'] = model_fea cat_data_hot = pd.get_dummies(cat_data_hot, columns=['model_fea'])效果如下:
但是發(fā)現(xiàn)KMeans聚類不好,可以嘗試層次聚類試試,并且這個(gè)聚類數(shù)量啥的應(yīng)該也會(huì)有影響,這里只是提供一個(gè)思路,我覺得這個(gè)特征做的并不是太好,還需改進(jìn)。
特征構(gòu)造
在特征構(gòu)造的時(shí)候,需要借助一些背景知識(shí),遵循的一般原則就是需要發(fā)揮想象力,盡可能多的創(chuàng)造特征,不用先考慮哪些特征可能好,可能不好,先彌補(bǔ)這個(gè)廣度。特征構(gòu)造的時(shí)候需要考慮數(shù)值特征,類別特征,時(shí)間特征。
對(duì)于數(shù)值特征,一般會(huì)嘗試一些它們之間的加減組合(當(dāng)然不要亂來,根據(jù)特征表達(dá)的含義)或者提取一些統(tǒng)計(jì)特征
對(duì)于類別特征,我們一般會(huì)嘗試之間的交叉組合,embedding也是一種思路
對(duì)于時(shí)間特征,這一塊又可以作為一個(gè)大專題來學(xué)習(xí),在時(shí)間序列的預(yù)測(cè)中這一塊非常重要,也會(huì)非常復(fù)雜,需要就盡可能多的挖掘時(shí)間信息,會(huì)有不同的方式技巧。當(dāng)然在這個(gè)比賽中涉及的實(shí)際序列數(shù)據(jù)有一點(diǎn)點(diǎn),不會(huì)那么復(fù)雜。
從這個(gè)比賽開始,看看這幾種類型的特征如何進(jìn)行構(gòu)造新特征出來。
根據(jù)上面的描述, 下面就可以著手進(jìn)行構(gòu)造特征了,由于在數(shù)據(jù)清洗的時(shí)候就根據(jù)字段的類型不同把數(shù)據(jù)進(jìn)行了劃分,現(xiàn)在可以直接對(duì)特征進(jìn)行構(gòu)造。
時(shí)間特征的構(gòu)造(time_data)
根據(jù)上面的分析,可以構(gòu)造的時(shí)間特征如下:
汽車的上線日期與汽車的注冊(cè)日期之差就是汽車的使用時(shí)間,一般來說與價(jià)格成反比
對(duì)汽車的使用時(shí)間進(jìn)行分箱,使用了3年以下,3-7年,7-10年和10年以上,分為四個(gè)等級(jí), 10年之后就是報(bào)廢車了,應(yīng)該會(huì)影響價(jià)格
淡旺季也會(huì)影響價(jià)格,所以可以從汽車的上線日期上提取一下淡旺季信息
汽車的使用時(shí)間特征
createDate-regDate, 反應(yīng)汽車使用時(shí)間,一般來說與價(jià)格成反比。但要注意的問題就是時(shí)間格式, regDateFalse這個(gè)字段有些是0月,如果忽略錯(cuò)誤計(jì)算的話,使用時(shí)間有一些會(huì)是空值, 當(dāng)然可以考慮刪除這些空值,但是因?yàn)橛?xùn)練集和測(cè)試集合并了,那么就不輕易刪除了。
本文采取的辦法是把錯(cuò)誤字段都給他加1個(gè)月,然后計(jì)算出天數(shù)之后在加上30天(這個(gè)有不同的處理方式, 但是一般不喜歡刪除或者置為空,因?yàn)閯h除和空值都有潛在的副作用)
# 這里是為了標(biāo)記一下哪些字段有錯(cuò)誤 def regDateFalse(x):if str(x)[4:6] == '00':return 1else: return 0 time_data['regDateFalse'] = time_data['regDate'].apply(lambda x: regDateFalse(x)) # 這里是改正錯(cuò)誤字段 def changeFalse(x):x = str(x)if x[4:6] == '00':x = x[0:4] + '01' + x[6:]x = int(x)return x time_data['regDate'] = time_data['regDate'].apply(lambda x: changeFalse(x)) # 使用時(shí)間:data['creatDate'] - data['regDate'],反應(yīng)汽車使用時(shí)間,一般來說價(jià)格與使用時(shí)間成反比 # 不過要注意,數(shù)據(jù)里有時(shí)間出錯(cuò)的格式,所以我們需要 errors='coerce' time_data['used_time'] = (pd.to_datetime(time_data['creatDate'], format='%Y%m%d') - pd.to_datetime(time_data['regDate'], format='%Y%m%d')).dt.days # 修改錯(cuò)誤 # 但是需要加上那一個(gè)月 time_data.loc[time_data.regDateFalse==1, 'used_time'] += 30 # 刪除標(biāo)記列 del time_data['regDateFalse']這樣,一個(gè)特征構(gòu)造完畢, used_time字段,表示汽車的使用時(shí)間。全部構(gòu)造完畢之后,我們?cè)倏匆幌陆Y(jié)果。
汽車是不是符合報(bào)廢
時(shí)間特征還可以繼續(xù)提取,我們假設(shè)用了10年的車作為報(bào)廢車的話, 那么我們可以根據(jù)使用天數(shù)計(jì)算出年數(shù), 然后根據(jù)年數(shù)構(gòu)造出一個(gè)特征是不是報(bào)廢
# 使用時(shí)間換成年來表示 time_data['used_time'] = time_data['used_time'] / 365.0 time_data['Is_scrap'] = time_data['used_time'].apply(lambda x: 1 if x>=10 else 0)我們還可以對(duì)used_time進(jìn)行分享,這個(gè)是根據(jù)背景估價(jià)的方法可以發(fā)現(xiàn), 汽車的使用時(shí)間3年,3-7年,10年以上的估價(jià)會(huì)有不同,所以分一下箱
bins = [0, 3, 7, 10, 20, 30] time_data['estivalue'] = pd.cut(time_data['used_time'], bins, labels=False)這樣就又構(gòu)造了兩個(gè)時(shí)間特征。Is_scrap表示是否報(bào)廢, estivalue表示使用時(shí)間的分箱。
是不是淡旺季
這個(gè)是根據(jù)汽車的上線售賣時(shí)間看, 每年的2, 3月份及6,7,8月份是整個(gè)汽車行業(yè)的低谷, 年初和年末及9月份是二手車銷售的黃金時(shí)期, 所以根據(jù)上線時(shí)間選出淡旺季。
# 選出淡旺季 low_seasons = ['3', '6', '7', '8'] time_data['is_low_seasons'] = time_data['creatDate'].apply(lambda x: 1 if str(x)[5] in low_seasons else 0)# 獨(dú)熱一下 time_data = pd.get_dummies(time_data, columns=['is_low_seasons'])# 這樣時(shí)間特征構(gòu)造完畢,刪除日期了 del time_data['regDate'] del time_data['creatDate']看一下最后的構(gòu)造結(jié)果, 報(bào)廢特征沒有構(gòu)造,因?yàn)榘l(fā)現(xiàn)了一個(gè)特點(diǎn)就是這里的數(shù)據(jù)10年以上的車會(huì)偏斜,所以感覺這個(gè)用10年作為分界線不太合適,只是提供一種思路。
根據(jù)汽車的使用時(shí)間或者淡旺季分桶進(jìn)行統(tǒng)計(jì)特征的構(gòu)造
這樣, 時(shí)間特征就基本構(gòu)造完畢,最后的結(jié)果如下:
這樣,時(shí)間特征這塊就構(gòu)造了10個(gè)特征出來, 當(dāng)然還可以更多, 由于篇幅原因,其他的可以自行嘗試。
類別特征的構(gòu)造(cat_data)
經(jīng)過上面的分析,可以構(gòu)造的類別特征如下:
從郵編中提取城市信息, 因?yàn)槭堑聡臄?shù)據(jù),所以參考德國的郵編,加入先驗(yàn)知識(shí), 但是感覺這個(gè)沒有用,可以先試一下
最好是從regioncode中提取出是不是華東地區(qū),因?yàn)槿A東地區(qū)是二手車交易的主要地區(qū)(這個(gè)沒弄出來,不知道這些編碼到底指的哪跟哪)
私用車和商用車分開(bodyType提取)
是不是微型車單獨(dú)處理,所以感覺那些車的類型OneHot的時(shí)候有點(diǎn)分散了(bodyType這個(gè)提取,然后one-hot)
新能源車和燃油車分開(在fuelType中提取,然后進(jìn)行OneHot)
地區(qū)編碼還是有影響的, 不同的地區(qū)汽車的保率不同
品牌這塊可以提取一些統(tǒng)計(jì)量, 統(tǒng)計(jì)特征的話上面這些新構(gòu)造的特征其實(shí)也可以提取
注意,OneHot不要太早,否則有些特征就沒法提取潛在信息了。
郵編特征
從郵編中提取城市信息, 因?yàn)槭堑聡臄?shù)據(jù),所以參考德國的郵編,加入先驗(yàn)知識(shí)。
cat_data['city'] = cat_data['regionCode'].apply(lambda x: str(x)[0])私用車和商務(wù)車分開(bodyType)
com_car = [2.0, 3.0, 6.0] # 商用車 GL_car = [0.0, 4.0, 5.0] # 豪華系列 self_car?=?[1.0,?7.0]def class_bodyType(x):if x in GL_car:return 0elif x in com_car:return 1else:return 2cat_data['car_class'] = cat_data['bodyType'].apply(lambda x : class_bodyType(x))新能源車和燃油車分開(fuelType)
# 是否是新能源 is_fuel = [0.0, 1.0, 2.0, 3.0] cat_data['is_fuel'] = cat_data['fuelType'].apply(lambda x: 1 if x in is_fuel else 0)構(gòu)造統(tǒng)計(jì)特征
這一塊依然是可以構(gòu)造很多統(tǒng)計(jì)特征,可以根據(jù)brand, 燃油類型, gearbox類型,車型等,都可以,這里只拿一個(gè)舉例,其他的類似,可以封裝成一個(gè)函數(shù)處理。
以gearbox構(gòu)建統(tǒng)計(jì)特征:
train_data_gearbox = train_data.copy() # 不要?jiǎng)觮rain_data train_data_gearbox['gearbox'] = cat_data['gearbox'][:train_data.shape[0]] train_data_gearbox['price']?=?train_targettrain_gb = train_data_gearbox.groupby('gearbox') all_info = {} for kind, kind_data in train_gb:info = {}kind_data = kind_data[kind_data['price'] > 0]info['gearbox_count'] = len(kind_data)info['gearbox_price_max'] = kind_data.price.max()info['gearbox_price_median'] = kind_data.price.median()info['gearbox_price_min'] = kind_data.price.min()info['gearbox_price_sum'] = kind_data.price.sum()info['gearbox_std'] = kind_data.price.std()info['gearbox_price_average'] = round(kind_data.price.sum() / (len(kind_data) + 1), 2)all_info[kind]?=?infogearbox_fe = pd.DataFrame(all_info).T.reset_index().rename(columns={"index": "gearbox"})cat_data = cat_data.merge(gearbox_fe, how='left', on='gearbox')當(dāng)然下面就可以把bodyType和fuelType刪除,因?yàn)樵撎崛〉男畔⒁蔡崛⊥炅?#xff0c;該獨(dú)熱的獨(dú)熱。
# 刪掉bodyType和fuelType,然后把gearbox, car_class is_fuel獨(dú)熱一下, 這個(gè)不能太早,構(gòu)造晚了統(tǒng)計(jì)特征之后再獨(dú)熱 del cat_data['bodyType'] del cat_data['fuelType']cat_data = pd.get_dummies(cat_data, columns=['gearbox', 'car_class', 'is_fuel', 'notRepairedDamage'])這樣,把類別特征構(gòu)造完畢。最終結(jié)果如下:
本文構(gòu)造了41個(gè)特征,當(dāng)然可以更多, 也是自己嘗試。
數(shù)值特征的構(gòu)造(num_data)
數(shù)值特征這塊,由于大部分都是匿名特征,處理起來不是太好處理,只能嘗試一些加減組合和統(tǒng)計(jì)特征
對(duì)里程進(jìn)行一個(gè)分箱操作
一部車有效壽命30萬公里,將其分為5段,每段6萬公里,每段價(jià)值依序?yàn)樾萝噧r(jià)的5/15、4/15、3/15、2/15、1/15。假設(shè)新車價(jià)12萬元,已行駛7.5萬公里(5年左右),那么該車估值為12萬元×(3+3+2+1)÷15=7.2萬元。
# 分成三段 bins = [0, 5, 10, 15] num_data['kil_bin'] = pd.cut(num_data['kilometer'], bins, labels=False)V系列特征的統(tǒng)計(jì)特征
平均值, 總和和標(biāo)準(zhǔn)差
v_features = ['v_' + str(i) for i in range(15)] num_data['v_sum'] = num_data[v_features].apply(lambda x: x.sum(), axis=1) num_data['v_mean'] = num_data[v_features].apply(lambda x: x.mean(), axis=1) num_data['v_std'] = num_data[v_features].apply(lambda x: x.std(), axis=1)這樣,數(shù)值特征構(gòu)造完畢,最終構(gòu)造的結(jié)果特征如下:
通過上面的步驟,特征工程就完成了。簡單的梳理一下, 基于二手車的背景信息進(jìn)行特征構(gòu)造的,首先是構(gòu)造的時(shí)間特征, 構(gòu)造了使用時(shí)間,是否報(bào)廢,使用時(shí)間分箱, 是否淡旺季等特征;然后是類別特征,構(gòu)造了郵編特征,是否私用,是否新能源,是否微型車,并且還提取了大量統(tǒng)計(jì)特征;最后是數(shù)值特征,給kilometer分箱, 對(duì)V特征進(jìn)行了統(tǒng)計(jì)等。
最后我們合并一下所有的數(shù)據(jù)
final_data = pd.concat([num_data, cat_data, time_data], axis=1) final_data.shape # (200000, 74) final_data.head()特征構(gòu)造后的最終數(shù)據(jù):
最終有74個(gè)特征, 當(dāng)然還可以更多,但是太多了也不是個(gè)好事,會(huì)造成冗余,特征相關(guān)等特征,對(duì)后面的模型造成一些負(fù)擔(dān)。所以,還得進(jìn)行特征篩選才可以,畢竟上面的74個(gè)特征不可能都是有用的,甚至有些還會(huì)造成負(fù)面影響。
特征選擇
特征選擇(排序)對(duì)于數(shù)據(jù)科學(xué)家、機(jī)器學(xué)習(xí)從業(yè)者來說非常重要。好的特征選擇能夠提升模型的性能,更能幫助我們理解數(shù)據(jù)的特點(diǎn)、底層結(jié)構(gòu),這對(duì)進(jìn)一步改善模型、算法都有著重要作用。
但是拿到數(shù)據(jù)集,一個(gè)特征選擇方法,往往很難同時(shí)完成這兩個(gè)目的。通常情況下,我們經(jīng)常不管三七二十一,選擇一種自己最熟悉或者最方便的特征選擇方法(往往目的是降維,而忽略了對(duì)特征和數(shù)據(jù)理解的目的), 但是真的好使嗎?只能說具體問題具體分析,也許會(huì)暴力出奇跡呢。
特征選擇主要有兩個(gè)功能:
減少特征數(shù)量、降維,使模型泛化能力更強(qiáng),減少過擬合
增強(qiáng)對(duì)特征和特征值之間的理解
通常來說,從兩個(gè)方面考慮來選擇特征:
特征是否發(fā)散:如果一個(gè)特征不發(fā)散,例如方差接近于0,也就是說樣本在這個(gè)特征上基本上沒有差異,這個(gè)特征對(duì)于樣本的區(qū)分并沒有什么用。
特征與目標(biāo)的相關(guān)性:這點(diǎn)比較顯見,與目標(biāo)相關(guān)性高的特征,應(yīng)當(dāng)優(yōu)選選擇。
根據(jù)特征選擇的形式又可以將特征選擇方法分為3種:
Filter:過濾法,按照發(fā)散性或者相關(guān)性對(duì)各個(gè)特征進(jìn)行評(píng)分,設(shè)定閾值或者待選擇閾值的個(gè)數(shù),選擇特征。
Wrapper:包裝法,根據(jù)目標(biāo)函數(shù)(通常是預(yù)測(cè)效果評(píng)分),每次選擇若干特征,或者排除若干特征。
Embedded:嵌入法,先使用某些機(jī)器學(xué)習(xí)的算法和模型進(jìn)行訓(xùn)練,得到各個(gè)特征的權(quán)值系數(shù),根據(jù)系數(shù)從大到小選擇特征。類似于Filter方法,但是是通過訓(xùn)練來確定特征的優(yōu)劣。
首先,導(dǎo)入之前處理備份的數(shù)據(jù):
# 導(dǎo)入最后的數(shù)據(jù) final_data = pd.read_csv('./pre_data/pre_data_beifen.csv')還是上面的final_data, 看一下構(gòu)造的特征:
過濾式
主要思想: 對(duì)每一維特征“打分”,即給每一維的特征賦予權(quán)重,這樣的權(quán)重就代表著該特征的重要性,然后依據(jù)權(quán)重排序。先進(jìn)行特征選擇,然后去訓(xùn)練學(xué)習(xí)器,所以特征選擇的過程與學(xué)習(xí)器無關(guān)。相當(dāng)于先對(duì)特征進(jìn)行過濾操作,然后用特征子集來訓(xùn)練分類器。
主要方法:
移除低方差的特征;
相關(guān)系數(shù)排序,分別計(jì)算每個(gè)特征與輸出值之間的相關(guān)系數(shù),設(shè)定一個(gè)閾值,選擇相關(guān)系數(shù)大于閾值的部分特征;
利用假設(shè)檢驗(yàn)得到特征與輸出值之間的相關(guān)性,方法有比如卡方檢驗(yàn)、t檢驗(yàn)、F檢驗(yàn)等。
互信息,利用互信息從信息熵的角度分析相關(guān)性。
這里,本文為大家提供一些有價(jià)值的小tricks:
對(duì)于數(shù)值型特征,方差很小的特征可以不要,因?yàn)樘]有什么區(qū)分度,提供不了太多的信息,對(duì)于分類特征,也是同理,取值個(gè)數(shù)高度偏斜的那種可以先去掉。
根據(jù)與目標(biāo)的相關(guān)性等選出比較相關(guān)的特征(當(dāng)然有時(shí)候根據(jù)字段含義也可以選)
卡方檢驗(yàn)一般是檢查離散變量與離散變量的相關(guān)性,當(dāng)然離散變量的相關(guān)性信息增益和信息增益比也是不錯(cuò)的選擇(可以通過決策樹模型來評(píng)估來看),person系數(shù)一般是查看連續(xù)變量與連續(xù)變量的線性相關(guān)關(guān)系。
去掉取值變化小的特征
這應(yīng)該是最簡單的特征選擇方法了:假設(shè)某特征的特征值只有0和1,并且在所有輸入樣本中,95%的實(shí)例的該特征取值都是1,那就可以認(rèn)為這個(gè)特征作用不大。如果100%都是1,那這個(gè)特征就沒意義了。
當(dāng)特征值都是離散型變量的時(shí)候這種方法才能用,如果是連續(xù)型變量,就需要將連續(xù)變量離散化之后才能用,而且實(shí)際當(dāng)中,一般不太會(huì)有95%以上都取某個(gè)值的特征存在,所以這種方法雖然簡單但是不太好用。
可以把它作為特征選擇的預(yù)處理,先去掉那些取值變化小的特征,然后再從接下來提到的的特征選擇方法中選擇合適的進(jìn)行進(jìn)一步的特征選擇。例如,我們前面的seller和offerType特征。
# 對(duì)方差的大小排序 select_data.std().sort_values() # select_data是final_data去掉了獨(dú)熱的那些特征根據(jù)這個(gè),可以把方差非常小的特征作為備選的刪除特征(備選,可別先盲目刪除)
單變量特征選擇
單變量特征選擇能夠?qū)γ恳粋€(gè)特征進(jìn)行測(cè)試,衡量該特征和響應(yīng)變量之間的關(guān)系,根據(jù)得分扔掉不好的特征。對(duì)于回歸和分類問題可以采用卡方檢驗(yàn)等方式對(duì)特征進(jìn)行測(cè)試。
這種方法比較簡單,易于運(yùn)行,易于理解,通常對(duì)于理解數(shù)據(jù)有較好的效果(但對(duì)特征優(yōu)化、提高泛化能力來說不一定有效);這種方法有許多改進(jìn)的版本、變種。
下面重點(diǎn)介紹一下pearson相關(guān)系數(shù),皮爾森相關(guān)系數(shù)是一種最簡單的,比較常用的方式。能幫助理解特征和響應(yīng)變量之間關(guān)系的方法,該方法衡量的是變量之間的線性相關(guān)性,結(jié)果的取值區(qū)間為[-1,1],-1表示完全的負(fù)相關(guān)(這個(gè)變量下降,那個(gè)就會(huì)上升),+1表示完全的正相關(guān),0表示沒有線性相關(guān)。
Pearson Correlation速度快、易于計(jì)算,經(jīng)常在拿到數(shù)據(jù)(經(jīng)過清洗和特征提取之后的)之后第一時(shí)間就執(zhí)行。Scipy的pearsonr方法能夠同時(shí)計(jì)算相關(guān)系數(shù)和p-value, 當(dāng)然pandas的corr也可以計(jì)算。
直接根據(jù)pearson系數(shù)畫出圖像:
corr = select_data.corr('pearson') # .corr('spearman') plt.figure(figsize=(25, 15)) corr['price'].sort_values(ascending=False)[1:].plot(kind='bar') plt.tight_layout()結(jié)果如下:
當(dāng)然,這個(gè)數(shù)據(jù)用pearson系數(shù)可能不是那么合理,可以使用spearman系數(shù),這個(gè)被認(rèn)為是排列后的變量的pearson的相關(guān)系數(shù), 具體的可以看(Pearson)皮爾遜相關(guān)系數(shù)和spearman相關(guān)系數(shù), 這里只整理兩者的區(qū)別和使用場(chǎng)景, 區(qū)別如下:
連續(xù)數(shù)據(jù),正態(tài)分布,線性關(guān)系,用pearson相關(guān)系數(shù)是最恰當(dāng),當(dāng)然用spearman相關(guān)系數(shù)也可以,效率沒有pearson相關(guān)系數(shù)高。
上述任一條件不滿足,就用spearman相關(guān)系數(shù),不能用pearson相關(guān)系數(shù)。
兩個(gè)定序測(cè)量數(shù)據(jù)(順序變量)之間也用spearman相關(guān)系數(shù),不能用pearson相關(guān)系數(shù)。
Pearson相關(guān)系數(shù)的一個(gè)明顯缺陷是,作為特征排序機(jī)制,他只對(duì)線性關(guān)系敏感。如果關(guān)系是非線性的,即便兩個(gè)變量具有一一對(duì)應(yīng)的關(guān)系,Pearson相關(guān)性也可能會(huì)接近0。
當(dāng)然還可以畫出熱力圖來,這個(gè)不陌生了吧, 這個(gè)的目的是可以看變量之間的關(guān)系, 相關(guān)性大的,可以考慮保留其中一個(gè):
# 下面看一下互相之間的關(guān)系 f, ax = plt.subplots(figsize=(50, 30)) sns.heatmap(corr, annot=True)結(jié)果如下:
從上面兩個(gè)步驟中,就可以發(fā)現(xiàn)一些結(jié)論:
根據(jù)與price的線性相關(guān)關(guān)系來看的話,我們可以考慮正負(fù)相關(guān)0.6以上的特征, v_std, v_12, v_0, v_8, estivalue_price_average, estivalue_price_median, estivalue_price_std, kil_bin, kilmoeter, estivalue_count, used_time, estivalue, v_3
某些變量之間有很強(qiáng)的的關(guān)聯(lián)性,比如v_mean和v_sum,這倆的相關(guān)性是1,所以可以刪掉其中一個(gè)。
當(dāng)然,依然是備選刪除選項(xiàng)和備選保留選項(xiàng)(這些都先別做), 因?yàn)槲覀冇袝r(shí)候不能盲目,就比如上面的相關(guān)性,明明知道pearson的缺陷是無法捕捉非線性相關(guān),所以得出的這個(gè)結(jié)論也是片面的結(jié)論。這些都是備選,先做個(gè)心中有數(shù),后面再用一些別的方式看看再說(如果現(xiàn)在就刪除了,后面的方法就不好判斷了)
包裹式
單變量特征選擇方法獨(dú)立的衡量每個(gè)特征與響應(yīng)變量之間的關(guān)系,另一種主流的特征選擇方法是基于機(jī)器學(xué)習(xí)模型的方法。有些機(jī)器學(xué)習(xí)方法本身就具有對(duì)特征進(jìn)行打分的機(jī)制,或者很容易將其運(yùn)用到特征選擇任務(wù)中,例如回歸模型,SVM,決策樹,隨機(jī)森林等等。
主要思想:包裹式從初始特征集合中不斷的選擇特征子集,訓(xùn)練學(xué)習(xí)器,根據(jù)學(xué)習(xí)器的性能來對(duì)子集進(jìn)行評(píng)價(jià),直到選擇出最佳的子集。包裹式特征選擇直接針對(duì)給定學(xué)習(xí)器進(jìn)行優(yōu)化。
主要方法:遞歸特征消除算法, 基于機(jī)器學(xué)習(xí)模型的特征排序
優(yōu)缺點(diǎn):
優(yōu)點(diǎn):從最終學(xué)習(xí)器的性能來看,包裹式比過濾式更好;
缺點(diǎn):由于特征選擇過程中需要多次訓(xùn)練學(xué)習(xí)器,因此包裹式特征選擇的計(jì)算開銷通常比過濾式特征選擇要大得多。
下面,這里整理基于學(xué)習(xí)模型的特征排序方法,這種方法的思路是直接使用你要用的機(jī)器學(xué)習(xí)算法,針對(duì)每個(gè)單獨(dú)的特征和響應(yīng)變量建立預(yù)測(cè)模型。其實(shí)Pearson相關(guān)系數(shù)等價(jià)于線性回歸里的標(biāo)準(zhǔn)化回歸系數(shù)。
假如某個(gè)特征和響應(yīng)變量之間的關(guān)系是非線性的,可以用基于樹的方法(決策樹、隨機(jī)森林)、或者擴(kuò)展的線性模型等?;跇涞姆椒ū容^易于使用,因?yàn)樗麄儗?duì)非線性關(guān)系的建模比較好,并且不需要太多的調(diào)試。但要注意過擬合問題,因此樹的深度最好不要太大,再就是運(yùn)用交叉驗(yàn)證。
我們可以用隨機(jī)森林來跑一下,看看隨機(jī)森林比較喜歡特征:
from sklearn.model_selection import cross_val_score, ShuffleSplit from sklearn.ensemble import RandomForestRegressor from?sklearn.model_selection?import?KFoldX = select_data.iloc[:, :-1] Y = select_data['price'] names?=?select_data.columnsrf = RandomForestRegressor(n_estimators=20, max_depth=4) kfold = KFold(n_splits=5, shuffle=True, random_state=7) scores = [] for column in X.columns:print(column)tempx = X[column].values.reshape(-1, 1)score = cross_val_score(rf, tempx, Y, scoring="r2",cv=kfold)scores.append((round(np.mean(score), 3), column)) print(sorted(scores, reverse=True))這里對(duì)喜歡的特征排序并打分,結(jié)果如下:
這里就可以看出隨機(jī)森林有用的特征排序,如果我們后面選擇隨機(jī)森林作為模型,就可以根據(jù)這個(gè)特征重要度選擇特征。當(dāng)然,如果你是xgboost,xgboost里面有個(gè)畫特征重要性的函數(shù),可以這樣做:
# 下面再用xgboost跑一下 from xgboost import XGBRegressor from xgboost import plot_importancexgb = XGBRegressor() xgb.fit(X, Y)plt.figure(figsize=(20, 10)) plot_importance(xgb) plt.show()這樣,直接把xgboost感興趣的特征畫出來:
最后,我們把上面的這兩種方式封裝起來, 還可以畫出邊際效應(yīng):
from mlxtend.feature_selection import SequentialFeatureSelector as SFS from sklearn.linear_model import LinearRegression from sklearn.ensemble import RandomForestRegressor # sfs = SFS(LinearRegression(), k_features=20, forward=True, floating=False, scoring='r2', cv=0) sfs?=?SFS(RandomForestRegressor(n_estimators=10,?max_depth=4),?k_features=20,?forward=True,?floating=False,?scoring='r2',?cv=0)X = select_data.iloc[:, :-1] Y = select_data['price']sfs.fit(X, Y) sfs.k_feature_names_ # 隨機(jī)森林放這里跑太慢了,所以中斷了結(jié)果如下:
畫出邊際效應(yīng):
# 畫出邊際效應(yīng) from mlxtend.plotting import plot_sequential_feature_selection as plot_sfsfig1 = plot_sfs(sfs.get_metric_dict(), kind='std_dev') plt.grid() plt.show()這個(gè)也是看選出的特征的重要性:
這樣,根據(jù)我們使用的模型,我們可以對(duì)特征進(jìn)行一個(gè)選擇,綜合上面的這幾種方式,我們就可以把保留和刪除的特征給選出來了,該刪除的可以刪除了。
如果真的這樣嘗試一下,就會(huì)發(fā)現(xiàn)保留的特征里面, v_std, v_3, used_time, power, kilometer, estivalue等這些特征都在,雖然我們不知道v系列特征的含義,但是汽車使用時(shí)間,發(fā)動(dòng)機(jī)功率,行駛公里, 汽車使用時(shí)間的分箱特征其實(shí)對(duì)price的影響都是比較大的。
嵌入式
在過濾式和包裹式特征選擇方法中,特征選擇過程與學(xué)習(xí)器訓(xùn)練過程有明顯的分別。而嵌入式特征選擇在學(xué)習(xí)器 訓(xùn)練過程中自動(dòng)地進(jìn)行特征選擇。嵌入式選擇最常用的是L1正則化與L2正則化。在對(duì)線性回歸模型加入兩種正則化方法后,他們分別變成了嶺回歸與Lasso回歸。
主要思想:在模型既定的情況下學(xué)習(xí)出對(duì)提高模型準(zhǔn)確性最好的特征。也就是在確定模型的過程中,挑選出那些對(duì)模型的訓(xùn)練有重要意義的特征。
主要方法:簡單易學(xué)的機(jī)器學(xué)習(xí)算法–嶺回歸(Ridge Regression),就是線性回歸過程加入了L2正則項(xiàng)。
L1正則化有助于生成一個(gè)稀疏權(quán)值矩陣,進(jìn)而可以用于特征選擇
L2正則化在擬合過程中通常都傾向于讓權(quán)值盡可能小,最后構(gòu)造一個(gè)所有參數(shù)都比較小的模型。因?yàn)橐话阏J(rèn)為參 數(shù)值小的模型比較簡單,能適應(yīng)不同的數(shù)據(jù)集,也在一定程度上避免了過擬合現(xiàn)象??梢栽O(shè)想一下對(duì)于一個(gè)線性 回歸方程,若參數(shù)很大,那么只要數(shù)據(jù)偏移一點(diǎn)點(diǎn),就會(huì)對(duì)結(jié)果造成很大的影響;但如果參數(shù)足夠小,數(shù)據(jù)偏移 得多一點(diǎn)也不會(huì)對(duì)結(jié)果造成什么影響,專業(yè)一點(diǎn)的說法是『抗擾動(dòng)能力強(qiáng)』
這里簡單介紹一下怎么使用,其實(shí)和上面機(jī)器學(xué)習(xí)模型的使用方法一樣, 所以有時(shí)候這些方法沒有必要嚴(yán)格的區(qū)分開:
from sklearn.linear_model import LinearRegression, Ridge,Lassomodels = [LinearRegression(), Ridge(), Lasso()] result = dict()for model in models:model_name = str(model).split('(')[0]scores = cross_val_score(model, X=train_X, y=train_y, verbose=0, cv=5, scoring='r2')result[model_name] = scoresPCA降維技術(shù)
通過上面的特征選擇部分,可以選出更好的分析特征,但是如果這些特征維度仍然很高怎么辦?
如果數(shù)據(jù)特征維度太高,首先計(jì)算很麻煩,其次增加了問題的復(fù)雜程度,分析起來也不方便。這時(shí)候就會(huì)想是不是再去掉一些特征就好了呢?但是這個(gè)特征也不是憑自己的意愿去掉的,因?yàn)槊つ繙p少數(shù)據(jù)的特征會(huì)損失掉數(shù)據(jù)包含的關(guān)鍵信息,容易產(chǎn)生錯(cuò)誤的結(jié)論,對(duì)分析不利。
所以想找到一個(gè)合理的方式,既可以減少需要分析的指標(biāo),而且盡可能多的保持原來數(shù)據(jù)的信息,PCA就是這個(gè)合理的方式之一。 但要注意一點(diǎn), 特征選擇是從已存在的特征中選取攜帶信息最多的,選完之后的特征依然具有可解釋性,而PCA,將已存在的特征壓縮,降維完畢后不是原來特征的任何一個(gè),也就是PCA降維之后的特征我們根本不知道什么含義了。
當(dāng)然,針對(duì)這個(gè)比賽,也不打算使用PCA降維技術(shù),因?yàn)槿绻鐾炅颂卣鬟x擇之后,就會(huì)發(fā)現(xiàn)特征的量不是那么多, 但筆者在這里用了一下,可以看看效果:
from sklearn.decomposition import PCA # 然后使用 pca = PCA(n_components=10) X_new = pca.fit_transform(X)"""查看PCA的一些屬性""" print(X_new.shape) # (200000, 10) print(pca.explained_variance_) # 屬性可以查看降維后的每個(gè)特征向量上所帶的信息量大小(可解釋性方差的大小) print(pca.explained_variance_ratio_) # 查看降維后的每個(gè)新特征的信息量占原始數(shù)據(jù)總信息量的百分比 print(pca.explained_variance_ratio_.sum()) # 降維后信息保留量上面假設(shè)保留了10個(gè)特征,然后運(yùn)行代碼,一下子就成了10維的矩陣, 我們可以看一下X_new
這些數(shù)已經(jīng)只能說盡可能的保留原有的數(shù)據(jù)信息,但是是什么含義,就不得而知了。
參考
【1】Datawhale 零基礎(chǔ)入門數(shù)據(jù)挖掘-Task3 特征工程
【2】數(shù)據(jù)清洗與準(zhǔn)備
【3】特征選擇,我們真的學(xué)會(huì)了嗎?
【4】(Pearson)皮爾遜相關(guān)系數(shù)和spearman相關(guān)系數(shù)
【5】Python機(jī)器學(xué)習(xí)庫sklearn自動(dòng)特征選擇
【6】白話機(jī)器學(xué)習(xí)算法理論+實(shí)戰(zhàn)之PCA降維
【7】機(jī)器學(xué)習(xí)中的異常值檢測(cè)和處理
【8】系列上篇「數(shù)據(jù)分析」之零基礎(chǔ)入門數(shù)據(jù)挖掘
往期精彩回顧適合初學(xué)者入門人工智能的路線及資料下載機(jī)器學(xué)習(xí)在線手冊(cè)深度學(xué)習(xí)在線手冊(cè)AI基礎(chǔ)下載(pdf更新到25集)本站qq群1003271085,加入微信群請(qǐng)回復(fù)“加群”獲取一折本站知識(shí)星球優(yōu)惠券,請(qǐng)回復(fù)“知識(shí)星球”喜歡文章,點(diǎn)個(gè)在看
總結(jié)
以上是生活随笔為你收集整理的【零基础入门数据挖掘】-特征工程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【零基础入门数据挖掘】-模型融合
- 下一篇: 【零基础入门数据挖掘】-建模调参