🟧 TensorFlow

Полный справочник: тензоры и Variable, tf.data, модели Keras, обучение и GradientTape, tf.function, сохранение, TensorBoard, GPU и распределение, развёртывание (Serving, Lite, JS) и типичные проблемы.

Шпаргалки · ИИ · #tensorflow #tf #deep-learning #python #keras

Что это

TensorFlow (Google) платформа машинного обучения: тензорные вычисления, автоматическое дифференцирование, Keras как основной высокоуровневый API, tf.data для конвейеров данных и полный набор для развёртывания (Serving, Lite, JS, TFX). Eager-режим по умолчанию (как обычный Python), @tf.function компилирует код в граф для скорости.

pip install tensorflow                 # CPU; GPU на Linux: pip install "tensorflow[and-cuda]"
python -c "import tensorflow as tf; print(tf.__version__, tf.config.list_physical_devices('GPU'))"
import tensorflow as tf
from tensorflow import keras

Нативная поддержка GPU на Windows закончилась на TF 2.10: используйте WSL2 или DirectML.

Тензоры и переменные

a = tf.constant([[1., 2.], [3., 4.]])                # неизменяемый тензор
v = tf.Variable([1., 2.])                             # изменяемое состояние (веса)
v.assign([3., 4.]); v.assign_add([1., 1.])
tf.zeros((2, 3)); tf.ones((2, 3)); tf.fill((2, 2), 7); tf.eye(3); tf.range(10); tf.linspace(0., 1., 5)
tf.random.set_seed(42); tf.random.normal((2, 3)); tf.random.uniform((2, 3)); tf.random.shuffle(a)
a.shape; a.dtype; a.numpy(); tf.shape(a); tf.rank(a); tf.size(a)
tf.cast(a, tf.float32); tf.reshape(a, [-1]); tf.transpose(a); tf.expand_dims(a, 0); tf.squeeze(a)
tf.concat([a, a], axis=0); tf.stack([a, a]); tf.split(a, 2); tf.gather(a, [0]); tf.where(a > 2, a, 0.)
a + a; a * a; a @ a; tf.matmul(a, a); tf.reduce_sum(a); tf.reduce_mean(a, axis=0); tf.argmax(a, axis=1); tf.nn.softmax(a); tf.math.top_k(a, 2)

Тензоры TF неизменяемы (не a[0] = 1): используйте tf.tensor_scatter_nd_update или Variable.

Данные: tf.data

ds = tf.data.Dataset.from_tensor_slices((X, y))
ds = (ds.shuffle(10_000, seed=42, reshuffle_each_iteration=True)
        .map(preprocess, num_parallel_calls=tf.data.AUTOTUNE)
        .batch(64, drop_remainder=False)
        .cache()                                       # кэш после дорогих преобразований
        .prefetch(tf.data.AUTOTUNE))                   # подготовка следующего батча параллельно с обучением
train_ds = keras.utils.image_dataset_from_directory("data/train", image_size=(224, 224), batch_size=32, validation_split=0.2, subset="training", seed=1)
text_ds = keras.utils.text_dataset_from_directory("texts/")
tf.data.TextLineDataset("a.txt"); tf.data.TFRecordDataset("a.tfrecord"); tf.data.experimental.make_csv_dataset("a.csv", 32, label_name="y")

Порядок: shuffle → map → batch → prefetch. Конвейер данных часто узкое место: проверьте загрузку GPU.

Модель: Sequential

model = keras.Sequential([
    keras.layers.Input(shape=(10,)),
    keras.layers.Dense(64, activation="relu"),
    keras.layers.Dropout(0.2),
    keras.layers.Dense(3, activation="softmax"),
])
model.summary()
model.compile(optimizer=keras.optimizers.Adam(1e-3), loss="sparse_categorical_crossentropy", metrics=["accuracy"])
history = model.fit(train_ds, epochs=20, validation_data=val_ds,
    callbacks=[keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True),
               keras.callbacks.ModelCheckpoint("best.keras", save_best_only=True),
               keras.callbacks.TensorBoard("logs")])
model.evaluate(test_ds); model.predict(X_new)

Подробно о слоях, Functional API и transfer learning см. шпаргалку «Keras».

Functional API и подклассы

inp = keras.Input(shape=(64,)); x = keras.layers.Dense(128, activation="relu")(inp); out = keras.layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inp, out)

class MyModel(keras.Model):
    def __init__(self):
        super().__init__(); self.d1 = keras.layers.Dense(64, activation="relu"); self.d2 = keras.layers.Dense(10)
    def call(self, x, training=False): return self.d2(self.d1(x))

Кастомный шаг обучения (GradientTape)

loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True)
opt = keras.optimizers.Adam(1e-3)

@tf.function                                            # компиляция в граф: быстрее и переносимо
def train_step(x, y):
    with tf.GradientTape() as tape:
        logits = model(x, training=True)
        loss = loss_fn(y, logits)
    grads = tape.gradient(loss, model.trainable_variables)
    opt.apply_gradients(zip(grads, model.trainable_variables))
    return loss

for epoch in range(epochs):
    for xb, yb in train_ds: loss = train_step(xb, yb)

Метод train_step можно переопределить в подклассе keras.Model, оставив fit(). Правила @tf.function: используйте тензоры и tf.* операции, избегайте побочных эффектов Python внутри (печать выполнится при трассировке), не создавайте Variable при каждом вызове; tf.print вместо print; следите за ретрассировкой (разные формы и типы аргументов).

Потери, метрики, оптимизаторы

Задача Потеря
Бинарная binary_crossentropy
Многоклассовая (целые метки) sparse_categorical_crossentropy
Многоклассовая (one-hot) categorical_crossentropy
Регрессия mse, mae, huber

Метрики: accuracy, AUC, Precision, Recall, MeanAbsoluteError. Оптимизаторы: Adam, AdamW, SGD(momentum), RMSprop. Скорость обучения: keras.optimizers.schedules.CosineDecay, ExponentialDecay; колбэки ReduceLROnPlateau, LearningRateScheduler. Смешанная точность: keras.mixed_precision.set_global_policy("mixed_float16").

Сохранение и загрузка

model.save("model.keras")                             # современный формат Keras (архитектура + веса + оптимизатор)
model = keras.models.load_model("model.keras")
model.save_weights("w.weights.h5"); model.load_weights("w.weights.h5")
model.export("saved_model_dir")                       # SavedModel для сервинга и конвертации
loaded = tf.saved_model.load("saved_model_dir"); loaded.signatures["serving_default"]

Кастомные слои и функции требуют регистрации (@keras.saving.register_keras_serializable()) или custom_objects. Формат .h5 устарел.

Развёртывание

Куда Инструмент
Сервер, REST и gRPC TensorFlow Serving (docker run -p 8501:8501 -v $PWD/saved:/models/m -e MODEL_NAME=m tensorflow/serving)
Мобильные, встраиваемые TensorFlow Lite: tf.lite.TFLiteConverter.from_saved_model(d), квантование (Optimize.DEFAULT), delegates (GPU, NNAPI, Core ML)
Браузер, Node TensorFlow.js: tensorflowjs_converter
Обмен между фреймворками ONNX (tf2onnx)
Пайплайны MLOps TFX, Vertex AI, Kubeflow
Предобработка в графе keras.layers.Rescaling, TextVectorization, Normalization внутри модели

Кладите предобработку внутрь модели, чтобы клиент и обучение не расходились.

Распределённое обучение и GPU

strategy = tf.distribute.MirroredStrategy()            # несколько GPU на одной машине
with strategy.scope():
    model = build_model(); model.compile(...)
# MultiWorkerMirroredStrategy (несколько машин), TPUStrategy
gpus = tf.config.list_physical_devices("GPU")
for g in gpus: tf.config.experimental.set_memory_growth(g, True)         # не занимать всю память сразу

Профилирование: tf.profiler, TensorBoard Profiler.

TensorBoard

tensorboard --logdir logs          # http://localhost:6006: кривые, граф, гистограммы весов, профиль, эмбеддинги
writer = tf.summary.create_file_writer("logs/run1")
with writer.as_default(): tf.summary.scalar("loss", loss, step=step)

Типичные проблемы

Симптом Причина и действия
OOM when allocating tensor уменьшите батч, mixed_float16, set_memory_growth, меньше модель
Потеря nan слишком большой lr, нет нормализации входов, log(0), clipnorm в оптимизаторе
Потеря не падает неверная активация выхода и функция потери (from_logits), метки не того формата, малый lr
Форма (None, ...) и ошибки размерности проверьте model.summary() и формы данных ds.element_spec
Постоянная ретрассировка @tf.function передаются Python-числа и меняющиеся формы: используйте тензоры и input_signature
Медленное обучение при простое GPU узкое место tf.data: num_parallel_calls, prefetch, cache, TFRecord
Предупреждения про версии CUDA и cuDNN подберите версии под выпуск TF (таблица на tensorflow.org)
Результат отличается между запусками keras.utils.set_random_seed(42), tf.config.experimental.enable_op_determinism()

TensorFlow или PyTorch

TensorFlow силён в промышленном развёртывании (Serving, Lite, JS, TFX) и мобильных устройствах. PyTorch преобладает в исследованиях и открытых моделях. Keras 3 работает поверх TensorFlow, PyTorch и JAX: один код, выбор бэкенда через KERAS_BACKEND.