TensorFlow — это open-source фреймворк машинного обучения от Google, который используется во всём: от распознавания изображений до обработки естественного языка. Понимание нейронных сетей стало необходимым для современных разработчиков по мере того, как возможности AI интегрируются во всё большее число приложений. В этом руководстве рассматривается создание практических нейронных сетей с TensorFlow с точки зрения senior-разработчика.
Почему TensorFlow
TensorFlow хорош тем, что:
- Готов к production: масштабируется от ноутбука до дата-центра
- Экосистема: Keras, TensorBoard, TFLite, TF.js
- Поддержка аппаратного ускорения: ускорение на CPU, GPU, TPU
- Варианты развёртывания: сервер, мобильные устройства, браузер, edge-устройства
- Сообщество: обширная документация и примеры
Настройка
Установка
# Базовая установка
pip install tensorflow
# С поддержкой GPU (требуется CUDA)
pip install tensorflow[and-cuda]
# Для Mac на Apple Silicon
pip install tensorflow-macos tensorflow-metal
# Дополнительные полезные пакеты
pip install pandas matplotlib scikit-learn
Проверка установки
import tensorflow as tf
print(f"TensorFlow version: {tf.__version__}")
print(f"GPU available: {tf.config.list_physical_devices('GPU')}")
Настройка GPU (опционально)
Для NVIDIA GPU:
# Установить CUDA Toolkit (Ubuntu)
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb
sudo apt update
sudo apt install cuda-toolkit-12-0
# Проверка
nvidia-smi
Основы нейронных сетей
Ключевые понятия
- Нейроны: базовые единицы, применяющие веса, смещение (bias) и активацию
- Слои: наборы нейронов
- Функции активации: нелинейные преобразования (ReLU, sigmoid)
- Функция потерь (loss): измеряет ошибку предсказания
- Оптимизатор (optimizer): обновляет веса, чтобы минимизировать loss
- Эпохи (epochs): полные проходы по обучающим данным
Простая структура модели
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
# Sequential-модель: слои последовательно «стекуются»
model = keras.Sequential([
layers.Dense(128, activation='relu', input_shape=(784,)),
layers.Dropout(0.2),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')
])
# Compile: настройка обучения
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
# Summary
model.summary()
Классификация изображений (MNIST)
Загрузка и подготовка данных
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
# Загрузить датасет MNIST
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# Нормализовать значения пикселей до 0–1
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
# Изменить форму для dense-слоёв: (28, 28) -> (784,)
x_train_flat = x_train.reshape(-1, 784)
x_test_flat = x_test.reshape(-1, 784)
print(f"Training samples: {len(x_train)}")
print(f"Test samples: {len(x_test)}")
print(f"Image shape: {x_train[0].shape}")
Построение и обучение модели
# Создать модель
model = keras.Sequential([
layers.Dense(256, activation='relu', input_shape=(784,)),
layers.Dropout(0.3),
layers.Dense(128, activation='relu'),
layers.Dropout(0.3),
layers.Dense(10, activation='softmax')
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
# Обучить
history = model.fit(
x_train_flat, y_train,
epochs=10,
batch_size=128,
validation_split=0.1,
verbose=1
)
# Оценить
test_loss, test_accuracy = model.evaluate(x_test_flat, y_test)
print(f"Test accuracy: {test_accuracy:.4f}")
Построение графика истории обучения
plt.figure(figsize=(12, 4))
# Accuracy
plt.subplot(1, 2, 1)
plt.plot(history.history['accuracy'], label='Training')
plt.plot(history.history['val_accuracy'], label='Validation')
plt.title('Model Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
# Loss
plt.subplot(1, 2, 2)
plt.plot(history.history['loss'], label='Training')
plt.plot(history.history['val_loss'], label='Validation')
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.tight_layout()
plt.savefig('training_history.png')
plt.show()
Свёрточные нейронные сети (CNN)
Для данных изображений CNN превосходят полносвязные сети:
# Изменить форму для CNN: добавить размерность канала
x_train_cnn = x_train.reshape(-1, 28, 28, 1)
x_test_cnn = x_test.reshape(-1, 28, 28, 1)
# Собрать CNN
cnn_model = keras.Sequential([
# Свёрточные слои
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
# Dense-слои
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dropout(0.5),
layers.Dense(10, activation='softmax')
])
cnn_model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
cnn_model.fit(
x_train_cnn, y_train,
epochs=5,
batch_size=64,
validation_split=0.1
)
# CNN обычно достигают точности 99%+ на MNIST
cnn_model.evaluate(x_test_cnn, y_test)
Transfer learning
Используйте предварительно обученные модели, чтобы получать лучшие результаты при меньшем объёме данных:
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# Загрузить предварительно обученную модель (без верхнего классификационного слоя)
base_model = MobileNetV2(
weights='imagenet',
include_top=False,
input_shape=(224, 224, 3)
)
# Заморозить веса базовой модели
base_model.trainable = False
# Добавить пользовательскую классификационную «голову»
model = keras.Sequential([
base_model,
layers.GlobalAveragePooling2D(),
layers.Dense(256, activation='relu'),
layers.Dropout(0.5),
layers.Dense(10, activation='softmax') # 10 классов
])
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=0.001),
loss='categorical_crossentropy',
metrics=['accuracy']
)
# Аугментация данных для обучения
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True,
validation_split=0.2
)
# Загрузить собственные изображения
train_generator = train_datagen.flow_from_directory(
'data/train',
target_size=(224, 224),
batch_size=32,
class_mode='categorical',
subset='training'
)
validation_generator = train_datagen.flow_from_directory(
'data/train',
target_size=(224, 224),
batch_size=32,
class_mode='categorical',
subset='validation'
)
# Обучить
model.fit(
train_generator,
epochs=10,
validation_data=validation_generator
)
Сохранение и загрузка моделей
# Сохранить модель целиком
model.save('my_model.keras')
# Загрузить модель
loaded_model = keras.models.load_model('my_model.keras')
# Сохранить только веса
model.save_weights('my_model_weights.weights.h5')
# Загрузить веса
model.load_weights('my_model_weights.weights.h5')
# Экспорт для TensorFlow Serving
model.export('saved_model_dir')
# Конвертировать в TensorFlow Lite (mobile/edge)
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
with open('model.tflite', 'wb') as f:
f.write(tflite_model)
Выполнение предсказаний
# Одиночное предсказание
image = x_test[0:1] # Сохранить batch-размерность
prediction = model.predict(image)
predicted_class = np.argmax(prediction[0])
confidence = prediction[0][predicted_class]
print(f"Predicted: {predicted_class}, Confidence: {confidence:.2%}")
# Пакетное предсказание
predictions = model.predict(x_test[:100])
predicted_classes = np.argmax(predictions, axis=1)
# Оценить предсказания
from sklearn.metrics import classification_report, confusion_matrix
print(classification_report(y_test[:100], predicted_classes))
Пользовательский цикл обучения
Для большего контроля:
# Пользовательское обучение
model = keras.Sequential([
layers.Dense(128, activation='relu'),
layers.Dense(10, activation='softmax')
])
loss_fn = keras.losses.SparseCategoricalCrossentropy()
optimizer = keras.optimizers.Adam()
# Метрики обучения
train_loss = keras.metrics.Mean()
train_accuracy = keras.metrics.SparseCategoricalAccuracy()
@tf.function
def train_step(x, y):
with tf.GradientTape() as tape:
predictions = model(x, training=True)
loss = loss_fn(y, predictions)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
train_loss.update_state(loss)
train_accuracy.update_state(y, predictions)
# Цикл обучения
epochs = 10
batch_size = 32
dataset = tf.data.Dataset.from_tensor_slices((x_train_flat, y_train))
dataset = dataset.shuffle(10000).batch(batch_size)
for epoch in range(epochs):
train_loss.reset_states()
train_accuracy.reset_states()
for x_batch, y_batch in dataset:
train_step(x_batch, y_batch)
print(f"Epoch {epoch + 1}: Loss = {train_loss.result():.4f}, "
f"Accuracy = {train_accuracy.result():.4f}")
TensorBoard для визуализации
from tensorflow.keras.callbacks import TensorBoard
import datetime
# Создать директорию логов
log_dir = "logs/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = TensorBoard(
log_dir=log_dir,
histogram_freq=1,
write_graph=True,
write_images=True
)
# Обучить с callback
model.fit(
x_train_flat, y_train,
epochs=10,
validation_split=0.1,
callbacks=[tensorboard_callback]
)
# Запустить TensorBoard
# tensorboard --logdir logs/
Практические советы
Предотвращение переобучения
# Ранняя остановка
early_stop = keras.callbacks.EarlyStopping(
monitor='val_loss',
patience=3,
restore_best_weights=True
)
# Снижение learning rate
reduce_lr = keras.callbacks.ReduceLROnPlateau(
monitor='val_loss',
factor=0.2,
patience=2,
min_lr=0.0001
)
model.fit(
x_train, y_train,
epochs=100,
validation_split=0.2,
callbacks=[early_stop, reduce_lr]
)
Checkpoint модели
checkpoint = keras.callbacks.ModelCheckpoint(
'best_model.keras',
monitor='val_accuracy',
save_best_only=True,
mode='max'
)
Ключевые выводы
- Начинайте с простого: полносвязные сети перед CNN
- Нормализуйте входные данные: масштабируйте до 0–1 или стандартизируйте
- Используйте validation split: отслеживайте переобучение
- Transfer learning: предварительно обученные модели для задач с изображениями
- GPU-ускорение: необходимо для более крупных моделей
- Сохраняйте checkpoints: не теряйте прогресс обучения
Нейронные сети мощны, но требуют экспериментов — начните с рабочих примеров и дальше итеративно улучшайте.