تاریخ را ذخیره کنید! Google I / O 18-20 مه بازمی گردد اکنون ثبت نام کنید
این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

محدودیت های شکل را با شبکه Tensorflow شکل دهید

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub دانلود دفترچه یادداشت

بررسی اجمالی

این آموزش مروری است بر محدودیت ها و تنظیم کننده های ارائه شده توسط کتابخانه TensorFlow Lattice (TFL). در اینجا ما از برآوردگرهای کنسرو شده TFL در مجموعه داده های مصنوعی استفاده می کنیم ، اما توجه داشته باشید که همه چیز در این آموزش با مدل های ساخته شده از لایه های TFL Keras نیز قابل انجام است.

قبل از ادامه ، اطمینان حاصل کنید که در زمان اجرا تمام بسته های مورد نیاز نصب شده است (همانطور که در سلول های کد زیر وارد شده است).

برپایی

نصب بسته TF Lattice:

pip install -q tensorflow-lattice

وارد کردن بسته های مورد نیاز:

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)

مقادیر پیش فرض مورد استفاده در این راهنما:

NUM_EPOCHS = 1000
BATCH_SIZE = 64
LEARNING_RATE=0.01

مجموعه آموزش داده ها برای رتبه بندی رستوران ها

یک سناریوی ساده را تصور کنید که در آن می خواهیم تعیین کنیم آیا کاربران روی نتیجه جستجوی رستوران کلیک می کنند یا خیر. وظیفه پیش بینی نرخ کلیک (CTR) با توجه به ویژگی های ورودی است:

  • میانگین امتیاز ( avg_rating ): یک ویژگی عددی با مقادیر در محدوده [1،5].
  • تعداد بازبینی ها ( num_reviews ): یک ویژگی عددی با مقادیر num_reviews 200 که از آن برای اندازه گیری روند روز استفاده می کنیم.
  • رتبه بندی دلار ( dollar_rating ): یک ویژگی طبقه بندی شده با مقادیر رشته در مجموعه {"D" ، "DD" ، "DDD" ، "DDDD"}.

در اینجا ما یک مجموعه داده مصنوعی ایجاد می کنیم که CTR واقعی با فرمول داده می شود:

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

جایی که $ b (\ cdot) $ هر dollar_rating به مقدار پایه ترجمه می کند:

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

این فرمول الگوهای معمولی کاربر را منعکس می کند. به عنوان مثال با توجه به سایر موارد ثابت ، کاربران رستوران هایی با رتبه بندی ستاره بالاتر را ترجیح می دهند و رستوران های "\ $ \ $" کلیک بیشتری نسبت به "\ $" دریافت می کنند و به دنبال آن "\ $ \ $ \ $" و "\ $ \ $ \ $" \ $ ".

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))

بیایید نگاهی به نمودارهای کانتور این عملکرد CTR بیندازیم.

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

آماده سازی داده ها

اکنون باید مجموعه داده های مصنوعی خود را ایجاد کنیم. ما با تولید یک مجموعه داده شبیه سازی شده از رستوران ها و ویژگی های آنها شروع می کنیم.

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

بیایید مجموعه داده های آموزش ، اعتبار سنجی و آزمایش را تولید کنیم. وقتی یک رستوران در نتایج جستجو مشاهده می شود ، می توانیم تعامل کاربر (کلیک یا بدون کلیک) را به عنوان یک نمونه از نمونه ثبت کنیم.

در عمل ، کاربران اغلب همه نتایج جستجو را انجام نمی دهند. این بدان معناست که کاربران احتمالاً فقط رستورانهایی را می بینند که قبلاً توسط مدل رتبه بندی فعلی "خوب" در نظر گرفته شده است. در نتیجه ، رستوران های "خوب" بیشتر تحت تأثیر قرار می گیرند و در مجموعه داده های آموزشی بیش از حد نمایان می شوند. هنگام استفاده از ویژگی های بیشتر ، مجموعه داده های آموزشی می توانند در قسمت های "بد" فضای ویژگی ها ، شکاف زیادی داشته باشند.

هنگامی که از این مدل برای رتبه بندی استفاده می شود ، اغلب در تمام نتایج مربوطه با توزیع یکنواخت تری که توسط مجموعه داده های آموزشی به خوبی نشان داده نمی شود ، ارزیابی می شود. یک مدل انعطاف پذیر و پیچیده ممکن است در این مورد به دلیل نصب بیش از حد نقاط داده ای که بیش از حد نشان داده شده است ، از کار بیفتد و بنابراین قابلیت تعمیم ندارد. این مسئله را با استفاده از دانش دامنه برای افزودن محدودیت های شکلی که مدل را برای پیش بینی معقول هدایت می کند ، وقتی نمی تواند آنها را از مجموعه داده های آموزشی انتخاب کند ، حل می کنیم.

در این مثال ، مجموعه داده های آموزشی بیشتر شامل تعاملات کاربر با رستوران های خوب و محبوب است. مجموعه داده آزمایش دارای توزیع یکنواختی برای شبیه سازی تنظیمات ارزیابی شده در بالا است. توجه داشته باشید که چنین مجموعه داده آزمایشی در یک مشکل واقعی موجود نخواهد بود.

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(500, testing_set=False)
data_val = sample_dataset(500, testing_set=False)
data_test = sample_dataset(500, 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

تعریف input_fns مورد استفاده برای آموزش و ارزیابی:

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,
)

نصب درختان تقویت شده شیب دار

بیایید فقط با دو ویژگی شروع کنیم: avg_rating و num_reviews .

ما چند توابع کمکی برای رسم و محاسبه اعتبار سنجی و معیارهای آزمون ایجاد می کنیم.

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)

ما می توانیم TensorFlow درختان تصمیم تقویت شده را در مجموعه داده جای دهیم:

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=2,
    n_trees=50,
    learning_rate=0.05,
    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.6333084106445312
Testing AUC: 0.774649977684021

png

حتی اگر این مدل شکل کلی CTR واقعی را به دست آورده و دارای معیارهای اعتبار سنجی مناسبی باشد ، در چندین قسمت از فضای ورودی رفتار ضد شهودی دارد: با افزایش میانگین رتبه یا تعداد بررسی ها ، CTR تخمین زده شده کاهش می یابد. این به دلیل کمبود نقاط نمونه در مناطقی است که به خوبی تحت مجموعه داده های آموزشی قرار ندارند. این مدل به سادگی راهی برای استنباط رفتار صحیح فقط از داده ها ندارد.

برای حل این مسئله ، ما محدودیت شکل را اعمال می کنیم که مدل باید مقادیر خروجی را افزایش دهد که با توجه به رتبه بندی متوسط ​​و تعداد بررسی ها به صورت یکنواخت افزایش می یابد. بعداً خواهیم دید که چگونه این مورد را در TFL پیاده سازی کنیم.

نصب یک DNN

می توانیم همان مراحل را با طبقه بندی DNN تکرار کنیم. ما می توانیم الگوی مشابهی را مشاهده کنیم: نداشتن امتیاز کافی با تعداد کمی بررسی منجر به برون یابی پوچ می شود. توجه داشته باشید که حتی اگر معیار سنجش از محلول درخت بهتر باشد ، معیار سنجش بسیار بدتر است.

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.6696228981018066
Testing AUC: 0.750156044960022

png

محدودیت های شکل

شبکه TensorFlow (TFL) بر اعمال محدودیت های شکل برای حفاظت از رفتار مدل فراتر از داده های آموزش متمرکز شده است. این محدودیت های شکل بر روی لایه های TFL Keras اعمال می شود. جزئیات آنها را می توان در مقاله JMLR ما یافت .

در این آموزش ما از برآوردگرهای کنسرو شده TF برای پوشش دادن محدودیت های مختلف شکل استفاده می کنیم ، اما توجه داشته باشید که تمام این مراحل را می توان با مدل های ایجاد شده از لایه های TFL Keras انجام داد.

همانند سایر برآوردگرهای TensorFlow ، برآوردگرهای کنسرو شده TFL از ستونهای ویژگی برای تعریف قالب ورودی و استفاده از آموزش input_fn برای انتقال داده استفاده می کنند. استفاده از برآورد کنسرو TFL همچنین به موارد زیر احتیاج دارد:

  • یک پیکربندی مدل : تعریف معماری مدل و محدودیت های شکل و قاعده آور شکل هر ویژگی.
  • یک تجزیه و تحلیل ویژگی input_fn : ورودی TF_FN برای انتقال مقادیر اولیه برای TFL.

برای توضیحات کامل تر ، لطفاً به آموزش برآورد کنسرو شده یا اسناد API مراجعه کنید.

یکنواختی

ما ابتدا با افزودن محدودیت های شکل یکنواختی به هر دو ویژگی ، نگرانی های یکنواختی را برطرف می کنیم.

برای آموزش TFL برای اجرای محدودیت های شکل ، محدودیت ها را در پیکربندی های ویژگی مشخص می کنیم. کد زیر نشان می دهد که چگونه می توان با تنظیم monotonicity="increasing" به یکنواختی خروجی با توجه به num_reviews و 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.6565533876419067
Testing AUC: 0.7784258723258972

png

با استفاده از CalibratedLatticeConfig یک طبقه بندی کنسرو شده ایجاد می شود که ابتدا یک کالیبراتور را برای هر ورودی اعمال می کند (یک تابع خطی قطعه ای برای ویژگی های عددی) و سپس یک لایه شبکه برای فیوز نکردن غیر خطی ویژگی های کالیبره شده اعمال می کند. برای تجسم مدل می توانیم از tfl.visualization استفاده tfl.visualization . به طور خاص ، نمودار زیر دو کالیبراتور آموزش دیده را در طبقه بندی کنسرو نشان می دهد.

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

با محدودیت های اضافه شده ، CTR تخمینی با افزایش میانگین امتیاز یا افزایش تعداد بازبینی ها همیشه افزایش می یابد. این کار با اطمینان از یکنواخت بودن کالیبراتورها و شبکه انجام می شود.

کاهش بازده

کاهش بازده به این معنی است که با افزایش مقدار ، سود حاشیه ای افزایش مقدار مشخصی کاهش می یابد. در مورد ما انتظار داریم که ویژگی num_reviews از این الگو پیروی کند ، بنابراین می توانیم کالیبراتور آن را بر اساس آن پیکربندی کنیم. توجه داشته باشید که می توان بازدهی کاهنده را به دو شرط کافی تجزیه کرد:

  • کالیبراتور بصورت یکنواخت در حال افزایش است ، و
  • کالیبراتور مقعر است.
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.6409633755683899
Testing AUC: 0.7891247272491455

png

png

توجه کنید که چگونه معیار آزمایش با افزودن محدودیت تقعر بهبود می یابد. طرح پیش بینی نیز بهتر با حقیقت زمین شباهت دارد.

محدودیت شکل 2D: اعتماد

رتبه بندی 5 ستاره برای یک رستوران که فقط یک یا دو بررسی دارد احتمالاً یک امتیاز غیر قابل اعتماد است (ممکن است رستوران در واقع خوب نباشد) ، در حالی که رتبه بندی 4 ستاره برای یک رستوران با صدها نظر بسیار قابل اعتماد تر است (رستوران در این مورد احتمالاً خوب است). می توانیم ببینیم که تعداد بازبینی های یک رستوران بر میزان اعتماد ما به رتبه بندی متوسط ​​آن تأثیر دارد.

ما می توانیم از محدودیت های اعتماد TFL استفاده کنیم تا به مدل اطلاع دهیم که مقدار بزرگتر (یا کوچکتر) یک ویژگی نشانگر اتکای بیشتر یا اعتماد به ویژگی دیگر است. این کار با تنظیم پیکربندی reflects_trust_in در پیکربندی ویژگی انجام می شود.

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.6409633755683899
Testing AUC: 0.7891043424606323

png

png

نمودار زیر عملکرد شبکه آموزش دیده را نشان می دهد. با توجه به محدودیت اعتماد ، ما انتظار داریم که مقادیر بزرگتر تعداد num_reviews درجه بندی شده شیب بیشتری را با توجه به avg_rating بندی کالیبره شده 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

کالیبراتورهای صاف کننده

بیایید اکنون نگاهی به کالیبراتور avg_rating . اگرچه به صورت یکنواخت در حال افزایش است ، اما تغییرات در دامنه های آن ناگهانی است و تفسیر آن دشوار است. این نشان می دهد که ممکن است بخواهیم این کالیبراتور را با استفاده از تنظیم تنظیم کننده در regularizer_configs .

در اینجا از تنظیم کننده wrinkle می کنیم تا تغییرات انحنا را کاهش دهد. شما همچنین می توانید با استفاده از laplacian تنظیم کننده به پهن کردن کالیبراتور و hessian تنظیم کننده، آن را به خطی تر است.

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.6465646028518677
Testing AUC: 0.7948372960090637

png

png

اکنون کالیبراتورها صاف هستند و CTR کلی تخمین زده شده با حقیقت زمین مطابقت بیشتری دارد. این امر هم در معیار آزمون و هم در نمودارهای کانتور منعکس می شود.

یکنواختی جزئی برای کالیبراسیون دسته ای

تاکنون ما فقط از دو ویژگی عددی در مدل استفاده کرده ایم. در اینجا ما با استفاده از یک لایه طبقه بندی طبقه ای ، ویژگی سوم را اضافه خواهیم کرد. باز هم ما با تنظیم توابع کمکی برای رسم نمودار و محاسبه معیار شروع می کنیم.

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 ، باید به یاد بیاوریم که ویژگی های طبقه بندی نیاز به برخورد کمی متفاوت در TFL دارند ، هم به عنوان ستون ویژگی و هم به عنوان پیکربندی ویژگی. در اینجا ما محدودیت یکنواختی جزئی را اعمال می کنیم که خروجی رستوران های "DD" باید بزرگتر از رستوران های "D" باشد ، وقتی همه ورودی های دیگر ثابت شوند. این کار با استفاده از تنظیم monotonicity در پیکربندی ویژگی انجام می شود.

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.7699775695800781
Testing AUC: 0.8594040274620056

png

png

این کالیبراتور طبقه بندی اولویت خروجی مدل را نشان می دهد: DD> D> DDD> DDDD ، که با تنظیمات ما سازگار است. توجه کنید که یک ستون نیز برای مقادیر از دست رفته وجود دارد. اگرچه هیچ ویژگی گمشده ای در داده های آموزش و آزمایش ما وجود ندارد ، اما این مدل درصورتی که در هنگام خدمت مدل پایین دست اتفاق بیفتد ، برای ما مقدار محاسبه شده ای در نظر می گیرد.

در اینجا ما همچنین CTR پیش بینی شده این مدل را با شرط بستگی به dollar_rating . توجه داشته باشید که تمام محدودیت های مورد نیاز ما در هر یک از برش ها برآورده شده است.

کالیبراسیون خروجی

برای تمام مدلهای TFL که تاکنون آموزش داده ایم ، لایه شبکه (که در نمودار مدل به عنوان "شبکه" نشان داده شده است) مستقیماً پیش بینی مدل را ارائه می دهد. بعضی اوقات مطمئن نیستیم که آیا باید خروجی شبکه برای تولید خروجی مدل مجدداً تغییر یابد:

  • ویژگی ها $ log $ counts در حالی که برچسب ها count هستند.
  • شبکه به گونه ای پیکربندی شده است که رئوس بسیار کمی دارد اما توزیع برچسب نسبتاً پیچیده است.

در این موارد می توان کالیبراتور دیگری بین خروجی شبکه و خروجی مدل اضافه کرد تا انعطاف پذیری مدل افزایش یابد. در اینجا بیایید یک لایه کالیبراتور با 5 نقطه کلیدی به مدلی که الان ساخته ایم اضافه کنیم. ما همچنین یک تنظیم کننده برای کالیبراتور خروجی اضافه می کنیم تا عملکرد صاف باشد.

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.7697908878326416
Testing AUC: 0.861327052116394

png

png

آخرین معیار و نمودار آزمایشی نشان می دهد که چگونه استفاده از محدودیت های عقل سلیم می تواند به مدل کمک کند تا از رفتار غیرمنتظره جلوگیری کرده و برتری بیشتری را به کل فضای ورودی وارد کند.