Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шолле Ф. - Глубокое обучение на Python (Библиотека программиста) - 2023.pdf
Скачиваний:
6
Добавлен:
07.04.2024
Размер:
11.34 Mб
Скачать

2.5. Оглядываясь на первый пример    99

Генератор пакетов

Нам.также.нужен.механизм,.который.поможет.выполнять.итерации.по.пакетам. и.изображениям.из.набора.MNIST..Реализуется.такой.механизм.просто:

import math

class BatchGenerator:

def __init__(self, images, labels, batch_size=128): assert len(images) == len(labels)

self.index = 0 self.images = images self.labels = labels

self.batch_size = batch_size

self.num_batches = math.ceil(len(images) / batch_size)

def next(self):

images = self.images[self.index : self.index + self.batch_size] labels = self.labels[self.index : self.index + self.batch_size] self.index += self.batch_size

return images, labels

2.5.2. Выполнение одного этапа обучения

Этап.обучения.—.самая.сложная.часть.процесса..Нам.требуется.скорректировать. веса.модели.после.обучения.на.одном.пакете.данных..Для.этого.нужно.сделать. следующее.

1.. Вычислить.прогнозы.для.изображений.в.пакете.

2.. Найти.значения.потерь.для.этих.прогнозов.с.учетом.фактических.меток. 3.. Вычислить.градиент.потерь.с.учетом.весов.модели.

4.. Скорректировать.веса.на.небольшую.величину.в.направлении,.противоположном.градиенту.

Для.вычисления.градиента.используем.объект.GradientTape .из.библиотеки. TensorFlow,.который.был.представлен.в.пункте.2.4.4:

def one_training_step(model, images_batch, labels_batch):

 

with tf.GradientTape() as tape:

 

 

 

 

 

predictions = model(images_batch)

 

 

 

per_sample_losses = tf.keras.losses.sparse_categorical_crossentropy(

 

 

 

labels_batch, predictions)

 

 

 

average_loss = tf.reduce_mean(per_sample_losses)

 

 

 

gradients = tape.gradient(average_loss, model.weights)

 

Выполнить

 

update_weights(gradients, model.weights)

 

«прямой проход»

 

return average_loss

 

 

 

Вычислить градиент потерь с учетом

(вычислить прогноз

 

 

Скорректировать веса с учетом

весов. Результат gradients — это список,

модели в контексте

градиентов (эту функцию мы

каждый элемент которого соответствует

GradientTape)

определим ниже)

весу в списке model.weights

 

 

100    Глава 2. Математические основы нейронных сетей

Как.вы.уже.знаете,.цель.шага.«корректировки.весов».(представленного.в.пре- дыдущем.листинге.функцией.update_weights).состоит.в.том,.чтобы.«чуть-чуть». скорректировать.веса.в.направлении,.которое.уменьшит.потери.в.этом.пакете..

Величина.корректировки.определяется.«скоростью.обучения»,.обычно.неболь- шой..Самый.простой.способ.реализовать.функцию.update_weights .—.вычесть. gradient .* .learning_rate .из.каждого.веса:

learning_rate = 1e-3

def update_weights(gradients, weights): for g, w in zip(gradients, weights):

w.assign_sub(g * learning_rate)

assign_sub — это эквивалент оператора –= для переменных TensorFlow

На.практике.вам.редко.придется.задумываться.о.реализации.корректировки. вручную,.потому.что.обычно.для.этого.используется.экземпляр.оптимизатора. из.Keras,.например:

from tensorflow.keras import optimizers

optimizer = optimizers.SGD(learning_rate=1e-3)

def update_weights(gradients, weights): optimizer.apply_gradients(zip(gradients, weights))

Теперь,.покончив.с.этапом.обучения.на.одном.пакете,.перейдем.к.реализации. целой.эпохи.обучения.

2.5.3. Полный цикл обучения

Эпоха.обучения.просто.повторяет.шаг.обучения.для.каждого.пакета.обучающих. данных,.а.полный.цикл.обучения.—.это.повторение.одной.эпохи:

def fit(model, images, labels, epochs, batch_size=128): for epoch_counter in range(epochs):

print(f"Epoch {epoch_counter}") batch_generator = BatchGenerator(images, labels)

for batch_counter in range(batch_generator.num_batches): images_batch, labels_batch = batch_generator.next()

loss = one_training_step(model, images_batch, labels_batch) if batch_counter % 100 == 0:

print(f"loss at batch {batch_counter}: {loss:.2f}")

Давайте.протестируем.получившееся:

from tensorflow.keras.datasets import mnist

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_images = train_images.reshape((60000, 28 * 28)) train_images = train_images.astype("float32") / 255