1. 程式人生 > >【ML】sklearn中, fit,fit_transform,transform的區別與聯絡

【ML】sklearn中, fit,fit_transform,transform的區別與聯絡

scikit-learn提供了一系列轉換庫,他們可以清洗,降維,提取特徵等。

在資料轉換中有三個很重要的方法,fit,fit_transform,transform

ss=StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.transform(X_test)

初學時候好奇為何,訓練樣本用fit_transform,而測試樣本用transform?

仔細閱讀官方文件發現,fit方法是用於從一個訓練集中學習模型引數,其中就包括了歸一化時用到的均值,標準偏差。transform方法就是用於將模型用於位置資料,fit_transform就很高效的將模型訓練和轉化合併到一起,訓練樣本先做fit,得到mean,standard deviation,然後將這些引數用於transform(歸一化訓練資料),使得到的訓練資料是歸一化的,而測試資料只需要在原先得到的mean,std上來做歸一化就行了,所以用transform就行了。

StandardScaler對矩陣作歸一化處理,變換後的矩陣各特徵均值為0,方差為1

網上抄來抄去都是一個意思,

fit_transform是fit和transform的組合。

我們知道fit(x,y)在新手入門的例子中比較多,但是這裡的fit_transform(x)的括號中只有一個引數,這是為什麼呢?

fit(x,y)傳兩個引數的是有監督學習的演算法,fit(x)傳一個引數的是無監督學習的演算法,比如降維、特徵提取、標準化

然後解釋為什麼出來fit_transform()這個東西,下面是重點:

fit和transform沒有任何關係,之所以出來這麼個函式名,僅僅是為了寫程式碼方便,

所以會發現transform()和fit_transform()的執行結果是一樣的。

注意:執行結果一模一樣不代表這兩個函式可以互相替換,絕對不可以!!!

transform函式是一定可以替換為fit_transform函式的

fit_transform函式不能替換為transform函式!!!理由解釋如下:

sklearn裡的封裝好的各種演算法都要fit、然後呼叫各種API方法,transform只是其中一個API方法,所以當你呼叫除transform之外的方法,必須要先fit,為了通用的寫程式碼,還是分開寫比較好

也就是說,這個fit相對於transform而言是沒有任何意義的,但是相對於整個程式碼而言,fit是為後續的API函式服務的,所以fit_transform不能改寫為transform。

下面的程式碼用來舉例示範,資料集是程式碼自動從網上下載的,如果把下面的乳腺癌相關的機器學習程式碼中的fit_transform改為transform,編譯器就會報錯。(下面給出的是無錯誤的程式碼)

# coding: utf-8
# 匯入pandas與numpy工具包。
import pandas as pd
import numpy as np

# 建立特徵列表。
column_names = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape', 'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin', 'Normal Nucleoli', 'Mitoses', 'Class']
# 使用pandas.read_csv函式從網際網路讀取指定資料。
data = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data', names = column_names )

# 將?替換為標準缺失值表示。
data = data.replace(to_replace='?', value=np.nan)
# 丟棄帶有缺失值的資料(只要有一個維度有缺失)。
data = data.dropna(how='any')

# 輸出data的資料量和維度。
data.shape


# In[2]:


# 使用sklearn.cross_valiation裡的train_test_split模組用於分割資料。
from sklearn.cross_validation import train_test_split

# 隨機取樣25%的資料用於測試,剩下的75%用於構建訓練集合。
X_train, X_test, y_train, y_test = train_test_split(data[column_names[1:10]], data[column_names[10]], test_size=0.25, random_state=33)
# print "data[column_names[10]]",data[column_names[10]]


# 查驗訓練樣本的數量和類別分佈。
y_train=pd.Series(y_train)
y_train.value_counts()

# 查驗測試樣本的數量和類別分佈。
y_test=pd.Series(y_test)
y_test.value_counts()


# 從sklearn.preprocessing裡匯入StandardScaler。
from sklearn.preprocessing import StandardScaler
# 從sklearn.linear_model裡匯入LogisticRegression與SGDClassifier。
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import SGDClassifier







#標準化資料,保證每個維度的特徵資料方差為1,均值為0。使得預測結果不會被某些維度過大的特徵值而主導。
ss = StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.transform(X_test)

#

# 初始化LogisticRegression與SGDClassifier。
lr = LogisticRegression()
sgdc = SGDClassifier()

# 呼叫LogisticRegression中的fit函式/模組用來訓練模型引數。
lr.fit(X_train, y_train)
# 使用訓練好的模型lr對X_test進行預測,結果儲存在變數lr_y_predict中。
lr_y_predict = lr.predict(X_test)

# 呼叫SGDClassifier中的fit函式/模組用來訓練模型引數。
sgdc.fit(X_train, y_train)
# 使用訓練好的模型sgdc對X_test進行預測,結果儲存在變數sgdc_y_predict中。
sgdc_y_predict = sgdc.predict(X_test)




# 從sklearn.metrics裡匯入classification_report模組。
from sklearn.metrics import classification_report

# 使用邏輯斯蒂迴歸模型自帶的評分函式score獲得模型在測試集上的準確性結果。
print ("Accuracy of LR Classifier:", lr.score(X_test, y_test))
# 利用classification_report模組獲得LogisticRegression其他三個指標的結果。
print (classification_report(y_test, lr_y_predict, target_names=['Benign', 'Malignant']))



# 使用隨機梯度下降模型自帶的評分函式score獲得模型在測試集上的準確性結果。
print 'Accuarcy of SGD Classifier:', sgdc.score(X_test, y_test)
# 利用classification_report模組獲得SGDClassifier其他三個指標的結果。
print classification_report(y_test, sgdc_y_predict, target_names=['Benign', 'Malignant'])

會得到報錯資訊
AttributeError: ‘StandardScaler’ object has no attribute ‘mean_’

有的版本報錯更加直接:

sklearn.exceptions.NotFittedError: This StandardScaler instance is not fitted yet. Call ‘fit’ with appropriate arguments before using this method.

原因就是因為程式碼中的fit_transform函式被改為了transform函式。

所以總結:

fit_transform與transform執行結果一致,但是fit與transform無關,fit是為了程式的後續函式呼叫而服務的,是個前提條件。

以上。