1. 程式人生 > >資料探勘工具---sklearn使用總結

資料探勘工具---sklearn使用總結

本文來源Cer_mlJorocco
sklearn是一個數據挖掘的python庫,github地址,該庫集成了大量的資料探勘演算法,並可以對資料做預處理,對演算法進行整合和預測結果進行驗證和評估。sklearn在資料量不是特別大的時候是很好用的;在大資料時,spark平臺有差不功能的mllib庫。

1、sklearn基礎介紹

1.1、估計器(Estimator)

估計器很多時候可以直接理解為分類器,主要包含兩個函式:
fit(): 訓練演算法,接收訓練集和類別兩個輸入引數。
predict(): 預測測試集類別,接收測試集作為輸入。
大多數sklearn的輸入和輸出的資料格式均為numpy格式或類似格式。

1.2、轉換器(Transformer)

用於資料的預處理和資料轉換,主要包含3個函式:
fit(): 訓練演算法。
transform(): 用於資料轉換。
fit_transform(): 合併fit()和transform()兩個函式的功能

1.3、流水線(Pipeline)

流水線的功能主要有3個:
一是跟蹤記錄各步驟的操作,以便重現實現結果;
二是對各操作步驟進行封閉;
三是使程式碼的複雜程度不至於超出掌控的範圍。
基本的使用方法:
流水線的輸入為一連竄的資料探勘步驟(裝在列表中),前幾步通過為轉換器,但最後一步必須為估計器。輸入的資料集經過轉換器的處理後,其輸出作為下一步的輸入,最後經過估計器對資料進行分類。每一步都用元組(名稱,函式)來表示。
下面來建立流水線。

scaling_pipeline=Pipeline([('scale',MinMaxScaler()),('predict',KNeighborsClassifier())])

上面的這個例子中包含兩個步驟,每個步驟都放在元組內,元組的第一個元素即為該步驟的名稱,隨便取便於理解功能即可,第二個元素為sklearn中實現相應功能的函式,很多時候直接看函式名便可猜到大致的功能。

1.4、預處理(Preprocessing)

在sklearn中我們會優先使用sklearn.preprocessing來完成預處理,但如果不能夠滿足自己的要求,我個人會使用map函式來做變換。

資料檢視

參考下面缺失值處理部分

資料型別的轉換

利用pandas.read_csv之類的介面來讀取資料,會自動判斷型別,並轉換。
如果數值型混雜著字元型,那麼後續處理過程很可能報錯,尤其是代入模型的時候。

缺失值處理

檢視各列有無缺失值
在sklearn中檢視缺失值可以利用pandas.DataFrame的一些特性,比如df[‘XX’].value_counts()函式來檢視各個值的情況,對於離散型資料較好用,會詳細列出有哪些值,每個值的個數,因為資料來源我們是不知道,不同的資料來源對缺失值的表示方法可能不同,比如用’'表示,用null表示,用NaN表示;或者利用df.describe()或df.info()來檢視。但是df.describe()只適用於缺失值用標準的NaN表示的時候,df.info()在缺失值用標準的NaN表示時會將缺失值排除在外進行基本的統計,因為我們也可以發現缺失值的情況,但如果存在一些其他方法的表示,就會造成不同型別資料混合而無法得到統計結果,我們就需要進一步的查看了。如下所示

a={'a':[1,'',2],'b':[3,4,float('NaN')],'c':[5,6,'Null']}
c=pd.DataFrame(a)
# print(c)
"""
    a    b     c
0  1  3.0     5
1     4.0     6
2  2  NaN  Null
"""
# print(c['a'].value_counts())
"""
2    1
1    1
     1
Name: a, dtype: int64
"""
# print(c['b'].value_counts())
"""
4.0    1
3.0    1
Name: b, dtype: int64
"""
# print(c['c'].value_counts())
"""
Null    1
6       1
5       1
Name: c, dtype: int64
"""
# print(c.info())
"""
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):
a    3 non-null object
b    2 non-null float64
c    3 non-null object
dtypes: float64(1), object(2)
memory usage: 152.0+ bytes
None
"""
# print(c.describe())
"""
             b
count  2.000000
mean   3.500000
std    0.707107
min    3.000000
25%    3.250000
50%    3.500000
75%    3.750000
max    4.000000
"""

轉換器

主要在sklearn.preprocessing包下。這裡的預處理都是針對特徵值來操作的。具體功能如下:
規範化:
MinMaxScaler(): 將特徵值縮放至0~1之間,公式 (ximin(x))/(max(x)min(x))(x_i-min(x))/(max(x)-min(x))
Normalizer(): 通過縮放使特徵值的和為1,公式xi/sum(x)x_i/sum(x)
StandScaler(): 通過縮放使特徵值的均值為0,方差為1,即為通常意義上的標準化,公式(ximean(x))/std(ximean(x))(x_i-mean(x))/std(x_i-mean(x))
編碼:是特徵工程的一部分
在sklearn中我們很多時候不需要去fit整個訓練集,只要把訓練集中包含的所有元素列出來,拿去fit就可以得到元素與編碼之間的對映關係,個人覺得這樣處理可以節省程式執行時間。
藉助pandas的replace,get_dummies等函式也同樣能實現LabelEncoder和OneHotEncoder的效果。
LabelEncoder: 將字串型別的資料轉換為整形

le = LabelEncoder()
le.fit([90063345,89950166,89950167,99999828,89016252,99104722,90109916,89950168,99999827,99999826,
                                  90155946,99999830,99999825,89016253,89016259])
y =le.transform(data['current_service'])
le.inverse_transform(yPred)

OneHotEncoder: 用二進位制數來表示特徵

enc=OneHotEncoder()
OneHotData={'service_type':[1,3,4,1,3,4,1,3,4,1,3,4,1,3,4,1,3,4,1,3,4,1,1,4,1,3,4,1,3,4,1,3,4,1,3,4,1,3,4,1,1],
            'is_mix_service':[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1],
            'many_over_bill':[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1],
            'contract_type':[0,1,3,9,12,7,6,2,8,0,1,3,9,12,7,6,2,8,0,0,0,0,0,7,6,2,8,0,1,3,9,12,7,6,2,8,0,0,0,0,0],
            'is_promise_low_consume':[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1],
            'net_service':[4,3,2,9,4,3,2,9,4,3,2,9,4,3,2,9,4,3,2,9,4,3,3,3,2,9,4,3,2,9,4,3,2,9,4,3,2,9,4,3,3],
            'gender':[0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,0.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,2.0,0.0,1.0,1.0],
            'complaint_level':[0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,1,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1],
            'former_complaint_num':[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,19,21,22,23,37,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],
            'contract_time':[0,12,24,36,10,13,30,23,11,26,15,18,100,8,7,34,35,16,19,17,25,20,6,29,27,21,33,31,9,14,28,32,22,45,39,48,50,52,5,37,40]}
OneHotData=pd.DataFrame(OneHotData)[discreteVar]
# print(OneHotData)
enc.fit(OneHotData)
discreteData=enc.transform(discreteData).toarray()

Binarizer: 將數值型特徵二值化

>>> X = [[ 1., -1.,  2.],
...      [ 2.,  0.,  0.],
...      [ 0.,  1., -1.]]

>>> binarizer = preprocessing.Binarizer().fit(X)  # fit does nothing
>>> binarizer
Binarizer(copy=True, threshold=0.0)

>>> binarizer.transform(X)
array([[ 1.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.]])
>>> binarizer = preprocessing.Binarizer(threshold=1.1)
>>> binarizer.transform(X)
array([[ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  0.,  0.]])

分桶
sklearn可惜沒有Bucketizer,但應該有其他方式來實現對特徵進行分段。下面是一個例子,也可以使用更方便的介面,pd.cut()和pd.qcut()

import numpy as np
np.set_printoptions(precision=2) #np.set_printoptions設定陣列列印資訊,precision設定輸出浮點數精度
bins = np.linspace(-3, 3, 11) #構造連續特徵切割分桶邊界
print(bins)
#array([-3. , -2.4, -1.8, -1.2, -0.6,  0. ,  0.6,  1.2,  1.8,  2.4,  3. ])
#共10段,按1-10編碼
X=[[-0.75],[ 2.7 ],[ 1.39],[ 0.59],[-2.06]]
which_bin = np.digitize(X, bins=bins) #np.digitize返回引數陣列對應分桶的索引
print("\nData points:\n", X)
print("\nBin membership for data points:\n", which_bin)
"""
Data points:
[[-0.75], [2.7], [1.39], [0.59], [-2.06]]
Bin membership for data points:
[[ 4]
 [10]
 [ 8]
 [ 6]
 [ 2]]
"""

FunctionTransformer:自定義一些變換,之前我是用map實現,看來直接就有現成的介面了。不過效果差不多

>>> import numpy as np
>>> from sklearn.preprocessing import FunctionTransformer
>>> transformer = FunctionTransformer(np.log1p)
>>> X = np.array([[0, 1], [2, 3]])
>>> transformer.transform(X)
array([[ 0.        ,  0.69314718],
       [ 1.09861229,  1.38629436]])

1.5、特徵

特徵工程

>>> import numpy as np
>>> from sklearn.preprocessing import PolynomialFeatures
>>> X = np.arange(6).reshape(3, 2)
>>> X                                                 
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> poly = PolynomialFeatures(2)
>>> poly.fit_transform(X)                             
array([[  1.,   0.,   1.,   0.,   0.,   1.],
       [  1.,   2.,   3.,   4.,   6.,   9.],
       [  1.,   4.,   5.,  16.,  20.,  25.]])

(X1,X2)to(1,X1,X2,X12,X<