資料探勘工具---sklearn使用總結
本文來源Cer_ml和Jorocco;
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之間,公式
Normalizer(): 通過縮放使特徵值的和為1,公式
StandScaler(): 通過縮放使特徵值的均值為0,方差為1,即為通常意義上的標準化,公式
編碼:是特徵工程的一部分
在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.]])
將