<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Copyright 2020 The TensorFlow Authors.
Step1:  TF Lattice 自定义 Estimator
<table class="tfo-notebook-buttons" align="left">
  <td><a target="_blank" href="https
Step2:  导入所需的软件包：
Step3:  下载 UCI Statlog (Heart) 数据集：
Step4:  设置用于在本指南中进行训练的默认值：
Step5:  特征列
与任何其他 TF Estimator 一样，数据通常需要通过 input_fn 传递给 Estimator，并使用 FeatureColumns 进行解析。
Step6:  请注意，分类特征不需要用密集特征列包装，因为 tfl.laysers.CategoricalCalibration 层可以直接使用分类索引。
创建 input_fn
与任何其他 Estimator 一样，您可以使用 input_fn 将数据馈送给模型进行训练和评估。
Step8:  创建 model_fn
您可以通过多种方式创建自定义 Estimator。在这里，我们将构造一个在已解析的输入张量上调用 Keras 模型的 model_fn。要解析输入特征，您可以使用 tf.feature_column.input_layer、tf.keras.layers.DenseFeatures 或 tfl.estimators.transform_features。如果使用后者，则不需要使用密集特征列包装分类特征，并且生成的张量不会串联，这样可以更轻松地在校准层中使用特征。
要构造模型，您可以搭配使用 TFL 层或任何其他 Keras 层。在这里，我们从 TFL 层创建一个校准点阵 Keras 模型，并施加一些单调性约束。随后，我们使用 Keras 模型创建自定义 Estimator。
Step9:  训练和 Estimator
使用 model_fn，我们可以创建和训练 Estimator。
<ASSISTANT_TASK:>
Python Code:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Explanation: Copyright 2020 The TensorFlow Authors.
End of explanation
#@test {"skip": true}
!pip install tensorflow-lattice
Explanation: TF Lattice 自定义 Estimator
<table class="tfo-notebook-buttons" align="left">
  <td><a target="_blank" href="https://tensorflow.google.cn/lattice/tutorials/custom_estimators"><img src="https://tensorflow.google.cn/images/tf_logo_32px.png">在 TensorFlow.org 上查看 </a></td>
  <td><a target="_blank" href="https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/zh-cn/lattice/tutorials/custom_estimators.ipynb"><img src="https://tensorflow.google.cn/images/colab_logo_32px.png">在 Google Colab 中运行 </a></td>
  <td><a target="_blank" href="https://github.com/tensorflow/docs-l10n/blob/master/site/zh-cn/lattice/tutorials/custom_estimators.ipynb"><img src="https://tensorflow.google.cn/images/GitHub-Mark-32px.png">在 GitHub 中查看源代码</a></td>
  <td><a href="https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/zh-cn/lattice/tutorials/custom_estimators.ipynb"><img src="https://tensorflow.google.cn/images/download_logo_32px.png"> 下载笔记本</a></td>
</table>
警告：不建议将 Estimator 用于新代码。Estimator 运行 v1.Session 风格的代码，此类代码更加难以正确编写，并且可能会出现意外行为，尤其是与 TF 2 代码结合使用时。Estimator 确实在我们的 [兼容性保证] (https://tensorflow.org/guide/versions) 范围内，但不会获得任何额外功能，而且没有除安全漏洞修复之外的任何其他修复。请参阅迁移指南以了解详情。
概述
您可以使用自定义 Estimator 通过 TFL 层创建任意单调模型。本指南概述了创建此类 Estimator 所需的步骤。
设置
安装 TF Lattice 软件包：
End of explanation
import tensorflow as tf
import logging
import numpy as np
import pandas as pd
import sys
import tensorflow_lattice as tfl
from tensorflow import feature_column as fc
from tensorflow_estimator.python.estimator.canned import optimizers
from tensorflow_estimator.python.estimator.head import binary_class_head
logging.disable(sys.maxsize)
Explanation: 导入所需的软件包：
End of explanation
csv_file = tf.keras.utils.get_file(
    'heart.csv', 'http://storage.googleapis.com/download.tensorflow.org/data/heart.csv')
df = pd.read_csv(csv_file)
target = df.pop('target')
train_size = int(len(df) * 0.8)
train_x = df[:train_size]
train_y = target[:train_size]
test_x = df[train_size:]
test_y = target[train_size:]
df.head()
Explanation: 下载 UCI Statlog (Heart) 数据集：
End of explanation
LEARNING_RATE = 0.1
BATCH_SIZE = 128
NUM_EPOCHS = 1000
Explanation: 设置用于在本指南中进行训练的默认值：
End of explanation
# Feature columns.
# - age
# - sex
# - ca        number of major vessels (0-3) colored by flourosopy
# - thal      3 = normal; 6 = fixed defect; 7 = reversable defect
feature_columns = [
    fc.numeric_column('age', default_value=-1),
    fc.categorical_column_with_vocabulary_list('sex', [0, 1]),
    fc.numeric_column('ca'),
    fc.categorical_column_with_vocabulary_list(
        'thal', ['normal', 'fixed', 'reversible']),
]
Explanation: 特征列
与任何其他 TF Estimator 一样，数据通常需要通过 input_fn 传递给 Estimator，并使用 FeatureColumns 进行解析。
End of explanation
train_input_fn = tf.compat.v1.estimator.inputs.pandas_input_fn(
    x=train_x,
    y=train_y,
    shuffle=True,
    batch_size=BATCH_SIZE,
    num_epochs=NUM_EPOCHS,
    num_threads=1)
test_input_fn = tf.compat.v1.estimator.inputs.pandas_input_fn(
    x=test_x,
    y=test_y,
    shuffle=False,
    batch_size=BATCH_SIZE,
    num_epochs=1,
    num_threads=1)
Explanation: 请注意，分类特征不需要用密集特征列包装，因为 tfl.laysers.CategoricalCalibration 层可以直接使用分类索引。
创建 input_fn
与任何其他 Estimator 一样，您可以使用 input_fn 将数据馈送给模型进行训练和评估。
End of explanation
def model_fn(features, labels, mode, config):
  model_fn for the custom estimator.
  del config
  input_tensors = tfl.estimators.transform_features(features, feature_columns)
  inputs = {
      key: tf.keras.layers.Input(shape=(1,), name=key) for key in input_tensors
  }
  lattice_sizes = [3, 2, 2, 2]
  lattice_monotonicities = ['increasing', 'none', 'increasing', 'increasing']
  lattice_input = tf.keras.layers.Concatenate(axis=1)([
      tfl.layers.PWLCalibration(
          input_keypoints=np.linspace(10, 100, num=8, dtype=np.float32),
          # The output range of the calibrator should be the input range of
          # the following lattice dimension.
          output_min=0.0,
          output_max=lattice_sizes[0] - 1.0,
          monotonicity='increasing',
      )(inputs['age']),
      tfl.layers.CategoricalCalibration(
          # Number of categories including any missing/default category.
          num_buckets=2,
          output_min=0.0,
          output_max=lattice_sizes[1] - 1.0,
      )(inputs['sex']),
      tfl.layers.PWLCalibration(
          input_keypoints=[0.0, 1.0, 2.0, 3.0],
          output_min=0.0,
          output_max=lattice_sizes[0] - 1.0,
          # You can specify TFL regularizers as tuple
          # ('regularizer name', l1, l2).
          kernel_regularizer=('hessian', 0.0, 1e-4),
          monotonicity='increasing',
      )(inputs['ca']),
      tfl.layers.CategoricalCalibration(
          num_buckets=3,
          output_min=0.0,
          output_max=lattice_sizes[1] - 1.0,
          # Categorical monotonicity can be partial order.
          # (i, j) indicates that we must have output(i) <= output(j).
          # Make sure to set the lattice monotonicity to 'increasing' for this
          # dimension.
          monotonicities=[(0, 1), (0, 2)],
      )(inputs['thal']),
  ])
  output = tfl.layers.Lattice(
      lattice_sizes=lattice_sizes, monotonicities=lattice_monotonicities)(
          lattice_input)
  training = (mode == tf.estimator.ModeKeys.TRAIN)
  model = tf.keras.Model(inputs=inputs, outputs=output)
  logits = model(input_tensors, training=training)
  if training:
    optimizer = optimizers.get_optimizer_instance_v2('Adagrad', LEARNING_RATE)
  else:
    optimizer = None
  head = binary_class_head.BinaryClassHead()
  return head.create_estimator_spec(
      features=features,
      mode=mode,
      labels=labels,
      optimizer=optimizer,
      logits=logits,
      trainable_variables=model.trainable_variables,
      update_ops=model.updates)
Explanation: 创建 model_fn
您可以通过多种方式创建自定义 Estimator。在这里，我们将构造一个在已解析的输入张量上调用 Keras 模型的 model_fn。要解析输入特征，您可以使用 tf.feature_column.input_layer、tf.keras.layers.DenseFeatures 或 tfl.estimators.transform_features。如果使用后者，则不需要使用密集特征列包装分类特征，并且生成的张量不会串联，这样可以更轻松地在校准层中使用特征。
要构造模型，您可以搭配使用 TFL 层或任何其他 Keras 层。在这里，我们从 TFL 层创建一个校准点阵 Keras 模型，并施加一些单调性约束。随后，我们使用 Keras 模型创建自定义 Estimator。
End of explanation
estimator = tf.estimator.Estimator(model_fn=model_fn)
estimator.train(input_fn=train_input_fn)
results = estimator.evaluate(input_fn=test_input_fn)
print('AUC: {}'.format(results['auc']))
Explanation: 训练和 Estimator
使用 model_fn，我们可以创建和训练 Estimator。
End of explanation
<END_TASK>