<kaggle_start><code># **Импорт зависимостей**
from tensorflow.keras.datasets import cifar10
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.layers import (
    Dropout,
    BatchNormalization,
    SpatialDropout2D,
    GaussianDropout,
)
from tensorflow.keras.layers import Conv2D, MaxPooling2D, AveragePooling2D
from tensorflow.keras.callbacks import (
    EarlyStopping,
    ModelCheckpoint,
    ReduceLROnPlateau,
    LearningRateScheduler,
    CSVLogger,
    LambdaCallback,
    TerminateOnNaN,
)
from tensorflow.keras.preprocessing import image
import matplotlib.pyplot as plt
from tensorflow.keras import utils

(x_train, y_train), (x_test, y_test) = cifar10.load_data()
classes = [
    "самолет",
    "автомобиль",
    "птица",
    "кот",
    "олень",
    "собака",
    "лягушка",
    "лошадь",
    "корабль",
    "грузовик",
]

# **Установка статических параметров**
batch_size = 200
nb_classes = 10
nb_epoch = 40
IMG_SIZE = [32, 32]
img_channels = 3

# **Нормализация данных**
x_train = x_train.astype("float32")
x_test = x_test.astype("float32")
x_train /= 255
x_test /= 255
y_train = utils.to_categorical(y_train, nb_classes)
y_test = utils.to_categorical(y_test, nb_classes)


# **Функция для получения последовательной модели для экспериментов с keras callbacks**
def get_model():
    model = Sequential()
    #
    model.add(
        Conv2D(
            filters=32,
            kernel_size=(3, 3),
            padding="same",
            input_shape=(*IMG_SIZE, img_channels),
            activation="relu",
        )
    )
    #
    model.add(Conv2D(filters=32, kernel_size=(3, 3), padding="same", activation="relu"))
    #
    model.add(AveragePooling2D(pool_size=(2, 2)))
    #
    model.add(BatchNormalization())
    #
    model.add(GaussianDropout(0.25))
    #
    model.add(Conv2D(filters=64, kernel_size=(3, 3), padding="same", activation="relu"))
    #
    model.add(Conv2D(filters=64, kernel_size=(3, 3), padding="same", activation="relu"))
    #
    model.add(AveragePooling2D(pool_size=(2, 2)))
    #
    model.add(Conv2D(filters=64, kernel_size=(4, 4), padding="same", activation="elu"))
    #
    model.add(Conv2D(filters=128, kernel_size=(3, 4), activation="relu"))
    #
    model.add(BatchNormalization())
    #
    model.add(GaussianDropout(0.4))
    #
    model.add(Flatten())
    #
    model.add(Dense(1024, activation="relu"))
    #
    model.add(Dropout(0.6))
    #
    model.add(Dense(nb_classes, activation="softmax"))
    #
    model.compile(
        loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
    )
    return model


# **Вспомогательная функция для представления графиков метрик**
def draw_model_plot(history, metric):
    plt.plot(history[metric], label="{} на обучающем наборе".format(metric))
    plt.plot(
        history["val_{}".format(metric)],
        label="val_{} на проверочном наборе".format(metric),
    )
    plt.xlabel("Эпоха обучения")
    plt.ylabel(metric)
    plt.legend()
    plt.show()


# Имитация жизненного цикла модели для экспериментов
def model_life_cycle(callback_list, verbose=1):
    model = get_model()
    history = model.fit(
        x=x_train,
        y=y_train,
        batch_size=batch_size,
        epochs=nb_epoch,
        callbacks=callback_list,
        validation_split=0.1,
        verbose=verbose,
    )
    #
    scores = model.evaluate(x_test, y_test, verbose=0)
    print("Evaluate val_accuracy: {}".format(scores[1] * 100))
    #
    draw_model_plot(history.history, "accuracy")
    draw_model_plot(history.history, "loss")


# **Callback** – набор функций, применяемых в определенные моменты во время процедуры обучения. Вы можете использовать функции callback чтобы получить информацию о внутреннем состоянии модели в процессе обучения. Нужно передавать список callback’ов (именованным аргументом callbacks) методу .fit() Sequential или Model классов. Подходящие методы callback будут вызваны на каждой стадии обучения.
# **1) ModelCheckpoint**
# ModelCheckpoint используется для сохранения модели или весов (в файле) через некоторый интервал, чтобы модель или веса можно было загрузить позже, чтобы продолжить обучение из сохраненного состояния
# **Аргументы:**
# — filepath: строка, путь сохранения модели
# — monitor: параметр для мониторинга
# — verbose: режим отображения, 0 или 1
# — save_best_only: если save_best_only=True, если результат текущей эпохи хуже предыдущей, он не будет сохранен.
# — save_weights_only: если True, тогда будут сохраняться только веса модели (model.save_weights(filepath)), в противном случае будет сохраняться вся модель (model.save(filepath)).
# — mode: один из {auto, min, max}. Если save_best_only=True, решение о перезаписи текущего файла будет приниматься в зависимости от уменьшения/увеличения параметра мониторинга. Для val_acc, необходим max, для val_loss необходим min. В auto режиме, mode выбирается в зависимости от имени monitor.
# — period: Интервал (число эпох) между сохранениями.
modelCheckpoint = ModelCheckpoint(
    filepath="best_model.h5",
    monitor="val_loss",
    mode="min",
    save_best_only=True,
    verbose=1,
    period=1,
    save_weights_only=False,
)
model_life_cycle(callback_list=[modelCheckpoint], verbose=0)

# **2) EarlyStopping**
# Используется для прекращение обучения, когда параметр monitor перестает улучшаться
# **Аргументы:**
# — monitor: параметр для мониторинга
# — min_delta: минимальное значение изменения величины monitor, расцениваемое как улучшение, то есть, если абсолютное изменение меньше min_delta, то улучшение не засчитывается
# — patience: число эпох, за которые величина monitor не улучшается, после которых обучение будет остановлено. Проверочные величины могут производиться не после каждой эпохи если validation_freq (model.fit(validation_freq=5)) больше единицы.
# — verbose: режим отображения, 0 или 1.
# — mode: один из {auto, min, max}. В режиме min, обучение остановится когда величина monitor перестанет уменьшаться; в режиме max, обучение остановится когда величина monitor перестанет увеличиваться; в режиме auto, mode выбирается в зависимости от имени monitor.
# — baseline: значение, которое должна достичь величина monitor, обучение прекращается по достижению этой величины[](http://)
# — restore_best_weights: восстанавливать ли веса модели с эпохи с лучшем значением параметра monitor. Если False, веса модели будут загружены из последней шага обучения.
earlyStopping = EarlyStopping(
    monitor="val_loss",
    min_delta=0,
    patience=3,
    verbose=1,
    restore_best_weights=True,
    mode="min",
)
model_life_cycle(callback_list=[earlyStopping], verbose=0)

# **3) LearningRateScheduler**
# Используется для регулировки скорости обучения с течением времени, используя schedule, эта функция возвращает желаемую скорость обучения. Входной параметр — индекс эпохи.
# **Аргументы:**
# — schedule: функция, принимающая индекс эпохи (integer, отсчет с нуля) и текущую скорость обучения, и возвращающая новую скорость обучения (float).
# — verbose: int. 0: «тихий» режим, 1: выводить сообщения
LR_START = 0.00001
LR_MAX = 0.0001
LR_MIN = 0.00001
LR_RAMPUP_EPOCHS = 10
LR_SUSTAIN_EPOCHS = 0
LR_EXP_DECAY = 0.8


def lrfn(epoch):
    if epoch < LR_RAMPUP_EPOCHS:
        lr = (LR_MAX - LR_START) / LR_RAMPUP_EPOCHS * epoch + LR_START
    elif epoch < LR_RAMPUP_EPOCHS + LR_SUSTAIN_EPOCHS:
        lr = LR_MAX
    else:
        lr = (LR_MAX - LR_MIN) * LR_EXP_DECAY ** (
            epoch - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS
        ) + LR_MIN
    return lr


rng = [i for i in range(nb_epoch)]
y = [lrfn(x) for x in rng]
plt.plot(rng, y)
plt.xlabel("Эпоха обучения")
plt.ylabel("Скорость обучения")
plt.show()
learningRateScheduler = LearningRateScheduler(schedule=lrfn, verbose=1)
model_life_cycle(callback_list=[learningRateScheduler], verbose=0)


# **4) ReduceLROnPlateau**
# Используется для изменения скорости обучения в factor раз, когда метрика перестала улучшаться patience эпох
# **Аргументы:**
# — monitor:  параметр для мониторинга
# — factor: коэффициент уменьшения скорости обучения. new_lr = lr * factor
# — patience: число эпох, за которые величина monitor не улучшается, после которых обучение будет остановлено. Проверочные величины могут производиться не после каждой эпохи если validation_freq (model.fit(validation_freq=5)) больше единицы.
# — verbose: int. 0: «тихий» режим, 1: выводить сообщения
# — mode: один из {auto, min, max}. В режиме min, скорость обучения уменьшится когда величина monitor перестанет уменьшаться; в режиме max, скорость обучения уменьшится когда величина monitor перестанет увеличиваться; в режиме auto, mode выбирается в зависимости от имени monitor.
# — min_delta: минимальное значение изменения величины monitor, расцениваемое как улучшение, то есть, если абсолютное изменение меньше min_delta, то улучшение не засчитывается
# — cooldown: число эпох после уменьшения скорости обучения, которые должны пройти, прежде чем стандартный процесс уменьшения возобновится.
# — min_lr: нижняя граница скорости обучения
#
reduceLROnPlateau = ReduceLROnPlateau(
    monitor="val_loss",
    factor=0.2,
    min_delta=0,
    patience=2,
    verbose=1,
    cooldown=1,
    mode="min",
)
model_life_cycle(callback_list=[reduceLROnPlateau], verbose=0)

# **5) CSVLogger**
# Callback, записывающий результаты эпох в csv файл
# **Аргументы:**
# — filename: имя csv файла (к примеру: ‘run/log.csv’)
# — separator: строка, используемая для разделения элементов в файле.
# — append: True: добавить к существующему файлу (если он существует). False: перезаписать существующий файл.
csvLogger = CSVLogger(filename="learning.csv", separator=",", append=False)
model_life_cycle(callback_list=[csvLogger])


# **6) LambdaCallback**
# Callback для создания простых пользовательских callback’ов «на лету»
# **Аргументы:**
# — on_epoch_begin: вызывается в начале каждой эпохи
# — on_epoch_end: вызывается в конце каждой эпохи
# — on_batch_begin: вызывается в начале каждого батча
# — on_batch_end: вызывается в конце каждого батча
# — on_train_begin: вызывается в начале обучения модели
# — on_train_end: вызывается в конце обучения модели
def foo(epochs, logs):
    """Любая пользовательская функция"""
    return


lambdaCallback = LambdaCallback(
    on_epoch_begin=foo,
    on_epoch_end=foo,
    on_batch_begin=foo,
    on_batch_end=foo,
    on_train_begin=lambda logs: print("on_train_begin"),
    on_train_end=lambda logs: print("on_train_end"),
)
model_life_cycle(callback_list=[lambdaCallback], verbose=0)
<|endoftext|>
[{"Id": 51143249, "ScriptId": 14026292, "ParentScriptVersionId": NaN, "ScriptLanguageId": 9, "AuthorUserId": 5783242, "CreationDate": "01/05/2021 14:43:28", "VersionNumber": 2.0, "Title": "Keras Callbacks_1", "EvaluationDate": "01/05/2021", "IsChange": true, "TotalLines": 388.0, "LinesInsertedFromPrevious": 8.0, "LinesChangedFromPrevious": 0.0, "LinesUnchangedFromPrevious": 380.0, "LinesInsertedFromFork": 367.0, "LinesDeletedFromFork": 131.0, "LinesChangedFromFork": 0.0, "LinesUnchangedFromFork": 21.0, "TotalVotes": 0}]
# **Импорт зависимостей**
from tensorflow.keras.datasets import cifar10
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.layers import (
    Dropout,
    BatchNormalization,
    SpatialDropout2D,
    GaussianDropout,
)
from tensorflow.keras.layers import Conv2D, MaxPooling2D, AveragePooling2D
from tensorflow.keras.callbacks import (
    EarlyStopping,
    ModelCheckpoint,
    ReduceLROnPlateau,
    LearningRateScheduler,
    CSVLogger,
    LambdaCallback,
    TerminateOnNaN,
)
from tensorflow.keras.preprocessing import image
import matplotlib.pyplot as plt
from tensorflow.keras import utils

(x_train, y_train), (x_test, y_test) = cifar10.load_data()
classes = [
    "самолет",
    "автомобиль",
    "птица",
    "кот",
    "олень",
    "собака",
    "лягушка",
    "лошадь",
    "корабль",
    "грузовик",
]

# **Установка статических параметров**
batch_size = 200
nb_classes = 10
nb_epoch = 40
IMG_SIZE = [32, 32]
img_channels = 3

# **Нормализация данных**
x_train = x_train.astype("float32")
x_test = x_test.astype("float32")
x_train /= 255
x_test /= 255
y_train = utils.to_categorical(y_train, nb_classes)
y_test = utils.to_categorical(y_test, nb_classes)


# **Функция для получения последовательной модели для экспериментов с keras callbacks**
def get_model():
    model = Sequential()
    #
    model.add(
        Conv2D(
            filters=32,
            kernel_size=(3, 3),
            padding="same",
            input_shape=(*IMG_SIZE, img_channels),
            activation="relu",
        )
    )
    #
    model.add(Conv2D(filters=32, kernel_size=(3, 3), padding="same", activation="relu"))
    #
    model.add(AveragePooling2D(pool_size=(2, 2)))
    #
    model.add(BatchNormalization())
    #
    model.add(GaussianDropout(0.25))
    #
    model.add(Conv2D(filters=64, kernel_size=(3, 3), padding="same", activation="relu"))
    #
    model.add(Conv2D(filters=64, kernel_size=(3, 3), padding="same", activation="relu"))
    #
    model.add(AveragePooling2D(pool_size=(2, 2)))
    #
    model.add(Conv2D(filters=64, kernel_size=(4, 4), padding="same", activation="elu"))
    #
    model.add(Conv2D(filters=128, kernel_size=(3, 4), activation="relu"))
    #
    model.add(BatchNormalization())
    #
    model.add(GaussianDropout(0.4))
    #
    model.add(Flatten())
    #
    model.add(Dense(1024, activation="relu"))
    #
    model.add(Dropout(0.6))
    #
    model.add(Dense(nb_classes, activation="softmax"))
    #
    model.compile(
        loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
    )
    return model


# **Вспомогательная функция для представления графиков метрик**
def draw_model_plot(history, metric):
    plt.plot(history[metric], label="{} на обучающем наборе".format(metric))
    plt.plot(
        history["val_{}".format(metric)],
        label="val_{} на проверочном наборе".format(metric),
    )
    plt.xlabel("Эпоха обучения")
    plt.ylabel(metric)
    plt.legend()
    plt.show()


# Имитация жизненного цикла модели для экспериментов
def model_life_cycle(callback_list, verbose=1):
    model = get_model()
    history = model.fit(
        x=x_train,
        y=y_train,
        batch_size=batch_size,
        epochs=nb_epoch,
        callbacks=callback_list,
        validation_split=0.1,
        verbose=verbose,
    )
    #
    scores = model.evaluate(x_test, y_test, verbose=0)
    print("Evaluate val_accuracy: {}".format(scores[1] * 100))
    #
    draw_model_plot(history.history, "accuracy")
    draw_model_plot(history.history, "loss")


# **Callback** – набор функций, применяемых в определенные моменты во время процедуры обучения. Вы можете использовать функции callback чтобы получить информацию о внутреннем состоянии модели в процессе обучения. Нужно передавать список callback’ов (именованным аргументом callbacks) методу .fit() Sequential или Model классов. Подходящие методы callback будут вызваны на каждой стадии обучения.
# **1) ModelCheckpoint**
# ModelCheckpoint используется для сохранения модели или весов (в файле) через некоторый интервал, чтобы модель или веса можно было загрузить позже, чтобы продолжить обучение из сохраненного состояния
# **Аргументы:**
# — filepath: строка, путь сохранения модели
# — monitor: параметр для мониторинга
# — verbose: режим отображения, 0 или 1
# — save_best_only: если save_best_only=True, если результат текущей эпохи хуже предыдущей, он не будет сохранен.
# — save_weights_only: если True, тогда будут сохраняться только веса модели (model.save_weights(filepath)), в противном случае будет сохраняться вся модель (model.save(filepath)).
# — mode: один из {auto, min, max}. Если save_best_only=True, решение о перезаписи текущего файла будет приниматься в зависимости от уменьшения/увеличения параметра мониторинга. Для val_acc, необходим max, для val_loss необходим min. В auto режиме, mode выбирается в зависимости от имени monitor.
# — period: Интервал (число эпох) между сохранениями.
modelCheckpoint = ModelCheckpoint(
    filepath="best_model.h5",
    monitor="val_loss",
    mode="min",
    save_best_only=True,
    verbose=1,
    period=1,
    save_weights_only=False,
)
model_life_cycle(callback_list=[modelCheckpoint], verbose=0)

# **2) EarlyStopping**
# Используется для прекращение обучения, когда параметр monitor перестает улучшаться
# **Аргументы:**
# — monitor: параметр для мониторинга
# — min_delta: минимальное значение изменения величины monitor, расцениваемое как улучшение, то есть, если абсолютное изменение меньше min_delta, то улучшение не засчитывается
# — patience: число эпох, за которые величина monitor не улучшается, после которых обучение будет остановлено. Проверочные величины могут производиться не после каждой эпохи если validation_freq (model.fit(validation_freq=5)) больше единицы.
# — verbose: режим отображения, 0 или 1.
# — mode: один из {auto, min, max}. В режиме min, обучение остановится когда величина monitor перестанет уменьшаться; в режиме max, обучение остановится когда величина monitor перестанет увеличиваться; в режиме auto, mode выбирается в зависимости от имени monitor.
# — baseline: значение, которое должна достичь величина monitor, обучение прекращается по достижению этой величины[](http://)
# — restore_best_weights: восстанавливать ли веса модели с эпохи с лучшем значением параметра monitor. Если False, веса модели будут загружены из последней шага обучения.
earlyStopping = EarlyStopping(
    monitor="val_loss",
    min_delta=0,
    patience=3,
    verbose=1,
    restore_best_weights=True,
    mode="min",
)
model_life_cycle(callback_list=[earlyStopping], verbose=0)

# **3) LearningRateScheduler**
# Используется для регулировки скорости обучения с течением времени, используя schedule, эта функция возвращает желаемую скорость обучения. Входной параметр — индекс эпохи.
# **Аргументы:**
# — schedule: функция, принимающая индекс эпохи (integer, отсчет с нуля) и текущую скорость обучения, и возвращающая новую скорость обучения (float).
# — verbose: int. 0: «тихий» режим, 1: выводить сообщения
LR_START = 0.00001
LR_MAX = 0.0001
LR_MIN = 0.00001
LR_RAMPUP_EPOCHS = 10
LR_SUSTAIN_EPOCHS = 0
LR_EXP_DECAY = 0.8


def lrfn(epoch):
    if epoch < LR_RAMPUP_EPOCHS:
        lr = (LR_MAX - LR_START) / LR_RAMPUP_EPOCHS * epoch + LR_START
    elif epoch < LR_RAMPUP_EPOCHS + LR_SUSTAIN_EPOCHS:
        lr = LR_MAX
    else:
        lr = (LR_MAX - LR_MIN) * LR_EXP_DECAY ** (
            epoch - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS
        ) + LR_MIN
    return lr


rng = [i for i in range(nb_epoch)]
y = [lrfn(x) for x in rng]
plt.plot(rng, y)
plt.xlabel("Эпоха обучения")
plt.ylabel("Скорость обучения")
plt.show()
learningRateScheduler = LearningRateScheduler(schedule=lrfn, verbose=1)
model_life_cycle(callback_list=[learningRateScheduler], verbose=0)


# **4) ReduceLROnPlateau**
# Используется для изменения скорости обучения в factor раз, когда метрика перестала улучшаться patience эпох
# **Аргументы:**
# — monitor:  параметр для мониторинга
# — factor: коэффициент уменьшения скорости обучения. new_lr = lr * factor
# — patience: число эпох, за которые величина monitor не улучшается, после которых обучение будет остановлено. Проверочные величины могут производиться не после каждой эпохи если validation_freq (model.fit(validation_freq=5)) больше единицы.
# — verbose: int. 0: «тихий» режим, 1: выводить сообщения
# — mode: один из {auto, min, max}. В режиме min, скорость обучения уменьшится когда величина monitor перестанет уменьшаться; в режиме max, скорость обучения уменьшится когда величина monitor перестанет увеличиваться; в режиме auto, mode выбирается в зависимости от имени monitor.
# — min_delta: минимальное значение изменения величины monitor, расцениваемое как улучшение, то есть, если абсолютное изменение меньше min_delta, то улучшение не засчитывается
# — cooldown: число эпох после уменьшения скорости обучения, которые должны пройти, прежде чем стандартный процесс уменьшения возобновится.
# — min_lr: нижняя граница скорости обучения
#
reduceLROnPlateau = ReduceLROnPlateau(
    monitor="val_loss",
    factor=0.2,
    min_delta=0,
    patience=2,
    verbose=1,
    cooldown=1,
    mode="min",
)
model_life_cycle(callback_list=[reduceLROnPlateau], verbose=0)

# **5) CSVLogger**
# Callback, записывающий результаты эпох в csv файл
# **Аргументы:**
# — filename: имя csv файла (к примеру: ‘run/log.csv’)
# — separator: строка, используемая для разделения элементов в файле.
# — append: True: добавить к существующему файлу (если он существует). False: перезаписать существующий файл.
csvLogger = CSVLogger(filename="learning.csv", separator=",", append=False)
model_life_cycle(callback_list=[csvLogger])


# **6) LambdaCallback**
# Callback для создания простых пользовательских callback’ов «на лету»
# **Аргументы:**
# — on_epoch_begin: вызывается в начале каждой эпохи
# — on_epoch_end: вызывается в конце каждой эпохи
# — on_batch_begin: вызывается в начале каждого батча
# — on_batch_end: вызывается в конце каждого батча
# — on_train_begin: вызывается в начале обучения модели
# — on_train_end: вызывается в конце обучения модели
def foo(epochs, logs):
    """Любая пользовательская функция"""
    return


lambdaCallback = LambdaCallback(
    on_epoch_begin=foo,
    on_epoch_end=foo,
    on_batch_begin=foo,
    on_batch_end=foo,
    on_train_begin=lambda logs: print("on_train_begin"),
    on_train_end=lambda logs: print("on_train_end"),
)
model_life_cycle(callback_list=[lambdaCallback], verbose=0)
