《機器學習實戰 學習筆記》(二):端到端的機器學習項目

文章目錄

1. 使用真實數據 ( 加州房價預測 )

   1.1 流行的各個領域的開放數據集存儲庫:
   ① UC Irvine ML Repository
   ② Kaggle datasets
   ③ Amazon AWS datasets
   1.2 元門戶站點
   ①http://dataportals.org/
   ② http://opendatamonitor.eu/
   ③ http://quandl.com/
   1.3 其他一些列出許多流行的開放數據存儲庫的頁面
   ① Wiki list of ML datasets
   ② Quora.com question
   ③ Datasets subreddit

2. 觀察大局

在這裏插入圖片描述

   Pipeline: 一個序列的數據處理組件稱爲一個數據流水線。

2.1 框架問題

   ① 首先要問老闆,我們的業務目標是什麼? 因爲建立模型本身可能不是最終問題。【審題很重要】
   ② 如果有現成的解決方案,可以參照。【站在巨人的肩膀上】
   ③ 如果數據量巨大,還會用到MapReduce技術。

2.2 選擇性能指標

   我們是預測房屋價格,典型的迴歸問題。迴歸常用的性能指標:RMSE(均方根誤差)、MAE(平均絕對誤差)。
   RMSE和MAE如何選擇?當異常值非常少時,RMSE更加優異。因爲RMSE對異常值非常敏感,爲什麼?很好理解,平方比絕對值使誤差變更大。

2.3 檢查假設

   搞清楚上下游系統到底是需要什麼數據,比如,下游系統需要輸出價格,那就是迴歸任務,需要輸出類別,就是分類任務。所以要溝通清楚後再着手開發,不要盲目。

3. 獲取數據

3.1 創建工作區

   關於python的系統環境,我用的是anaconda,而且之前寫python爬蟲的時候也介紹過隔離環境如何去安裝。所以這裏就不過多介紹了。

3.2 下載數據

# 下載數據
import os
import tarfile
from six.moves import urllib

downLoad_root = "https://raw.githubusercontent.com/ageron/handson-ml/master/"
housing_path = "datasets/housing"
housing_url = downLoad_root + housing_path + "/housing.tgz"

# 定義獲取房子數據的函數
def fetch_housing_data(housing_url = housing_url,housing_path = housing_path):
    if not os.path.isdir(housing_path):
        os.makedirs(housing_path)
    print("=======   housing_url ================",housing_url)
    tgz_path = os.path.join(housing_path,"housing.tgz")
    print("=======   tgz_path ================",tgz_path)
    urllib.request.urlretrieve(housing_url,tgz_path)#下載遠程文件 並保存爲本地名爲tgz_path的文件
    housing_taz = tarfile.open(tgz_path)# 讀取本地文件
    housing_taz.extractall(path=housing_path)#解壓到housing_path目錄下
    housing_taz.close()#關閉IO流

#定義加載數據方法 
def load_data(housing_path = housing_path):
    csv_path = os.path.join(housing_path,"housing.csv")
    print("=======   csv_path ================",csv_path)
    return pd.read_csv(csv_path)

3.3 快速查看數據結構

data.shape
data.describe()
data.info()

在這裏插入圖片描述

   describe依次展示的是:總數、均值、標準差、最小值、25%分位數、50%分位數、75%分位數、最大值。

在這裏插入圖片描述

   從數據看出,total_bedrooms有缺失值,ocean_proximity是對象類型,可能是分類屬性。

在這裏插入圖片描述

   另一種比較直觀的瞭解數據的方式:直方圖。反應的是落在某一範圍內(橫軸)的實例數量(縱軸)。
data.hist(bins=50,figsize=(20,15))

在這裏插入圖片描述

3.4 創建測試集(經常被忽視但至關重要)

   ① 可以直接用sklearn提供的切分方法,但是在這之前要考慮數據量,數據量大的話用隨機抽樣的方法,數據量小的話最好用分層抽樣,否則會造成明顯的抽樣偏差
#分層抽樣
from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits=1,test_size=0.2,random_state=42)
# 分層是基於label進行的,這裏基於收入類別屬性進行分層!!!
for train_index,test_index in split.split(data,data["income_cat"]):
#     print("==========")
    strat_train_set = data.loc[train_index]
    strat_test_set = data.loc[test_index]

   咦,data[“income_cat”]哪裏來的?這是因爲我們想讓測試集代表整個數據集中各種不同類型的收入而加的新特徵—收入類別。處理如下:
data["income_cat"] = np.ceil(data["median_income"] / 1.5)#取整後得到離散類別
data["income_cat"].where(data["income_cat"] < 5,5.0,inplace = True) # 大於5的都歸屬於類別5
data["income_cat"].value_counts()
data["income_cat"].hist()
   注意:data[“income_cat”]就是爲了切分後的數據分佈更接近整個數據集的數據分佈,所以,切分完後還要刪掉。
#刪掉income_cat列
for d in (strat_train_set,strat_test_set):
    d.drop(["income_cat"],axis = 1,inplace=True)
   至此,我們就完成了數據集的切分,得到了分層抽樣後的測試集。分層抽樣的測試集中的比例分佈更接近於完整數據集中的分佈。

4. 從數據探索和可視化中獲得洞見 EDA(pandas、matplotlib、seaborn)

4.1 將地理數據可視化

h.plot(kind="scatter",x="longitude",y="latitude",alpha=0.4,
      s=h["population"]/100,label="population",
      c="median_house_value",cmap=plt.get_cmap("jet"),colorbar=True,
      figsize=(15,10),fontsize=20)
plt.legend()

在這裏插入圖片描述

4.2 尋找相關性

   數據集不大的話,可以直接用corr()方法計算出每對屬性之間的相關係數,即皮爾遜相關係數。
#尋找相關性
corr_matrix = h.corr()
corr_matrix["median_house_value"].sort_values(ascending=False)

在這裏插入圖片描述

   從上面可以分析出,收入越高,房價越高。越往北走,房價越低。(常識:北緯爲正,東經爲正,南緯和西經爲負
   各種數據集的標準相關係數:

在這裏插入圖片描述

   還有一種方法可以檢測屬性之間的相關性,就是使用pandas的scatter_matrix。
from pandas.tools.plotting import scatter_matrix
# h.columns
attr = ["median_house_value","median_income","total_rooms","housing_median_age"]
scatter_matrix(h[attr],figsize=(12,8))

在這裏插入圖片描述

   最有潛力預測房價中位數的特徵是收入中位數,所以我們放大其散點圖:
h.plot(kind="scatter",x="median_income",y="median_house_value",alpha=0.1)

在這裏插入圖片描述

   分析上圖:
   ① 相關性很強。
   ② 50萬和35附近有一條水平線,可能數據已經經過了處理。

4.3 試驗不同屬性的組合

   其實這屬於是特徵工程的部分。嘗試不同的組合特徵,可以簡單的使用四則運算來實驗。
   思考:其實我認爲這塊東西要跟實際業務緊密相連,比如房價,在我們生活中很普遍,從購房者的角度來看,希望買到什麼樣的房子? 我會考慮是否學區,房屋質量(澆築或板樓),建築年代,是否可貸款,周邊配套等等方面,那麼這些特徵較好的房價肯定貴啊,所以多從實際業務思考,當然除了我們能想到的,也有很多想不到的特徵,就要多去試驗一下(四則運算、決策樹等方式),畢竟每個人的想法和心理是不一樣的。
#組合特徵嘗試
h["rooms_per_household"] = h["total_rooms"] / h["households"] #每戶多少個房間
h["bedrooms_per_room"] = h["total_bedrooms"] / h["total_rooms"] #房價/臥室比例
h["population_per_household"] = h["population"] / h["households"] #每戶有多少人
corr_matrix = h.corr()
corr_matrix["median_house_value"].sort_values(ascending=False)

在這裏插入圖片描述

   分析:臥室房間比例越低,房價越高;每個家庭的房價數量越多,房價越貴。

5. 機器學習算法的數據準備 ( 數據清洗、特徵工程)

   這裏我們應該開始編寫函數和積累函數,自己逐步建立一個轉換函數的函數庫,而不是每次都手動操作。最大原因:重用

5.1 數據清理

   對於缺失值,一般有3種方式:
   ① 刪除對應的樣本;
   ② 刪除對應的特徵;
   ③ 填充缺失值,填充值:中位數、衆數、均值等。
   對於第3種方式,sk提供了imputer來處理缺失值。
from sklearn.preprocessing import Imputer
imputer = Imputer(strategy = "median")
#只保留數值型特徵
housing_nums = housing.drop("ocean_proximity",axis=1)
#對數值型的有缺失值的樣本進行估算填充
imputer.fit(housing_nums )
   注意:此時imputer的估算只是針對【當前實例】,系統如果重啓,則失效。 所以,爲了穩妥,要對所有數值屬性進行變換transform
#結果爲轉換後的Numpy數組
X = imputer.transform(housing_nums) 
#再轉成df
housing_transform = pd.DataFrame(X,columns=housing_nums.columns)
5.1.1 【插曲1】 數據的拼接和合並:
   ① concat,基於axis拼接,類似union,適合縱向
   ② merge,基於某列做關聯,表的合併,類似sql的表連接,適合橫向
   ③ join,基於index合併。
5.1.2 【插曲2】 sk的幾個常用函數:
   sklearn做了一致性的設計,所以大部分數據集的操作通過以下函數就可以實現:
   ① fit 擬合;
   ② transform 變換;
   ③ fit_transform 擬合+變換;
   ④ predict 預測;
   ⑤ predict_prob 預測概率;
   fit 和 transform 的區別和聯繫:舉個通俗點的例子,從字面上來看,transform更像數據的實際轉換方法,比如標準化StandardScaler(),當數據集執行了transform纔算標準化完成,而fit更像是在這之前做一些基礎數據的計算,爲後面的transform作準備,所以一般我們在訓練集做fit_transform,然後在測試集直接用transform,因爲前面一步已經做了fit生成了一些基礎數據比如均值,標準差等。

5.2 處理文本和分類屬性

   之前我們排除了分類屬性ocean_proximity,因爲它是一個文本屬性,我們無法計算中位數。大部分的機器學習更易於跟數字打交道,所以我們可以將這種數據轉換爲數字。sk中提供了這種轉換器,比如LabelEncoder。
# 處理文本和分類屬性  編碼
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
housing_cat = housing["ocean_proximity"]
housing_cat_encoded = encoder.fit_transform(housing_cat)
housing_cat_encoded
encoder.classes_

在這裏插入圖片描述

   注意:這裏有個比較實際的問題,映射器將類別型特徵轉換爲了0,1,2,3,4,但是這樣的編碼是有大小關係的,而實際ocean_proximity這個特徵不具有大小關係的含義,所以通常解決方式:轉化爲二進制屬性。
   如果特徵的值爲高等、中等、低等,這種具有大小關係的含義,就可以映射爲3,2,1這樣的編碼。
from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder()
housing_cat_1hot = encoder.fit_transform(housing_cat_encoded.reshape(-1,1))#需要一個二維數組,所以需要重塑 housing_cat_encoded(一維) 成二維
housing_cat_1hot

在這裏插入圖片描述

   這裏輸出是一個Scipy稀疏矩陣,但是隻存非0元素的位置,因爲大量0佔用內存,所以做了優化。如果想轉換成密集的二維數組:
housing_cat_1hot.toarray()

在這裏插入圖片描述

   這樣是不是就更像one-hot了?但是,LabelBinarizer默認返回的是一個密集的Numpy數組

在這裏插入圖片描述

   但是,是不是很麻煩,難道每次我要先LabelEncoder再OneHotEncoder? sk提供了一個LabelBinarizer可以一次性完成2個轉換(從文本類別轉化爲整數類別,再從整數類別轉化爲獨熱向量)
from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
housing_cat_1hot = encoder.fit_transform(housing_cat)#直接將文本類別轉化爲獨熱向量
housing_cat_1hot

5.3 自定義轉化器

   ① 爲什麼?因爲一些清理操作或組合特定特徵等任務需要自定義;再就是轉換器能和sk的pipeline無縫銜接
   ② 具體實現:新建類,添加兩個基類BaseEstimator和TransformerMixin分別得到get_params()、set_params() 和 fit_transform() (這裏的基類類似於繼承),類中再實現fit和transform即可。
#自定義轉化器
from sklearn.base import BaseEstimator,TransformerMixin
#單個特徵的列號
rooms_ix,bedrooms_ix,population_ix,household_ix = 3,4,5,6

class CombinedAttributesAdder(BaseEstimator,TransformerMixin):
    def __init__(self,add_bedrooms_per_room = True):
        self.add_bedrooms_per_room = add_bedrooms_per_room
    def fit(self,X,y=None):
        return self
    #創建組合特徵並加入到原始特徵數組即可
    def transform(self,X,y=None):
        rooms_per_household = X[:,rooms_ix] / X[:,household_ix]
        population_per_household = X[:,population_ix] / X[:,household_ix]
        if self.add_bedrooms_per_room :
            bedrooms_per_room = X[:,bedrooms_ix] / X[:,rooms_ix]
            return np.c_[X,rooms_per_household,population_per_household,bedrooms_per_room]
        else:
            # X爲原特徵數組,在此基礎上加上新特徵:rooms_per_household 和 population_per_household
            return np.c_[X,rooms_per_household,population_per_household]
        
attr_adder = CombinedAttributesAdder(add_bedrooms_per_room = False)
housing_extra_attr = attr_adder.transform(housing.values)
type(housing_extra_attr)
# attr_adder.get_params


5.4 特徵縮放

   爲什麼?比如有的特徵是0 ~ 9999,有的特徵是2 ~ 9,會導致算法對取值較大的特徵有所偏好,性能不佳,所以如果將兩個特徵都縮放到 0 ~ 1範圍內,就能提高模型算法的泛化能力。
   常用方法:最小最大值縮放 MinMaxScaler(默認範圍0~1,可調)和 標準化StandadScaler。
   區別:標準化不會將值縮放到特定範圍,但是標準化能減小異常值的影響。

5.5 轉換流水線

   爲什麼? 許多數據轉換的步驟需要以正確的順序執行。
   LabelBinarizer版本更新問題
#自定義轉化器
from sklearn.base import BaseEstimator,TransformerMixin
#單個特徵的列號
rooms_ix,bedrooms_ix,population_ix,household_ix = 3,4,5,6

class CombinedAttributesAdder(BaseEstimator,TransformerMixin):
    def __init__(self,add_bedrooms_per_room = True):
        self.add_bedrooms_per_room = add_bedrooms_per_room
    def fit(self,X,y=None):
        return self
    def transform(self,X,y=None):
        rooms_per_household = X[:,rooms_ix] / X[:,household_ix]
        population_per_household = X[:,population_ix] / X[:,household_ix]
        if self.add_bedrooms_per_room :
            bedrooms_per_room = X[:,bedrooms_ix] / X[:,rooms_ix]
            return np.c_[X,rooms_per_household,population_per_household,bedrooms_per_room]
        else:
            # X爲原特徵數組,在此基礎上加上新特徵:rooms_per_household 和 population_per_household
            return np.c_[X,rooms_per_household,population_per_household]
        
#測試舉例
attr_adder = CombinedAttributesAdder(add_bedrooms_per_room = False)
housing_extra_attr = attr_adder.transform(housing.values)
type(housing_extra_attr)
# attr_adder.get_params

#需要自定義,sk沒有可以處理pd.DataFrame的
class DataFrameSelector(BaseEstimator,TransformerMixin):
    def __init__(self,attribute_names): #可以爲列表
        self.attribute_names = attribute_names
    def fit(self,X,y=None):
        return self
    def transform(self,X):
        return X[self.attribute_names].values #返回的爲numpy array

#LabelBinarizer參數有問題,可能是版本問題,重寫一下即可
class MyLabelBinarizer(TransformerMixin):
    def __init__(self, *args, **kwargs):
        self.encoder = LabelBinarizer(*args, **kwargs)
    def fit(self, x, y=0):
        self.encoder.fit(x)
        return self
    def transform(self, x, y=0):
        return self.encoder.transform(x)

#轉換器流水線
from sklearn.pipeline import Pipeline,FeatureUnion
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import Imputer

housing_num = housing.drop("ocean_proximity",axis=1)

#一個完整的處理數值和分類特徵的流水線如下: (pipeline必須保證前面都是轉換器,最後是估算器)
num_attr = list(housing_num)
cat_attr = ["ocean_proximity"]

#數值特徵pipeline
num_pipeline = Pipeline([
    ('selector',DataFrameSelector(num_attr)),
    ('imputer',Imputer(strategy="median")),      # 缺失值填充爲中位數               #
    ('attribs_adder',CombinedAttributesAdder()), # 添加組合特徵
    ('std_scaler',StandardScaler()),             # 標準化
])

#文本分類特徵pipeline
cat_pipeline = Pipeline([
    ('selector',DataFrameSelector(cat_attr)),
    ('label_binarizer',MyLabelBinarizer()),       #LabelEncoder + OneHotEncoder
])

#利用FeatureUnion整合2條流水線
full_pipeline = FeatureUnion(transformer_list=[
    ("num_pipeline",num_pipeline),
    ("cat_pipeline",cat_pipeline),
])

housing_prepared = full_pipeline.fit_transform(housing)
housing_prepared
   這一節主要完成了:自動清理 和 準備ML算法的數據的轉換流水線

   至此,看看我們完成了哪些內容:明確目標問題、獲取數據、EDA、對訓練集和測試集進行分層抽樣、編寫了自動清理和準備數據的轉換器。

6. 選擇和訓練模型

6.1 訓練和評估

   首先,測試一下我們前面的組件。
#線性迴歸測試一下模型
from sklearn.linear_model import LinearRegression
m1  = LinearRegression()
m1.fit(housing_prepared,housing_label)
some_data = housing.iloc[:5]
some_labels = housing_label.iloc[:5]
housing_prepared = full_pipeline.fit_transform(housing)
some_data_prepared = full_pipeline.transform(some_data)

print("Predictions:",m1.predict(some_data_prepared))
print("Labels:",list(some_labels))

在這裏插入圖片描述

   測試成功,說明我們前面的組件都可以正常工作。但是準確度堪憂~ 所以,先評估一下吧。
#選擇評估標準RMSE評估訓練效果
from sklearn.metrics import mean_squared_error
housing_predictions = m1.predict(housing_prepared)
m1_mse = mean_squared_error(housin_label,housing_predictions)
m1_rmse = np.sqrt(m1_mse)
m1_rmse

在這裏插入圖片描述

   貌似損失有點大,說明欠擬合。如何解決?選擇一個更復雜的模型試試,比如DecisionTreeRegressor

在這裏插入圖片描述

   竟然0損失,好吧,模型過擬合了。所以我們還需要模型進行評估,正常來說要對訓練集切分成訓練集和驗證集,然後用交叉驗證評估,最後得到驗證的模型再去預測測試集

6.2 使用交叉驗證來更好地進行評估

   k-fold交叉驗證
#決策樹10折交叉驗證
from sklearn.model_selection import cross_val_score
scores = cross_val_score(m2,housing_prepared,housing_label,scoring="neg_mean_squared_error",cv =10)
rmse_scores = np.sqrt(-scores)

def display_scores(scores):
    print("Scores:",scores)
    print("Mean:",scores.mean())
    print("Std:",scores.std())

display_scores(rmse_scores)

在這裏插入圖片描述

#線性迴歸交叉驗證
l_scores = cross_val_score(m1,housing_prepared,housing_label,scoring="neg_mean_squared_error",cv =10)
l_rmse_scores = np.sqrt(-l_scores)
display_scores(l_rmse_scores)

在這裏插入圖片描述

#隨機森林
from sklearn.ensemble import RandomForestRegressor
m3 = RandomForestRegressor()
m3.fit(housing_prepared,housing_label)
rf_scores = cross_val_score(m3,housing_prepared,housing_label,scoring="neg_mean_squared_error",cv =10)
rf_rmse_scores = np.sqrt(-rf_scores)
display_scores(rf_rmse_scores)

在這裏插入圖片描述

   上面試驗了3種不同模型的交叉驗證效果,隨機森林效果最好,但是還是過擬合。注意:此時不要急於去調超參數,而是要多試驗幾種其他模型(不同內核的SVM,神經網絡模型等),我們這個階段的目的是篩選有效模型(一般選出2~5個)
   模型保存:嘗試過的模型要保存下來,包括超參數和訓練過的參數,以及交叉驗證的評分和實際預測的結果。比賽和實際工作都要這麼做。我們通過python的pickel模塊或sklearn.externals.joblib,這樣可以有效將大型Numpy數組序列化。
#模型保存
from sklearn.externals import joblib
joblib.dump(m1,"linearReg_model.pkl")#保存訓練過的線性迴歸模型
my_model = joblib.load("linearReg_model.pkl")# 加載模型
my_model.predict(some_data_prepared)

在這裏插入圖片描述

7. 微調模型

   經過上面過程,我們已經有了一個有效的模型列表,下一步需要對它們進行微調。

8. 網格搜索

   可以直接使用sk的GridSearchCV來替代手動調整超參數。
from sklearn.model_selection import GridSearchCV

#候選參數列表
params = {
    'n_estimators': (3, 10, 30), 'max_features': (2, 3, 4, 6, 8),
}


#使用隨機森林(評估器)尋找最佳參數
rf_reg = RandomForestRegressor() 
grid_search = GridSearchCV(rf_reg,params,cv=5,scoring="neg_mean_squared_error")
grid_search.fit(housing_prepared,housing_label)

在這裏插入圖片描述

   查看最佳參數和最優估算器
grid_search.best_params_ 
grid_search.best_estimator_

在這裏插入圖片描述

   查看評估分數
cvres = grid_search.cv_results_
for mean_score,param in zip(cvres["mean_test_score"],cvres["params"]):
    print(np.sqrt(-mean_score),param)

在這裏插入圖片描述

8.1 隨機搜索

   當數據量很大時,用網格搜索太慢,此時使用隨機搜索RandomizedSearchCV:在每次迭代中,爲每個超參數選擇一個隨機值,然後對一定數量的隨機組合進行評估。

8.2 集成方法

   將表現最優的幾個模型組合起來。集成方法詳細介紹

8.3 分析最佳模型及其錯誤

   RF可以指出每個屬性的相對重要程度 ( 怎麼算的?根據某種增益和分裂次數等,曾經被面試官問到過。)
extra_attrs = ["rooms_per_hhold","pop_per_hhold","bedrooms_per_room"] #新增的組合特徵
cat_one_hot_attrs = list(encoder.classes_) #類別特徵名稱列表
attrs = num_attr + extra_attrs + cat_one_hot_attrs
# attrs
# housing_prepared
sorted(zip(feature_importances,attrs),reverse=True)

在這裏插入圖片描述

   從圖中看出,收入中位數median_income是最重要的特徵。

8.4 通過測試集評估系統

   記住:在這之前我們沒有動過測試集,也不應該動。
final_m = grid_search.best_estimator_
X_test = strat_test_set.drop("median_house_value",axis=1)
y_test = strat_test_set["median_house_value"].copy()

X_test_prepared = full_pipeline.transform(X_test)
final_predictions = final_m.predict(X_test_prepared)

final_mse = mean_squared_error(y_test,final_predictions)
final_rmse = np.sqrt(final_mse)
final_rmse
   特別注意: 測試集效果可能略差於交叉驗證的結果,但是此時不要再調整超參數了,因爲再調可能會導致新數據集上的泛化能力變差。

9. 啓動、監控和維護系統

   ① 將生產數據源接入系統。
   ② 編寫監控代碼,實時監控系統的性能,在性能下降時觸發警報。因爲模型會慢慢腐壞,除非定期使用新數據訓練模型。
   ③ 評估系統性能,需要對系統的預測結果進行抽樣評估(人工分析)。這塊需要將人工評估的流水線接入學習系統。
   ④ 需要定期用新數據訓練模型,並且能保存系統當前狀態,以便發生錯誤能及時回滾。

10. 試試看和練習

   經過這一系列的過程,其實機器學習的大部分工作是:數據準備、構建監控工具、建立人工評估的流水線、自動定期訓練模型
   嘗試A ~ Z的過程:kaggle競賽網站

11. 那些年我們踩過的坑。。。

   ① 已經訓練好的模型predict數據,報特徵維度不一致。報錯信息如下:

在這裏插入圖片描述

   錯誤代碼:
#線性迴歸測試一下模型
from sklearn.linear_model import LinearRegression
m1  = LinearRegression()
m1.fit(housing_prepared,housing_label)
some_data = housing.iloc[:5]
some_labels = housing_label.iloc[:5]
housing_prepared = full_pipeline.fit_transform(housing)
some_data_prepared = full_pipeline.fit_transform(some_data) 【錯誤處】

print("Predictions:",m1.predict(some_data_prepared))
   仔細看上述代碼,訓練數據和測試數據都進行了fit_transform操作,相當於產生了2個不同pipeline實例,編碼出來特徵維度肯定不一致。我還傻傻的畫了個圖,造成這種情況的原因是創建了2個pipeline實例去編碼:

在這裏插入圖片描述

   錯誤修改

some_data_prepared = full_pipeline.transform(some_data) 【修改後】
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章