Kaggle教程 機器學習中級3 分類變量

轉載請註明出處:https://leytton.blog.csdn.net/article/details/101350667
如果本文對您有所幫助,請點個贊讓我知道哦 😃

在本教程中,你將瞭解什麼是分類變量,以及處理這類數據的三種方法。

1、介紹

分類變量類似於枚舉,擁有特定數量的值類型。

  • 比如一項調查,詢問你多久喫一次早餐,並提供四個選項:“從不”、“很少”、“大多數日子”或“每天”。在本例中,數據是分類的,因爲答案屬於一組固定的類別。

  • 如果對人們所擁有的汽車品牌進行調查,回答可以分爲“本田”、“豐田”和“福特”。在本例中,數據也是分類的。

如果您沒有預處理這些分類變量,就將這些變量應用於機器學習模型中,大多數情況您將得到一個錯誤結果。在本教程中,我們將比較三種預處理分類數據的方法。

2、三種方法

1) 刪除分類變量
處理分類變量最簡單的方法是從數據集中刪除它們。這種方法適用於該列中不包含有用信息的情況。

2) 標籤編碼
標籤編碼將每個變量類型標記爲不同的整數。
在這裏插入圖片描述
這種方法假設類別的順序爲:“Never”(0)<“rare”(1)<“Most days”(2)<“Every day”(3)。

在本例中,這個假設是有意義的,因爲對類別有個唯一的排名。 並不是所有的分類變量在值中都有一個明確的順序,但是我們將那些有順序的變量稱爲有序變量。對於基於樹的模型(如決策樹和隨機森林),有序變量的標籤編碼可能效果不錯。

3) One-Hot 編碼

“One-hot”編碼創建新列,表明原始數據中每個可能值的存在(或不存在)。爲了說明這點,我們舉個例子:
在這裏插入圖片描述

在原始數據集中,“Color”是一個分類變量,包含“Red”、“Yellow”和“Green”三個類別。對應的one-hot編碼是每個可能的值各自作爲一列,原始數據集中的每一行作爲一行。當原始值爲“Red”時,我們在“Red”列中放入1;如果原始值是“Yellow”,則在“Yellow”列中放入1,以此類推。

標籤編碼不同,one-hot編碼不假定類別的順序。因此,如果在分類數據中沒有明確的順序(例如,“紅色”既不比“黃色”多也不比“黃色”少),這種方法可能會特別有效。我們把沒有內在排序的分類變量稱爲名義變量

如果分類變量具有大量不同的值(超過15個),效果將不會很好。

3、案例

像前一篇教程一樣,我們將使用 Melbourne Housing數據集

我們不會關注數據加載步驟。假設您已經擁有了X_trainX_validy_trainy_valid中的訓練和驗證數據。

import pandas as pd
from sklearn.model_selection import train_test_split

# Read the data
data = pd.read_csv('../input/melbourne-housing-snapshot/melb_data.csv')

# Separate target from predictors
y = data.Price
X = data.drop(['Price'], axis=1)

# Divide data into training and validation subsets
X_train_full, X_valid_full, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2,
                                                                random_state=0)

# Drop columns with missing values (simplest approach)
cols_with_missing = [col for col in X_train_full.columns if X_train_full[col].isnull().any()] 
X_train_full.drop(cols_with_missing, axis=1, inplace=True)
X_valid_full.drop(cols_with_missing, axis=1, inplace=True)

# "Cardinality" means the number of unique values in a column
# Select categorical columns with relatively low cardinality (convenient but arbitrary)
low_cardinality_cols = [cname for cname in X_train_full.columns if X_train_full[cname].nunique() < 10 and 
                        X_train_full[cname].dtype == "object"]

# Select numerical columns
numerical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].dtype in ['int64', 'float64']]

# Keep selected columns only
my_cols = low_cardinality_cols + numerical_cols
X_train = X_train_full[my_cols].copy()
X_valid = X_valid_full[my_cols].copy()

我們使用下面的head()方法查看訓練數據。

X_train.head()

輸出結果:

	Type 	Method 	Regionname 	Rooms 	Distance 	Postcode 	Bedroom2 	Bathroom 	Landsize 	Lattitude 	Longtitude 	Propertycount
12167 	u 	S 	Southern Metropolitan 	1 	5.0 	3182.0 	1.0 	1.0 	0.0 	-37.85984 	144.9867 	13240.0
6524 	h 	SA 	Western Metropolitan 	2 	8.0 	3016.0 	2.0 	2.0 	193.0 	-37.85800 	144.9005 	6380.0
8413 	h 	S 	Western Metropolitan 	3 	12.6 	3020.0 	3.0 	1.0 	555.0 	-37.79880 	144.8220 	3755.0
2919 	u 	SP 	Northern Metropolitan 	3 	13.0 	3046.0 	3.0 	1.0 	265.0 	-37.70830 	144.9158 	8870.0
6043 	h 	S 	Western Metropolitan 	3 	13.3 	3020.0 	3.0 	1.0 	673.0 	-37.76230 	144.8272 	4217.0

接下來,我們獲得訓練數據中所有分類變量的列。

我們通過檢查每個列的數據類型(或dtype)來做到這一點。object 類型表示改列存在文本(理論上它還可以是其他東西,但對於我們的目的來說並不重要)。對於這個數據集,帶有文本的列表示分類變量。

# Get list of categorical variables
s = (X_train.dtypes == 'object')
object_cols = list(s[s].index)

print("Categorical variables:")
print(object_cols)

輸出結果:

Categorical variables:
['Type', 'Method', 'Regionname']

定義函數來評估每種方法的效果

我們定義了一個函數score_dataset()來比較處理分類變量的不同方法。該函數計算隨機森林模型平均絕對誤差(MAE)。一般來說,我們希望MAE越低越好!

方法1的得分(刪除分類變量)

我們使用select_dtypes()方法刪除對象列。

drop_X_train = X_train.select_dtypes(exclude=['object'])
drop_X_valid = X_valid.select_dtypes(exclude=['object'])

print("MAE from Approach 1 (Drop categorical variables):")
print(score_dataset(drop_X_train, drop_X_valid, y_train, y_valid))
MAE from Approach 1 (Drop categorical variables):
175703.48185157913

方法2的得分(標籤編碼)

Scikit-learn有一個LabelEncoder類,可以用來獲取標籤編碼。我們循環遍歷分類變量,並將標籤編碼器分別應用於每一列。

from sklearn.preprocessing import LabelEncoder

# 複製一份數據防止改變源數據 
label_X_train = X_train.copy()
label_X_valid = X_valid.copy()

# 將標籤編碼器分別應用於每一列
label_encoder = LabelEncoder()
for col in object_cols:
    label_X_train[col] = label_encoder.fit_transform(X_train[col])
    label_X_valid[col] = label_encoder.transform(X_valid[col])

print("MAE from Approach 2 (Label Encoding):") 
print(score_dataset(label_X_train, label_X_valid, y_train, y_valid))
MAE from Approach 2 (Label Encoding):
165936.40548390493

在上面的代碼中,對於每個列,我們隨機分配一個唯一整數。這是一種比提供自定義標籤更簡單的常見方法;然而,如果我們爲所有有序變量提供更好的信息標籤,效果會更好。

方法3的得分((One-Hot編碼)

我們使用scikit-learnOneHotEncoder類來獲得one-hot編碼。有許多參數可定義。

  • 設置handle_unknown='ignore',以避免在驗證數據包含訓練數據中沒有包括的值時發生錯誤
  • 設置sparse=False可以確保將已編碼的列作爲numpy數組(而不是稀疏矩陣)返回。

爲了使用這個編碼器,我們提供了只有分類變量的數據列。舉例來說,爲了對訓練數據進行編碼,我們提供了X_train[object_cols](代碼中的object_cols表示分類變量名稱,X_train[object_cols]包含了訓練數據的所有分類變量)。

from sklearn.preprocessing import OneHotEncoder

# 將one-hot編碼器分別應用於每一列分類變量
OH_encoder = OneHotEncoder(handle_unknown='ignore', sparse=False)
OH_cols_train = pd.DataFrame(OH_encoder.fit_transform(X_train[object_cols]))
OH_cols_valid = pd.DataFrame(OH_encoder.transform(X_valid[object_cols]))

# One-hot編碼時移除了index;補回來
OH_cols_train.index = X_train.index
OH_cols_valid.index = X_valid.index

# 刪除分類列(將替換爲One-hot編碼),留下編碼列
num_X_train = X_train.drop(object_cols, axis=1)
num_X_valid = X_valid.drop(object_cols, axis=1)

# 向數值特徵添加One-hot編碼列
OH_X_train = pd.concat([num_X_train, OH_cols_train], axis=1)
OH_X_valid = pd.concat([num_X_valid, OH_cols_valid], axis=1)

print("MAE from Approach 3 (One-Hot Encoding):") 
print(score_dataset(OH_X_train, OH_X_valid, y_train, y_valid))

輸出結果:

MAE from Approach 3 (One-Hot Encoding):
166089.4893009678

4、哪種方法最好?

在本案例中,刪除分類變量(方法1)的性能最差,因爲它有最高的MAE分數。至於另外兩種方法,由於返回的MAE分數值非常接近,沒有太大差異。

通常,one-hot編碼(方法3)的效果最好,刪除分類變量(方法1)的效果最差,但還得視情況而定。

5、結論

這個世界充滿了分類數據。如果您知道如何使用這種常見的數據類型,您將成爲一個更高效的數據科學家!

6、去吧,皮卡丘

把你的新技能運用到下面的練習中

原文:
https://www.kaggle.com/alexisbcook/categorical-variables

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