谷歌機器學習實戰的7個步驟:用於結構化數據的TensorFlow示例

互聯網上有不少很棒的機器學習教程。可是,它們大多數都專一於機器學習的特定部分,例如,探索數據,創建模型,訓練和評估。其中不多有人介紹構建機器學習模型的完整步驟。算法

最受歡迎的文章之一律述了進行機器學習的步驟,這是Google雲端平臺推出的郭玉峯的《機器學習的7個步驟》。api

提出瞭如下七個步驟:瀏覽器

  1. Gathering data
  2. Preparing data (and exploring data)
  3. Choosing a model
  4. Training
  5. Evaluation
  6. Hyperparameter tuning
  7. Prediction (and save model)

在本文中,咱們將實踐上述步驟,並從頭開始構建機器學習模型。網絡

定義問題和環境設置

在開始討論細節以前,對於任何機器學習項目,咱們要作的第一件事是爲咱們的機器學習模型定義問題。session

對於本教程,咱們將使用Kaggle的Titanic Dataset。這是一個很是著名的數據集,一般是學生學習機器學習的第一步。架構

假設咱們被要求建立一個能夠預測泰坦尼克號生存時間的系統。app

環境設置

爲了運行本教程,您須要安裝dom

TensorFlow 2, TensorBoard 2, numpy, pandas, matplotlib, seaborn

它們均可以直接經過PyPI安裝,我強烈建議建立一個新的虛擬環境。最好避免使用base(root),由於它可能會破壞系統。機器學習

有關建立Python虛擬環境的教程,您能夠看一下:svg

https://towardsdatascience.com/create-virtual-environment-using-virtualenv-and-add-it-to-jupyter-notebook-6e1bf4e03415​towardsdatascience.com

1. Gathering data

定義好問題後,就該進行機器學習的第一步,那就是收集數據。這一步是最重要的,由於您收集的數據的質量和數量將直接決定您的預測模型的質量。

在本教程中,數據未來自Kaggle。讓咱們導入一些庫並加載數據以開始使用:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

讓咱們將train.csv和test.csv文件加載到pandas DataFrame中。

df_train_raw = pd.read_csv('data/titanic/train.csv')
df_test_raw = pd.read_csv('data/titanic/test.csv')
df_train_raw.head()

preview of Titanic data

Data Dictionary from Kaggle

2. Preparing data

讓咱們從一些探索性數據分析(EDA)開始。咱們將從檢查缺失值開始。

2.1 Missing values

咱們可使用seaborn來建立一個簡單的熱圖,以查看缺乏的值:

sns.heatmap(df_train_raw.isnull(), 
            yticklabels=False, 
            cbar=False, 
            cmap='viridis')

output of seaborn heatmap plot for missing values

年齡,機艙和出發缺乏值。年齡缺失的比例可能很小,不足以用某種形式的估算合理地替代。查看「機艙」列,該數據彷佛缺乏太多值,沒法作有用的事情。咱們可能會在之後放下機艙,或將其更改成其餘功能,例如「機艙已知:1或0」。出發的比例很小,在本教程中,咱們保留它。

2.2 Visualizing some more of the data

讓咱們繼續可視化更多數據:

sns.countplot(x='Survived', data=df_train_raw, palette='RdBu_r')

plot of Survived

sns.countplot(x='Survived', 
              hue='Sex', 
              data=df_train_raw,
              palette='RdBu_r')

sns.countplot(x='Survived',
              hue='Pclass', 
              data=df_train_raw,
              palette='rainbow')

sns.distplot(df_train_raw['Age'].dropna(),
             kde=True,
             color='darkred',
             bins=30)

sns.countplot(x='SibSp',data=df_train_raw)

df_train_raw['Fare'].hist(color='green', 
                          bins=40, 
                          figsize=(8,4))

2.3 Data cleaning

咱們想用某種形式的估算來代替失蹤的時代。一種方法是填寫全部乘客的平均年齡。可是,咱們能夠對此有所瞭解,並按旅客等級檢查平均年齡。例如:

sns.boxplot(x='Pclass',
            y='Age',
            data=df_train_raw,
            palette='winter')

咱們能夠看到,較高階層的較富裕乘客每每年齡較大,這是有道理的。咱們將使用這些平均年齡值根據年齡的Pclass進行估算。

def impute_age(cols):
    Age = cols[0]
    Pclass = cols[1]
    
    if pd.isnull(Age):
        if Pclass == 1:
            return 37
        elif Pclass == 2:
            return 29
        else:
            return 24
    else:
        return Age

如今,咱們應用該功能並檢查其是否有效:

# Make a copy for test only
train_copy = df_train_raw.copy() 
train_copy['Age'] = train_copy[['Age','Pclass']]
   .apply(impute_age, axis=1)
# check that heat map again
sns.heatmap(train_copy.isnull(), 
            yticklabels=False, 
            cbar=False, 
            cmap='viridis')

很是好! impute_age()有效。讓咱們繼續進行轉換,並刪除「機艙」列。

2.4 Converting Categorical Features

咱們須要將分類功能轉換爲一鍵編碼。不然,咱們的機器學習算法將沒法直接將這些功能做爲輸入。

讓咱們使用info()檢查列數據類型:

df_train_raw.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 712 entries, 0 to 711
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  712 non-null    int64  
 1   Survived     712 non-null    int64  
 2   Pclass       712 non-null    int64  
 3   Name         712 non-null    object 
 4   Sex          712 non-null    object 
 5   Age          566 non-null    float64
 6   SibSp        712 non-null    int64  
 7   Parch        712 non-null    int64  
 8   Ticket       712 non-null    object 
 9   Fare         712 non-null    float64
 10  Cabin        168 non-null    object 
 11  Embarked     710 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 66.9+ KB

有5列具備對象數據類型的列。其中,不須要名稱,機票和機艙。另外,根據上面看到的數據字典,咱們注意到Pclass是分類數據。讓咱們作一個函數preprocessing()來保留這些有用的數字功能,並將Pclass,Sex和Embarked轉換爲一鍵編碼。

讓咱們應用該功能並建立訓練和測試數據集以構建咱們的機器學習模型。

x_train = preprocessing(df_train_raw)
y_train = df_train_raw['Survived'].values
x_test = preprocessing(df_test_raw)
y_test = df_test_raw['Survived'].values
print("x_train.shape =", x_train.shape )
print("x_test.shape =", x_test.shape )

經過在上面運行,您應該得到以下訓練和測試數據集的形狀:

x_train.shape = (712, 13)
x_test.shape = (179, 13)

讓咱們看看x_train.head()的數據:

咱們的數據已準備好用於模型。

3. Choose a model

在TensorFlow 2.0中有三種方法來實現神經網絡架構:

  • Sequential API: 是使用Keras入門和運行的最簡單方法。
  • Functional API: 適用於更復雜的模型。
  • Model Subclassing: 徹底可自定義,使您可以實現本身的模型自定義前向傳遞。

爲簡單起見,讓咱們使用最簡單的方法:帶有Sequential()的Sequential API。讓咱們繼續前進,構建一個具備3個密集層的神經網絡。每一層中的全部參數均已進行硬編碼,以下所示:

import tensorflow as tf 
from tensorflow.keras import models, layers
tf.keras.backend.clear_session()
model = models.Sequential()
model.add(layers.Dense(10, activation='relu', input_shape=(13,)))
model.add(layers.Dense(20, activation='relu' ))
model.add(layers.Dense(1, activation='sigmoid'))
model.summary()

下面是model.summary() 的輸出:

4. Training

首先,讓咱們使用model.compile()配置模型:

  • 使用優化程序隨機梯度降低(SGD)
  • 使用二進制交叉熵損失函數(binary_crossentropy)進行二進制分類
  • 爲簡單起見,請在培訓和測試期間使用「準確性」做爲咱們的評估指標來評估模型

對於訓練,有三種方法能夠訓練Keras模型:

  • 對模型使用model.fit()以獲取固定數量的紀元。
  • 使用model.train_on_batch() 能夠只對一個批次進行一次訓練。
  • 建立自定義訓練循環。

在本教程中,讓咱們繼續最簡單的方式model.fit()。

# Convert DataFrame into np array
x_train = np.asarray(x_train)
y_train = np.asarray(y_train)
# Get around with KMP duplicate issue
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
# Use binary cross entropy loss function for binary classification
model.compile(optimizer='sgd',
            loss='binary_crossentropy',
            metrics=['accuracy'])
history = model.fit(x_train,y_train,
                    batch_size= 64,
                    epochs= 30,
                    validation_split=0.2
                   )

若是一切運行順利,咱們應該獲得以下輸出。

Train on 569 samples, validate on 143 samples
Epoch 1/30
569/569 [==============================] - 1s 2ms/sample - loss: 0.5568 - accuracy: 0.7206 - val_loss: 0.6139 - val_accuracy: 0.6713
Epoch 2/30
569/569 [==============================] - 0s 91us/sample - loss: 0.5639 - accuracy: 0.7047 - val_loss: 0.6212 - val_accuracy: 0.6643
Epoch 3/30
569/569 [==============================] - 0s 112us/sample - loss: 0.5705 - accuracy: 0.6907 - val_loss: 0.6379 - val_accuracy: 0.6573
Epoch 4/30
569/569 [==============================] - 0s 109us/sample - loss: 0.5538 - accuracy: 0.7065 - val_loss: 0.6212 - val_accuracy: 0.6713
......
......
Epoch 30/30
569/569 [==============================] - 0s 102us/sample - loss: 0.5597 - accuracy: 0.7065 - val_loss: 0.6056 - val_accuracy: 0.7203

5. Model Evaluation

訓練結束後,就可使用「模型評估」來查看模型是否良好。模型評估一般涉及:

  • 繪製損失和準確性指標的進度圖
  • 針對從未用於訓練的數據測試咱們的模型。這是咱們前面放置的測試數據集df_test發揮做用的地方。

讓咱們建立一個函數plot_metric()來繪製指標。

%matplotlib inline
%config InlineBackend.figure_format = 'svg'
def plot_metric(history, metric):
    train_metrics = history.history[metric]
    val_metrics = history.history['val_'+metric]
    epochs = range(1, len(train_metrics) + 1)
    plt.plot(epochs, train_metrics, 'bo--')
    plt.plot(epochs, val_metrics, 'ro-')
    plt.title('Training and validation '+ metric)
    plt.xlabel("Epochs")
    plt.ylabel(metric)
    plt.legend(["train_"+metric, 'val_'+metric])
    plt.show()

經過運行plot_metric(history,'loss')繪製損失進度。

經過運行plot_metric(history,'accuracy')繪製準確性進度。

針對測試數據集測試咱們的模型:

# Convert DataFrame into np array
x_test = np.asarray(x_test)
y_test = np.asarray(y_test)
model.evaluate(x = x_test,y = y_test)

並且咱們應該獲得具備損失和準確性的輸出,以下所示:

179/1 [====] - 0s 43us/sample - loss: 0.5910 - accuracy: 0.6760
[0.5850795357586951, 0.67597765]

6. Hyperparameter tuning

太酷了,咱們已經對第一個機器學習模型進行了評估。如今該看看咱們是否能夠經過任何方式進一步改進它。咱們能夠經過旋轉超參數來作到這一點。當咱們進行第一次訓練時,咱們隱式假設了一些參數,如今是時候回過頭來測試這些假設並嘗試其餘值了。

對於本教程,咱們只關注模型中如下三個超參數的實驗:

  • 第一密集層中的單位數
  • 第二致密層中的單位數
  • 優化器

6.1 Experiment setup

首先,首先加載TensorBoard notebook擴展程序:

# Load the TensorBoard notebook extension
%load_ext tensorboard

而後,添加一條語句以清除上一次運行中的全部日誌。若是您不清除儀表盤,則會弄亂儀表盤。

# Clear any logs from previous runs
!rm -rf ./logs/

導入TensorBoard HParams插件:

from tensorboard.plugins.hparams import api as hp

列出要嘗試的值,並將實驗配置記錄到TensorBoard。

  • 第一層中的單元數爲51020
  • 第二層的單元數爲102040
  • adamsgd用於優化程序

6.2 Adapt TensorFlow runs to log hyperparameters and metrics

咱們的模型很是簡單:3個密集層。儘管再也不對超參數進行硬編碼,但代碼看起來很熟悉。相反,超參數在hyparams字典中提供,並在整個訓練功能中使用:

對於每次運行,請記錄具備超參數和最終精度的hparams摘要:

def run(run_dir, hparams):
  with tf.summary.create_file_writer(run_dir).as_default():
    hp.hparams(hparams)  # record the values used in this trial
    accuracy = train_test_model(hparams)
    tf.summary.scalar(METRIC_ACCURACY, accuracy, step=1)

6.3 Start runs and log them

如今,咱們能夠嘗試進行多個實驗,並使用不一樣的一套超級血壓計來訓練每一個實驗。爲簡單起見,讓咱們使用網格搜索來嘗試離散參數的全部組合以及實值參數的上限和下限。

session_num = 0
for num_units_one in HP_NUM_UNITS_ONE.domain.values:
  for num_units_two in HP_NUM_UNITS_TWO.domain.values:
    for optimizer in HP_OPTIMIZER.domain.values:
      hparams = {
          HP_NUM_UNITS_ONE: num_units_one,
          HP_NUM_UNITS_TWO: num_units_two,
          HP_OPTIMIZER: optimizer,
      }
      run_name = "run-%d" % session_num
      print('>> Starting trial: %s' % run_name)
      print({h.name: hparams[h] for h in hparams})
      run('logs/hparam_tuning/' + run_name, hparams)
      session_num += 1

若是一切運行順利,咱們應該獲得以下輸出:

6.4 Visualize the results in TensorBoard’s HParams plugin

運行完成後,打開終端並cd進入項目目錄。而後,如今能夠經過在終端中運行如下命令來打開HParams儀表板:

admin@Mac:~/Code/WorkSpace/machine-learning/tf2
⇒  tensorboard --logdir logs/hparam_tuning
Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
TensorBoard 2.0.0 at http://localhost:6006/ (Press CTRL+C to quit)

在瀏覽器中打開儀表板,而後直接轉到HPARAMS-> PARALLEL COORDINATES VIEW

經過查看「平行座標」視圖,而後在精度軸上單擊並拖動,能夠選擇精度最高的運行。

當這些運行經過不一樣的超參數時,咱們能夠得出如下結論:

  • 第一層5個單元
  • 第二層10個單位
  • 「 adam」優化器

在這些實驗中表現最好。

7. Prediction (and save model)

如今,就準確度而言,咱們已經有了最好的機器學習模型。最後一步是使用此模型進行預測或推斷。這是全部這些工做的重點,在那裏機器學習的價值得以實現。咱們最終可使用咱們的模型來預測乘客是否存活。

使用模型進行預測:

model.predict(x_test[0:10])
array([[0.56895125],
       [0.37735564],
       [0.5005745 ],
       [0.60003537],
       [0.5371451 ],
       [0.36402294],
       [0.49169463],
       [0.49049523],
       [0.4984674 ],
       [0.1470165 ]], dtype=float32)

使用該模型爲輸入樣本生成類別預測。

model.predict_classes(x_test[0:10])
array([[1],
       [0],
       [1],
       [1],
       [1],
       [0],
       [0],
       [0],
       [0],
       [0]], dtype=int32)

最後,咱們能夠將整個模型保存到單個HDF5文件中:

model.save('data/keras_model.h5')

並加載經過save()保存的模型:

model = models.load_model('data/keras_model.h5')
# Predict class
model.predict_classes(x_test[0:10])

結論

本文是一個快速教程,主要向全部人展現如何將Google的機器學習的7個步驟付諸實踐。我試圖避免使用許多機器學習概念,並儘可能簡化本教程。

在實際的應用程序中,它們還有不少要考慮的地方。例如,選擇評估指標,特徵縮放,選擇有意義的特徵,拆分數據集,處理過分擬合和欠擬合等。此外,本教程僅適用於結構化數據,而實際數據並不老是結構化數據,全部諸如圖像,音頻或文本之類的東西都是非結構化數據。

PS:本文屬於翻譯,原文

相關文章
相關標籤/搜索