Trang này được dịch bởi Cloud Translation API.
Switch to English

Hồi quy cơ bản: Dự đoán hiệu suất nhiên liệu

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ tay

Trong một bài toán hồi quy , chúng tôi hướng đến dự đoán đầu ra của một giá trị liên tục, như giá cả hoặc xác suất. Đối chiếu điều này với một bài toán phân loại , trong đó chúng ta muốn chọn một lớp từ danh sách các lớp (ví dụ: trong đó một bức tranh có một quả táo hoặc một quả cam, nhận biết loại quả nào trong ảnh).

Máy tính xách tay này sử dụng Bộ dữ liệu MPG tự động cổ điển và xây dựng một mô hình để dự đoán hiệu suất nhiên liệu của ô tô cuối những năm 1970 và đầu những năm 1980. Để làm điều này, chúng tôi sẽ cung cấp mô hình mô tả về nhiều loại ô tô trong khoảng thời gian đó. Mô tả này bao gồm các thuộc tính như: xi lanh, dịch chuyển, mã lực và trọng lượng.

Ví dụ này sử dụng API tf.keras , hãy xem hướng dẫn này để biết chi tiết.

# Use seaborn for pairplot
pip install -q seaborn
WARNING: You are using pip version 20.2.2; however, version 20.2.3 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.

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


# Make numpy printouts easier to read.
np.set_printoptions(precision=3, suppress=True)
import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.layers.experimental import preprocessing

print(tf.__version__)
2.3.0

Tập dữ liệu MPG tự động

Tập dữ liệu có sẵn từ Kho lưu trữ Học máy UCI .

Lấy dữ liệu

Trước tiên, hãy tải xuống và nhập tập dữ liệu bằng cách sử dụng gấu trúc:

url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data'
column_names = ['MPG', 'Cylinders', 'Displacement', 'Horsepower', 'Weight',
                'Acceleration', 'Model Year', 'Origin']

raw_dataset = pd.read_csv(url, names=column_names,
                          na_values='?', comment='\t',
                          sep=' ', skipinitialspace=True)
dataset = raw_dataset.copy()
dataset.tail()

Làm sạch dữ liệu

Tập dữ liệu chứa một vài giá trị không xác định.

dataset.isna().sum()
MPG             0
Cylinders       0
Displacement    0
Horsepower      6
Weight          0
Acceleration    0
Model Year      0
Origin          0
dtype: int64

Bỏ các hàng đó để giữ cho hướng dẫn ban đầu này đơn giản.

dataset = dataset.dropna()

Cột "Origin" thực sự là phân loại, không phải số. Vì vậy, chuyển đổi nó thành một nóng:

dataset['Origin'] = dataset['Origin'].map({1: 'USA', 2: 'Europe', 3: 'Japan'})
dataset = pd.get_dummies(dataset, prefix='', prefix_sep='')
dataset.tail()

Chia dữ liệu thành đào tạo và kiểm tra

Bây giờ hãy chia tập dữ liệu thành tập huấn luyện và tập thử nghiệm.

Chúng tôi sẽ sử dụng bộ thử nghiệm để đánh giá cuối cùng các mô hình của chúng tôi.

train_dataset = dataset.sample(frac=0.8, random_state=0)
test_dataset = dataset.drop(train_dataset.index)

Kiểm tra dữ liệu

Hãy xem nhanh sự phân bố chung của một vài cặp cột từ tập huấn luyện.

Nhìn vào hàng trên, có thể thấy rõ rằng hiệu suất nhiên liệu (MPG) là một hàm của tất cả các thông số khác. Nhìn vào các hàng khác, rõ ràng rằng chúng là mỗi chức năng của nhau.

sns.pairplot(train_dataset[['MPG', 'Cylinders', 'Displacement', 'Weight']], diag_kind='kde')
<seaborn.axisgrid.PairGrid at 0x7ff4c67838d0>

png

Ngoài ra, hãy xem thống kê tổng thể, lưu ý cách mỗi tính năng bao gồm một phạm vi rất khác nhau:

train_dataset.describe().transpose()

Tách các tính năng khỏi nhãn

Tách giá trị mục tiêu, "nhãn", khỏi các tính năng. Nhãn này là giá trị mà bạn sẽ đào tạo mô hình để dự đoán.

train_features = train_dataset.copy()
test_features = test_dataset.copy()

train_labels = train_features.pop('MPG')
test_labels = test_features.pop('MPG')

Bình thường hóa

Trong bảng thống kê, dễ dàng thấy được mức độ khác nhau của từng đối tượng địa lý.

train_dataset.describe().transpose()[['mean', 'std']]

Thông lệ tốt là chuẩn hóa các đối tượng địa lý sử dụng các quy mô và phạm vi khác nhau.

Một lý do khiến điều này quan trọng là vì các tính năng được nhân với trọng lượng của mô hình. Vì vậy quy mô của các đầu ra và quy mô của độ dốc bị ảnh hưởng bởi quy mô của các đầu vào.

Mặc dù một mô hình có thể hội tụ mà không có tính năng chuẩn hóa, nhưng việc chuẩn hóa sẽ giúp việc đào tạo ổn định hơn nhiều.

Lớp chuẩn hóa

Lớp preprocessing.Normalization là một cách đơn giản và gọn gàng để xây dựng quá trình tiền xử lý đó vào mô hình của bạn.

Bước đầu tiên là tạo lớp:

normalizer = preprocessing.Normalization()

Sau đó .adapt() nó vào dữ liệu:

normalizer.adapt(np.array(train_features))

Điều này sẽ tính toán giá trị trung bình và phương sai, và lưu trữ chúng trong lớp.

print(normalizer.mean.numpy())
[   5.478  195.318  104.869 2990.252   15.559   75.898    0.178    0.197
    0.624]

Khi lớp được gọi, nó trả về dữ liệu đầu vào, với mỗi tính năng được chuẩn hóa độc lập:

first = np.array(train_features[:1])

with np.printoptions(precision=2, suppress=True):
  print('First example:', first)
  print()
  print('Normalized:', normalizer(first).numpy())
First example: [[   4.    90.    75.  2125.    14.5   74.     0.     0.     1. ]]

Normalized: [[-0.87 -1.01 -0.79 -1.03 -0.38 -0.52 -0.47 -0.5   0.78]]

Hồi quy tuyến tính

Trước khi xây dựng mô hình DNN, hãy bắt đầu với hồi quy tuyến tính.

Một biến

Bắt đầu với hồi quy tuyến tính một biến, để dự đoán MPG từ Horsepower .

Đào tạo một mô hình với tf.keras thường bắt đầu bằng cách xác định kiến ​​trúc mô hình.

Trong trường hợp này, hãy sử dụng mô hình keras.Sequential . Mô hình này đại diện cho một chuỗi các bước. Trong trường hợp này, có hai bước:

  • Bình thường hóa horsepower đầu vào.
  • Áp dụng phép biến đổi tuyến tính ($ y = mx + b $) để tạo ra 1 đầu ra bằng cách sử dụng các layers.Dense .

Số lượng đầu vào có thể được đặt bằng đối số input_shape hoặc tự động khi mô hình được chạy lần đầu tiên.

Đầu tiên tạo lớp Normalization mã lực:

horsepower = np.array(train_features['Horsepower'])

horsepower_normalizer = preprocessing.Normalization(input_shape=[1,])
horsepower_normalizer.adapt(horsepower)

Xây dựng mô hình tuần tự:

horsepower_model = tf.keras.Sequential([
    horsepower_normalizer,
    layers.Dense(units=1)
])

horsepower_model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
normalization_1 (Normalizati (None, 1)                 3         
_________________________________________________________________
dense (Dense)                (None, 1)                 2         
=================================================================
Total params: 5
Trainable params: 2
Non-trainable params: 3
_________________________________________________________________

Mô hình này sẽ dự đoán MPG từ Horsepower .

Chạy mô hình chưa được đào tạo trên 10 giá trị mã lực đầu tiên. Đầu ra sẽ không tốt, nhưng bạn sẽ thấy rằng nó có hình dạng mong đợi, (10,1) :

horsepower_model.predict(horsepower[:10])
array([[ 0.252],
       [ 0.142],
       [-0.465],
       [ 0.353],
       [ 0.319],
       [ 0.125],
       [ 0.378],
       [ 0.319],
       [ 0.083],
       [ 0.142]], dtype=float32)

Sau khi xây dựng mô hình, hãy cấu hình quy trình đào tạo bằng phương thức Model.compile() . Các đối số quan trọng nhất để biên dịch là loss và trình optimizer vì chúng xác định những gì sẽ được tối ưu hóa ( mean_absolute_error ) và cách thức (sử dụng optimizers.Adam ).

horsepower_model.compile(
    optimizer=tf.optimizers.Adam(learning_rate=0.1),
    loss='mean_absolute_error')

Sau khi khóa đào tạo được định cấu hình, hãy sử dụng Model.fit() để thực hiện khóa đào tạo:

%%time
history = horsepower_model.fit(
    train_features['Horsepower'], train_labels,
    epochs=100,
    # suppress logging
    verbose=0,
    # Calculate validation results on 20% of the training data
    validation_split = 0.2)
CPU times: user 3.87 s, sys: 893 ms, total: 4.76 s
Wall time: 2.97 s

Hình dung tiến trình đào tạo của mô hình bằng cách sử dụng số liệu thống kê được lưu trữ trong đối tượng history .

hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
hist.tail()
def plot_loss(history):
  plt.plot(history.history['loss'], label='loss')
  plt.plot(history.history['val_loss'], label='val_loss')
  plt.ylim([0, 10])
  plt.xlabel('Epoch')
  plt.ylabel('Error [MPG]')
  plt.legend()
  plt.grid(True)
plot_loss(history)

png

Thu thập các kết quả trên bộ thử nghiệm, để sử dụng sau:

test_results = {}

test_results['horsepower_model'] = horsepower_model.evaluate(
    test_features['Horsepower'],
    test_labels, verbose=0)

Vì đây là một hồi quy biến duy nhất, nên dễ dàng xem xét các dự đoán của mô hình như một hàm của đầu vào:

x = tf.linspace(0.0, 250, 251)
y = horsepower_model.predict(x)
def plot_horsepower(x, y):
  plt.scatter(train_features['Horsepower'], train_labels, label='Data')
  plt.plot(x, y, color='k', label='Predictions')
  plt.xlabel('Horsepower')
  plt.ylabel('MPG')
  plt.legend()
plot_horsepower(x,y)

png

Nhiều đầu vào

Bạn có thể sử dụng một thiết lập gần như giống hệt nhau để đưa ra dự đoán dựa trên nhiều đầu vào. Mô hình này vẫn thực hiện tương tự $ y = mx + b $ ngoại trừ $ m $ là một ma trận và $ b $ là một vectơ.

Lần này, hãy sử dụng lớp Normalization đã được điều chỉnh cho phù hợp với toàn bộ tập dữ liệu.

linear_model = tf.keras.Sequential([
    normalizer,
    layers.Dense(units=1)
])

Khi bạn gọi mô hình này trên một lô đầu vào, nó tạo ra units=1 đầu ra cho mỗi ví dụ.

linear_model.predict(train_features[:10])
array([[-0.241],
       [ 0.492],
       [-1.162],
       [ 0.915],
       [-0.663],
       [ 0.459],
       [-0.511],
       [ 2.999],
       [-0.289],
       [-1.593]], dtype=float32)

Khi bạn gọi mô hình, ma trận trọng lượng sẽ được xây dựng. Bây giờ bạn có thể thấy rằng kernel ($ m $ trong $ y = mx + b $) có hình dạng là (9,1) .

linear_model.layers[1].kernel
<tf.Variable 'dense_1/kernel:0' shape=(9, 1) dtype=float32, numpy=
array([[-0.277],
       [ 0.696],
       [-0.155],
       [-0.476],
       [ 0.265],
       [ 0.453],
       [ 0.7  ],
       [-0.704],
       [-0.099]], dtype=float32)>

Sử dụng các lệnh gọi compilefit tương tự như đối với mô hình horsepower đầu vào duy nhất:

linear_model.compile(
    optimizer=tf.optimizers.Adam(learning_rate=0.1),
    loss='mean_absolute_error')
%%time
history = linear_model.fit(
    train_features, train_labels, 
    epochs=100,
    # suppress logging
    verbose=0,
    # Calculate validation results on 20% of the training data
    validation_split = 0.2)
CPU times: user 3.72 s, sys: 777 ms, total: 4.5 s
Wall time: 2.8 s

Sử dụng tất cả các đầu vào đạt được sai số đào tạo và xác nhận thấp hơn nhiều so với mô hình horsepower :

plot_loss(history)

png

Thu thập các kết quả trên bộ thử nghiệm, để sử dụng sau:

test_results['linear_model'] = linear_model.evaluate(
    test_features, test_labels, verbose=0)

Hồi quy DNN

Phần trước đã triển khai các mô hình tuyến tính cho đầu vào đơn và nhiều đầu vào.

Phần này triển khai các mô hình DNN một đầu vào và nhiều đầu vào. Mã về cơ bản giống nhau ngoại trừ mô hình được mở rộng để bao gồm một số lớp phi tuyến tính "ẩn". Tên "hidden" ở đây chỉ có nghĩa là không kết nối trực tiếp với các đầu vào hoặc đầu ra.

Các mô hình này sẽ chứa nhiều lớp hơn mô hình tuyến tính:

  • Lớp chuẩn hóa.
  • Hai ẩn, phi tuyến, Dense lớp bằng cách sử dụng relu phi tuyến.
  • Một lớp đầu ra đơn tuyến tính.

Cả hai sẽ sử dụng cùng một quy trình đào tạo nên phương thức compile được bao gồm trong hàm build_and_compile_model bên dưới.

def build_and_compile_model(norm):
  model = keras.Sequential([
      norm,
      layers.Dense(64, activation='relu'),
      layers.Dense(64, activation='relu'),
      layers.Dense(1)
  ])

  model.compile(loss='mean_absolute_error',
                optimizer=tf.keras.optimizers.Adam(0.001))
  return model

Một biến

Bắt đầu với mô hình DNN cho một đầu vào duy nhất: "Mã lực"

dnn_horsepower_model = build_and_compile_model(horsepower_normalizer)

Mô hình này có nhiều tham số có thể huấn luyện hơn so với mô hình tuyến tính.

dnn_horsepower_model.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
normalization_1 (Normalizati (None, 1)                 3         
_________________________________________________________________
dense_2 (Dense)              (None, 64)                128       
_________________________________________________________________
dense_3 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_4 (Dense)              (None, 1)                 65        
=================================================================
Total params: 4,356
Trainable params: 4,353
Non-trainable params: 3
_________________________________________________________________

Huấn luyện mô hình:

%%time
history = dnn_horsepower_model.fit(
    train_features['Horsepower'], train_labels,
    validation_split=0.2,
    verbose=0, epochs=100)
CPU times: user 4.06 s, sys: 792 ms, total: 4.85 s
Wall time: 3.08 s

Mô hình này hoạt động tốt hơn một chút so với mô hình mã lực tuyến tính.

plot_loss(history)

png

Nếu bạn vẽ các dự đoán dưới dạng một hàm của Horsepower , bạn sẽ thấy cách mô hình này tận dụng tính phi tuyến được cung cấp bởi các lớp ẩn:

x = tf.linspace(0.0, 250, 251)
y = dnn_horsepower_model.predict(x)
plot_horsepower(x, y)

png

Thu thập các kết quả trên bộ thử nghiệm, để sử dụng sau:

test_results['dnn_horsepower_model'] = dnn_horsepower_model.evaluate(
    test_features['Horsepower'], test_labels,
    verbose=0)

Đầy đủ mô hình

Nếu bạn lặp lại quy trình này bằng cách sử dụng tất cả các đầu vào, nó sẽ cải thiện một chút hiệu suất trên tập dữ liệu xác thực.

dnn_model = build_and_compile_model(normalizer)
dnn_model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
normalization (Normalization (None, 9)                 19        
_________________________________________________________________
dense_5 (Dense)              (None, 64)                640       
_________________________________________________________________
dense_6 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_7 (Dense)              (None, 1)                 65        
=================================================================
Total params: 4,884
Trainable params: 4,865
Non-trainable params: 19
_________________________________________________________________

%%time
history = dnn_model.fit(
    train_features, train_labels,
    validation_split=0.2,
    verbose=0, epochs=100)
CPU times: user 4.12 s, sys: 696 ms, total: 4.81 s
Wall time: 3.05 s

plot_loss(history)

png

Thu thập các kết quả trên bộ thử nghiệm:

test_results['dnn_model'] = dnn_model.evaluate(test_features, test_labels, verbose=0)

Hiệu suất

Bây giờ, tất cả các mô hình đã được đào tạo, hãy kiểm tra hiệu suất của bộ thử nghiệm và xem cách họ đã làm:

pd.DataFrame(test_results, index=['Mean absolute error [MPG]']).T

Các kết quả này khớp với lỗi xác thực được thấy trong quá trình đào tạo.

Đưa ra dự đoán

Cuối cùng, dự đoán hãy xem các lỗi của mô hình khi đưa ra dự đoán trên bộ thử nghiệm:

test_predictions = dnn_model.predict(test_features).flatten()

a = plt.axes(aspect='equal')
plt.scatter(test_labels, test_predictions)
plt.xlabel('True Values [MPG]')
plt.ylabel('Predictions [MPG]')
lims = [0, 50]
plt.xlim(lims)
plt.ylim(lims)
_ = plt.plot(lims, lims)

png

Có vẻ như mô hình dự đoán khá tốt.

Bây giờ hãy xem phân phối lỗi:

error = test_predictions - test_labels
plt.hist(error, bins=25)
plt.xlabel('Prediction Error [MPG]')
_ = plt.ylabel('Count')

png

Nếu bạn hài lòng với mô hình, hãy lưu nó để sử dụng sau:

dnn_model.save('dnn_model')
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Layer.updates (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.
INFO:tensorflow:Assets written to: dnn_model/assets

Nếu bạn tải lại mô hình, nó cho kết quả giống hệt nhau:

reloaded = tf.keras.models.load_model('dnn_model')

test_results['reloaded'] = reloaded.evaluate(
    test_features, test_labels, verbose=0)
pd.DataFrame(test_results, index=['Mean absolute error [MPG]']).T

Phần kết luận

Sổ tay này giới thiệu một số kỹ thuật để xử lý vấn đề hồi quy. Dưới đây là một số mẹo khác có thể hữu ích:

  • Lỗi bình phương trung bình (MSE)Lỗi tuyệt đối trung bình (MAE) là các hàm mất mát phổ biến được sử dụng cho các bài toán hồi quy. Sai số tuyệt đối trung bình ít nhạy cảm hơn với các ngoại lệ. Các hàm tổn thất khác nhau được sử dụng cho các bài toán phân loại.
  • Tương tự, các số liệu đánh giá được sử dụng cho hồi quy khác với phân loại.
  • Khi các đối tượng địa lý dữ liệu đầu vào dạng số có các giá trị với các phạm vi khác nhau, mỗi đối tượng địa lý phải được chia tỷ lệ độc lập thành cùng một phạm vi.
  • Overfitting là một vấn đề phổ biến đối với các mô hình DNN, nó không phải là vấn đề đối với hướng dẫn này. Xem hướng dẫn overfit và underfit để được trợ giúp thêm về vấn đề này.
# MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.