สร้างแบบจำลองเชิงเส้นด้วยเครื่องมือประมาณการ

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค

ภาพรวม

คำแนะนำแบบ end-to-end นี้ฝึกโมเดลการถดถอยโลจิสติกโดยใช้ tf.estimator API แบบจำลองนี้มักใช้เป็นพื้นฐานสำหรับอัลกอริธึมอื่นที่ซับซ้อนกว่า

ติดตั้ง

pip install sklearn
import os
import sys

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import clear_output
from six.moves import urllib

โหลดชุดข้อมูลไททานิค

คุณจะใช้ชุดข้อมูลไททานิคโดยมีเป้าหมาย (ค่อนข้างผิดปกติ) ในการทำนายการอยู่รอดของผู้โดยสาร ลักษณะที่กำหนด เช่น เพศ อายุ ชั้น ฯลฯ

import tensorflow.compat.v2.feature_column as fc

import tensorflow as tf
# Load dataset.
dftrain = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/train.csv')
dfeval = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/eval.csv')
y_train = dftrain.pop('survived')
y_eval = dfeval.pop('survived')

สำรวจข้อมูล

ชุดข้อมูลมีคุณสมบัติดังต่อไปนี้

dftrain.head()
dftrain.describe()

มีตัวอย่าง 627 และ 264 ชุดในชุดฝึกอบรมและประเมินผล ตามลำดับ

dftrain.shape[0], dfeval.shape[0]
(627, 264)

ผู้โดยสารส่วนใหญ่อายุ 20 และ 30 ปี

dftrain.age.hist(bins=20)
<AxesSubplot:>

png

มีผู้โดยสารชายมากกว่าผู้โดยสารหญิงประมาณสองเท่า

dftrain.sex.value_counts().plot(kind='barh')
<AxesSubplot:>

png

ผู้โดยสารส่วนใหญ่อยู่ในชั้น "สาม"

dftrain['class'].value_counts().plot(kind='barh')
<AxesSubplot:>

png

ผู้หญิงมีโอกาสรอดชีวิตสูงกว่าผู้ชายมาก นี่เป็นคุณลักษณะการคาดการณ์อย่างชัดเจนสำหรับโมเดล

pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')
Text(0.5, 0, '% survive')

png

วิศวกรรมคุณลักษณะสำหรับโมเดล

เครื่องมือประมาณค่าใช้ระบบที่เรียกว่า คอลัมน์คุณลักษณะ เพื่ออธิบายว่าโมเดลควรตีความแต่ละคุณลักษณะอินพุตดิบอย่างไร เครื่องมือประมาณการคาดหวังเวกเตอร์ของอินพุตที่เป็นตัวเลข และ คอลัมน์คุณลักษณะ จะอธิบายว่าโมเดลควรแปลงแต่ละจุดสนใจอย่างไร

การเลือกและสร้างชุดคอลัมน์คุณลักษณะที่เหมาะสมเป็นกุญแจสำคัญในการเรียนรู้แบบจำลองที่มีประสิทธิภาพ คอลัมน์คุณลักษณะสามารถเป็นอินพุตดิบอย่างใดอย่างหนึ่งใน dict คุณลักษณะเดิม ( คอลัมน์คุณลักษณะพื้นฐาน ) หรือคอลัมน์ใหม่ที่สร้างขึ้นโดยใช้การแปลงที่กำหนดไว้ในคอลัมน์ฐานหนึ่งหรือหลายคอลัมน์ ( คอลัมน์คุณลักษณะที่ได้รับ )

ตัวประมาณเชิงเส้นใช้ทั้งคุณสมบัติตัวเลขและหมวดหมู่ คอลัมน์คุณลักษณะทำงานร่วมกับตัวประมาณค่า TensorFlow ทั้งหมด และมีวัตถุประสงค์เพื่อกำหนดคุณลักษณะที่ใช้สำหรับการสร้างแบบจำลอง นอกจากนี้ ยังให้ความสามารถด้านวิศวกรรมคุณลักษณะบางอย่าง เช่น การเข้ารหัสแบบครั้งเดียว การทำให้เป็นมาตรฐาน และการทำให้ฝากข้อมูล

คอลัมน์คุณสมบัติฐาน

CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck',
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']

feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(tf.feature_column.categorical_column_with_vocabulary_list(feature_name, vocabulary))

for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(tf.feature_column.numeric_column(feature_name, dtype=tf.float32))

input_function ระบุวิธีการแปลงข้อมูลเป็น tf.data.Dataset ที่ฟีดไปป์ไลน์อินพุตในรูปแบบการสตรีม tf.data.Dataset สามารถรับได้จากหลายแหล่ง เช่น dataframe ไฟล์ที่จัดรูปแบบ csv และอื่นๆ

def make_input_fn(data_df, label_df, num_epochs=10, shuffle=True, batch_size=32):
  def input_function():
    ds = tf.data.Dataset.from_tensor_slices((dict(data_df), label_df))
    if shuffle:
      ds = ds.shuffle(1000)
    ds = ds.batch(batch_size).repeat(num_epochs)
    return ds
  return input_function

train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, num_epochs=1, shuffle=False)

คุณสามารถตรวจสอบชุดข้อมูล:

ds = make_input_fn(dftrain, y_train, batch_size=10)()
for feature_batch, label_batch in ds.take(1):
  print('Some feature keys:', list(feature_batch.keys()))
  print()
  print('A batch of class:', feature_batch['class'].numpy())
  print()
  print('A batch of Labels:', label_batch.numpy())
Some feature keys: ['sex', 'age', 'n_siblings_spouses', 'parch', 'fare', 'class', 'deck', 'embark_town', 'alone']

A batch of class: [b'Third' b'Third' b'Third' b'Third' b'Third' b'First' b'Second' b'First'
 b'First' b'Third']

A batch of Labels: [0 1 1 0 0 1 0 1 1 0]

คุณยังสามารถตรวจสอบผลลัพธ์ของคอลัมน์คุณลักษณะเฉพาะได้โดยใช้เลเยอร์ tf.keras.layers.DenseFeatures :

age_column = feature_columns[7]
tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()
array([[35.],
       [14.],
       [28.],
       [19.],
       [28.],
       [35.],
       [60.],
       [63.],
       [45.],
       [21.]], dtype=float32)
ตัวยึดตำแหน่ง22

DenseFeatures ยอมรับเฉพาะเทนเซอร์ที่มีความหนาแน่นเท่านั้น ในการตรวจสอบคอลัมน์ที่จัดหมวดหมู่ คุณต้องแปลงสิ่งนั้นเป็นคอลัมน์ตัวบ่งชี้ก่อน:

gender_column = feature_columns[0]
tf.keras.layers.DenseFeatures([tf.feature_column.indicator_column(gender_column)])(feature_batch).numpy()
array([[1., 0.],
       [0., 1.],
       [0., 1.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [0., 1.],
       [0., 1.],
       [0., 1.]], dtype=float32)

หลังจากเพิ่มคุณสมบัติพื้นฐานทั้งหมดให้กับโมเดลแล้ว เรามาฝึกโมเดลกัน การฝึกโมเดลเป็นเพียงคำสั่งเดียวโดยใช้ tf.estimator API:

linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns)
linear_est.train(train_input_fn)
result = linear_est.evaluate(eval_input_fn)

clear_output()
print(result)
{'accuracy': 0.7537879, 'accuracy_baseline': 0.625, 'auc': 0.8060607, 'auc_precision_recall': 0.7480768, 'average_loss': 0.5639972, 'label/mean': 0.375, 'loss': 0.5542658, 'precision': 0.7741935, 'prediction/mean': 0.25232768, 'recall': 0.4848485, 'global_step': 200}

คอลัมน์คุณสมบัติที่ได้รับ

ตอนนี้คุณมีความแม่นยำถึง 75% แล้ว การใช้คอลัมน์คุณลักษณะพื้นฐานแต่ละคอลัมน์แยกกันอาจไม่เพียงพอต่อการอธิบายข้อมูล ตัวอย่างเช่น ความสัมพันธ์ระหว่างอายุกับฉลากอาจแตกต่างกันสำหรับเพศที่ต่างกัน ดังนั้น หากคุณเรียนรู้น้ำหนักแบบจำลองเพียงอย่างเดียวสำหรับ gender="Male" และ gender="Female" คุณจะไม่จับทุกชุดอายุและเพศ (เช่น การแยกแยะระหว่าง gender="Male" AND age="30" AND gender="Male" และ age="40" )

หากต้องการเรียนรู้ความแตกต่างระหว่างการผสมผสานคุณลักษณะต่างๆ คุณสามารถเพิ่ม คอลัมน์คุณลักษณะที่ข้าม ไปยังแบบจำลองได้ (คุณยังสามารถใส่คอลัมน์อายุก่อนคอลัมน์ข้ามได้):

age_x_gender = tf.feature_column.crossed_column(['age', 'sex'], hash_bucket_size=100)

หลังจากเพิ่มคุณสมบัติการรวมเข้ากับโมเดลแล้ว เรามาฝึกโมเดลกันอีกครั้ง:

derived_feature_columns = [age_x_gender]
linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns+derived_feature_columns)
linear_est.train(train_input_fn)
result = linear_est.evaluate(eval_input_fn)

clear_output()
print(result)
{'accuracy': 0.7462121, 'accuracy_baseline': 0.625, 'auc': 0.845577, 'auc_precision_recall': 0.7873878, 'average_loss': 0.47313985, 'label/mean': 0.375, 'loss': 0.46722567, 'precision': 0.6509434, 'prediction/mean': 0.41550797, 'recall': 0.6969697, 'global_step': 200}

ตอนนี้มีความแม่นยำถึง 77.6% ซึ่งดีกว่าเพียงเล็กน้อยที่ได้รับการฝึกฝนในคุณสมบัติพื้นฐานเท่านั้น คุณสามารถลองใช้คุณสมบัติและการเปลี่ยนแปลงเพิ่มเติมเพื่อดูว่าคุณทำได้ดีกว่านี้หรือไม่!

ตอนนี้คุณสามารถใช้โมเดลรถไฟเพื่อคาดการณ์ผู้โดยสารจากชุดประเมินผลได้แล้ว โมเดล TensorFlow ได้รับการปรับให้เหมาะสมเพื่อคาดการณ์ชุดหรือคอลเล็กชันของตัวอย่างในคราวเดียว ก่อนหน้านี้ eval_input_fn ถูกกำหนดโดยใช้ชุดการประเมินทั้งหมด

pred_dicts = list(linear_est.predict(eval_input_fn))
probs = pd.Series([pred['probabilities'][1] for pred in pred_dicts])

probs.plot(kind='hist', bins=20, title='predicted probabilities')
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpe5vngw46/model.ckpt-200
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
<AxesSubplot:title={'center':'predicted probabilities'}, ylabel='Frequency'>

png

สุดท้าย ดูลักษณะการทำงานของตัวรับ (ROC) ของผลลัพธ์ ซึ่งจะทำให้เรามีความคิดที่ดีขึ้นเกี่ยวกับการแลกเปลี่ยนระหว่างอัตราผลบวกที่แท้จริงและอัตราผลบวกลวง

from sklearn.metrics import roc_curve
from matplotlib import pyplot as plt

fpr, tpr, _ = roc_curve(y_eval, probs)
plt.plot(fpr, tpr)
plt.title('ROC curve')
plt.xlabel('false positive rate')
plt.ylabel('true positive rate')
plt.xlim(0,)
plt.ylim(0,)
(0.0, 1.05)
ตัวยึดตำแหน่ง33

png