Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

Rachel發表於2019-06-05

問題

在實際應用中,我們經常會遇到像下圖這樣的情況,那就是有的列是非數字的。但是 Machine Learning 只善於處理數字,所以我們需要將非數字的內容進行合理的轉換,再來訓練模型。

Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

在上圖中的 town 列被稱為 categorical variables(類別變數)。categorical variables 又分為兩種,一種是 nominal,另一種是 ordinal。下面分別解釋一下:

nominal: 分類的值沒有任何先後順序或等級關係
ordinal:分類的值是有等級關係的

例子如下:

Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

解決方案

很顯然,上面 town 列應該屬於 nominal category variables, 我們可以用一種名為 One Hot Encoding 的技術來解決這個問題。我們為列中的每一種分類都分別單獨建一個列,用 0 或 1 填充,這些新建的列被稱作 dummy vaiables。最終想要的效果如下圖:

Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

具體實現方法(兩種):

方法一:使用 Pandas 的 get_dummies 方法

import pandas as pd
from sklearn import linear_model
df = pd.read_csv('/Users/rachel/Downloads/py-master/ML/5_one_hot_encoding/homeprices.csv')

// 獲取 town 列的 dummies
dummies = pd.get_dummies(df.town)

// 合併新生成的 dummies 列與原表
merged = pd.concat([df, dummies], axis='columns')

// 把原表的 town 列刪掉, 還要刪掉 dummies 列中的任意一列
final = merged.drop(['town', 'west windsor'], axis='columns')

Tips:

這裡使用 'west windsor', 'monroe township' 和 'robbinsville' 三個列來分別表示原來 'town' 列的三個類別, 然後用 0 和 1 區別到底是哪個類別. 之所以要刪掉一列, 是因為用兩個列的值就可以推匯出第三列的值, 比如, 我們現在隨機刪掉了 'west windsor' 列的值, 那麼 'monroe township' 列或者 'robbinsville' 是 1 的時候, 'west windsor' 列必然是 0, 而如果這兩列都為 0 的時候, 'west windsor' 列必然是 1, 所以, 就可以省掉那一列,據說也是必須刪掉這多餘的一列,否則在訓練模型的時候會出現錯誤。另外, 如果是用 LinearRegression 的話, 其實, 它會自動幫我們刪除一列, 但是為了養成良好的習慣, 還是自己主動刪除吧.

看下最後整理後的資料:

Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

// 例項化一個模型
model = linear_model.LinearRegression()

// 準備資料, 這裡 x 的資料就是表裡除了 price 的所有欄位, 所以直接把 price 欄位刪了, 方便快捷
x = final.drop('price', axis='columns')
y = final.price
// 訓練模型
model.fit(x, y)

// 從模型取資料: area 2800, robinsville 的房子價格
model.predict([[2800, 0, 1]])

// 這個方法是測下這個模型的精準度, 這個值應該是還可以
model.score(x, y)  //0.9573929037221873

方法二:使用 sklearn 的 OneHotEncoder

1. 重新引入 dataframe

Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

2. 將 town 列的值轉為數字

from sklearn.preprocessing import LabelEncoder

// 建立 LabelEncoder 物件
le = LabelEncoder()

// 把原 dataframe 重新賦給變數 dfle
dfle = df

// 把 town 列轉為數值
dfle.town = le.fit_transform(dfle.town)
dfle

看下效果:

Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

// 設定 x 的值, 通過 values 方法, 把 x 值轉為陣列, 否則是 dataframe
x = dfle[['town', 'area']].values
x

Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

3. 用 OneHotEncoder 獲取 dummy variables

from sklearn.preprocessing import OneHotEncoder

// 用 OneHotEncoder 將陣列的第一列轉為 dummy variable
ohe = OneHotEncoder(categorical_features=[0])
x = ohe.fit_transform(x).toarray()

// 取所有行的值, 去掉第一列的值, 也就是隻保留 dummy variables 中的任意兩列
x = x[:, 1:]

Machine Learning (4) - 用 Dummy Variables & One Hot Encoding 處理非數字列值

y = dfle.price

// 訓練模型
model.fit(x, y)

model.predict([[1, 0, 2800]])

相關文章