1. 程式人生 > >機器學習之 資料預處理(sklearn preprocessing)

機器學習之 資料預處理(sklearn preprocessing)

資料預處理(data preprocessing)是指在主要的處理以前對資料進行的一些處理。如對大部分地球物理面積性觀測資料在進行轉換或增強處理之前,首先將不規則分佈的測網經過插值轉換為規則網的處理,以利於計算機的運算。另外,對於一些剖面測量資料,如地震資料預處理有垂直疊加、重排、加道頭、編輯、重新取樣、多路編輯等。

預處理內容

資料稽核

從不同渠道取得的統計資料,在稽核的內容和方法上有所不同。 [1]

對於原始資料應主要從完整性準確性兩個方面去稽核。完整性稽核主要是檢查應調查的單位或個體是否有遺漏,所有的調查專案或指標是否填寫齊全。準確性稽核主要是包括兩個方面:一是檢查資料資料是否真實地反映了客觀實際情況,內容是否符合實際;二是檢查資料是否有錯誤,計算是否正確等。稽核資料準確性的方法主要有邏輯檢查和計算檢查。邏輯檢查主要是稽核資料是否符合邏輯,內容是否合理,各專案或數字之間有無相互矛盾的現象,此方法主要適合對定性(品質)資料的稽核。計算檢查是檢查調查表中的各項資料在計算結果和計算方法上有無錯誤,主要用於對定量(數值型)資料的稽核。 [1]

對於通過其他渠道取得的二手資料,除了對其完整性和準確性進行稽核外,還應該著重稽核資料的適用性和時效性。二手資料可以來自多種渠道,有些資料可能是為特定目的通過專門調查而獲得的,或者是已經按照特定目的需要做了加工處理。對於使用者來說,首先應該弄清楚資料的來源、資料的口徑以及有關的背景資料,以便確定這些資料是否符合自己分析研究的需要,是否需要重新加工整理等,不能盲目生搬硬套。此外,還要對資料的時效性進行稽核,對於有些時效性較強的問題,如果取得的資料過於滯後,可能失去了研究的意義。一般來說,應儘可能使用最新的統計資料。資料經稽核後,確認適合於實際需要,才有必要做進一步的加工整理。 [1]

資料稽核的內容主要包括以下四個方面:

1.準確性稽核。主要是從資料的真實性與精確性角度檢查資料,其稽核的重點是檢查調查過程中所發生的誤差。 [2]

2.適用性稽核。主要是根據資料的用途,檢查資料解釋說明問題的程度。具體包括資料與調查主題、與目標總體的界定、與調查專案的解釋等是否匹配。 [2]

3.及時性稽核。主要是檢查資料是否按照規定時間報送,如未按規定時間報送,就需要檢查未及時報送的原因。 [2]

4.一致性稽核。主要是檢查資料在不同地區或國家、在不同的時間段是否具有可比性。 [2]

資料篩選

對稽核過程中發現的錯誤應儘可能予以糾正。調查結束後,當資料發現的錯誤不能予以糾正,或者有些資料不符合調查的要求而又無法彌補時,就需要對資料進行

篩選。資料篩選包括兩方面的內容:一是將某些不符合要求的資料或有明顯錯誤地資料予以剔除;二是將符合某種特定條件的資料篩選出來,對不符合特定條件的資料予以剔除。資料的篩選在市場調查、經濟分析、管理決策中是十分重要的。 [1]

資料排序

資料排序是按照一定順序將資料排列,以便於研究者通過瀏覽資料發現一些明顯的特徵或趨勢,找到解決問題的線索。除此之外,排序還有助於對資料檢查糾錯,為重新歸類或分組等提供依據。在某些場合,排序本身就是分析的目的之一。排序可藉助於計算機很容易的完成。 [1]

對於分類資料,如果是字母型資料,排序有升序與降序之分,但習慣上升序使用得更為普遍,因為升序與字母的自然排列相同;如果是漢字型資料,排序方式有很多,比如按漢字的首位拼音字母排列,這與字母型資料的排序完全一樣,也可按筆畫排序,其中也有筆畫多少的升序降序之分。交替運用不同方式排序,在漢字型資料的檢查糾錯過程中十分有用。 [1]

對於數值型資料,排序只有兩種,即遞增和遞減。排序後的資料也稱為順序統計量。 [1]

方法

資料清理

資料清理例程通過填寫缺失的值、光滑噪聲資料、識別或刪除離群點並解決不一致性來“清理”資料。主要是達到如下目標:格式標準化,異常資料清除,錯誤糾正,重複資料的清除。

資料整合

資料整合例程將多個數據源中的資料結合起來並統一儲存,建立資料倉庫的過程實際上就是資料整合。

資料變換

通過平滑聚集,資料概化,規範化等方式將資料轉換成適用於資料探勘的形式。

資料歸約

資料探勘時往往資料量非常大,在少量資料上進行挖掘分析需要很長的時間,資料歸約技術可以用來得到資料集的歸約表示,它小得多,但仍然接近於保持原資料的完整性,並結果與歸約前結果相同或幾乎相同。

資料預處理 [3] 是資料探勘一個熱門的研究方面,畢竟這是由資料預處理的產生背景所決定的--現實世界中的資料幾乎都髒資料

'''
機器學習基礎之 資料預處理(sklearn preprocessing)
Standardization即標準化,儘量將資料轉化為均值為零,方差為一的資料,形如標準正態分佈(高斯分佈)。
實際中我們會忽略資料的分佈情況,僅僅是通過改變均值來集中資料,然後將非連續特徵除以他們的標準差。

### 標準化,均值去除 和 按方差比例縮放 (Standardization, or mean removal and variance scaling)
資料集的標準化:當個體特徵太過或明顯不遵從高斯正態分佈時,標準化表現的效果較差。
實際操作中,經常忽略特徵資料的分佈形狀,移除每個特徵均值,劃分離散特徵的標準差,從而等級化,進而實現資料中心化。
'''
from sklearn import preprocessing
import numpy as np

'''
[ 資料 標準化/歸一化 normalization ]
sklearn中 scale函式提供了簡單快速的 singlearray-like 資料集操作。
scale函式標準化  --  preprocessing.scale(X)

def scale(X, axis=0, with_mean=True, with_std=True, copy=True)
注意,scikit-learn中 assume that all features are centered around zero and have variance in the same order.
公式:(X-X_mean)/X_std 分別計算每個屬性 features(axis=0 列),如果資料不是這樣的要注意!

引數解釋:
    X:{array-like, sparse matrix} 陣列或者矩陣,一維的資料都可以(但是在0.19版本後一維的資料會報錯了!)
    axis:int型別,初始值為0,axis用來計算均值 means 和標準方差 standard deviations.
        如果是0,則單獨的標準化每個特徵(列),如果是1,則標準化每個觀測樣本(行)。
    with_mean: boolean型別,預設為True,表示將資料均值規範到0
    with_std: boolean型別,預設為True,表示將資料方差規範到1

這種標準化相當於 z-score 標準化(zero-mean normalization)
'''
X = np.array([[1., -1., 2.],
              [2., 0., 0.],
              [0., 1., -1.]])

X_scaled = preprocessing.scale(X) # scale 零均值 單位方差
print('sklearn.preprocessing.scale 標準化  \n', X_scaled)
# cn = preprocessing.scale([[p] for _, _, p in X_scaled]).reshape(-1)
cn = preprocessing.scale([[p[-1]] for p in X_scaled]).reshape(-1)
''' 每個特徵(列),每個觀測樣本(行) '''
print('取標準化後每個樣本里的最後一個值\n', cn)
print('二維轉一維\n', X_scaled.copy().reshape(-1))
'''對於一維資料的一種可能的處理:先轉換成二維,再在結果中轉換為一維'''
print('轉換後的資料零均值(zero mean,均值為零) \n', X_scaled.mean(axis=0))
print('轉換後的資料單位方差(unit variance,方差為1) \n', X_scaled.std(axis=0))

'''
sklearn.preprocessing.StandardScaler()
可儲存訓練集的標準化引數(均值、方差),然後應用在轉換測試集資料。
一般我們的標準化先在訓練集上進行,在測試集上也應該做同樣 mean 和 variance 的標準化,
'''
scaler = preprocessing.StandardScaler().fit(X)
print('訓練集的標準化引數(均值、方差) \n 均值:', scaler.mean_ , '\n 方差:', scaler.var_)  # 預設為 列
print('將訓練集得到的標準化引數應用到測試集上 \n', scaler.transform([[-1., 1., 0.]]))

'''
注 :1)若設定 with_mean=False 或 with_std=False,則不做 centering 或 scaling 處理。
2)scale 和 StandardScaler 可以用於 迴歸模型 中的目標值處理。

二、將資料特徵縮放至某一範圍(scaling features to a range)
另外一種標準化方法是將資料縮放至給定的最小值與最大值之間,通常是0與1之間,可用 MinMaxScaler 實現。
或者 將最大的絕對值縮放至單位大小,可用 MaxAbsScaler 實現。

使用這種標準化方法的原因是,有時資料集的標準差非常非常小,有時資料中有很多很多零(稀疏資料)需要儲存住0元素。

1. MinMaxScaler(最小最大值標準化)
將一個特徵中最大的值轉換為1,最小的那個值轉換為0,其餘的值按照一定比例分佈在(0,1)之間
公式:MinMaxScaler =((X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))) * (max - min) + min

注意,如果原來是稀疏矩陣,因為原來的0轉換後會不在是0,而只有最小值才是0,所以轉換後價格形成一個密集矩陣。
'''
'''例子:將資料縮放至[0, 1]間。訓練過程: fit_transform()'''
X_train = np.array([[1., -1., 2.], [2., 0., 0.], [0., 1., -1.]])
min_max_scaler = preprocessing.MinMaxScaler()
X_train_minmax = min_max_scaler.fit_transform(X_train)
print('將資料縮放至[0, 1]間 \n',X_train_minmax)
'''將上述得到的scale引數應用至測試資料'''
X_test = np.array([[-3., -1., 4.]])
X_test_minmax = min_max_scaler.transform(X_test)
print('將上述得到的scale引數應用至測試資料 \n',X_test_minmax)
print('檢視scaler的屬性 min_max_scaler.scale_  \n', min_max_scaler.scale_)
print('檢視scaler的屬性 min_max_scaler.min_  \n', min_max_scaler.min_)
'''
MinMaxScaler函式:將特徵的取值縮小到一個範圍(如0到1)
將屬性縮放到一個指定的最大值和最小值(通常是1-0)之間,這可以通過 preprocessing.MinMaxScaler 類來實現。
使用這種方法的目的包括:
    1、對於方差非常小的屬性可以增強其穩定性;
    2、維持稀疏矩陣中為0的條目。

有大量異常值的歸一化
sklearn.preprocessing.robust_scale(X, axis=0, with_centering=True,
with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
'''

'''
自定義歸一化函式:大於某個 閾值THRESHOLD 時其屬於1的概率值要大於0.5,小於 THRESHOLD 時概率值小於0.5,
接近最大值時其概率值越接近1,接近最小值時其概率值越接近0。相當於min-max歸一化的一點改進吧。
'''
from sklearn.preprocessing import FunctionTransformer
import numpy as np

def scalerFunc(x, maxv, minv, THRESHOLD=200):
    label = x >= THRESHOLD
    result = 0.5 * (1 + (x - THRESHOLD) * (label / (maxv - THRESHOLD) + (label - 1) / (minv - THRESHOLD)))
    return result

x = np.array([100, 150, 201, 250, 300]).reshape(-1, 1)
scaler = FunctionTransformer(func=scalerFunc, kw_args={'maxv': x.max(), 'minv': x.min()}).fit(x)
print('自定義歸一化函式\n',scaler.transform(x))

'''
2. MaxAbsScaler(絕對值最大標準化)
與上述標準化方法相似,但是它通過除以最大值(特徵值中的最大絕對數)將訓練集縮放至[-1,1]。
這樣的做法並不會改變原來為0的值,所以也不會改變稀疏性。
'''
X_train = np.array([[1., -1., 2.],
                    [2., 0., 0.],
                    [0., 1., -1.]])
max_abs_scaler = preprocessing.MaxAbsScaler()

X_train_maxabs = max_abs_scaler.fit_transform(X_train)
print('X_train_maxabs \n', X_train_maxabs)
print('訓練集每一列的最大絕對值 \n', max_abs_scaler.scale_)

X_test = np.array([[-3., -1., 4.]])
X_test_maxabs = max_abs_scaler.transform(X_test)
print('測試集資料除以訓練集得到的最大絕對值縮放 \n', X_test_maxabs)
'''
Scikit-learn:資料預處理 Preprocessing data
標準化、資料最大最小縮放處理、正則化、特徵二值化和資料缺失值處理。
Note: 一定要注意歸一化是歸一化什麼,歸一化features還是samples。

資料標準化:去除均值和方差進行縮放 Standardization: mean removal and variance scaling
當單個特徵的樣本取值相差甚大或明顯不遵從高斯正態分佈時,資料標準化表現的效果較差。
實際操作中,經常忽略特徵資料的分佈形狀,移除每個特徵均值,劃分離散特徵的標準差,從而等級化,進而實現資料中心化。
Note: test set、training set 都要做相同的預處理操作(standardization、data transformation、etc)
'''
from sklearn import preprocessing
import numpy as np
'''
二值化 Binarization 主要是為了將 資料特徵 轉變成 boolean變數。
在sklearn中,sklearn.preprocessing.Binarizer 函式可以實現這一功能。
可以設定一個閾值(預設為0.0),結果資料值大於閾值的為1,小於閾值的為0。
'''
X = [[ 1., -1.,  2.],
     [ 2.,  0.,  0.],
     [ 0.,  1., -1.]]
binarizer = preprocessing.Binarizer().fit(X)
print('binarizer 列印函式 \n',binarizer)
print('binarizer.transform(X) 轉換為list \n',binarizer.transform(X))

binarizer22 = preprocessing.Binarizer(copy=True, threshold=1.0).fit(X)
print('binarizer22 列印函式 \n',binarizer22)
print('binarizer22.transform(X) 轉換為list \n',binarizer22.transform(X))

from sklearn import preprocessing
from sklearn import tree

'''
對於標稱型資料來說,preprocessing.LabelBinarizer是一個很好用的工具。
比如可以把yes和no轉化為0和1,或是把incident和normal轉化為0和1。當然,對於兩類以上的標籤也是適用的。
help(preprocessing.LabelBinarizer) # 檢視詳細用法
'''
featureList=[[1,0],[1,1],[0,0],[0,1]]  # 特徵矩陣
labelList=['yes', 'no', 'no', 'yes']  # 標籤矩陣
lb = preprocessing.LabelBinarizer()  # 將標籤矩陣二值化
dummY=lb.fit_transform(labelList)
print('將標籤矩陣二值化 \n',dummY)
# 模型建立和訓練
clf = tree.DecisionTreeClassifier()
clf = clf.fit(featureList, dummY)
#print(clf)
p=clf.predict([[0,1]])
print(p)  # [1]

# 逆過程 再把 0 和 1 轉回原始 數值
yesORno=lb.inverse_transform(p)
print(yesORno)

'''
缺失值處理Imputation of missing values
由於許多現實中的資料集都包含有缺失值,要麼是空白的,要麼使用NaNs或者其它的符號替代。
這些資料無法直接使用 scikit-learn 分類器直接訓練,所以需要進行處理。
幸運地是,sklearn 中的 Imputer 類提供了一些基本的方法來處理缺失值,
如使用均值、中位值或者缺失值所在列中頻繁出現的值來替換。
Imputer類同樣支援稀疏矩陣。
'''
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
imp.fit([[1, 2], [np.nan, 3], [7, 6]]) # 擬合得出 列均值,填充給 X 的 缺失值

# Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)
X = [[np.nan, 2], [6, np.nan], [7, 6]]
print('缺失值處理Imputation of missing values \n',imp.transform(X))

'''
正則化Normalization 的過程是將每個樣本縮放到單位範數(每個樣本的範數為1),
如果要使用如二次型(點積)或者其它核方法計算兩個樣本之間的相似性這個方法會很有用。
該方法是文字分類和聚類分析中經常使用的向量空間模型(Vector Space Model)的基礎.
Normalization 主要思想是對每個樣本計算其p-範數,然後對該樣本中每個元素除以該範數,
這樣處理的結果是使得每個處理後樣本的p-範數(l1-norm,l2-norm)等於1。

def normalize(X, norm='l2', axis=1, copy=True)
注意,這個操作是對所有樣本(而不是features)進行的,也就是將每個樣本的值除以這個樣本的Li範數。
所以這個操作是針對axis=1進行的。

三、正則化
對每個樣本計算其 p-範數,再對每個元素除以該範數,這使得每個處理後樣本的p-範數(l1-norm,l2-norm)等於1。
如果後續要使用二次型等方法計算兩個樣本之間的相似性會有用。
preprocessing.Normalizer(norm=’l2’, copy=True)
'''
X = np.array([[1., -1., 2.], [2., 0., 0.], [0., 1., -1.]])
X_normalized = preprocessing.normalize(X, norm='l2')
print( '正則化Normalization\n',X_normalized )
normalizer = preprocessing.Normalizer().fit(X)
print( 'normalizer.transform(X) 正則化 \n' , normalizer.transform(X) )
print( '所有元素求和 \n' , normalizer.transform(X).sum() )
print( 'X所有元素的範數和 \n' , abs(X).sum() )
# print( abs(X).sum(axis=0) )
# print( abs(X).sum(axis=1) )
print( 'X所有元素都除以 所有元素的範數和 \n' , X / X.sum() )
'''
幾個概念
1-範數:向量各分量絕對值之和
2-範數:向量長度
最大範數:向量各分量絕對值的最大值
p-範數的計算公式:||X||p=(|x1|^p+|x2|^p+…+|xn|^p)^1/p
'''

'''
標準化(Scale)和正則化(Normalization)是兩種常用的資料預處理方法,
其作用是讓資料變得更加“規範”一些。在文字聚類等任務中使用的比較多。
1.資料標準化
公式為:(X-mean)/std  計算時對每個屬性/每列分別進行。將資料按期屬性(按列進行)減去其均值,並處以其方差。
得到的結果是,對於每個屬性/每列來說所有資料都聚集在0附近,方差為1。經過資料標準化的資料,可以看到有些特徵被凸顯出來了。

2.資料正則化
正則化的過程是將每個樣本縮放到單位範數(每個樣本的範數為1),
如果後面要使用如二次型(點積)或者其它核方法計算兩個樣本之間的相似性這個方法會很有用。

Normalization主要思想是對每個樣本計算其p-範數,然後對該樣本中每個元素除以該範數,
這樣處理的結果是使得每個處理後樣本的p-範數(l1-norm,l2-norm)等於1。
p-範數的計算公式:||X||p=(|x1|^p+|x2|^p+...+|xn|^p)^1/p
該方法主要應用於文字分類和聚類中。例如,對於兩個TF-IDF向量的l2-norm進行點積,就可以得到這兩個向量的餘弦相似性。

在sklearn中有三種正則化方法,l1範數、l2範數、max範數。
使用這三種範數生成的結果如下圖所示:
在肉眼上很難看出有什麼區別,
不過還是能看出l2範數的結果相對更好,即能儘可能的削弱“強勢”特徵,將一些數值較小但是比較有特點的特徵“凸顯”出來。

sklearn官方文件:
http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.scale.html#sklearn.preprocessing.scale
http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.normalize.html#sklearn.preprocessing.normalize
'''

'''
更多的資料預處理方法參考官方文件:
http://scikit-learn.org/stable/modules/preprocessing.html#standardization-or-mean-removal-and-variance-scaling

參考官方文件:http://scikit-learn.org/stable/modules/preprocessing.html
官網:http://scikit-learn.org/stable/
'''