python機器學習-乳腺癌細胞挖掘(博主親自錄制視頻)
https://study.163.com/course/introduction.htm?courseId=1005269003&utm_campaign=commission&utm_source=cp-400000000398149&utm_medium=share
#author:231469242@qq.com
from sklearn import preprocessing import numpy as np a=np.array([[10,2.7,3.6],[-100,5,-2],[120,20,40]],dtype=np.float64) process_a=preprocessing.scale(a)
比較數據標准化前后准確性差別
# -*- coding: utf-8 -*- """ Created on Sun Jan 7 16:29:35 2018 @author: 231469242@qq.com
微信公眾號:pythonEducation """ #導入數據預處理 from sklearn import preprocessing import matplotlib.pyplot as plt #導入數據生成分類器 from sklearn.datasets import make_classification #導入sklearn測試數據庫 from sklearn import datasets #用於訓練數據和測試數據分類 from sklearn.cross_validation import train_test_split #導入邏輯回歸分類器 from sklearn.linear_model import LogisticRegression #導入knn分類器 from sklearn.neighbors import KNeighborsClassifier #導入支持向量分類器 from sklearn.svm import SVC #生成分類數據,數據維度相差很小 #X, Y = make_classification(n_samples=1000,n_features=2, n_redundant=0, n_informative=2,n_clusters_per_class=1, n_classes=2) #生成分類數據,數據維度相差很大,scale值越大,數據維度相差越大 X, Y = make_classification(n_samples=1000,n_features=2, n_redundant=0, n_informative=2, n_clusters_per_class=1, n_classes=2,random_state=22,scale=100) #標准化X數據,縮小不同維度數據差異 X1=preprocessing.scale(X) #數據未標准化:分成訓練數據和測試數據 X_train, X_test, y_train, y_test = train_test_split( X, Y, test_size=0.3) #X數據標准化后:分成訓練數據和測試數據 X_train1, X_test1, y_train1, y_test1 = train_test_split( X1, Y, test_size=0.3) #畫布的大小為長20cm高20cm plt.figure(figsize=(10,6)) #標題,fontsize為標題字體大小 plt.title("classification", fontsize='large') #繪制點,X1[:, 0]為點的x列表值, X1[:, 1]為點的y列表值, c=Y1表示顏色,c為color縮寫 plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y) #創建兩個支持向量模型 model=SVC() model_normal=SVC() #未標准化的訓練模型 model.fit(X_train,y_train) #標准化的訓練模型 model_normal.fit(X_train1,y_train1) #測試未標准化得分 print("data non normalization:",model.score(X_test,y_test)) #測試標准化得分 print("data normalization:",model_normal.score(X_test1,y_test1))
預處理數
1. 標准化:去均值,方差規模化
Standardization標准化:將特征數據的分布調整成標准正太分布,也叫高斯分布,也就是使得數據的均值維0,方差為1.
標准化的原因在於如果有些特征的方差過大,則會主導目標函數從而使參數估計器無法正確地去學習其他特征。
標准化的過程為兩步:去均值的中心化(均值變為0);方差的規模化(方差變為1)。
在sklearn.preprocessing中提供了一個scale的方法,可以實現以上功能。
from sklearn import preprocessing
import numpy as np
# 創建一組特征數據,每一行表示一個樣本,每一列表示一個特征
x = np.array([[1., -1., 2.], [2., 0., 0.], [0., 1., -1.]]) # 將每一列特征標准化為標准正太分布,注意,標准化是針對每一列而言的 x_scale = preprocessing.scale(x) x_scale
array([[ 0. , -1.22474487, 1.33630621],
[ 1.22474487, 0. , -0.26726124],
[-1.22474487, 1.22474487, -1.06904497]])
# 可以查看標准化后的數據的均值與方差,已經變成0,1了 x_scale.mean(axis=0)
array([ 0., 0., 0.])
# axis=1表示對每一行去做這個操作,axis=0表示對每一列做相同的這個操作
x_scale.mean(axis=1)
array([ 0.03718711, 0.31916121, -0.35634832])
# 同理,看一下標准差 x_scale.std(axis=0)
array([ 1., 1., 1.])
preprocessing這個模塊還提供了一個實用類StandarScaler,它可以在訓練數據集上做了標准轉換操作之后,把相同的轉換應用到測試訓練集中。
這是相當好的一個功能。可以對訓練數據,測試數據應用相同的轉換,以后有新的數據進來也可以直接調用,不用再重新把數據放在一起再計算一次了。
# 調用fit方法,根據已有的訓練數據創建一個標准化的轉換器 scaler = preprocessing.StandardScaler().fit(x) scaler
StandardScaler(copy=True, with_mean=True, with_std=True)
# 使用上面這個轉換器去轉換訓練數據x,調用transform方法 scaler.transform(x)
array([[ 0. , -1.22474487, 1.33630621],
[ 1.22474487, 0. , -0.26726124],
[-1.22474487, 1.22474487, -1.06904497]])
# 好了,比如現在又來了一組新的樣本,也想得到相同的轉換
new_x = [[-1., 1., 0.]] scaler.transform(new_x)
array([[-2.44948974, 1.22474487, -0.26726124]])
恩,完美。
另外,StandardScaler()中可以傳入兩個參數:with_mean,with_std.這兩個都是布爾型的參數,默認情況下都是true,但也可以自定義成false.即不要均值中心化或者不要方差規模化為1.
1.1 規模化特征到一定的范圍內
也就是使得特征的分布是在一個給定最小值和最大值的范圍內的。一般情況下是在[0,1]之間,或者是特征中絕對值最大的那個數為1,其他數以此維標准分布在[[-1,1]之間
以上兩者分別可以通過MinMaxScaler 或者 MaxAbsScaler方法來實現。
之所以需要將特征規模化到一定的[0,1]范圍內,是為了對付那些標准差相當小的特征並且保留下稀疏數據中的0值。
MinMaxScaler
在MinMaxScaler中是給定了一個明確的最大值與最小值。它的計算公式如下:
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std / (max - min) + min
以下這個例子是將數據規與[0,1]之間,每個特征中的最小值變成了0,最大值變成了1,請看:
min_max_scaler = preprocessing.MinMaxScaler() x_minmax = min_max_scaler.fit_transform(x) x_minmax
array([[ 0.5 , 0. , 1. ],
[ 1. , 0.5 , 0.33333333],
[ 0. , 1. , 0. ]])
同樣的,如果有新的測試數據進來,也想做同樣的轉換咋辦呢?請看:
x_test = np.array([[-3., -1., 4.]]) x_test_minmax = min_max_scaler.transform(x_test) x_test_minmax
array([[-1.5 , 0. , 1.66666667]])
MaxAbsScaler
原理與上面的很像,只是數據會被規模化到[-1,1]之間。也就是特征中,所有數據都會除以最大值。這個方法對那些已經中心化均值維0或者稀疏的數據有意義。
來個小例子感受一下:
max_abs_scaler = preprocessing.MaxAbsScaler() x_train_maxsbs = max_abs_scaler.fit_transform(x) x_train_maxsbs
array([[ 0.5, -1. , 1. ],
[ 1. , 0. , 0. ],
[ 0. , 1. , -0.5]])
# 同理,也可以對新的數據集進行同樣的轉換
x_test = np.array([[-3., -1., 4.]]) x_test_maxabs = max_abs_scaler.transform(x_test) x_test_maxabs
array([[-1.5, -1. , 2. ]])
1.2 規模化稀疏數據
如果對稀疏數據進行去均值的中心化就會破壞稀疏的數據結構。雖然如此,我們也可以找到方法去對稀疏的輸入數據進行轉換,特別是那些特征之間的數據規模不一樣的數據。
MaxAbsScaler 和 maxabs_scale這兩個方法是專門為稀疏數據的規模化所設計的。
1.3 規模化有異常值的數據
如果你的數據有許多異常值,那么使用數據的均值與方差去做標准化就不行了。
在這里,你可以使用robust_scale 和 RobustScaler這兩個方法。它會根據中位數或者四分位數去中心化數據。
2 正則化Normalization
正則化是將樣本在向量空間模型上的一個轉換,經常被使用在分類與聚類中。
函數normalize 提供了一個快速有簡單的方式在一個單向量上來實現這正則化的功能。正則化有l1,l2等,這些都可以用上:
x_normalized = preprocessing.normalize(x, norm='l2') print x print x_normalized
[[ 1. -1. 2.]
[ 2. 0. 0.]
[ 0. 1. -1.]]
[[ 0.40824829 -0.40824829 0.81649658]
[ 1. 0. 0. ]
[ 0. 0.70710678 -0.70710678]]
preprocessing這個模塊還提供了一個實用類Normalizer,實用transform方法同樣也可以對新的數據進行同樣的轉換
# 根據訓練數據創建一個正則器 normalizer = preprocessing.Normalizer().fit(x) normalizer
Normalizer(copy=True, norm='l2')
# 對訓練數據進行正則 normalizer.transform(x)
array([[ 0.40824829, -0.40824829, 0.81649658],
[ 1. , 0. , 0. ],
[ 0. , 0.70710678, -0.70710678]])
# 對新的測試數據進行正則
normalizer.transform([[-1., 1., 0.]])
array([[-0.70710678, 0.70710678, 0. ]])
normalize和Normalizer都既可以用在密集數組也可以用在稀疏矩陣(scipy.sparse)中
對於稀疏的輸入數據,它會被轉變成維亞索的稀疏行表征(具體請見scipy.sparse.csr_matrix)
3 二值化–特征的二值化
特征的二值化是指將數值型的特征數據轉換成布爾類型的值。可以使用實用類Binarizer。
from sklearn import preprocessing
import numpy as np
# 創建一組特征數據,每一行表示一個樣本,每一列表示一個特征
x = np.array([[1., -1., 2.], [2., 0., 0.], [0., 1., -1.]]) binarizer = preprocessing.Binarizer().fit(x) binarizer.transform(x)
array([[ 1., 0., 1.],
[ 1., 0., 0.],
[ 0., 1., 0.]])
默認是根據0來二值化,大於0的都標記為1,小於等於0的都標記為0。
當然也可以自己設置這個閥值,只需傳出參數threshold即可。
binarizer = preprocessing.Binarizer(threshold=1.5) binarizer.transform(x)
array([[ 0., 0., 1.],
[ 1., 0., 0.],
[ 0., 0., 0.]])
binarize and Binarizer都可以用在密集向量和稀疏矩陣上。
4 為類別特征編碼
我們知道特征可能是連續型的也可能是類別型的變量,比如說:
[“male”, “female”], [“from Europe”, “from US”, “from Asia”], [“uses Firefox”, “uses Chrome”, “uses Safari”, “uses Internet Explorer”].
這些類別特征無法直接進入模型,它們需要被轉換成整數來表征,比如:
[“male”, “from US”, “uses Internet Explorer”] could be expressed as [0, 1, 3] while [“female”, “from Asia”, “uses Chrome”] would be [1, 2, 1].
然而上面這種表征的方式仍然不能直接為scikit-learn的模型所用,因為模型會把它們當成序列型的連續變量。
要想使得類別型的變量能最終被模型直接使用,可以使用one-of-k編碼或者one-hot編碼。這些都可以通過OneHotEncoder實現,它可以將有n種值的一個特征變成n個二元的特征。
enc = preprocessing.OneHotEncoder()
enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]]) enc.transform([[0,1,3]]).toarray()
- 1
- 2
- 3
array([[ 1., 0., 0., 1., 0., 0., 0., 0., 1.]])
- 1
- 2
特征1中有(0,1)兩個值,特征2中有(0,1,2)3個值,特征3中有(0,1,2,3)4個值,所以編碼之后總共有9個二元特征。
但是呢,也會存在這樣的情況,某些特征中可能對一些值有缺失,比如明明有男女兩個性別,樣本數據中都是男性,這樣就會默認被判別為我只有一類值。這個時候我們可以向OneHotEncoder傳如參數n_values,用來指明每個特征中的值的總個數。如下:
enc = preprocessing.OneHotEncoder(n_values=[2,3,4]) enc.fit([[1, 2, 3], [0, 2, 0]]) enc.transform([[1,0,0]]).toarray()
- 1
- 2
- 3
array([[ 0., 1., 1., 0., 0., 1., 0., 0., 0.]])
- 1
- 2
5 彌補缺失數據
在scikit-learn的模型中都是假設輸入的數據是數值型的,並且都是有意義的,如果有缺失數據是通過NAN,或者空值表示的話,就無法識別與計算了。
要彌補缺失值,可以使用均值,中位數,眾數等等。Imputer這個類可以實現。請看:
import numpy as np
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values='NaN', strategy='mean', axis=0) imp.fit([[1, 2], [np.nan, 3], [7, 6]]) x = [[np.nan, 2], [6, np.nan], [7, 6]] imp.transform(x)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
array([[ 4. , 2. ],
[ 6. , 3.66666667],
[ 7. , 6. ]])
- 1
- 2
- 3
- 4
Imputer類同樣也可以支持稀疏矩陣,以下例子將0作為了缺失值,為其補上均值
import scipy.sparse as sp
# 創建一個稀疏矩陣
x = sp.csc_matrix([[1, 2], [0, 3], [7, 6]]) imp = Imputer(missing_values=0, strategy='mean', verbose=0) imp.fit(x) x_test = sp.csc_matrix([[0, 2], [6, 0], [7, 6]]) imp.transform(x_test)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
array([[ 4. , 2. ],
[ 6. , 3.66666667],
[ 7. , 6. ]])
- 1
- 2
- 3
- 4
6 創建多項式特征
有的時候線性的特征並不能做出美的模型,於是我們會去嘗試非線性。非線性是建立在將特征進行多項式地展開上的。
比如將兩個特征 (X_1, X_2),它的平方展開式便轉換成5個特征(1, X_1, X_2, X_1^2, X_1X_2, X_2^2). 代碼案例如下:
import numpy as np from sklearn.preprocessing import PolynomialFeatures # 自建一組3*2的樣本 x = np.arange(6).reshape(3, 2) # 創建2次方的多項式 poly = PolynomialFeatures(2) poly.fit_transform(x)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
array([[ 1., 0., 1., 0., 0., 1.],
[ 1., 2., 3., 4., 6., 9.],
[ 1., 4., 5., 16., 20., 25.]])
- 1
- 2
- 3
- 4
看,變成了3*6的特征矩陣,里面有5個特征,加上第一列的是Bias.
也可以自定義選擇只要保留特征相乘的項。
即將 (X_1, X_2, X_3) 轉換成 (1, X_1, X_2, X_3, X_1X_2, X_1X_3, X_2X_3, X_1X_2X_3).
x = np.arange(9).reshape(3, 3) poly = PolynomialFeatures(degree=3, interaction_only=True) poly.fit_transform(x)
- 1
- 2
- 3
- 4
array([[ 1., 0., 1., 2., 0., 0., 2., 0.],
[ 1., 3., 4., 5., 12., 15., 20., 60.],
[ 1., 6., 7., 8., 42., 48., 56., 336.]])
- 1
- 2
- 3
- 4
7 自定義特征的轉換函數
通俗的講,就是把原始的特征放進一個函數中做轉換,這個函數出來的值作為新的特征。
比如說將特征數據做log轉換,做倒數轉換等等。
FunctionTransformer 可以實現這個功能
import numpy as np
from sklearn.preprocessing import FunctionTransformer
transformer = FunctionTransformer(np.log1p)
x = np.array([[0, 1], [2, 3]]) transformer.transform(x)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
array([[ 0. , 0.69314718],
[ 1.09861229, 1.38629436]])
- 1
- 2
- 3
將上面講到的7個預處理的方法綜合起來。
當我們拿到一批原始的數據
- 首先要明確有多少特征,哪些是連續的,哪些是類別的。
- 檢查有沒有缺失值,對確實的特征選擇恰當方式進行彌補,使數據完整。
- 對連續的數值型特征進行標准化,使得均值為0,方差為1。
- 對類別型的特征進行one-hot編碼。
- 將需要轉換成類別型數據的連續型數據進行二值化。
- 為防止過擬合或者其他原因,選擇是否要將數據進行正則化。
- 在對數據進行初探之后發現效果不佳,可以嘗試使用多項式方法,尋找非線性的關系。
- 根據實際問題分析是否需要對特征進行相應的函數轉換。
恩,准備好美美的數據將為我們尋找美美的模型如虎添翼。
官方文檔鏈接http://scikit-learn.org/stable/modules/preprocessing.html#preprocessing