機器學習之特徵工程

前言

之前照着kaggle上的幾個大神的帖子對“泰坦尼克存活率”的例子進行了學習和模仿,發現特徵工程真的很重要,特徵工程有一定的套路,這裏的套路我更想理解爲是一些必備的處理數據的步驟。當我們手上拿到了一組數據的時候,爲了“讓數據說話”(當然數據不會說話,我們做特徵工程就是爲了讓數據說話),使用這些常規套路,能夠讓我們更快地去了解這些陌生的數據,進而加上我們對這批數據的理解,發散思維,去完成對數據的處理。

廢話不多說,下面直接進入正題

step1:將後續所需要的包導入,包括:pandas,numpy,matplotlib,sklearn等

import pandas as pd   
import numpy as np
from pandas import Series,DataFrame
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor
from sklearn import cross_validation

step2:導入數據,沒有數據你去搗鼓誰去。這裏數據分爲兩個,訓練集和測試集,具體怎麼下載可以直接上kaggle官網下或者自行百度下載。

這裏可以使用read_csv或者read_table來讀取數據,針對你存儲數據文件的類型選取合適的方法。

data_train = pd.read_csv("train.csv")
data_test = pd.read_csv("test.csv")


step3:查看數據的信息,包括數據的每列的數量(查看是否有缺失值),查看每列數據的表達形式,是數字還是字符串。


step4:針對不同的數據類型,我們有不同的處理方法,主要有以下幾大類:

(1)有限個數的關係型,也就是在這一列中只有這麼幾個選項,對於這種數據,我們通常採用one-hot encoder.

(2)數字:幾乎任何一個數據集都會存在數據缺失的問題,現在,我們先來討論一下如何處理缺失值。

step5:通常遇到缺值的情況,我們會有幾種常見的處理方式

  • 如果缺值的樣本佔總數比例極高,我們可能就直接捨棄了,作爲特徵加入的話,可能反倒帶入noise,影響最後的結果了
  • 如果缺值的樣本適中,而該屬性非連續值特徵屬性(比如說類目屬性),那就把NaN作爲一個新類別,加到類別特徵中
  • 如果缺值的樣本適中,而該屬性爲連續值特徵屬性,有時候我們會考慮給定一個step(比如這裏的age,我們可以考慮每隔2/3歲爲一個步長),然後把它離散化,之後把NaN作爲一個type加到屬性類目中。
  • 有些情況下,缺失的值個數並不是特別多,那我們也可以試着根據已有的值,擬合一下數據,補充上。
方法一:
在這個例子中,Age這個feature的缺失值大概100多個,不是很多,而且年齡對於最終的獲救率是十分重要的,因此不能輕易的捨棄,而應該努力進行補全操作,在衆多擬合算法中我們可以挑選一個去進行補全。
#首先將年齡爲空和不爲空的數據分開
age_df = data_train[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]#將數據集以這幾個feature爲內容提取出來
know_age = age_df.Age.notnull()  #得到一個Series
know_age = age_df[know_age].as_matrix()#將年齡不爲空的那部分數據提取出來  然後將DataFrame格式變爲array的矩陣格式:as_matrix
unknow_age = age_df[age_df.Age.isnull()].as_matrix()
這樣我們就獲得了新的兩個數據集,將age非空的數據集作爲訓練集,空集爲待預測集,接下來就可以使用擬合算法了(想用什麼就用什麼,這我就不管了,不過一般推薦隨機森林)。
方法二:
將年齡離散化:求得訓練集和測試集年齡的均值和方差,在(均值-方差,均值+方差)的範圍內隨機生成年齡將其填充進去。
#計算titanic_df中Age這一列的均值,方差和空值的個數
average_age_titanic = titanic_df['Age'].mean()
std_age_titanic = titanic_df['Age'].std()
count_nan_age_titanic = titanic_df['Age'].isnull().sum()

#計算test_df中Age這一列的均值,方差和空值的個數
average_age_test = test_df['Age'].mean()
std_age_test = test_df['Age'].std()
count_nan_age_test = test_df['Age'].isnull().sum()

#以均值爲基準,方差爲波動範圍,用這個範圍內的隨機數去填充缺失的年齡值
rand_1 = np.random.randint(average_age_titanic - std_age_titanic, average_age_titanic + std_age_titanic, size = count_nan_age_titanic)
rand_2 = np.random.randint(average_age_test - std_age_test, average_age_test + std_age_test, size = count_nan_age_test)
dataset['Age'][np.isnan(dataset['Age'])] = rand1


step6:有的feature是字符串表示,只有這麼幾個選項的,這時就用one-hot encoder,可以使用pd.get_dummies
dummies_Cabint = pd.get_dummies(data_test['Cabin'],prefix='Cabin')
這樣,feature就變成了用0 1表示的了,會多出幾列。







step6:在一組數據中,數字類型的feature往往佔大多數,因此我們可以先簡單看一下數字類型的數據分佈。


通過這個命令可以看到所有是數字類型的feature的簡單的統計數據:各個feature的含有數據的個數,他們的均值,方差,最小值,四分之一值,中值,四分之三值以及最大值是多少。

step6:畢竟數據量都很大,光看數字還是很抽象的,什麼也看不出來,接下來是重頭戲,將數據直觀化:畫圖

  畫圖一般會用到兩個包:matplotlib和seaborn,下面先說說matplotlib。

  在matplotlib畫圖的時候,能畫很多種圖,可以使用kind參數來控制:

  kind參數 : 'line', 'bar', 'barh', 'kde',其中:

  bar:柱狀圖(豎着的) 可以畫出某一個feature的數量對比;

  barh:也是柱狀圖,只不過把柱狀圖橫過來了;

  kde:與直方圖相關的一種類型圖,是通過計算“可能會產生觀測數據的連續概率分佈的估計”而產生的;

  line:折線圖 橫軸是序號 縱軸是表中的數值 連起來得到的。

  在使用matplotlib畫圖的時候,我們通常要定義一個存放圖的布,可以理解爲畫布,這張畫布的大小我們可以控制,一幅畫布上有多少張圖也由我們來定。

fig, (axis1,axis2,axis3) = plt.subplots(1,3,figsize=(15,5))
我們採用這種方法,一句話就定義了畫布fig,畫布上三個子圖axis1,axis2,axis3,而且還可以順帶着把畫布的大小一起定義了,多麼省事。


  

  



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章