1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/Python_Ai_Road-eat_tensorflow2_in_30_days

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
5-7,优化器optimizers.md 10 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 03.12.2024 15:14 374a95e

5-7, оптимизаторы

В мире машинного обучения есть группа алхимиков, их повседневная жизнь заключается в следующем:

Берут ингредиенты (данные), строят алхимические печи (модели), разжигают шесть видов истинного огня (алгоритмы оптимизации) и затем машут веером в ожидании, пока эликсир будет готов.

Однако любой, кто когда-либо был поваром, знает, что из одних и тех же ингредиентов, по одному и тому же рецепту, но при разной температуре получаются совершенно разные вкусы. Если температура слишком низкая, то блюдо не доварится, если слишком высокая — подгорит, а если температура неравномерная, то получится наполовину готовое блюдо.

То же самое и с машинным обучением, выбор алгоритма оптимизации модели напрямую влияет на производительность конечной модели. Иногда плохие результаты связаны не с характеристиками или дизайном модели, а именно с алгоритмом оптимизации.

Алгоритмы оптимизации глубокого обучения, вероятно, прошли путь развития от SGD -> SGDM -> NAG -> Adagrad -> Adadelta(RMSprop) -> Adam -> Nadam.

Подробнее см. в статье «Понимание различий и сходств между SGD/AdaGrad/Adam с помощью одной структуры».

Для начинающих алхимиков достаточно просто использовать Adam с его параметрами по умолчанию.

Некоторые алхимики, любящие писать статьи, могут предпочесть сначала использовать Adam для быстрого снижения показателей, а затем перейти на SGD и точно настроить параметры оптимизатора для получения лучших результатов.

Кроме того, существуют передовые алгоритмы оптимизации, которые, как утверждается, работают лучше, чем Adam, например, LazyAdam, Look-ahead, RAdam, Ranger и другие.

Один, использование оптимизаторов

Оптимизаторы в основном используют метод apply_gradients для передачи переменных и соответствующих градиентов для итеративной обработки заданных переменных или непосредственно используют метод minimize для итерационной оптимизации целевой функции.

Конечно, более распространённым является использование оптимизатора при компиляции путём передачи его в keras Model, и вызов model.fit реализует итеративную оптимизацию Loss.

При инициализации оптимизатора создаётся переменная optimier.iterations для записи количества итераций. Поэтому, как и tf.Variable, оптимизатор обычно необходимо создавать вне @tf.function.

import tensorflow as tf
import numpy as np

# Печатаем разделительную линию времени
@tf.function
def printbar():
    ts = tf.timestamp()
    today_ts = ts % (24 * 60 * 60)

    hour = tf.cast(today_ts // 3600 + 8, tf.int32) % tf.constant(24)
    minute = tf.cast((today_ts % 3600) // 60, tf.int32)
    second = tf.cast(tf.floor(today_ts % 60), tf.int32)

    def timeformat(m):
        if tf.strings.length(tf.strings.format("{}", m)) == 1:
            return (tf.strings.format("0{}", m))
        else:
            return (tf.strings.format("{}", m))

    timestring = tf.strings.join([timeformat(hour), timeformat(minute),
                                timeformat(second)], separator=":")
    tf.print("==========" * 8, end="")
    tf.print(timestring)

# Находим минимальное значение f(x) = a*x**2 + b*x + c

# Используем optimizer.apply_gradients

x = tf.Variable(0.0, name="x", dtype=tf.float32)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)

@tf.function
def minimizef():
    a = tf.constant(1.0)
    b = tf.constant(-2.0)
    c = tf.constant(1.0)

    while tf.constant(True):
        with tf.GradientTape() as tape:
            y = a * tf.pow(x, 2) + b * x + c
        dy_dx = tape.gradient(y, x)
        optimizer.apply_gradients(grads_and_vars=[(dy_dx, x)])

        # Условия завершения итерации
        if tf.abs(dy_dx) < tf.constant(0.00001):
            break

        if tf.math.mod(optimizer.iterations, 100) == 0:
            printbar()
            tf.print("step = ", optimizer.iterations)
            tf.print("x = ", x)
            tf.print("")

    y = a * tf.pow(x, 2) + b * x + c
    return y

tf.print("y =", minimizef())
tf.print("x =", x)
# Находим минимальное значение f(x) = a*x**2 + b*x + c

# Используем optimizer.minimize

x = tf.Variable(0.0, name="x", dtype=tf.float32)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)

def f():
    a = tf.constant(1.0)
    b = tf.constant(-2.0)
    c = tf.constant(1.0)
    y = a * tf.pow(x, 2) + b * x + c
    return(y)

@tf.function
def train(epoch=1000):
    for _ in tf.range(epoch):
        optimizer.minimize(f, [x])
    tf.print("epoch = ", optimizer.iterations)
    return(f())

train(1000)
tf.print("y = ", f())
tf.print("x = ", x)
# Находим минимальное значение f(x) = a*x**2 + b*x + c
# Используем model.fit

tf.keras.backend.clear_session()

class FakeModel(tf.keras.models.Model):
    def __init__(self, a, b, c):
        super(FakeModel, self).__init__()
        self.a = a
        self.b = b
        self.c = c

    def build(self):
        self.x = tf.Variable(0.0, name="x")
        self.built = True

    def call(self, features):
        loss = self.a * (self.x)**2 + self.b * self.x + self.c
        return (tf.ones_like(features) * loss)

def myloss(y_true, y_pred):
    return tf.reduce_mean(y_pred)

model = FakeModel(tf.constant(1.0), tf.constant(-2.0), tf.constant(1.0))

model.build()
model.summary()

model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.01), loss=myloss)
history = model.fit(tf.zeros((100, 2)),
                    tf.ones(100), batch_size=1, epochs=10)  # Итерация 1000 раз

tf.print("x=", model.x)
tf.print("loss=", model(tf.constant(0.0)))

Два, встроенные оптимизаторы

Алгоритмы оптимизации глубокого обучения, вероятно, прошли путь развития от SGD -> SGDM -> NAG -> Adagrad -> Adadelta(RMSprop) -> Adam -> Nadam. В подмодуле keras.optimizers в основном есть реализации соответствующих классов.

  • SGD, параметры по умолчанию — это чистый SGD. Если установить параметр momentum не равным 0, фактически получится SGDM, учитывающий первый порядок импульса. Установка nesterov в значение True приводит к NAG, то есть Nesterov Accelerated Gradient, который при вычислении градиента вычисляет градиент позиции, продвигаясь на шаг вперёд.

  • Adagrad, учитывает второй порядок импульса и имеет разные скорости обучения для разных параметров, то есть адаптивную скорость обучения. Недостатком является то, что скорость обучения монотонно убывает, и в конце концов скорость обучения может стать слишком медленной или обучение может прекратиться досрочно.

  • RMSprop, учитывает второй порядок импульса и имеет разные скорости обучения для разных параметров, то есть адаптивную скорость обучения, оптимизированную по сравнению с Adagrad путём экспоненциального сглаживания, которое учитывает только второй порядок импульса в определённом окне.

  • Adadelta, учитывает второй порядок импульса, аналогично RMSprop, но более сложен и обладает большей адаптивностью.

  • Adam, одновременно учитывает первый и второй порядки импульса, можно рассматривать как дальнейшее рассмотрение первого порядка импульса на основе RMSprop.

  • Nadam, на основе Adam дополнительно рассматривает Nesterov Acceleration.

Если у вас есть вопросы по содержанию этой книги, вы можете оставить комментарий в общедоступной учётной записи «Алгоритмная кухня». Автор ответит по мере возможности.

Вы также можете отправить сообщение через интерфейс общедоступной учётной записи, ответив ключевым словом: присоединиться к группе обсуждения читателей.



Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/Python_Ai_Road-eat_tensorflow2_in_30_days.git
git@api.gitlife.ru:oschina-mirror/Python_Ai_Road-eat_tensorflow2_in_30_days.git
oschina-mirror
Python_Ai_Road-eat_tensorflow2_in_30_days
Python_Ai_Road-eat_tensorflow2_in_30_days
master