tensorflow-deep-learning

v2026.09.24

Best practices for building, training, evaluating, and deploying neural networks with TensorFlow and Keras. Use when writing tf.data input pipelines, defining or training a Keras model, configuring callbacks for checkpointing and early stopping, evaluating a trained model, or exporting a model for serving.

GitHub
安装命令
npx skhub add mindrally/tensorflow-deep-learning
Markdown
SKILL.md

TensorFlow and Deep Learning

This skill covers project structure, model development, training, evaluation, and deployment practices for neural networks built with TensorFlow and Keras.

Workflow for Training and Shipping a Model

  1. Separate concerns into modules — Keep data loading, model definition, training, evaluation, and serving code in distinct files; treat notebooks as exploratory only.
  2. Build the input pipeline first — Use tf.data.Dataset for scalable, prefetching input processing; validate shapes, dtypes, label ranges, and class balance before writing any model code.
  3. Split before any fitting — Create train/validation/test splits before fitting normalization statistics or augmentation parameters, to avoid leakage.
  4. Start with a tiny baseline — Build a small model and run a tiny overfit test (fit on a handful of examples until loss goes to ~0) to prove the training loop works before scaling up.
  5. Train with callbacks — Wire in ModelCheckpoint (save best by validation metric, not final epoch), EarlyStopping, a learning-rate schedule, and TensorBoard logging.
  6. Evaluate with task-appropriate metrics — Use a held-out test set only for final reporting, never for tuning.
  7. Export with a explicit signature — Save with model.export() or tf.saved_model.save() and define serving input signatures explicitly.
  8. Smoke test the export — Load the exported model and run inference on sample inputs before deploying.

Project Structure

  • Separate data loading, model definition, training, evaluation, and serving code into distinct modules (e.g., data.py, model.py, train.py, evaluate.py, serve.py).
  • Keep model hyperparameters in typed config objects (dataclasses) or config files, not scattered as literals through training code.
  • Store checkpoints, logs, and exported models outside source directories (e.g., under artifacts/ or a configured output path), so they don't get swept into version control accidentally.
  • Keep notebooks exploratory; once an approach is validated, move the repeatable training code into modules that can be run as scripts and covered by tests.
project/
  data.py          # tf.data pipeline construction
  model.py         # Keras model definition
  config.py        # typed hyperparameter config
  train.py         # training loop / Keras fit orchestration
  evaluate.py       # metrics computation on held-out data
  serve.py         # export + inference smoke test
  artifacts/       # checkpoints, logs, saved models (gitignored)

Input Pipeline (tf.data)

import tensorflow as tf

def build_dataset(file_pattern: str, batch_size: int, shuffle: bool) -> tf.data.Dataset:
    files = tf.data.Dataset.list_files(file_pattern, shuffle=shuffle)
    ds = files.interleave(
        tf.data.TFRecordDataset,
        cycle_length=tf.data.AUTOTUNE,
        num_parallel_calls=tf.data.AUTOTUNE,
    )
    ds = ds.map(_parse_example, num_parallel_calls=tf.data.AUTOTUNE)
    if shuffle:
        ds = ds.shuffle(buffer_size=10_000)
    ds = ds.batch(batch_size, drop_remainder=False)
    return ds.prefetch(tf.data.AUTOTUNE)

def _parse_example(record: tf.Tensor) -> tuple[tf.Tensor, tf.Tensor]:
    feature_spec = {
        "features": tf.io.FixedLenFeature([32], tf.float32),
        "label": tf.io.FixedLenFeature([], tf.int64),
    }
    parsed = tf.io.parse_single_example(record, feature_spec)
    return parsed["features"], parsed["label"]
  • Use num_parallel_calls=tf.data.AUTOTUNE on .map()/.interleave() and always end the pipeline with .prefetch(tf.data.AUTOTUNE).
  • Shuffle before batching, with a buffer large enough to approximate a full shuffle for the dataset size.
  • Validate data shapes, dtypes, label ranges, and class balance on a sample batch before starting a long training run.

Model Development

  • Use Keras layers and models (tf.keras.Model, tf.keras.Sequential) unless a specific need requires lower-level tf.GradientTape control.
  • Prefer explicit input shapes and named inputs/outputs — this makes serving signatures and debugging easier.
  • Start with a small baseline model and confirm it can overfit a tiny subset of data (loss near zero) before scaling depth, width, or dataset size — this catches pipeline and loss-function bugs early.
  • Pin random seeds (tf.random.set_seed, numpy.random.seed) where reproducibility matters, but document that GPU execution can still be nondeterministic for some ops (e.g., certain cuDNN reductions).
  • Only enable mixed precision (tf.keras.mixed_precision.set_global_policy("mixed_float16")) after validating numerical stability at full precision — some losses (e.g., ones involving log or exp) need loss scaling to avoid underflow.
import tensorflow as tf

def build_model(input_dim: int, num_classes: int) -> tf.keras.Model:
    inputs = tf.keras.Input(shape=(input_dim,), name="features")
    x = tf.keras.layers.Dense(128, activation="relu")(inputs)
    x = tf.keras.layers.Dropout(0.3)(x)
    x = tf.keras.layers.Dense(64, activation="relu")(x)
    outputs = tf.keras.layers.Dense(num_classes, activation="softmax", name="predictions")(x)
    return tf.keras.Model(inputs=inputs, outputs=outputs, name="baseline_classifier")

Training

import tensorflow as tf

model = build_model(input_dim=32, num_classes=10)
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)

callbacks = [
    tf.keras.callbacks.ModelCheckpoint(
        filepath="artifacts/checkpoints/best.keras",
        monitor="val_accuracy",
        save_best_only=True,
    ),
    tf.keras.callbacks.EarlyStopping(
        monitor="val_loss", patience=5, restore_best_weights=True,
    ),
    tf.keras.callbacks.ReduceLROnPlateau(
        monitor="val_loss", factor=0.5, patience=3, min_lr=1e-6,
    ),
    tf.keras.callbacks.TensorBoard(log_dir="artifacts/logs"),
]

train_ds = build_dataset("data/train-*.tfrecord", batch_size=64, shuffle=True)
val_ds = build_dataset("data/val-*.tfrecord", batch_size=64, shuffle=False)

history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=50,
    callbacks=callbacks,
)
  • Split data into train/validation/test before fitting any normalization layer or augmentation parameters — fitting on the full dataset leaks test statistics into training.
  • Use the validation set for tuning (architecture, learning rate, regularization); reserve a separate test set purely for final reporting, touched once.
  • Track loss curves, metrics, learning rate, and resource utilization (TensorBoard, or an experiment tracker) for every run.
  • Save the checkpoint with the best validation metric (save_best_only=True), not just the weights from the final epoch — the final epoch is not necessarily the best one, especially with EarlyStopping.

Evaluation

  • Report task-appropriate metrics: AUROC/F1/calibration for classification, perplexity or BLEU/ROUGE for language tasks, MAE/RMSE for regression.
  • Include confusion matrices or per-class error slices for classification tasks — aggregate accuracy hides class-level failures.
  • Evaluate on edge cases and known distribution shifts when data allows (e.g., a held-out slice from a different time period or source).
  • Compare against non-neural baselines (logistic regression, gradient-boosted trees) when the dataset is small or tabular — a deep model that underperforms a simple baseline is a signal, not a footnote.
test_ds = build_dataset("data/test-*.tfrecord", batch_size=64, shuffle=False)
results = model.evaluate(test_ds, return_dict=True)
print(results)  # {'loss': ..., 'accuracy': ...}

Deployment

  • Export models with an explicit input signature so serving infrastructure (TF Serving, Vertex AI, etc.) knows the expected input shape and dtype:
model.export("artifacts/saved_model/v1")

# Or with an explicit serving signature:
@tf.function(input_signature=[tf.TensorSpec(shape=[None, 32], dtype=tf.float32, name="features")])
def serve_fn(features):
    return {"predictions": model(features, training=False)}

tf.saved_model.save(model, "artifacts/saved_model/v1", signatures={"serving_default": serve_fn})
  • Keep preprocessing identical between training and serving — bake normalization/tokenization into the exported graph (e.g., tf.keras.layers.Normalization as part of the model) rather than duplicating logic in a separate serving-side script.
  • Add a smoke test that loads the exported SavedModel and runs inference on a handful of known sample inputs, asserting outputs are in the expected range/shape, before promoting a model to production.
  • Monitor latency, memory, prediction drift, and input schema changes once deployed — a model that was correct at export time can silently degrade as upstream data shifts.

Common Mistakes

  • Tuning architecture before verifying labels and data quality — a data bug will outlast any architecture change.
  • Leaking validation or test data through preprocessing or augmentation fit on the full dataset instead of the training split alone.
  • Relying on accuracy alone for imbalanced datasets — use precision/recall, F1, or AUROC instead.
  • Deploying a notebook-only model with no reproducible training script or pinned dependencies.
  • Ignoring batch size, dtype, or device (CPU/GPU) differences between training and inference, which can silently change numerical results (especially under mixed precision).
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

Apache-2.0

源路径

tensorflow-deep-learning

默认分支

main

最新提交

9718410

Tree SHA

81ba3c7