機器學習 - 數據預處理 | 均值移除 | 範圍縮放 | 歸一化 | 二值化 | 獨熱編碼 | 標籤編碼

數據預處理

數據預處理的過程: 輸入數據 -> 模型 -> 輸出數據

數據樣本矩陣

年齡 學歷 經驗 性別 月薪
25 碩士 2 10000
20 本科 3 8000

一行一樣本,一列一特徵。

數據預處理相關庫

# 解決機器學習問題的科學計算工具包
from sklearn import preprocessing

均值移除(標準化)

由於一個樣本的不同特徵值差異較大,不利於使用現有機器學習算法進行樣本處理。**均值移除**可以讓樣本矩陣中的每一列的平均值爲0,標準差爲1。

如何使樣本矩陣中的每一列的平均值爲0呢?

例如有一列特徵值表示年齡: 17, 20, 23
mean = (17 + 20 + 23)/3 = 20
a' = -3
b' =  0
c' =  3
完成!

如何使樣本矩陣中的每一列的標準差爲1呢?

a' = -3
b' =  0
c' =  3
s' = std(a', b', c') 
[a'/s',  b'/s',  c'/s']

均值移除API:

import sklearn.preprocessing as sp
# scale函數用於對函數進行預處理,實現均值移除。
# array爲原數組,返回A爲均值移除後的結果。
A = sp.scale(array)

案例:

import numpy
from sklearn import preprocessing

raw_samples=numpy.array(
    [[17., 100., 4000],
    [20., 80., 5000],
    [23., 75., 5500]])

std_samples=preprocessing.scale(raw_samples)

print(std_samples)
#[[-1.22474487  1.38873015 -1.33630621]
# [ 0.         -0.46291005  0.26726124]
# [ 1.22474487 -0.9258201   1.06904497]]

print(std_samples.mean(axis=0))
# 每一列均值爲0
# [ 0.00000000e+00 -3.70074342e-17  5.18104078e-16]

print(std_samples.std(axis=0))
# 每一列標準差爲1
# [1. 1. 1.]

範圍縮放

將樣本矩陣中的每一列的最小值和最大值設定爲相同的區間,統一各列特徵值的範圍。一般情況下會把特徵值縮放至[0, 1]區間。

如何使一組特徵值的最小值爲0呢?

例如有一列特徵值表示年齡: [17, 20, 23]
每個元素減去特徵值數組所有元素的最小值即可:[0, 3, 6]

如何使一組特徵值的最大值爲1呢?

[0, 3, 6]
把特徵值數組的每個元素除以最大值即可:[0, 1/2, 1]

範圍縮放API:

# 創建MinMax縮放器
mms = sp.MinMaxScaler(feature_range=(0, 1))
# 調用mms對象的方法執行縮放操作, 返回縮放過後的結果
result = mms.fit_transform(原始樣本矩陣)

案例:

import numpy
from sklearn import preprocessing

raw_samples=numpy.array(
    [[17., 100., 4000],
    [20., 80., 5000],
    [23., 75., 5500]])

# 根據給定範圍創建一個範圍縮放器
min_max_scaler=preprocessing.MinMaxScaler(feature_range=(0,1))
# 用範圍縮放器實現特徵值的範圍縮放
mms_samples=min_max_scaler.fit_transform(raw_samples)
print(mms_samples)
#[[0.         1.         0.        ]
# [0.5        0.2        0.66666667]
# [1.         0.         1.        ]]


# 算法實現
copy_samples=raw_samples.copy()
for col in copy_samples.T:
    col_min=col.min()
    col_max=col.max()
    A=numpy.array([
        [col_min,1],
        [col_max,1]])
    B=numpy.array([0,1])
    a,b=numpy.linalg.solve(A,B)
    col *= a
    col += b
print(copy_samples)
#[[0.         1.         0.        ]
# [0.5        0.2        0.66666667]
# [1.         0.         1.        ]]

歸一化

有些情況每個樣本的每個特徵值具體的值並不重要,但是每個樣本特徵值的佔比更加重要。

Python Java PHP
2017 10 20 5
2018 8 5 0

所以歸一化即是用每個樣本的每個特徵值除以該樣本各個特徵值絕對值的總和。變換後的樣本矩陣,每個樣本的特徵值絕對值之和爲1。

歸一化相關API:

# array 原始樣本矩陣
# norm  範數
#    l1 - l1範數,向量中個元素絕對值之和
#    l2 - l2範數,向量中個元素平方之和
# 返回歸一化預處理後的樣本矩陣
sp.normalize(array, norm='l1')

案例:

import numpy
from sklearn import preprocessing

raw_samples=numpy.array(
    [[17., 100., 4000],
    [20., 80., 5000],
    [23., 75., 5500]])

# 歸一化處理,每個樣本的特徵值絕對值之和爲1
nor_samples=preprocessing.normalize(raw_samples,norm='l1')
print(nor_samples)
#[[0.00412922 0.02428953 0.97158125]
# [0.00392157 0.01568627 0.98039216]
# [0.00410861 0.01339764 0.98249375]]


# 算法實現1
nor_samples=raw_samples.copy()
for row in nor_samples:
    row/=abs(row).sum()
print(nor_samples)
print(nor_samples.sum(axis=1))

# 算法實現2
nor_samples/=abs(nor_samples).sum(axis=1)
print(nor_samples)
print(nor_samples.sum(axis=1))
#[[0.00412922 0.02428953 0.97158125]
# [0.00392157 0.01568627 0.98039216]
# [0.00410861 0.01339764 0.98249375]]
#[1. 1. 1.]

二值化

有些業務並不需要分析矩陣的詳細完整數據(比如圖像邊緣識別只需要分析出圖像邊緣即可),可以根據一個事先給定的閾值,用0和1表示特徵值不高於或高於閾值。二值化後的數組中每個元素非0即1,達到簡化數學模型的目的。

二值化相關API:

# 給出閾值, 獲取二值化器
bin = sp.Binarizer(threshold=閾值)
# 調用transform方法對原始樣本矩陣進行二值化預處理操作
result = bin.transform(原始樣本矩陣)

案例:

import numpy
from sklearn import preprocessing

raw_samples=numpy.array(
    [[17., 100., 4000],
    [20., 80., 5000],
    [23., 75., 5500]])

# 二值化器(threshold=閾值)
bin=preprocessing.Binarizer(threshold=80)
# 通過二值化器進行二值化處理
bin_samples=bin.transform(raw_samples)
print(bin_samples)
#[[0. 1. 1.]
# [0. 0. 1.]
# [0. 0. 1.]]

# 算法實現
bin_samples=raw_samples.copy()
# 以下兩句順序不能變
bin_samples[bin_samples<80]=0
bin_samples[bin_samples>=80]=1
print(bin_samples)
#[[0. 1. 1.]
# [0. 0. 1.]
# [0. 0. 1.]]

獨熱編碼

爲樣本特徵的每個值建立一個由一個1和若干個0組成的序列,用該序列對所有的特徵值進行編碼。

兩個數   三個數	四個數
1		3		2
7		5		4
1		8		6  
7		3		9
爲每一個數字進行獨熱編碼:
1-10    3-100	2-1000
7-01    5-010   4-0100
        8-001   6-0010
                9-0001
編碼完畢後得到最終經過獨熱編碼後的樣本矩陣:
101001000
010100100
100010010
011000001

獨熱編碼相關API:

# 創建一個獨熱編碼器
# sparse: 是否使用緊縮格式(稀疏矩陣)
# dtyle:  數據類型
ohe = sp.OneHotEncoder(sparse=是否採用緊縮格式, dtype=數據類型)
# 對原始樣本矩陣進行處理,返回獨熱編碼後的樣本矩陣。
result = ohe.fit_transform(原始樣本矩陣)
# 或 :
ohe = sp.OneHotEncoder(sparse=是否採用緊縮格式, dtype=數據類型)
# 對原始樣本矩陣進行訓練,得到編碼字典
encode_dict = ohe.fit(原始樣本矩陣)
# 調用encode_dict字典的transform方法 對數據樣本矩陣進行獨熱編碼
result = encode_dict.transform(原始樣本矩陣)

案例:

import numpy
from sklearn import preprocessing

raw_samples=numpy.array(
    [[17., 100., 4000],
    [20., 80., 5000],
    [23., 75., 5500]])

# 創建獨熱編碼器
ohe=preprocessing.OneHotEncoder(sparse=False,dtype=int)

# 用獨熱編碼器對原始樣本矩陣做獨熱編碼
# 1.
ohe_samples=ohe.fit_transform(raw_samples)
print(ohe_samples)
#[[1 0 0 0 0 1 1 0 0]
# [0 1 0 0 1 0 0 1 0]
# [0 0 1 1 0 0 0 0 1]]
 
# 2.
ohe_dict=ohe.fit(raw_samples)
ohe_samples=ohe_dict.transform(raw_samples)
print(ohe_samples)
#[[1 0 0 0 0 1 1 0 0]
# [0 1 0 0 1 0 0 1 0]
# [0 0 1 1 0 0 0 0 1]]

標籤編碼

根據字符串形式的特徵值在特徵序列中的位置,爲其指定一個數字標籤,用於提供給基於數值算法的學習模型。

標籤編碼相關API:

# 獲取標籤編碼器
lbe = sp.LabelEncoder()
# 調用標籤編碼器的fit_transform方法訓練並且爲原始樣本矩陣進行標籤編碼
result = lbe.fit_transform(原始樣本矩陣)
# 根據標籤編碼的結果矩陣反查字典 得到原始數據矩陣
samples = lbe.inverse_transform(result)

案例:

import numpy
from sklearn import preprocessing

raw_samples = numpy.array([
    'audi', 'ford', 'audi', 'toyota',
    'ford', 'bmw', 'toyota', 'ford',
    'audi'])

# 創建標籤編碼器
lib=preprocessing.LabelEncoder()
# 標籤編碼
lib_samples=lib.fit_transform(raw_samples)
print(lib_samples)
#[0 2 0 3 2 1 3 2 0]

# 反查字典
samples=lib.inverse_transform(lib_samples)
print(samples)
#['audi' 'ford' 'audi' 'toyota' 'ford' 'bmw' 'toyota' 'ford' 'audi']

samples=lib.inverse_transform([0,0,1,2,2])
print(samples)
#['audi' 'audi' 'bmw' 'ford' 'ford']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章