機器學習數據預處理該怎樣做?(轉載)

訓練一個機器學習項目,對數據的預處理是非常重要的,所謂“磨刀不誤砍柴工”,這決定了整個項目的效率,多花半個小時來對數據進行更優化的處理,也許在之後的訓練運行過程中會節省一個小時甚至一天的時間。

接下來我們就來看看如何磨這把“刀”吧。

導入數據

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

先導入數據預處理所需要的庫,在Python中,最流行的三個庫也就是Numpy、Matplotlib 和 Pandas。對於數據預處理而言,Pandas 和 Numpy 基本是必需的,而Matplotlib.pyplot則是滿足繪圖所需要的庫。

我們通常處理的數據集是csv文件,這時我們用下面這條語句

dataset = pd.read_csv('train_data.csv')

用Pandas(pd.read_csv)來讀入數據集。之後輸入dataset並回車可以看到我們讀入的數據。(圖中僅顯示了一部分)
在這裏插入圖片描述
然而有的時候我們想要輸入的數據已經壓縮好了譬如是一文件夾的圖片,那我們可以用另一種讀取數據的方式,如下:

import glob
image = glob.glob('./*.jpg')

這樣的操作會讀入當前目錄下的所有jpg格式的圖片

數據處理的第一步應該是打亂輸入的數據,以防數據集是以某種規律整合在一起的,這對於我們的訓練是有利的

dataset= np.random.permutation(image)

在這之後我們需要將我們視作標籤的一列與其他的分離開,形成兩個矩陣(或者說一個矩陣一個向量),並將標籤視作因變量,其餘的作爲自變量。

X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, 3].values

這兩行語句分別將從第一列到倒數第二列與最後一列分開並存入兩個變量中。“,”的前面表示取所有行,後面表示取對應的列。

如果數據有缺失怎麼辦?

事實上,我們總會遇到數據缺失。對此,我們可以將存在缺失的行直接刪除,但這不是一個好辦法,還很容易引發問題。因此需要一個更好的解決方案。最常用的方法是,用其所在列的均值來填充缺失。爲此,你可以利用 scikit-learn 預處理模型中的 imputer 類來很輕鬆地實現。

from sklearn.preprocessing import Imputer
imputer = Imputer(missing_values = np.nan, strategy = ‘mean’, axis = 0)

均值填充是默認的填充策略,所以其實不需要指定,加在此處是爲了方便了解可以包含什麼信息。missing_values 的默認值是 nan。如果你的數據集中存在「NaN」形式的缺失值,那麼你應該關注 np.nan,可以在此查看官方文檔:
https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html

我們只希望在數據存在缺失的列上擬合 imputer。爲了擬合這個 imputer,輸入:

imputer = imputer.fit(X[:, 1:3])

現在,我們希望調用實際上可以替換填充缺失數據的方法。通過輸入以下語句完成:

X[:, 1:3] = imputer.transform(X[:, 1:3])

By the way,也許在某些項目中,你會發現,使用缺失值所在列的中位數或衆數來填充缺失值會更加合理。填充策略之類的決策看似細微,但其實意義重大。因爲流行通用的方法並不一定就是正確的選擇,對於模型而言,均值也不一定是最優的缺失填充選擇。

如果包含屬性數據,會怎麼樣呢?

這是一個好問題。沒有辦法明確地計算諸如貓、狗、麋鹿的均值。那麼可以怎麼做呢?可以將屬性數據編碼爲數值!你可能希望使用 sklearn.preprocessing 所提供的 LabelEncoder 類。從你希望進行編碼的某列數據入手,調用 label encoder 並擬合在你的數據上。

from sklearn.preprocessing import LabelEncoder
labelencoder_X = LabelEncoder()
X[:, 0] = labelencoder_X.fit_transform(X[:, 0])

這就是將第一列中的屬性變量替換爲數值所需的全部工作了。例如,麋鹿將用 0 表示,狗將用 2 表示,貓將用 3 表示。

你發現什麼潛在問題了嗎?

對了!所使用的數值層級關係可能會影響模型結果:在程序中,3 比 0 的數值大,會導致程序認爲貓比麋鹿大(但這並不是可比較的),但貓並不一定比麋鹿大。

如何解決這個問題呢?輸入 OneHotEncoder 吧!也就是所謂的獨熱編碼。比如在mnist手寫數據集中,我們會把0,1,2,3…9這十個數字用一個十位的二進制(至少看起來像二進制)表示,1000000000表示0,0100000000表示1,…。下面看程序

導入編碼器,並制定對應列的索引:

from sklearn.preprocessing import OneHotEncoder
onehotencoder = OneHotEncoder(categorical_features = [0])

接着是一點擬合和轉換:

X = onehotencoder.fit_transform(X).toarray()

現在,你的那一列數據已經被替換爲了這種形式:數據組中的每一個屬性數據對應一列,並以 1 和 0 取代屬性變量。非常貼心,對吧?如果我們的 Y 列也是如「Y」和「N」的屬性變量,那麼我們也可以在其上使用這個編碼器。

labelencoder_y = LabelEncoder()
y = labelencoder_y.fit_transform(y)

這會直接擬合併將 y 表示爲編碼變量:1 表示「Y」,0 表示「N」。

訓練集與測試集的劃分

如果你導入的數據並沒有將訓練集數據與測試集數據分開,你可以開始將數據集劃分爲訓練集和測試集了。不過記得,一定要將你的數據分爲訓練集和測試集,永遠不要用測試集來訓練!

現在,我們有了需要學習的模型。模型需要在數據上訓練,並在另外的數據上完成測試。對訓練集的記憶並不等於學習。模型在訓練集上學習得越好,就應該在測試集給出更好的預測結果。過擬合永遠都不是你想要的結果,學習纔是!

首先,導入:

from sklearn.model_selection import train_test_split

現在,可以創建 X_train、X_test、y_train 和 y_test 集合了。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)

一種常見的方法是將數據集按 80/20 進行劃分,其中 80% 的數據用作訓練,20% 的數據用作測試。這也是爲何指定 test_size 爲 0.2 的原因。你也可以根據自己的需求來任意劃分,如果你的數據集特別大,譬如有一百萬張圖片,那完全可以只用五萬張圖片來作爲測試集。你並不需要設置 random_state,這裏設置的原因是爲了可以完全復現結果。

特徵縮放

什麼是特徵縮放?爲什麼需要特徵縮放?

看看我們的數據。我們有一列動物年齡,範圍是 4~17,還有一列動物價值,範圍是$48,000-$83,000。價值一欄的數值不僅遠大於年齡一欄,而且它還包含更加廣闊的數據範圍。這表明,歐式距離將完全由價值這一特徵所主導,而忽視年齡數據的主導效果。如果歐式距離在特定機器學習模型中並沒有具體作用會怎麼樣?縮放特徵將仍能夠加速模型,因此,你可以在數據預處理中,加入特徵縮放這一步。

特徵縮放的方法有很多。但它們都意味着我們將所有的特徵放在同一量綱上,進而沒有一個會被另一個所主導。

導入相關庫開始:

from sklearn.preprocessing import StandardScaler

創建一個需要縮放對象並調用 Standard Scaler

sc_X = StandardScaler()

直接在數據集上進行擬合以及變換。獲取對象並應用方法。

X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)

不需要在測試集上進行擬合,只進行變換

sc_y = StandardScaler()
y_train = sc_y.fit_transform(y_train)

原文鏈接:https://towardsdatascience.com/the-complete-beginners-guide-to-data-cleaning-and-preprocessing-2070b7d4c6d

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