Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Tensorflow Lattice ile Şekil Kısıtlamaları

TensorFlow.org'da görüntüleyin Google Colab'de çalıştırın Kaynağı GitHub'da görüntüleyin Defteri indirin

Genel Bakış

Bu öğretici, TensorFlow Lattice (TFL) kitaplığı tarafından sağlanan kısıtlamalar ve düzenleyicilere genel bir bakıştır. Burada sentetik veri kümelerinde TFL hazır tahmin ediciler kullanıyoruz, ancak bu eğitimdeki her şeyin TFL Keras katmanlarından oluşturulan modellerle de yapılabileceğini unutmayın.

Devam etmeden önce, çalışma zamanınızda gerekli tüm paketlerin kurulu olduğundan emin olun (aşağıdaki kod hücrelerinde içe aktarıldığı gibi).

Kurmak

TF Lattice paketinin kurulması:

pip install -q tensorflow-lattice

Gerekli paketleri içe aktarma:

import tensorflow as tf

from IPython.core.pylabtools import figsize
import itertools
import logging
import matplotlib
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
import sys
import tensorflow_lattice as tfl
logging.disable(sys.maxsize)

Bu kılavuzda kullanılan varsayılan değerler:

NUM_EPOCHS = 500
BATCH_SIZE = 64
LEARNING_RATE=0.001

Restoranlar Sıralaması için Eğitim Veri Kümesi

Kullanıcıların bir restoran arama sonucunu tıklayıp tıklamayacağını belirlemek istediğimiz basitleştirilmiş bir senaryo hayal edin. Görev, giriş özellikleri verilen tıklama oranını (TO) tahmin etmektir:

  • Ortalama derecelendirme ( avg_rating ): [1,5] aralığında değerlere sahip sayısal bir özellik.
  • num_reviews sayısı ( num_reviews ): num_reviews bir ölçüsü olarak kullandığımız, değerleri 200 ile sınırlanmış sayısal bir özellik.
  • Dolar derecelendirmesi ( dollar_rating ): {"D", "DD", "DDD", "DDDD"} kümesindeki dize değerlerine sahip kategorik bir özellik.

Burada, gerçek TO'nun formülle verildiği sentetik bir veri kümesi oluşturuyoruz:

$$ CTR = 1 / (1 + exp\{\mbox{b(dollar_rating)}-\mbox{avg_rating}\times log(\mbox{num_reviews}) /4 \}) $$

$ b (\ cdot) $, her dollar_rating temel bir değere dollar_rating :

$$ \mbox{D}\to 3,\ \mbox{DD}\to 2,\ \mbox{DDD}\to 4,\ \mbox{DDDD}\to 4.5. $$

Bu formül, tipik kullanıcı kalıplarını yansıtır. örneğin, her şeyin düzeltildiği düşünüldüğünde, kullanıcılar yıldız derecelendirmesi daha yüksek restoranları tercih ederler ve "\ $ \ $" restoranlar "\ $" dan daha fazla tıklama alır, ardından "\ $ \ $ \ $" ve "\ $ \ $ \ $ \ $ ".

def click_through_rate(avg_ratings, num_reviews, dollar_ratings):
  dollar_rating_baseline = {"D": 3, "DD": 2, "DDD": 4, "DDDD": 4.5}
  return 1 / (1 + np.exp(
      np.array([dollar_rating_baseline[d] for d in dollar_ratings]) -
      avg_ratings * np.log1p(num_reviews) / 4))

Bu CTR fonksiyonunun kontur grafiklerine bir göz atalım.

def color_bar():
  bar = matplotlib.cm.ScalarMappable(
      norm=matplotlib.colors.Normalize(0, 1, True),
      cmap="viridis",
  )
  bar.set_array([0, 1])
  return bar


def plot_fns(fns, split_by_dollar=False, res=25):
  """Generates contour plots for a list of (name, fn) functions."""
  num_reviews, avg_ratings = np.meshgrid(
      np.linspace(0, 200, num=res),
      np.linspace(1, 5, num=res),
  )
  if split_by_dollar:
    dollar_rating_splits = ["D", "DD", "DDD", "DDDD"]
  else:
    dollar_rating_splits = [None]
  if len(fns) == 1:
    fig, axes = plt.subplots(2, 2, sharey=True, tight_layout=False)
  else:
    fig, axes = plt.subplots(
        len(dollar_rating_splits), len(fns), sharey=True, tight_layout=False)
  axes = axes.flatten()
  axes_index = 0
  for dollar_rating_split in dollar_rating_splits:
    for title, fn in fns:
      if dollar_rating_split is not None:
        dollar_ratings = np.repeat(dollar_rating_split, res**2)
        values = fn(avg_ratings.flatten(), num_reviews.flatten(),
                    dollar_ratings)
        title = "{}: dollar_rating={}".format(title, dollar_rating_split)
      else:
        values = fn(avg_ratings.flatten(), num_reviews.flatten())
      subplot = axes[axes_index]
      axes_index += 1
      subplot.contourf(
          avg_ratings,
          num_reviews,
          np.reshape(values, (res, res)),
          vmin=0,
          vmax=1)
      subplot.title.set_text(title)
      subplot.set(xlabel="Average Rating")
      subplot.set(ylabel="Number of Reviews")
      subplot.set(xlim=(1, 5))

  _ = fig.colorbar(color_bar(), cax=fig.add_axes([0.95, 0.2, 0.01, 0.6]))


figsize(11, 11)
plot_fns([("CTR", click_through_rate)], split_by_dollar=True)

png

Verilerin Hazırlanması

Şimdi sentetik veri kümelerimizi oluşturmamız gerekiyor. Restoranlar ve özelliklerinin simüle edilmiş bir veri setini oluşturarak başlıyoruz.

def sample_restaurants(n):
  avg_ratings = np.random.uniform(1.0, 5.0, n)
  num_reviews = np.round(np.exp(np.random.uniform(0.0, np.log(200), n)))
  dollar_ratings = np.random.choice(["D", "DD", "DDD", "DDDD"], n)
  ctr_labels = click_through_rate(avg_ratings, num_reviews, dollar_ratings)
  return avg_ratings, num_reviews, dollar_ratings, ctr_labels


np.random.seed(42)
avg_ratings, num_reviews, dollar_ratings, ctr_labels = sample_restaurants(2000)

figsize(5, 5)
fig, axs = plt.subplots(1, 1, sharey=False, tight_layout=False)
for rating, marker in [("D", "o"), ("DD", "^"), ("DDD", "+"), ("DDDD", "x")]:
  plt.scatter(
      x=avg_ratings[np.where(dollar_ratings == rating)],
      y=num_reviews[np.where(dollar_ratings == rating)],
      c=ctr_labels[np.where(dollar_ratings == rating)],
      vmin=0,
      vmax=1,
      marker=marker,
      label=rating)
plt.xlabel("Average Rating")
plt.ylabel("Number of Reviews")
plt.legend()
plt.xlim((1, 5))
plt.title("Distribution of restaurants")
_ = fig.colorbar(color_bar(), cax=fig.add_axes([0.95, 0.2, 0.01, 0.6]))

png

Eğitim, doğrulama ve test veri setlerini oluşturalım. Arama sonuçlarında bir restoran görüntülendiğinde, kullanıcı katılımını (tıklama veya tıklama yok) örnek nokta olarak kaydedebiliriz.

Pratikte, kullanıcılar genellikle tüm arama sonuçlarından geçmezler. Bu, kullanıcıların büyük olasılıkla yalnızca, kullanımda olan mevcut sıralama modeline göre zaten "iyi" kabul edilen restoranları görecekleri anlamına gelir. Sonuç olarak, "iyi" restoranlar daha sık etkilenir ve eğitim veri kümelerinde aşırı temsil edilir. Daha fazla özellik kullanılırken, eğitim veri kümesi, özellik alanının "kötü" bölümlerinde büyük boşluklara sahip olabilir.

Model sıralama için kullanıldığında, genellikle eğitim veri kümesinde iyi temsil edilmeyen daha tekdüze bir dağılımla tüm ilgili sonuçlar üzerinde değerlendirilir. Bu durumda esnek ve karmaşık bir model, aşırı temsil edilen veri noktalarının aşırı uyması nedeniyle başarısız olabilir ve bu nedenle genelleştirilebilirlikten yoksun olabilir. Bu sorunu, modeli eğitim veri kümesinden alamadığında makul tahminlerde bulunmaya yönlendiren şekil kısıtlamaları eklemek için alan bilgisini uygulayarak ele alıyoruz.

Bu örnekte, eğitim veri kümesi çoğunlukla iyi ve popüler restoranlarla kullanıcı etkileşimlerinden oluşur. Test veri seti, yukarıda tartışılan değerlendirme ayarını simüle etmek için tek tip bir dağılıma sahiptir. Bu tür test veri kümesinin gerçek bir sorun ortamında mevcut olmayacağını unutmayın.

def sample_dataset(n, testing_set):
  (avg_ratings, num_reviews, dollar_ratings, ctr_labels) = sample_restaurants(n)
  if testing_set:
    # Testing has a more uniform distribution over all restaurants.
    num_views = np.random.poisson(lam=3, size=n)
  else:
    # Training/validation datasets have more views on popular restaurants.
    num_views = np.random.poisson(lam=ctr_labels * num_reviews / 50.0, size=n)

  return pd.DataFrame({
      "avg_rating": np.repeat(avg_ratings, num_views),
      "num_reviews": np.repeat(num_reviews, num_views),
      "dollar_rating": np.repeat(dollar_ratings, num_views),
      "clicked": np.random.binomial(n=1, p=np.repeat(ctr_labels, num_views))
  })


# Generate datasets.
np.random.seed(42)
data_train = sample_dataset(2000, testing_set=False)
data_val = sample_dataset(1000, testing_set=False)
data_test = sample_dataset(1000, testing_set=True)

# Plotting dataset densities.
figsize(12, 5)
fig, axs = plt.subplots(1, 2, sharey=False, tight_layout=False)
for ax, data, title in [(axs[0], data_train, "training"),
                        (axs[1], data_test, "testing")]:
  _, _, _, density = ax.hist2d(
      x=data["avg_rating"],
      y=data["num_reviews"],
      bins=(np.linspace(1, 5, num=21), np.linspace(0, 200, num=21)),
      density=True,
      cmap="Blues",
  )
  ax.set(xlim=(1, 5))
  ax.set(ylim=(0, 200))
  ax.set(xlabel="Average Rating")
  ax.set(ylabel="Number of Reviews")
  ax.title.set_text("Density of {} examples".format(title))
  _ = fig.colorbar(density, ax=ax)

png

Eğitim ve değerlendirme için kullanılan input_fns'yi tanımlama:

train_input_fn = tf.compat.v1.estimator.inputs.pandas_input_fn(
    x=data_train,
    y=data_train["clicked"],
    batch_size=BATCH_SIZE,
    num_epochs=NUM_EPOCHS,
    shuffle=False,
)

# feature_analysis_input_fn is used for TF Lattice estimators.
feature_analysis_input_fn = tf.compat.v1.estimator.inputs.pandas_input_fn(
    x=data_train,
    y=data_train["clicked"],
    batch_size=BATCH_SIZE,
    num_epochs=1,
    shuffle=False,
)

val_input_fn = tf.compat.v1.estimator.inputs.pandas_input_fn(
    x=data_val,
    y=data_val["clicked"],
    batch_size=BATCH_SIZE,
    num_epochs=1,
    shuffle=False,
)

test_input_fn = tf.compat.v1.estimator.inputs.pandas_input_fn(
    x=data_test,
    y=data_test["clicked"],
    batch_size=BATCH_SIZE,
    num_epochs=1,
    shuffle=False,
)

Degrade Güçlendirilmiş Ağaçların Takılması

Yalnızca iki özellikle avg_rating : avg_rating ve num_reviews .

Doğrulama ve test ölçümlerini çizmek ve hesaplamak için birkaç yardımcı fonksiyon oluşturuyoruz.

def analyze_two_d_estimator(estimator, name):
  # Extract validation metrics.
  metric = estimator.evaluate(input_fn=val_input_fn)
  print("Validation AUC: {}".format(metric["auc"]))
  metric = estimator.evaluate(input_fn=test_input_fn)
  print("Testing AUC: {}".format(metric["auc"]))

  def two_d_pred(avg_ratings, num_reviews):
    results = estimator.predict(
        tf.compat.v1.estimator.inputs.pandas_input_fn(
            x=pd.DataFrame({
                "avg_rating": avg_ratings,
                "num_reviews": num_reviews,
            }),
            shuffle=False,
        ))
    return [x["logistic"][0] for x in results]

  def two_d_click_through_rate(avg_ratings, num_reviews):
    return np.mean([
        click_through_rate(avg_ratings, num_reviews,
                           np.repeat(d, len(avg_ratings)))
        for d in ["D", "DD", "DDD", "DDDD"]
    ],
                   axis=0)

  figsize(11, 5)
  plot_fns([("{} Estimated CTR".format(name), two_d_pred),
            ("CTR", two_d_click_through_rate)],
           split_by_dollar=False)

Veri kümesine TensorFlow gradyan artırılmış karar ağaçlarını sığdırabiliriz:

feature_columns = [
    tf.feature_column.numeric_column("num_reviews"),
    tf.feature_column.numeric_column("avg_rating"),
]
gbt_estimator = tf.estimator.BoostedTreesClassifier(
    feature_columns=feature_columns,
    # Hyper-params optimized on validation set.
    n_batches_per_layer=1,
    max_depth=3,
    n_trees=20,
    min_node_weight=0.1,
    config=tf.estimator.RunConfig(tf_random_seed=42),
)
gbt_estimator.train(input_fn=train_input_fn)
analyze_two_d_estimator(gbt_estimator, "GBT")
Validation AUC: 0.7248634099960327
Testing AUC: 0.6980501413345337

png

Model, gerçek TO'nun genel şeklini yakalamış ve yeterli doğrulama ölçütlerine sahip olsa da, giriş alanının birkaç bölümünde sezgisel davranışı vardır: Ortalama puan veya inceleme sayısı arttıkça tahmini TO azalır. Bunun nedeni, eğitim veri kümesinin yeterince kaplamadığı alanlardaki örnek noktalarının eksikliğidir. Modelin, yalnızca verilerden doğru davranışı çıkarmanın bir yolu yoktur.

Bu sorunu çözmek için, modelin hem ortalama derecelendirme hem de inceleme sayısına göre monoton olarak artan değerler vermesi gerektiği biçim kısıtlamasını uyguluyoruz. Bunu daha sonra TFL'de nasıl uygulayacağımızı göreceğiz.

DNN takma

Aynı adımları bir DNN sınıflandırıcısı ile tekrarlayabiliriz. Benzer bir model gözlemleyebiliriz: Az sayıda inceleme ile yeterli örnek noktasına sahip olmamak, anlamsız bir ekstrapolasyona neden olur. Doğrulama ölçüsü ağaç çözümünden daha iyi olsa da, test ölçüsü çok daha kötüdür.

feature_columns = [
    tf.feature_column.numeric_column("num_reviews"),
    tf.feature_column.numeric_column("avg_rating"),
]
dnn_estimator = tf.estimator.DNNClassifier(
    feature_columns=feature_columns,
    # Hyper-params optimized on validation set.
    hidden_units=[16, 8, 8],
    optimizer=tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE),
    config=tf.estimator.RunConfig(tf_random_seed=42),
)
dnn_estimator.train(input_fn=train_input_fn)
analyze_two_d_estimator(dnn_estimator, "DNN")
Validation AUC: 0.7518489956855774
Testing AUC: 0.745200514793396

png

Şekil Kısıtlamaları

TensorFlow Lattice (TFL), model davranışını eğitim verilerinin ötesinde korumak için şekil kısıtlamalarını uygulamaya odaklanır. Bu şekil kısıtlamaları, TFL Keras katmanlarına uygulanır. Ayrıntıları JMLR belgemizde bulunabilir.

Bu öğreticide çeşitli şekil kısıtlamalarını kapsamak için TF hazır tahmin ediciler kullanıyoruz, ancak tüm bu adımların TFL Keras katmanlarından oluşturulan modellerle yapılabileceğini unutmayın.

Diğer tüm TensorFlow tahmin edicilerinde olduğu gibi, TFL hazır tahmin edicileri, girdi formatını tanımlamak için özellik sütunlarını kullanır ve verileri geçirmek için bir eğitim input_fn kullanır. TFL hazır tahmin edicilerinin kullanılması ayrıca şunları gerektirir:

  • bir model yapılandırması : model mimarisini ve özellik başına şekil kısıtlamalarını ve düzenleyicileri tanımlama.
  • bir özellik analizi input_fn : TFL başlatması için veri geçen bir TF input_fn.

Daha kapsamlı bir açıklama için lütfen hazır tahmin ediciler eğiticisine veya API belgelerine bakın.

Monotonluk

İlk olarak, her iki özelliğe de monotonluk şekli kısıtlamaları ekleyerek monotonluk endişelerini ele alıyoruz.

TFL'ye şekil kısıtlamalarını zorlama talimatı vermek için, özellik yapılandırmalarında kısıtlamaları belirtiyoruz . Aşağıdaki kod, monotonicity="increasing" ayarlayarak avg_rating hem num_reviews hem de num_reviews göre monoton olarak artmasını nasıl gerekli avg_rating .

feature_columns = [
    tf.feature_column.numeric_column("num_reviews"),
    tf.feature_column.numeric_column("avg_rating"),
]
model_config = tfl.configs.CalibratedLatticeConfig(
    feature_configs=[
        tfl.configs.FeatureConfig(
            name="num_reviews",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_num_keypoints=20,
        ),
        tfl.configs.FeatureConfig(
            name="avg_rating",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_num_keypoints=20,
        )
    ])
tfl_estimator = tfl.estimators.CannedClassifier(
    feature_columns=feature_columns,
    model_config=model_config,
    feature_analysis_input_fn=feature_analysis_input_fn,
    optimizer=tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE),
    config=tf.estimator.RunConfig(tf_random_seed=42),
)
tfl_estimator.train(input_fn=train_input_fn)
analyze_two_d_estimator(tfl_estimator, "TF Lattice")
Validation AUC: 0.7402218580245972
Testing AUC: 0.735464870929718

png

Bir CalibratedLatticeConfig kullanmak, önce her girişe bir kalibratör (sayısal özellikler için parça bazında doğrusal bir işlev) ve ardından kalibre edilmiş özellikleri doğrusal olmayan bir şekilde birleştirmek için bir kafes katmanı uygulayan bir hazır sınıflandırıcı oluşturur. Modeli görselleştirmek için tfl.visualization kullanabiliriz. Özellikle, aşağıdaki grafik, kutulu sınıflandırıcıya dahil edilen iki eğitimli kalibratörü göstermektedir.

def save_and_visualize_lattice(tfl_estimator):
  saved_model_path = tfl_estimator.export_saved_model(
      "/tmp/TensorFlow_Lattice_101/",
      tf.estimator.export.build_parsing_serving_input_receiver_fn(
          feature_spec=tf.feature_column.make_parse_example_spec(
              feature_columns)))
  model_graph = tfl.estimators.get_model_graph(saved_model_path)
  figsize(8, 8)
  tfl.visualization.draw_model_graph(model_graph)
  return model_graph

_ = save_and_visualize_lattice(tfl_estimator)

png

Sınırlamalar eklendiğinde, tahmini TO her zaman ortalama puan arttıkça veya yorum sayısı arttıkça artacaktır. Bu, kalibratörlerin ve kafesin monoton olduğundan emin olarak yapılır.

Azalan İade

Azalan getiri , belirli bir özellik değerini artırmanın marjinal kazancının, değeri artırdıkça azalacağı anlamına gelir. Bizim durumumuzda, num_reviews özelliğinin bu kalıbı takip etmesini num_reviews , böylece kalibratörünü buna göre yapılandırabiliriz. Azalan getirileri iki yeterli koşula ayırabileceğimize dikkat edin:

  • kalibratör monoton olarak artıyor ve
  • kalibratör içbükeydir.
feature_columns = [
    tf.feature_column.numeric_column("num_reviews"),
    tf.feature_column.numeric_column("avg_rating"),
]
model_config = tfl.configs.CalibratedLatticeConfig(
    feature_configs=[
        tfl.configs.FeatureConfig(
            name="num_reviews",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_convexity="concave",
            pwl_calibration_num_keypoints=20,
        ),
        tfl.configs.FeatureConfig(
            name="avg_rating",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_num_keypoints=20,
        )
    ])
tfl_estimator = tfl.estimators.CannedClassifier(
    feature_columns=feature_columns,
    model_config=model_config,
    feature_analysis_input_fn=feature_analysis_input_fn,
    optimizer=tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE),
    config=tf.estimator.RunConfig(tf_random_seed=42),
)
tfl_estimator.train(input_fn=train_input_fn)
analyze_two_d_estimator(tfl_estimator, "TF Lattice")
_ = save_and_visualize_lattice(tfl_estimator)
Validation AUC: 0.7382229566574097
Testing AUC: 0.739747166633606

png

png

İçbükeylik kısıtlaması ekleyerek test metriğinin nasıl geliştiğine dikkat edin. Tahmin planı da temel gerçeğe daha çok benziyor.

2D Şekil Kısıtlaması: Güven

Yalnızca bir veya iki yorumu olan bir restoranın 5 yıldızlı puanı, muhtemelen güvenilmez bir derecelendirmedir (restoran aslında iyi olmayabilir), oysa yüzlerce yorumu olan bir restoranın 4 yıldızlı puanı çok daha güvenilirdir (restoran bu durumda muhtemelen iyidir). Bir restoranın yorum sayısının, ortalama derecelendirmesine ne kadar güvendiğimizi etkilediğini görebiliriz.

Modele, bir özelliğin daha büyük (veya daha küçük) değerinin başka bir özelliğe daha fazla güven duyulduğunu veya güveni gösterdiğini bildirmek için TFL güven kısıtlamalarını uygulayabiliriz. Bu, özellik yapılandırmasında reflects_trust_in yapılandırması ayarlanarak yapılır.

feature_columns = [
    tf.feature_column.numeric_column("num_reviews"),
    tf.feature_column.numeric_column("avg_rating"),
]
model_config = tfl.configs.CalibratedLatticeConfig(
    feature_configs=[
        tfl.configs.FeatureConfig(
            name="num_reviews",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_convexity="concave",
            pwl_calibration_num_keypoints=20,
            # Larger num_reviews indicating more trust in avg_rating.
            reflects_trust_in=[
                tfl.configs.TrustConfig(
                    feature_name="avg_rating", trust_type="edgeworth"),
            ],
        ),
        tfl.configs.FeatureConfig(
            name="avg_rating",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_num_keypoints=20,
        )
    ])
tfl_estimator = tfl.estimators.CannedClassifier(
    feature_columns=feature_columns,
    model_config=model_config,
    feature_analysis_input_fn=feature_analysis_input_fn,
    optimizer=tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE),
    config=tf.estimator.RunConfig(tf_random_seed=42),
)
tfl_estimator.train(input_fn=train_input_fn)
analyze_two_d_estimator(tfl_estimator, "TF Lattice")
model_graph = save_and_visualize_lattice(tfl_estimator)
Validation AUC: 0.7389558553695679
Testing AUC: 0.7397989630699158

png

png

Aşağıdaki grafik eğitimli kafes işlevini göstermektedir. Güven kısıtlaması nedeniyle, daha büyük kalibre edilmiş num_reviews değerlerinin, kalibre edilmiş num_reviews daha yüksek eğimi avg_rating ve bunun da kafes çıktısında daha önemli bir hareketle sonuçlanacağını avg_rating .

lat_mesh_n = 12
lat_mesh_x, lat_mesh_y = tfl.test_utils.two_dim_mesh_grid(
    lat_mesh_n**2, 0, 0, 1, 1)
lat_mesh_fn = tfl.test_utils.get_hypercube_interpolation_fn(
    model_graph.output_node.weights.flatten())
lat_mesh_z = [
    lat_mesh_fn([lat_mesh_x.flatten()[i],
                 lat_mesh_y.flatten()[i]]) for i in range(lat_mesh_n**2)
]
trust_plt = tfl.visualization.plot_outputs(
    (lat_mesh_x, lat_mesh_y),
    {"Lattice Lookup": lat_mesh_z},
    figsize=(6, 6),
)
trust_plt.title("Trust")
trust_plt.xlabel("Calibrated avg_rating")
trust_plt.ylabel("Calibrated num_reviews")
trust_plt.show()

png

Pürüzsüzleştirici Kalibratörler

Şimdi avg_rating kalibratörüne bir göz avg_rating . Monoton bir şekilde artmasına rağmen, yamaçlarındaki değişiklikler ani ve yorumlanması zor. Bu, bu kalibratörü, regularizer_configs bir düzenleyici kurulumu kullanarak yumuşatmayı düşünmek isteyebileceğimizi gösterir.

Burada eğrilikteki değişiklikleri azaltmak için bir wrinkle düzenleyici uyguluyoruz. Kalibratörü düzleştirmek için laplacian düzenleyiciyi ve daha doğrusal hale getirmek için hessian düzenleyiciyi de kullanabilirsiniz.

feature_columns = [
    tf.feature_column.numeric_column("num_reviews"),
    tf.feature_column.numeric_column("avg_rating"),
]
model_config = tfl.configs.CalibratedLatticeConfig(
    feature_configs=[
        tfl.configs.FeatureConfig(
            name="num_reviews",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_convexity="concave",
            pwl_calibration_num_keypoints=20,
            regularizer_configs=[
                tfl.configs.RegularizerConfig(name="calib_wrinkle", l2=1.0),
            ],
            reflects_trust_in=[
                tfl.configs.TrustConfig(
                    feature_name="avg_rating", trust_type="edgeworth"),
            ],
        ),
        tfl.configs.FeatureConfig(
            name="avg_rating",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_num_keypoints=20,
            regularizer_configs=[
                tfl.configs.RegularizerConfig(name="calib_wrinkle", l2=1.0),
            ],
        )
    ])
tfl_estimator = tfl.estimators.CannedClassifier(
    feature_columns=feature_columns,
    model_config=model_config,
    feature_analysis_input_fn=feature_analysis_input_fn,
    optimizer=tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE),
    config=tf.estimator.RunConfig(tf_random_seed=42),
)
tfl_estimator.train(input_fn=train_input_fn)
analyze_two_d_estimator(tfl_estimator, "TF Lattice")
_ = save_and_visualize_lattice(tfl_estimator)
Validation AUC: 0.7512660026550293
Testing AUC: 0.7544151544570923

png

png

Kalibratörler artık pürüzsüz ve genel tahmini TO, temel gerçekle daha iyi eşleşiyor. Bu, hem test metriğine hem de kontur grafiklerine yansıtılır.

Kategorik Kalibrasyon için Kısmi Monotonluk

Şimdiye kadar modeldeki sayısal özelliklerden sadece ikisini kullandık. Burada kategorik bir kalibrasyon katmanı kullanarak üçüncü bir özellik ekleyeceğiz. Yine çizim ve metrik hesaplama için yardımcı işlevler ayarlayarak başlıyoruz.

def analyze_three_d_estimator(estimator, name):
  # Extract validation metrics.
  metric = estimator.evaluate(input_fn=val_input_fn)
  print("Validation AUC: {}".format(metric["auc"]))
  metric = estimator.evaluate(input_fn=test_input_fn)
  print("Testing AUC: {}".format(metric["auc"]))

  def three_d_pred(avg_ratings, num_reviews, dollar_rating):
    results = estimator.predict(
        tf.compat.v1.estimator.inputs.pandas_input_fn(
            x=pd.DataFrame({
                "avg_rating": avg_ratings,
                "num_reviews": num_reviews,
                "dollar_rating": dollar_rating,
            }),
            shuffle=False,
        ))
    return [x["logistic"][0] for x in results]

  figsize(11, 22)
  plot_fns([("{} Estimated CTR".format(name), three_d_pred),
            ("CTR", click_through_rate)],
           split_by_dollar=True)

dollar_rating adlı üçüncü özelliği dahil etmek için, kategorik özelliklerin hem bir özellik sütunu hem de özellik yapılandırması olarak dollar_rating biraz farklı bir işlem gerektirdiğini hatırlamalıyız. Burada, diğer tüm girdiler sabitlendiğinde "DD" restoranlar için çıktıların "D" restoranlardan daha büyük olması gerektiği şeklindeki kısmi monotonluk kısıtlamasını uyguluyoruz. Bu, özellik yapılandırmasındaki monotonicity ayarı kullanılarak yapılır.

feature_columns = [
    tf.feature_column.numeric_column("num_reviews"),
    tf.feature_column.numeric_column("avg_rating"),
    tf.feature_column.categorical_column_with_vocabulary_list(
        "dollar_rating",
        vocabulary_list=["D", "DD", "DDD", "DDDD"],
        dtype=tf.string,
        default_value=0),
]
model_config = tfl.configs.CalibratedLatticeConfig(
    feature_configs=[
        tfl.configs.FeatureConfig(
            name="num_reviews",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_convexity="concave",
            pwl_calibration_num_keypoints=20,
            regularizer_configs=[
                tfl.configs.RegularizerConfig(name="calib_wrinkle", l2=1.0),
            ],
            reflects_trust_in=[
                tfl.configs.TrustConfig(
                    feature_name="avg_rating", trust_type="edgeworth"),
            ],
        ),
        tfl.configs.FeatureConfig(
            name="avg_rating",
            lattice_size=2,
            monotonicity="increasing",
            pwl_calibration_num_keypoints=20,
            regularizer_configs=[
                tfl.configs.RegularizerConfig(name="calib_wrinkle", l2=1.0),
            ],
        ),
        tfl.configs.FeatureConfig(
            name="dollar_rating",
            lattice_size=2,
            pwl_calibration_num_keypoints=4,
            # Here we only specify one monotonicity:
            # `D` resturants has smaller value than `DD` restaurants
            monotonicity=[("D", "DD")],
        ),
    ])
tfl_estimator = tfl.estimators.CannedClassifier(
    feature_columns=feature_columns,
    model_config=model_config,
    feature_analysis_input_fn=feature_analysis_input_fn,
    optimizer=tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE),
    config=tf.estimator.RunConfig(tf_random_seed=42),
)
tfl_estimator.train(input_fn=train_input_fn)
analyze_three_d_estimator(tfl_estimator, "TF Lattice")
_ = save_and_visualize_lattice(tfl_estimator)
Validation AUC: 0.8136826753616333
Testing AUC: 0.8294427394866943

png

png

Bu kategorik kalibratör, model çıktısının tercihini gösterir: DD> D> DDD> DDDD, bu bizim kurulumumuzla tutarlıdır. Eksik değerler için bir sütun olduğuna dikkat edin. Eğitim ve test verilerimizde eksik bir özellik olmasa da, model, aşağı akış model sunumu sırasında meydana gelmesi durumunda eksik değer için bize bir belirleme sağlar.

Burada, bu modelin öngörülen TO'sunu da dollar_rating alınarak dollar_rating . Her dilimde ihtiyaç duyduğumuz tüm kısıtlamaların yerine getirildiğine dikkat edin.

Çıktı Kalibrasyonu

Şimdiye kadar eğittiğimiz tüm TFL modelleri için, örgü katmanı (model grafiğinde "Kafes" olarak gösterilir) doğrudan model tahminini verir. Bazen, kafes çıktısının model çıktılarını yayacak şekilde yeniden ölçeklendirilmesi gerekip gerekmediğinden emin değiliz:

  • etiketler sayılırken özellikler $ log $ counts şeklindedir.
  • kafes çok az köşeye sahip olacak şekilde yapılandırılmıştır, ancak etiket dağıtımı nispeten karmaşıktır.

Bu durumlarda, model esnekliğini artırmak için kafes çıktısı ile model çıktısı arasına başka bir kalibratör ekleyebiliriz. Şimdi oluşturduğumuz modele 5 anahtar noktalı bir kalibratör katmanı ekleyelim. Ayrıca, işlevi sorunsuz tutmak için çıktı kalibratörü için bir düzenleyici ekledik.

feature_columns = [
    tf.feature_column.numeric_column("num_reviews"),
    tf.feature_column.numeric_column("avg_rating"),
    tf.feature_column.categorical_column_with_vocabulary_list(
        "dollar_rating",
        vocabulary_list=["D", "DD", "DDD", "DDDD"],
        dtype=tf.string,
        default_value=0),
]
model_config = tfl.configs.CalibratedLatticeConfig(
    output_calibration=True,
    output_calibration_num_keypoints=5,
    regularizer_configs=[
        tfl.configs.RegularizerConfig(name="output_calib_wrinkle", l2=0.1),
    ],
    feature_configs=[
    tfl.configs.FeatureConfig(
        name="num_reviews",
        lattice_size=2,
        monotonicity="increasing",
        pwl_calibration_convexity="concave",
        pwl_calibration_num_keypoints=20,
        regularizer_configs=[
            tfl.configs.RegularizerConfig(name="calib_wrinkle", l2=1.0),
        ],
        reflects_trust_in=[
            tfl.configs.TrustConfig(
                feature_name="avg_rating", trust_type="edgeworth"),
        ],
    ),
    tfl.configs.FeatureConfig(
        name="avg_rating",
        lattice_size=2,
        monotonicity="increasing",
        pwl_calibration_num_keypoints=20,
        regularizer_configs=[
            tfl.configs.RegularizerConfig(name="calib_wrinkle", l2=1.0),
        ],
    ),
    tfl.configs.FeatureConfig(
        name="dollar_rating",
        lattice_size=2,
        pwl_calibration_num_keypoints=4,
        # Here we only specify one monotonicity:
        # `D` resturants has smaller value than `DD` restaurants
        monotonicity=[("D", "DD")],
    ),
])
tfl_estimator = tfl.estimators.CannedClassifier(
    feature_columns=feature_columns,
    model_config=model_config,
    feature_analysis_input_fn=feature_analysis_input_fn,
    optimizer=tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE),
    config=tf.estimator.RunConfig(tf_random_seed=42),
)
tfl_estimator.train(input_fn=train_input_fn)
analyze_three_d_estimator(tfl_estimator, "TF Lattice")
_ = save_and_visualize_lattice(tfl_estimator)
Validation AUC: 0.8131163716316223
Testing AUC: 0.830264151096344

png

png

Son test metriği ve çizimleri, sağduyu kısıtlamalarının kullanılmasının modelin beklenmedik davranışlardan kaçınmasına ve tüm girdi alanına daha iyi tahminler yapmasına nasıl yardımcı olabileceğini gösterir.