機器學習基礎課程-5-課程實驗

5.1 實驗介紹

實驗背景

在這個項目中,您將使用1994年美國人口普查收集的數據,選用幾個監督學習算法以準確地建模被調查者的收入。然后,您將根據初步結果從中選擇出最佳的候選算法,并進一步優化該算法以最好地建模這些數據。你的目標是建立一個能夠準確地預測被調查者年收入是否超過50000美元的模型。這種類型的任務會出現在那些依賴于捐款而存在的非營利性組織。了解人群的收入情況可以幫助一個非營利性的機構更好地了解他們要多大的捐贈,或是否他們應該接觸這些人。雖然我們很難直接從公開的資源中推斷出一個人的一般收入階層,但是我們可以(也正是我們將要做的)從其他的一些公開的可獲得的資源中獲得一些特征從而推斷出該值。

這個項目的數據集來自UCI機器學習知識庫。這個數據集是由Ron KohaviBarry Becker在發表文章"Scale Up the Accuracy of Naive-Bayes Classifiers A Decision-Tree Hybrid"之后捐贈的,你可以在Ron Kohavi提供的在線版本中找到這個文章。我們在這里探索的數據集相比于原有的數據集有一些小小的改變,比如說移除了特征 以及一些遺失的或者是格式不正確的記錄。'fnlwgt'

5.2 數據探索

導入數據

運行下面的代碼單元以載入需要的Python庫并導入人口普查數據。

注意數據集的最后一列 將是我們需要預測的列(表示被調查者的年收入會大于或者是最多50,000美元),人口普查數據中的每一列都將是關于被調查者的特征。'income'

# 引入此項目需要的庫
import numpy as np
import pandas as pd
from time import time
import matplotlib as mpl
# 使用 display() 顯示 DataFrame
from IPython.display import display 
 
# 引入可視化代碼 visuals.py
import visuals as vs
 
# 讓可視化更方便更美觀
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
 
# 設置matplotlib中文顯示
mpl.rcParams['font.family'] = 'SimHei'
mpl.rcParams['axes.unicode_minus'] = False
# 載入人口普查數據
try:
??? data = pd.read_csv('census.csv')
??? print('數據集有 {} 個樣本,每個樣本有 {} 個特征。'.format(
??????? *data.shape))
??? display(data.head())
except:
??? print('數據集無法加載,數據集丟失了嗎?')

數據集有 45222 個樣本,每個樣本有 14 個特征

特征

  • age: 一個整數,表示被調查者的年齡。
  • workclass: 一個類別變量表示被調查者的通常勞動類型,允許的值有 {Private, Self-emp-not-inc, Self-emp-inc, Federal-gov, Local-gov, State-gov, Without-pay, Never-work}
  • education_level: 一個類別變量表示教育程度,允許的值有 {Bachelors, Some-college, 11th, HS-grad, Prof-school, Assoc-acdm, Assoc-voc, 9th, 7th-8th, 12th, Masters, 1st-4th, 10th, Doctorate, 5th-6th, Preschool}
  • education-num: 一個整數表示在學校學習了多少年
  • 婚姻狀態: 一個類別變量,允許的值有 {已婚-公民-配偶, 離婚, 從未結婚, 分居, 寡居, 已婚-配偶-缺席, 已婚-AF-配偶}
  • 職業: 一個類別變量表示一般的職業領域,允許的值有 {Tech-support, Craft-repair, Other-service, Sales, Exec-Managemential, Prof-specialty, Handlers-cleaners, Machine-op-inspct, Adm-clerical, Farming-fishing , Transport-move, Priv-house-serv, Protective-serv, Armed Forces}
  • relationship: 一個類別變量表示家庭情況,允許的值有
  • race: 一個類別變量表示人種,允許的值有 {White, Asia-Pac-Islander, Amer-Indian-Eskimo, Other, Black}
  • :一個類別變量表示性別,允許的值有 { Female , Male }
  • 資本收益:連續值。
  • 資本損失: 連續值。
  • 小時/周: 連續值。
  • native-country: 一個類別變量表示原始的國家,允許的值有 {美國, 柬埔寨, 英國, 波多黎各, 加拿大, 德國, Outlying-US(關島-USVI-etc), 印度, 日本, 希臘, 南部, 中國, 古巴, 伊朗, 洪都拉斯, 菲律賓, 意大利, 波蘭, 牙買加, 越南, 墨西哥, 葡萄牙, 愛爾蘭, 法國, 多米尼加共和國, 老撾, 厄瓜多爾, 臺灣, 海地, 哥倫比亞, 匈牙利, 危地馬拉, 尼加拉瓜, 蘇格蘭, 泰國, 南斯拉夫, 薩爾瓦多, 特里納達德和多巴哥, 秘魯, 洪, 荷蘭荷蘭}

數據探索

首先我們對數據集進行一個粗略的探索,我們將看看每一個類別里會有多少被調查者?并且告訴我們這些里面多大比例是年收入大于 50,000 美元的。在下面的代碼單元中,你將需要計算以下量:

  • 總的記錄數量,'n_records'
  • 年收入大于50,000美元的人數,.'n_greater_50k'
  • 年收入最多為50,000美元的人數?.'n_at_most_50k'
  • 年收入大于50,000美元的人所占的比例,?.'greater_percent'

**提示:**您可能需要查看上面的生成的表,以了解 條目的格式是什么樣的。'income'

# TODO: 總記錄數
n_records = len(data.index)
 
# TODO: 個人收入超過50,000美元
n_greater_50k = len(data[data['income'] != '<=50K'].index)
 
# TODO: 個人最多可獲得50,000美元
n_at_most_50k = len(data[data['income'] == '<=50K'].index)
 
# TODO: 個人收入超過5萬美元的百分比
greater_percent = float(n_greater_50k) / n_records * 100
 
# 輸出結果
print('總記錄數:{}'.format(n_records))
print('個人收入超過50,000美元:{}'.format(n_greater_50k))
print('個人最多可獲得50,000美元:{}'.format(n_at_most_50k))
print('個人收入超過5萬美元的百分比:{:.2f}'.format(greater_percent))

總記錄數:45222
個人收入超過50000美元:11208
個人最多可獲得50000美元:34014
個人收入超過5萬美元的百分比:24.78%

5.3 數據預處理

準備數據

在數據能夠被作為輸入提供給機器學習算法之前,它經常需要被清洗、格式化和重新組織 - 這通常被叫做預處理

幸運的是,對于這個數據集,沒有我們必須處理的無效或丟失的條目,然而,由于某一些特征存在的特性我們必須進行一定的調整。這個預處理都可以極大地幫助我們提升幾乎所有的學習算法的結果和預測能力。

display(data.dtypes)

data.describe()

import seaborn as sns

display(data.select_dtypes(include=['int64','float64']).columns)

sns.pairplot(data.select_dtypes(include=['int64','float64']),diag_kind='kde')

轉換傾斜的連續特征

一個數據集有時可能包含至少一個靠近某個數字的特征,但有時也會有一些相對來說存在極大值或者極小值的不平凡分布的的特征。算法對這種分布的數據會十分敏感,并且如果這種數據沒有能夠很好地歸一化處理會使得算法表現不佳。

在人口普查數據集的兩個特征符合這個描述:??'capital-gain''capital-loss'

運行下面的代碼單元以創建一個關于這兩個特征的條形圖。請注意當前的值的范圍和它們是如何分布的。

# 將數據切分成特征和對應的標簽

income_raw = data['income']

features_raw = data.drop('income', axis = 1)

# 可視化原來數據的傾斜的連續特征

vs.distribution(data)

# TODO: MatplotLib Seaborn 實現可視化

import matplotlib.pyplot as plt

import seaborn as sns

plt.figure(figsize=(10,5))

plt.subplot(121)

sns.distplot(data['capital-gain'])

plt.subplot(122)

sns.distplot(data['capital-loss'])

對于高度傾斜分布的特征如和,常見的做法是對數據施加一個對數轉換,將數據轉換成對數,這樣非常大和非常小的值不會對學習算法產生負面的影響。并且使用對數變換顯著降低了由于異常值所造成的數據范圍異常。'capital-gain''capital-loss'

但是在應用這個變換時必須小心:因為0的對數是沒有定義的,所以我們必須先將數據處理成一個比0稍微大一點的數以成功完成對數轉換。

運行下面的代碼單元來執行數據的轉換和可視化結果。再次,注意值的范圍和它們是如何分布的。

# 對于傾斜的數據使用 np.log() 函數轉換

skewed = ['capital-gain', 'capital-loss']

features_log_transformed = pd.DataFrame(data = features_raw)

features_log_transformed[skewed] = features_raw[skewed].apply(lambda x: np.log(x + 1))

# 可視化對數轉換后的數據分布

vs.distribution(features_log_transformed, transformed=True)

plt.figure(figsize=(10,5))

plt.subplot(121)

sns.distplot(features_log_transformed['capital-gain'])

plt.subplot(122)

sns.distplot(features_log_transformed['capital-loss'])

歸一化數字特征

除了對于高度傾斜的特征施加轉換,對數值特征施加一些形式的縮放通常會是一個好的習慣。

在數據上面施加一個縮放并不會改變數據分布的形式(比如上面說的 );但是歸一化保證了每一個特征在使用監督學習器的時候能夠被平等的對待。'capital-gain''capital-loss'

注意一旦使用了縮放,觀察數據的原始形式不再具有它本來的意義了,就像下面的例子展示的。

運行下面的代碼單元來規一化每一個數字特征。我們將使用sklearn.preprocessing.MinMaxScaler來完成這個任務。

# 引入 sklearn.preprocessing MinMaxScaler

from sklearn.preprocessing import MinMaxScaler

# 初始化一個 scaler,然后將其應用于特征

scaler = MinMaxScaler()

numerical = ['age', 'education-num', 'capital-gain', 'capital-loss', 'hours-per-week']

features_log_minmax_transform = pd.DataFrame(data = features_log_transformed)

features_log_minmax_transform[numerical] = scaler.fit_transform(features_log_transformed[numerical])

# 顯示應用了 scaler 的樣本示例

display(features_log_minmax_transform.head(n = 5))

for key in numerical:

??? sns.distplot(features_log_transformed[key])

??? plt.show()

數據預處理

從上面的數據探索中的表中,我們可以看到有幾個屬性的每一條記錄都是非數字的。通常情況下,學習算法期望輸入是數字的,這要求非數字的特征(稱為類別變量)被轉換。轉換類別變量的一種流行的方法是使用獨熱編碼 One-Hot編碼)方案。

獨熱編碼為每一個非數字特征的每一個可能的類別創建一個"虛擬"變量。例如,假設 有三個可能的取值 或者 。我們將把這個特征編碼成 someFeatureABCsomeFeature_AsomeFeature_BsomeFeature_C

特征

特征_A

特征_B

特征_C

0

B

0

1

0

1

C

–>一熱編碼 -->

0

0

1

2

一個

1

0

0

此外,對于非數字的特征,我們需要將非數字的標簽 轉換成數值以保證學習算法能夠正常工作。因為這個標簽只有兩種可能的類別("<=50K" ">50K"),我們不必要使用獨熱編碼,可以直接將他們編碼分別成兩個類 ,在下面的代碼單元中你將實現以下功能:'income'01

  • 使用pandas.get_dummies()對 數據進行獨熱編碼'features_raw'
  • 將目標標簽 轉換成數字'income_raw'
    • 將 "<=50K" 轉換成0
    • 將 ">50K" 轉換成1

# TODO: 使用 pandas.get_dummies() 'features_log_minmax_transform' 數據進行獨熱編碼

feature_object = features_log_minmax_transform.select_dtypes(include=['object'])

features_log_minmax_transform[feature_object.columns] = feature_object.apply(

??? lambda x: x.str.strip())

features_final = pd.get_dummies(features_log_minmax_transform)

# TODO: 'income_raw' 編碼成為數字

income = (income_raw == '>50K').astype(np.uint8)

# 輸出經過獨熱編碼之后的特征數量

encoded = list(features_final.columns)

print('獨熱編碼之后共有 {} 個全部特征'.format(len(encoded)))

# 移除下面一行的注釋以觀察編碼后的特征名稱

print(encoded)

獨熱編碼之后共有 103
全部特征 ['age' 'education-num' 'capital-gain' 'capital-loss' '每周小時數' 'workclass_Federal-gov' 'workclass_Local-gov' 'workclass_Private' 'workclass_Self-emp-inc' 'workclass_Self workclass_State-nmp-inc' 'workclass_State-gov' 'workclass_Without-pay' 'education_level_10th' 'education_level_11th' 'education_level_12th' 'education_level_1st-4th' 'education_level_5th-6th' 'education_level_7th-8th' 'education_level_9th' 'education_level_Assoc-acdm' 'education_level_Assoc-voc' 'education_level_Bachelors' 'education_level_Doctorate' 'education_level_HS-grad' 'education_level_Masters' 'education_level_Preschool' 'education_level_Prof-school' 'education_level_Some-College' 'marital-status_Divorced' 'marital-status_Married-AF-配偶' '婚姻-status_Married-civ-配偶' '婚姻-status_Married-配偶-缺席' '婚姻-status_Never-已婚' '婚姻-status_Separated' '婚姻-status_喪偶""occupation_Adm文職人員""occupation_Armed部隊""occupation_Craft修理""occupation_Exec管理""occupation_Farming捕魚""occupation_Handlers清潔工""occupation_Machine行動者""occupation_Other服務""occupation_Priv服務""occupation_Prof專業""occupation_Protective服務""occupation_Sales""occupation_Tech支持""occupation_Transport移動""relationship_Husband""家庭relationship_Not""家庭relationship_Not"""relationship _ Other 親戚、 relationship _ Own 兒童、 relationship _ Unmarried relationship _ Wife race _ Amer - 印度 - 愛斯基摩人、 race _ Asian - 太平洋島民、 race _ Black race _ Other race _ White _ Female _ Male 、本土 country _ Cambodia 、本土 country _ Canada 、本土 country _ China 、本土 country _ Columbia 、本土 country _ Cuba 、本土 country _ Dominican 共和國、本土 country _ Ecuador 、本土 country _ El 薩爾瓦多、本土 country _ England "本地-country_France""本地-country_Germany""本地-country_Greece""本地-country_Guatemala""本地-country_Haiti""本地-country_Holand-荷蘭""本地-country_Honduras""本地-country_Hong""本地-country_Hungary""本地-country_India""本地-country_Iran""本地-country_Ireland""本地-country_Italy""本地-country_Jamaica""本地-country_Japan""本地-country_Laos""本地-country_Mexico""本地-country_Nicaragua' "本地country_Outlying-美國(關島-USVI-等)""本地country_Peru""本地country_Philippines""本地country_Poland""本地country_Portugal""本地country_Puerto-Rico""本地country_Scotland""本地country_South""本地country_Taiwan""本地country_Thailand""本地country_Trinadad和多巴哥""本地country_United""本地國家_越南""本地country_Yugoslavia"]

混洗和切分數據

現在所有的類別變量已被轉換成數值特征,而且所有的數值特征已被規一化。和我們一般情況下做的一樣,我們現在將數據(包括特征和它們的標簽)切分成訓練和測試集。其中 80% 的數據將用于訓練和 20% 的數據用于測試。

運行下面的代碼單元來完成切分。

# 引入 sklearn.model_selection train_test_split

from sklearn.model_selection import train_test_split

# 'features' 'income' 數據切分成訓練集和測試集

X_train, X_test, y_train, y_test = train_test_split(

??? features_final,income,test_size=0.2,random_state=0)

# 顯示切分的結果

print('訓練集有 {} 個樣本。'.format(X_train.shape[0]))

print('測試集有 {} 個樣本。'.format(X_test.shape[0]))

訓練集有 36177 個樣本。
測試集有 9045 個樣本。

5.4 評價模型性能

在這一部分中,我們將嘗試四種不同的算法,并確定哪一個能夠最好地建模數據。

這里面的三個將是你選擇的監督學習器,而第四種算法被稱為一個樸素的預測器

評價方法和樸素的預測器

UdacityML通過他們的研究人員知道被調查者的年收入大于 $50000 最有可能向他們捐款。因為這個原因UdacityML對于準確預測誰能夠獲得 $50000 以上收入尤其有興趣。這樣看起來使用準確率作為評價模型的標準是合適的。

另外,把沒有收入大于 $50000 的人識別成年收入大于 $50000 對于UdacityML來說是有害的,因為他想要找到的是有意愿捐款的用戶。

這樣,我們期望的模型具有準確預測那些能夠年收入大于 $50,000 的能力比模型去召回這些被調查者更重要。我們能夠使用F-beta score作為評價指標,這樣能夠同時考慮準確率和召回率:

F_{\beta}=1+\beta^2\cdot\frac{precision\ \cdot\ recall}{\left\beta^2\ \cdot\ precision\right+recall}Fβ?=(1+β2)?(β2??precision?)+recallprecision?recall???

尤其是,當\beta =0.5β=0.5 的時候跟多的強調準確率,這叫做F_{0.5}0.5 ?得分(或者為了簡單叫做 F-score)。

通過查看不同類別的數據分布(那些最多賺 $50,000 和那些能夠賺更多的),我們能發現:很明顯的是很多的被調查者年收入沒有超過 $50,000。這點會顯著地影響準確率,因為我們可以簡單地預測說"這個人的收入沒有超過$50,000",這樣我們甚至不用看數據就能做到我們的預測在一般情況下是正確的!

做這樣一個預測被稱作是樸素的,因為我們沒有任何信息去證實這種說法。通常考慮對你的數據使用一個樸素的預測器是十分重要的,這樣能夠幫助我們建立一個模型的表現是否好的基準。那有人說,使用這樣一個預測是沒有意義的:如果我們預測所有人的收入都低于 $50000,那么UdacityML就不會有人捐款了。

注意: 準確、精密 召回 概要

準確度 accuracy衡量分類器進行正確預測的頻率。它是正確預測數量與預測總數(測試數據點數量)的比率。

精確度 precision告訴我們,我們將哪些郵件歸類為垃圾郵件,實際上是垃圾郵件。這是一個真正的肯定比例(被分類為垃圾郵件,實際上是垃圾郵件)與所有正面比率(所有被歸類為垃圾郵件,無論這是否正確的分類)。

換句話說:[ 真實肯定 / ( 真實肯定 + 錯誤肯定) ]

召回度(敏感度) recall告訴我們實際上垃圾郵件的比例是由我們分類為垃圾郵件。這是真正的肯定比例(被分類為垃圾郵件,實際上是垃圾郵件)與所有實際上是垃圾郵件的比率。

換句話說:[ 真正肯定 / (真正肯定 + 錯誤否定)]

對于像我們這樣的分類分布有偏差的分類問題,例如,如果我們有100條短信,只有2條是垃圾信息,其余98條不是,則準確度本身并不是一個很好的指標。

我們可以將90封郵件歸類為非垃圾郵件(包括2封垃圾郵件,但我們將其歸類為非垃圾郵件,因此它們將是錯誤的否定信息),10封為垃圾郵件(全部10個誤報),仍然得到相當好的準確性分數。

對于這種情況,精確度和召回率非常方便。這兩個指標可以合并得到F_1F1?分數,這是精度和召回分數的加權平均值(調和平均值)。這個分數可以從01,其中1是最好的F_1F1?分數(當我們處理比率時,我們采用調和平均值)。

樸素預測器的性能

如果我們選擇一個無論什么情況都預測被調查者年收入大于 $50000 的模型,那么這個模型在這個數據集上的準確率和F-score是多少?

**注意:**你必須使用下面的代碼單元將你的計算結果賦值給 ,這些值會在后面被使用,請注意這里不能使用scikit-learn,你需要根據公式自己實現相關計算。'accuracy''fscore'

# TODO: 計算準確率
accuracy = income.mean()
 
# TODO: 使用上面的公式,并設置 `beta=0.5` 計算 F-score
prediction = np.ones(len(income))
 
beta2 = 0.5 ** 2
recall = 1
precision = accuracy
fscore = (1 + beta2) * precision * recall / (beta2 * precision + recall)
 
# 輸出結果
print('樸素預測器得分:[ 準確度: {:.4f}F-score: {:.4f}]'.format(
??? accuracy, fscore))
樸素預測器得分:[ 準確度: 0.2478F-score: 0.2917]

5.5 監督學習模型

下面的監督學習模型是現在在scikit-learn中你能夠選擇的模型

  • 樸素貝葉斯 (GaussianNB)
  • 決策樹
  • 集成方法 (Bagging, AdaBoost, Random Forest, Gradient Boosting)
  • K近鄰 (KNeighbors)
  • 隨機梯度下降分類器 (SGDC)
  • 支撐向量機 (SVM)
  • 物流回歸

創建一個訓練和預測的管道

為了正確評估你選擇的每一個模型的性能,創建一個能夠幫助你快速有效地使用不同大小的訓練集并在測試集上做預測的訓練和測試的流水線是十分重要的。
你在這里實現的功能將會在接下來的部分中被用到。在下面的代碼單元中,你將實現以下功能:

  • 從sklearn.metrics中導入 和fbeta_scoreaccuracy_score
  • 用樣例訓練集擬合學習器,并記錄訓練時間
  • 用學習器來對訓練集進行預測并記錄預測時間
  • 在最前面的 500 個訓練數據上做預測
  • 計算訓練數據和測試數據的準確率
  • 計算訓練數據和測試數據的 F-score

# TODO: sklearn.metrics 中導入 fbeta_score accuracy_score

from sklearn.metrics import fbeta_score, accuracy_score

def train_predict(learner, sample_size, X_train, y_train, X_test, y_test):

??? '''

??? 輸入:

??????? - learner:????? 要訓練和預測的機器學習算法

??????? - sample_size:? 從訓練集中抽取的樣本(數量)的大小

??????? - X_train:????? 特征訓練集

??????? - y_train:????? 目標培訓集

??????? - X_test:?????? 特征測試集

??????? - y_test:?????? 目標測試集

??? '''

???

??? results = {}

???

??? # TODO: 使用 sample_size 大小的訓練數據來擬合 learner

??? start = time() # 獲取開始時間

??? learn = learner.fit(X_train[:sample_size], y_train[:sample_size])

??? end = time() # 獲取結束時間

???

??? # TODO: 計算訓練時間

??? results['train_time'] = end - start

???

??? # TODO: 獲得測試集 (X_test) 的預測結果,

??? #?????? 然后使用 .predict() 獲得前300個訓練樣本 (X_train) 的預測值。

??? start = time() # 獲取開始時間

??? predictions_test = learner.predict(X_test)

??? predictions_train = learner.predict(X_train[:300])

??? end = time() # 獲取結束時間

???

??? # TODO: 計算預測用時

??? results['pred_time'] = end - start

???

??? # TODO: 計算前300個訓練樣本的準確率

??? results['acc_train'] = accuracy_score(y_train[:300], predictions_train)

???

??? # TODO: 計算測試集的準確率

??? results['acc_test'] = accuracy_score(y_test, predictions_test)

???

??? # TODO: 計算前300個訓練樣本的準確率

??? results['f_train'] = fbeta_score(y_train[:300], predictions_train, 0.5)

???

??? # TODO: 計算測試集的F-score

??? results['f_test'] = fbeta_score(y_test, predictions_test, 0.5)

???

??? # 成功

??? print(' {} {} 個樣本進行了訓練。'.format(

??????? learner.__class__.__name__, sample_size))

???

??? # 返回結果

??? return results

初始模型的評估

在下面的代碼單元中,您將需要實現以下功能:

  • 導入你在前面的討論的三個監督學習模型。
  • 初始化三模型并存儲在 , 和 中。'clf_A''clf_B''clf_C'
    • 如果可能對每一個模型都設置一個?。random_state
    • **注意:**這里先使用每一個模型的默認參數,在接下來的部分中你將需要對某一個模型的參數進行調整。
  • 計算記錄的數目等于 1%,10% 和 100% 的訓練數據,并將這些值存儲在 中'samples'

**注意:**取決于你選擇的算法,下面實現的代碼可能需要一些時間來運行!

# TODO: sklearn 中導入三個監督學習模型

# 下面是所有算法的示例

# 1. 樸素貝葉斯 (GaussianNB)

# 2. 決策樹

# 3. 集成方法 (AdaBoost)

# 4. 集成方法 (Random Forest)

# 5. 集成方法 (Gradient Boosting)

# 6. K近鄰 (KNeighbors)

# 7. 隨機梯度下降分類器 (SGDC)

# 8. 支撐向量機 (SVM)

# 9. Logistic回歸

# 10. XGBClassifier

from sklearn.naive_bayes import GaussianNB

from sklearn.tree import DecisionTreeClassifier

from sklearn.ensemble import AdaBoostClassifier

from sklearn.ensemble import RandomForestClassifier

from sklearn.ensemble import GradientBoostingClassifier

from sklearn.neighbors import KNeighborsClassifier

from sklearn.linear_model import SGDClassifier

from sklearn.svm import SVC

from sklearn.linear_model import LogisticRegression

# TODO: 初始化三個模型

clf_A = GaussianNB()

clf_B = DecisionTreeClassifier(random_state=42)

clf_C = AdaBoostClassifier(random_state=42)

clf_D = RandomForestClassifier(random_state=42)

clf_E = GradientBoostingClassifier(random_state=42)

clf_F = KNeighborsClassifier()

clf_G = SGDClassifier(max_iter=1000, tol=1e-3,random_state=42)

clf_H = SVC(random_state=42)

clf_I = LogisticRegression(random_state=42)

# TODO: 計算 1%10%100% 的訓練數據分別對應多少個數據點

samples_1 = int(0.01*len(X_train))

samples_10 = int(0.1*len(X_train))

samples_100 = len(X_train)

# 收集學習器的結果

results = {}

for clf in [clf_D, clf_C, clf_E]: #[clf_A, clf_B, clf_C, clf_D, clf_E, clf_F, clf_G, clf_H, clf_I, clf_J]:

??? clf_name = clf.__class__.__name__

??? results[clf_name] = {}

???

??? for i, samples in enumerate([samples_1, samples_10, samples_100]):

??????? results[clf_name][i] = train_predict(

??????????? clf, samples, X_train, y_train, X_test, y_test)

# 對選擇的三個模型得到的評價結果進行可視化

vs.evaluate(results, accuracy, fscore)

RandomForestClassifier 361 個樣本進行了訓練。
RandomForestClassifier 3617 個樣本進行了訓練。
RandomForestClassifier 36177 個樣本進行了訓練。
AdaBoostClassifier 361 個樣本進行了訓練。
AdaBoostClassifier 3617 個樣本進行了訓練。
AdaBoostClassifier 36177 個樣本進行了訓練。
GradientBoostingClassifier 361 個樣本進行了訓練。
GradientBoostingClassifier 3617 個樣本進行了訓練。
GradientBoostingClassifier 36177 個樣本進行了訓練。

提高效果

在這最后一節中,您將從三個有監督的學習模型中選擇 最好的模型來使用數據。

你將在整個訓練集(??)上通過使用網格搜索優化至少調節一個參數以獲得一個比沒有調節之前更好的 F-scoreX_trainy_train

模型調優

調節選擇的模型的參數。使用網格搜索 來至少調整模型的重要參數(至少調整一個),這個參數至少需給出并嘗試3個不同的值。你要使用整個訓練集來完成這個過程。在接下來的代碼單元中,你需要實現以下功能:'GridSearchCV'

  • 導入sklearn.grid_search.gridSearchCV和sklearn.metrics.make_scorer
  • 初始化你選擇的分類器,并將其存儲在 中。clf
    • 如果能夠設置的話,設置random_state
  • 創建一個對于這個模型你希望調整參數的字典。
    • 例如:?。parameters = {'parameter' : [list of values]}
    • **注意:**如果你的學習器(學習者)有 參數,請不要調節它!max_features
  • 使用 來創建一個 評分對象(設置make_scorerfbeta_score\beta =0.5β=0.5 個)。
  • 在分類器 上用 作為評價函數運行網格搜索,并將結果存儲在 中。clf'scorer'grid_obj
  • 用訓練集(, )訓練 ,并將結果存儲在 中。X_trainy_traingrid_objgrid_fit

**注意:**取決于你選擇的參數列表,下面實現的代碼可能需要花一些時間運行!

# TODO: 導入 GridSearchCV, make_scorer

from sklearn.linear_model import LogisticRegression

from sklearn.ensemble import AdaBoostClassifier

from sklearn.ensemble import GradientBoostingClassifier

from sklearn.model_selection import GridSearchCV

from sklearn.metrics import accuracy_score

from sklearn.metrics import fbeta_score

from sklearn.metrics import make_scorer

# TODO: 初始化分類器

clf_lr = LogisticRegression(random_state=42)

clf_ada = AdaBoostClassifier(random_state=42)

clf_gb = GradientBoostingClassifier(random_state=42)

# TODO: 創建您希望調優的參數列表

# LogisticRegression 參數列表

solver_lr = 'newton-cg liblinear'.split()

c_lr = np.logspace(-2,1,4)

param_grid_lr = dict(

??? solver=solver_lr,

??? C=c_lr

)

# AdaBoostClassifier 參數列表

n_estimators_ada = range(150,180,10)

learning_rate_ada = [x/10 for x in range(13,16)]

param_grid_ada = dict(

??? n_estimators=n_estimators_ada,

??? learning_rate=learning_rate_ada

)

# GradientBoostingClassifier 參數列表

max_depth_gb = range(5,8)

learning_rate_gb = np.logspace(-2,0,3)

n_estimators_gb = range(120,150,10)

param_grid_gb = dict(

??? n_estimators=n_estimators_gb,

??? learning_rate=learning_rate_gb,

??? max_depth=max_depth_gb

)

# TODO: 創建一個 fbeta_score 打分對象

scorer = make_scorer(fbeta_score)

# TODO: 在分類上使用網格搜索,使用 scorer 作為評價函數

# 使用 LogisticRegression 分類器

# grid_obj = GridSearchCV(clf_lr,param_grid_lr)

# 未優化的模型

# ------

# 測試數據的準確性評分:0.8630

# 測試數據的F得分:0.7395

# 使用 AdaBoostClassifier 分類器

grid_obj = GridSearchCV(clf_ada,param_grid_ada)

# 優化模型

# ------

# 測試數據的最終準確度分數:0.8649

# 測試數據的最終F得分:0.7398

# 使用 GradientBoostingClassifier 分類器

# grid_obj = GridSearchCV(clf_gb,param_grid_gb)

# 優化模型

# ------

# 測試數據的最終準確度分數:0.8706

# 測試數據的最終F得分:0.7511

# TODO: 用訓練數據擬合網格搜索對象并找出最佳參數

grid_fit = grid_obj.fit(X_train, y_train)

# 得到最佳參數

best_clf = grid_fit.best_estimator_

# 使用沒有調優的模型進行預測

predictions = (clf.fit(X_train, y_train)).predict(X_test)

best_predictions = best_clf.predict(X_test)

print('未優化的模型\n------')

print('測試數據的準確性評分:{:.4f}'.format(

??? accuracy_score(y_test, predictions)))

print('測試數據的F得分:{:.4f}'.format(

??? fbeta_score(y_test, predictions, beta=0.5)))

print('\n優化模型\n------')

print('測試數據的最終準確度分數:{:.4f}'.format(

??? accuracy_score(y_test, best_predictions)))

print('測試數據的最終F得分:{:.4f}'.format(

??? fbeta_score(y_test, best_predictions, beta=0.5)))

print('\n調優后的參數\n------')

print(grid_fit.best_params_)

print(best_clf.get_params())

未優化的模型

測試數據的準確性評分:0.8630
測試數據的F得分:0.7395

優化模型

測試數據的最終準確度分數:0.8649
測試數據的最終F得分:0.7398

調優后的參數

{'learning_rate' 1.4 'n_estimators' 160}
{'algorithm'
'SAMME.R' 'base_estimator' None 'learning_rate' 1.4 'n_estimators' 160 'random_state' 42}

5.6 最終模型評估

結果

評價指標

樸素預測器

未優化模型

優化后模型

準確率

0.2478

0.8630

0.8649

F得分

0.2917

0.7395

0.7398

特征的重要性

在數據上(比如我們這里使用的人口普查的數據)使用監督學習算法的一個重要的任務是決定哪些特征能夠提供最強的預測能力。

通過專注于一些少量的有效特征和標簽之間的關系,我們能夠更加簡單地理解這些現象,這在很多情況下都是十分有用的。在這個項目的情境下這表示我們希望選擇一小部分特征,這些特征能夠在預測被調查者是否年收入大于 $50,000 這個問題上有很強的預測能力。

選擇一個有 屬性(這是一個根據這個選擇的分類器來對特征的重要性進行排序的函數)的scikit學習分類器(例如,AdaBoost,隨機森林)。在下一個Python代碼單元中用這個分類器擬合訓練集數據并使用這個屬性來決定這個人口普查數據中最重要的5個特征。feature_importance_

提取特征重要性

選擇一個 中有 屬性的監督學習分類器分類器,這個屬性是一個在做預測的時候根據所選擇的算法來對特征重要性進行排序的功能。scikit-learnfeature_importance_

在下面的代碼單元中,你將要實現以下功能:

  • 如果這個模型和你前面使用的三個模型不一樣的話從 sklearn 中導入一個監督學習模型。
  • 在整個訓練集上訓練一個監督學習模型。
  • 使用模型中的 提取特征的重要性。.feature_importances_

# TODO: 導入一個擁有 'feature_importances_' 的監督學習模型

from xgboost import XGBClassifier

# TODO: 在訓練集上建立一個監督學習模型

model = XGBClassifier()

model.fit(X_train, y_train)

# TODO: 提取特征重要性

importances = model.feature_importances_

# 繪制特征重要性

vs.feature_plot(importances, X_train, y_train)

pd.Series(importances,index=X_train.columns).sort_values(ascending=False)[:10]

特征選擇

如果我們只是用可用特征的一個子集的話模型表現會怎么樣?

通過使用更少的特征來訓練,在評價指標的角度來看我們的期望是訓練和預測的時間會更少。

從上面的可視化來看,我們可以看到前五個最重要的特征貢獻了數據中所有特征中超過一半的重要性。

這提示我們可以嘗試去減小特征空間,并簡化模型需要學習的信息。下面代碼單元將使用你前面發現的優化模型,并只使用五個最重要的特征在相同的訓練集上訓練模型。

np.argsort(importances)[::-1][:5]

array([2, 0, 3, 1, 4])

# 導入模型克隆功能

from sklearn.base import clone

# 減小特征空間

X_train_reduced = X_train[X_train.columns.values[(np.argsort(importances)[::-1])[:5]]]

X_test_reduced = X_test[X_test.columns.values[(np.argsort(importances)[::-1])[:5]]]

# 克隆之前得到的最優模型繼續訓練

clf = (clone(best_clf)).fit(X_train_reduced, y_train)

# 做出一個新的預測

reduced_predictions = clf.predict(X_test_reduced)

# 輸出每一個版本的數據應用最終模型的分數

print('最終模型接受完整數據的訓練\n------')

print('測試數據的準確性:{:.4f}'.format(

??? accuracy_score(y_test,best_predictions)))

print('測試數據的F分數:{:.4f}'.format(

??? fbeta_score(y_test,reduced_predictions,0.5)))

print('\n最終模型接受壓縮數據的訓練\n------')

print('測試數據的準確性:{:.4f}'.format(

??? accuracy_score(y_test,best_predictions)))

print('測試數據的F分數:{:.4f}'.format(

??? fbeta_score(y_test,reduced_predictions,0.5)))

最終模型接受完整數據的訓練

測試數據的準確性:0.8649
測試數據的F分數:0.6855

最終模型接受壓縮數據的訓練

測試數據的準確性:0.8649
測試數據的F分數:0.6855

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905479.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905479.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905479.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android RecyclerView自帶的OnFlingListener,Kotlin

Android RecyclerView自帶的OnFlingListener&#xff0c;Kotlin Android啟動應用時屏蔽RecyclerView滑動&#xff0c;延時后再允許滑動&#xff0c;Kotlin-CSDN博客 使用了GestureDetectorRecyclerView的setOnTouchListener檢測用戶的快滑fling事件。發現RecyclerView也自帶了監…

第3.4節 調用鏈路分析服務開發

3.4.1 什么是Code Call Graph&#xff08;CCG&#xff09; Code Call Graph&#xff08;CCG&#xff09;即業務代碼中的調用關系圖&#xff0c;是通過靜態分析手段分析并構建出的一種描述代碼間關系的圖。根據精度不同&#xff0c;一般分為類級別、方法級別、控制流級別&#x…

【Liblib】基于LiblibAI自定義模型,總結一下Python開發步驟

一、前言 Liblib AI&#xff08;哩布哩布 AI&#xff09;是一個集成了先進人工智能技術和用戶友好設計的 AI 圖像創作繪畫平臺和模型分享社區。 強大的圖像生成能力 &#xff1a;以 Stable Diffusion 技術為核心&#xff0c;提供文生圖、圖生圖、圖像后期處理等功能&#xff…

編程日志5.5

樹的結構代碼 #include<iostream> using namespace std; //由于樹的每個結點可能有一些孩子結點,這些孩子結點的數量不確定,所以可以用一個鏈表來把所有的孩子結點給串起來 //鏈表結點定義 //這段代碼定義了一個結構體ListNode,用于表示鏈表中的一個結點。這個結構…

【消息隊列】RabbitMQ基本認識

目錄 一、基本概念 1. 生產者&#xff08;Producer&#xff09; 2. 消費者&#xff08;Consumer&#xff09; 3. 隊列&#xff08;Queue&#xff09; 4. 交換器&#xff08;Exchange&#xff09; 5. 綁定&#xff08;Binding&#xff09; 6. 路由鍵&#xff08;Routing …

uniapp -- 驗證碼倒計時按鈕組件

jia-countdown-verify 驗證碼倒計時按鈕組件 一個用于發送短信驗證碼的倒計時按鈕組件&#xff0c;支持自定義樣式、倒計時時間和文本內容。適用于各種需要驗證碼功能的表單場景。 代碼已經 發布到插件市場 可以自行下載 下載地址 特性 支持自定義按鈕樣式&#xff08;顏色、…

知識圖譜重構電商搜索:下一代AI搜索引擎的底層邏輯

1. 搜索引擎的進化論 從雅虎目錄式搜索到Google的PageRank算法&#xff0c;搜索引擎經歷了三次技術躍遷。而AI搜索引擎正在掀起第四次革命&#xff1a;在電商場景中&#xff0c;傳統的「關鍵詞匹配」已無法滿足個性化購物需求&#xff0c;MOE搜索等新一代架構開始融合知識圖譜…

深度學習 自然語言處理(RNN) day_02

1. 感知機與神經網絡 1.1 感知機 生物神經元&#xff1a; 1.1.1 感知機的概念 感知機&#xff08;Perceptron&#xff09;&#xff0c;又稱神經元&#xff08;Neuron&#xff0c;對生物神經元進行了模仿&#xff09;是神 經網絡&#xff08;深度學習&#xff09;的起源算法&am…

PYTHON訓練營DAY25

BUG與報錯 一、try else try:# 可能會引發異常的代碼 except ExceptionType: # 最好指定具體的異常類型&#xff0c;例如 ZeroDivisionError, FileNotFoundError# 當 try 塊中發生 ExceptionType 類型的異常時執行的代碼 except: # 不推薦&#xff1a;捕獲所有類型的異常&…

LU分解求解線性方程組

L U LU LU分解 前言 L U LU LU分解 由以下定理得以保證&#xff1a; 設 A \boldsymbol{A} A為 n n n階方陣&#xff0c;若其各界階順序主子式都不為 0 0 0&#xff0c;那么它可以 被唯一的上下三角矩陣積分解。 步驟 確定各矩陣形式 A L U \mathbf{A}\mathbf{LU} ALU ( a 1…

Linux——數據庫備份與恢復

一&#xff0c;Mysql數據庫備份概述 1&#xff0c;數據庫備份的重要性 數據災難恢復&#xff1a;數據庫可能會因為各種原因出現故障&#xff0c;如硬件故障、軟件錯誤、誤操作、病毒攻擊、自然災害等。這些情況都可能導致數據丟失或損壞。如果有定期的備份&#xff0c;就可以…

SVM在醫療設備故障維修服務決策中的應用:策略、技術與實踐

SVM在醫療設備故障維修服務決策中的應用&#xff1a;策略、技術與實踐 醫療設備的高可靠性、安全性及嚴格合規性要求&#xff0c;使其故障維修決策具有顯著的特殊性。支持向量機&#xff08;SVM&#xff09;憑借小樣本學習、非線性建模及高精度分類能力&#xff0c;可有效解決…

WEB安全--Java安全--CC1利用鏈

一、梳理基本邏輯 WEB后端JVM通過readObject()的反序列化方式接收用戶輸入的數據 用戶編寫惡意代碼并將其序列化為原始數據流 WEB后端JVM接收到序列化后惡意的原始數據并進行反序列化 當調用&#xff1a; ObjectInputStream.readObject() JVM 內部邏輯&#xff1a; → 反…

FlashInfer - 介紹 LLM服務加速庫 地基的一塊石頭

FlashInfer - 介紹 LLM服務加速庫 地基的一塊石頭 flyfish 大型語言模型服務中的注意力機制 大型語言模型服務&#xff08;LLM Serving&#xff09;迅速成為重要的工作負載。Transformer中的算子效率——尤其是矩陣乘法&#xff08;GEMM&#xff09;、自注意力&#xff08;S…

反向操作:如何用AI檢測工具優化自己的論文“人味”?

大家好&#xff0c;這里是論文寫手的一線自救指南&#x1f624; 在AIGC橫行的今天&#xff0c;誰還沒偷偷用過AI寫幾段論文內容&#xff1f;但問題來了&#xff1a;學校越來越會“識AI”了&#xff01; 有的學校甚至不看重復率&#xff0c;只盯AIGC率報告&#xff0c;一句“AI…

關于單片機的基礎知識(一)

成長路上不孤單&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///計算機愛好者&#x1f60a;///持續分享所學&#x1f60a;///如有需要歡迎收藏轉發///&#x1f60a;】 今日分享關于單片機基礎知識的相關內容&#xf…

AWS技術助力企業滿足GDPR合規要求

GDPR(通用數據保護條例)作為歐盟嚴格的數據保護法規,給許多企業帶來了合規挑戰。本文將探討如何利用AWS(亞馬遜云服務)的相關技術來滿足GDPR的核心要求,幫助企業實現數據保護合規。 一、GDPR核心要求概覽 GDPR的主要目標是保護歐盟公民的個人數據和隱私權。其核心要求包括: 數…

FFplay 音視頻同步機制解析:以音頻為基準的時間校準與動態幀調整策略

1.?視頻同步基礎 1.2 簡介 看視頻時&#xff0c;要是聲音和畫面不同步&#xff0c;體驗會大打折扣。之所以會出現這種情況&#xff0c;和音視頻數據的處理過程密切相關。音頻和視頻的輸出不在同一個線程&#xff0c;就像兩個工人在不同車間工作&#xff0c;而且不一定會同時…

車載網關--- 職責邊界劃分與功能解耦設計

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 鈍感力的“鈍”,不是木訥、遲鈍,而是直面困境的韌勁和耐力,是面對外界噪音的通透淡然。 生活中有兩種人,一種人格外在意別人的眼光;另一種人無論…

最優化方法Python計算:有約束優化應用——近似線性可分問題支持向量機

二分問題的數據集 { ( x i , y i ) } \{(\boldsymbol{x}_i,y_i)\} {(xi?,yi?)}&#xff0c; i 1 , 2 , ? , m i1,2,\cdots,m i1,2,?,m中&#xff0c;特征數據 { x i } \{\boldsymbol{x}_i\} {xi?}未必能被一塊超平面按其標簽值 y i ∈ { ? 1 , 1 } y_i\in\{-1,1\} yi?∈…