Temel regresyon: Yakıt verimliliğini tahmin edin

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir

Bir regresyon probleminde amaç, fiyat veya olasılık gibi sürekli bir değerin çıktısını tahmin etmektir. Bunu, amacın bir sınıf listesinden bir sınıf seçmek olduğu bir sınıflandırma problemi ile karşılaştırın (örneğin, bir resmin bir elma veya bir portakal içerdiği, resimde hangi meyvenin olduğunu fark ederek).

Bu öğretici, klasik Auto MPG veri kümesini kullanır ve 1970'lerin sonu ve 1980'lerin başındaki otomobillerin yakıt verimliliğini tahmin etmek için modellerin nasıl oluşturulacağını gösterir. Bunu yapmak için, modellere o döneme ait birçok otomobilin tanımını vereceksiniz. Bu açıklama, silindirler, yer değiştirme, beygir gücü ve ağırlık gibi özellikleri içerir.

Bu örnek, Keras API'sini kullanır. (Daha fazla bilgi edinmek için Keras eğitimlerini ve kılavuzlarını ziyaret edin.)

# Use seaborn for pairplot.
pip install -q seaborn
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)
yer tutucu8 l10n-yer
import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers

print(tf.__version__)
2.8.0-rc1

Otomatik MPG veri seti

Veri kümesi, UCI Machine Learning Repository'den edinilebilir.

verileri al

Önce pandaları kullanarak veri kümesini indirin ve içe aktarın:

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)
tutucu11 l10n-yer
dataset = raw_dataset.copy()
dataset.tail()

Verileri temizle

Veri kümesi birkaç bilinmeyen değer içeriyor:

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

Bu ilk öğreticiyi basit tutmak için bu satırları bırakın:

dataset = dataset.dropna()

"Origin" sütunu sayısal değil, kategoriktir. Dolayısıyla bir sonraki adım, sütundaki değerleri pd.get_dummies ile tek tuşla kodlamaktır.

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

Verileri eğitim ve test setlerine ayırın

Şimdi veri setini eğitim seti ve test seti olarak ikiye ayırın. Modellerinizin son değerlendirmesinde test setini kullanacaksınız.

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

Verileri inceleyin

Eğitim setinden birkaç çift sütunun ortak dağılımını gözden geçirin.

En üst sıra, yakıt verimliliğinin (MPG) diğer tüm parametrelerin bir fonksiyonu olduğunu gösterir. Diğer satırlar birbirlerinin işlevleri olduklarını gösterir.

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

png

Genel istatistikleri de kontrol edelim. Her özelliğin çok farklı bir aralığı nasıl kapsadığına dikkat edin:

train_dataset.describe().transpose()

Etiketlerden özellikleri ayırma

Hedef değeri ("etiket") özelliklerden ayırın. Bu etiket, modeli tahmin etmesi için eğiteceğiniz değerdir.

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

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

normalleştirme

İstatistik tablosunda, her bir özelliğin aralıklarının ne kadar farklı olduğunu görmek kolaydır:

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

Farklı ölçekler ve aralıklar kullanan özellikleri normalleştirmek iyi bir uygulamadır.

Bunun önemli olmasının bir nedeni, özelliklerin model ağırlıkları ile çarpılmasıdır. Dolayısıyla, çıktıların ölçeği ve gradyanların ölçeği, girdilerin ölçeğinden etkilenir.

Bir model , özellik normalleştirmesi olmadan yakınsayabilir, ancak normalleştirme, eğitimi çok daha kararlı hale getirir.

Normalleştirme katmanı

tf.keras.layers.Normalization , modelinize özellik normalleştirmesi eklemenin temiz ve basit bir yoludur.

İlk adım katmanı oluşturmaktır:

normalizer = tf.keras.layers.Normalization(axis=-1)

Ardından, Normalization.adapt çağırarak ön işleme katmanının durumunu verilere uydurun:

normalizer.adapt(np.array(train_features))

Ortalamayı ve varyansı hesaplayın ve bunları katmanda saklayın:

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

Katman çağrıldığında, her bir özellik bağımsız olarak normalleştirilmiş olarak giriş verilerini döndürür:

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

with np.printoptions(precision=2, suppress=True):
  print('First example:', first)
  print()
  print('Normalized:', normalizer(first).numpy())
tutucu28 l10n-yer
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]]

Doğrusal regresyon

Derin bir sinir ağı modeli oluşturmadan önce, bir ve birkaç değişken kullanarak doğrusal regresyonla başlayın.

Tek değişkenli doğrusal regresyon

'Horsepower' 'MPG' tahmin etmek için tek değişkenli doğrusal bir regresyonla başlayın.

Bir modeli tf.keras ile eğitmek tipik olarak model mimarisini tanımlayarak başlar. Bir dizi adımı temsil eden bir tf.keras.Sequential modeli kullanın.

Tek değişkenli doğrusal regresyon modelinizde iki adım vardır:

  • tf.keras.layers.Normalization ön işleme katmanını kullanarak 'Horsepower' giriş özelliklerini normalleştirin.
  • Doğrusal bir katman ( tf.keras.layers.Dense ) kullanarak 1 çıktı üretmek için doğrusal bir dönüşüm (\(y = mx+b\)) uygulayın.

input_shape bağımsız değişkeni tarafından veya model ilk kez çalıştırıldığında otomatik olarak ayarlanabilir.

İlk olarak, 'Horsepower' özelliklerinden oluşan bir NumPy dizisi oluşturun. Ardından, tf.keras.layers.Normalization somutlaştırın ve durumunu horsepower verilerine uydurun:

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

horsepower_normalizer = layers.Normalization(input_shape=[1,], axis=None)
horsepower_normalizer.adapt(horsepower)

Keras Sıralı modelini oluşturun:

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

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

Bu model, 'Horsepower' 'MPG' tahmin edecektir.

Eğitimsiz modeli ilk 10 'Beygir Gücü' değerinde çalıştırın. Çıktı iyi olmayacak, ancak beklenen şekle sahip olduğuna dikkat edin (10, 1) :

horsepower_model.predict(horsepower[:10])
tutucu33 l10n-yer
array([[-1.186],
       [-0.67 ],
       [ 2.189],
       [-1.662],
       [-1.504],
       [-0.59 ],
       [-1.782],
       [-1.504],
       [-0.392],
       [-0.67 ]], dtype=float32)

Model oluşturulduktan sonra, Model.compile yöntemini kullanarak eğitim prosedürünü yapılandırın. Derlenecek en önemli argümanlar, loss ve optimizer edicidir, çünkü bunlar neyin optimize edileceğini ( ortalama_absolute_error ) ve nasıl ( mean_absolute_error kullanılarak) tf.keras.optimizers.Adam .

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

100 dönemlik eğitimi yürütmek için Model.fit kullanın:

%%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)
tutucu36 l10n-yer
CPU times: user 4.79 s, sys: 797 ms, total: 5.59 s
Wall time: 3.8 s

history nesnesinde depolanan istatistikleri kullanarak modelin eğitim ilerlemesini görselleştirin:

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)
tutucu39 l10n-yer
plot_loss(history)

png

Sonuçları daha sonra kullanmak üzere test setinde toplayın:

test_results = {}

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

Bu tek değişkenli bir regresyon olduğundan, modelin tahminlerini girdinin bir fonksiyonu olarak görmek kolaydır:

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()
-yer tutucu43 l10n-yer
plot_horsepower(x, y)

png

Çoklu girişli doğrusal regresyon

Birden çok girdiye dayalı tahminler yapmak için hemen hemen aynı kurulumu kullanabilirsiniz. Bu model, \(m\) bir matris ve \(b\) bir vektör olması dışında aynı \(y = mx+b\) yapar.

Daha önce tanımladığınız ve tüm veri kümesine uyarladığınız ilk katman normalizer ( tf.keras.layers.Normalization(axis=-1) ) olacak şekilde tekrar iki adımlı bir Keras Sequential modeli oluşturun:

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

Bir grup Model.predict , her örnek için units=1 çıktı üretir:

linear_model.predict(train_features[:10])
tutucu46 l10n-yer
array([[ 0.441],
       [ 1.522],
       [ 0.188],
       [ 1.169],
       [ 0.058],
       [ 0.965],
       [ 0.034],
       [-0.674],
       [ 0.437],
       [-0.37 ]], dtype=float32)

Modeli çağırdığınızda, ağırlık matrisleri oluşturulacaktır— kernel ağırlıklarının ( \(m\) içindeki \(y=mx+b\)) (9, 1) şeklinde olup olmadığını kontrol edin:

linear_model.layers[1].kernel
tutucu48 l10n-yer
<tf.Variable 'dense_1/kernel:0' shape=(9, 1) dtype=float32, numpy=
array([[-0.702],
       [ 0.307],
       [ 0.114],
       [ 0.233],
       [ 0.244],
       [ 0.322],
       [-0.725],
       [-0.151],
       [ 0.407]], dtype=float32)>

Modeli Model.compile ile yapılandırın ve 100 dönem için Model.fit ile eğitin:

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)
-yer tutucu51 l10n-yer
CPU times: user 4.89 s, sys: 740 ms, total: 5.63 s
Wall time: 3.75 s

Bu regresyon modelindeki tüm girdileri kullanmak, bir girdiye sahip olan horsepower_model çok daha düşük bir eğitim ve doğrulama hatası sağlar:

plot_loss(history)

png

Sonuçları daha sonra kullanmak üzere test setinde toplayın:

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

Derin sinir ağı (DNN) ile regresyon

Önceki bölümde, tekli ve çoklu girişler için iki doğrusal model uyguladınız.

Burada tek girişli ve çok girişli DNN modellerini uygulayacaksınız.

Kod, modelin bazı "gizli" doğrusal olmayan katmanları içerecek şekilde genişletilmesi dışında temelde aynıdır. Buradaki "gizli" adı, doğrudan giriş veya çıkışlara bağlı olmadığı anlamına gelir.

Bu modeller, doğrusal modelden birkaç katman daha içerecektir:

  • Normalleştirme katmanı, daha önce olduğu gibi (tek girişli bir model için horsepower_normalizer ve çok girişli bir model için normalizer ile).
  • ReLU ( relu ) aktivasyon fonksiyonu doğrusal olmayan iki gizli, doğrusal olmayan, Dense katman.
  • Doğrusal Dense tek çıkışlı katman.

Her iki model de aynı eğitim prosedürünü kullanacak, bu nedenle compile yöntemi aşağıdaki build_and_compile_model işlevine dahil edilmiştir.

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

Bir DNN ve tek bir giriş kullanarak regresyon

Giriş olarak yalnızca 'Horsepower' ve normalleştirme katmanı olarak horsepower_normalizer (daha önce tanımlanmış) olan bir DNN modeli oluşturun:

dnn_horsepower_model = build_and_compile_model(horsepower_normalizer)

Bu model, lineer modellerden oldukça fazla eğitilebilir parametreye sahiptir:

dnn_horsepower_model.summary()
tutucu57 l10n-yer
Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 normalization_1 (Normalizat  (None, 1)                3         
 ion)                                                            
                                                                 
 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
_________________________________________________________________

Modeli Model.fit ile eğitin:

%%time
history = dnn_horsepower_model.fit(
    train_features['Horsepower'],
    train_labels,
    validation_split=0.2,
    verbose=0, epochs=100)
tutucu59 l10n-yer
CPU times: user 5.07 s, sys: 691 ms, total: 5.76 s
Wall time: 3.92 s

Bu model, doğrusal tek girişli horsepower_model biraz daha iyi sonuç verir:

plot_loss(history)

png

Tahminleri 'Horsepower' bir fonksiyonu olarak çizerseniz, bu modelin gizli katmanlar tarafından sağlanan doğrusal olmama özelliğinden nasıl yararlandığını fark etmelisiniz:

x = tf.linspace(0.0, 250, 251)
y = dnn_horsepower_model.predict(x)
tutucu62 l10n-yer
plot_horsepower(x, y)

png

Sonuçları daha sonra kullanmak üzere test setinde toplayın:

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

DNN ve çoklu girişler kullanarak regresyon

Tüm girişleri kullanarak önceki işlemi tekrarlayın. Modelin performansı, doğrulama veri kümesinde biraz iyileşir.

dnn_model = build_and_compile_model(normalizer)
dnn_model.summary()
Model: "sequential_3"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 normalization (Normalizatio  (None, 9)                19        
 n)                                                              
                                                                 
 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 5.08 s, sys: 725 ms, total: 5.8 s
Wall time: 3.94 s
plot_loss(history)

png

Test setindeki sonuçları toplayın:

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

Verim

Tüm modeller eğitildiğinden, test seti performanslarını inceleyebilirsiniz:

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

Bu sonuçlar, eğitim sırasında gözlemlenen doğrulama hatasıyla eşleşir.

tahminlerde bulunun

Artık dnn_model kullanarak test setinde Model.predict ile tahminler yapabilir ve kaybı inceleyebilirsiniz:

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

Görünen o ki, model oldukça iyi tahmin yapıyor.

Şimdi hata dağılımını kontrol edin:

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

png

Modelden memnunsanız, Model.save ile daha sonra kullanmak üzere kaydedin:

dnn_model.save('dnn_model')
tutucu74 l10n-yer
2022-01-26 07:26:13.372245: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: dnn_model/assets

Modeli yeniden yüklerseniz, aynı çıktıyı verir:

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

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

Çözüm

Bu defter, bir regresyon sorununu çözmek için birkaç teknik tanıttı. Yardımcı olabilecek birkaç ipucu daha:

  • Ortalama kare hatası (MSE) ( tf.losses.MeanSquaredError ) ve ortalama mutlak hata (MAE) ( tf.losses.MeanAbsoluteError ) regresyon problemleri için kullanılan yaygın kayıp fonksiyonlarıdır. MAE aykırı değerlere karşı daha az duyarlıdır. Sınıflandırma problemleri için farklı kayıp fonksiyonları kullanılmaktadır.
  • Benzer şekilde, regresyon için kullanılan değerlendirme ölçütleri de sınıflandırmadan farklıdır.
  • Sayısal giriş verisi özellikleri farklı aralıklara sahip değerlere sahip olduğunda, her bir özellik bağımsız olarak aynı aralığa ölçeklendirilmelidir.
  • Bu öğretici için bir sorun olmamasına rağmen, fazla takma DNN modelleri için yaygın bir sorundur. Bununla ilgili daha fazla yardım için Üst ve iç giyim eğitimini ziyaret edin.
# 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.