Как установить и отследить снижение веса? - PullRequest
1 голос
/ 28 апреля 2020

Что такое руководство по настройке снижения веса (например, штраф l2) - и главным образом, как я отслеживаю , работает ли он на протяжении всего обучения? (т. е. действительно ли снижаются веса, и на сколько по сравнению с штрафом l2).

1 Ответ

2 голосов
/ 28 апреля 2020

Обычный подход - «попробуй диапазон значений, посмотри, что работает», но его ловушкой является отсутствие ортогональности ; l2=2e-4 может лучше всего работать в сети X , но не в сети Y . Обходной путь - управлять спадами веса в подсети способом: (1) групповые слои (например, Conv1D стеки и LSTM s отдельно), (2) установить целевую норму веса, (3) отслеживать.

(1) : см. здесь ; те же самые аргументы и предложенные значения веса не будут применяться к принудительным значениям - таким образом, потребность в различных группировках

(2) : звуковая опция - l2-норма регуляризации весовой матрицы; тогда возникает вопрос, по какой оси вычислить ее по отношению к. Подход, ориентированный на извлечение признаков, состоит в том, чтобы выбрать ось канала (последний в Керасе), получая вектор длины = количество каналов / объектов, так что каждый элемент является l2-нормой канала.

(3) : Векторы l2-нормы могут быть добавлены в список итеративно, или, может быть, их среднее / максимальное в качестве краткой совокупной статистики - затем нанесены на график в конце обучения.

Полный пример показан ниже; ключевая функция, weights_norm, дана снизу и взята из См. RNN . Я также рекомендую Keras AdamW для улучшенного снижения веса.

enter image description here

Интерпретация :

  • wd=2e-3 распадается на выходном слое сильнее, чем 2e-4, но не на входе, что предполагает взаимодействие противовеса со слоем узкого места.
  • wd=2e-3 дает меньшую дисперсию весовых норм относительно 2e-4
  • Нормы выходного слоя растут даже с 2e-3, предлагая более сильные градиенты к выходу
  • Интересно изучить поведение с добавлением BatchNormalization добавлено

Код и объяснение ; делается следующее:

  1. Прогресс поезда и пути

    • Создание фиктивной модели и данных, выберите n_batches и wd (штраф l2)
    • Настроить поезд l oop, выбрать n_epochs
    • Создать l2_stats диктовать для отслеживания прогресса
    • На каждой итерации поезда вычислять weights_norm() и добавьте к l2_stats
  2. Предварительная обработка данных о прогрессе для построения

    • Получите имена весов с потерей веса; включить неразложившееся в omit_names
    • l2_stats, к которому удобно добавлять, но его необходимо преобразовать в np.ndarray правильных тусклостей; распаковать так, чтобы .shape == (n_epochs, n_layers, n_weights, n_batches) -> (n_rows, n_cols, hists_per_subplot). Обратите внимание, что для этого требуется, чтобы количество отслеживаемых весовых матриц было одинаковым для каждого слоя
  3. График

    • Явно установлен xlims и ylim для равномерного сравнения различных значений wd
    • По умолчанию вычисляются две характеристики: np.mean (оранжевый) и np.max. Также, как Керас обращается с maxnorm регуляризацией веса.
import numpy as np
import tensorflow as tf
import random

np.random.seed(1)
random.seed(2)
tf.compat.v1.set_random_seed(3)

from keras.layers import Input, Conv1D
from keras.models import Model
from keras.regularizers import l2

from see_rnn import weights_norm, features_hist_v2

########### Model & data funcs ################################################
def make_model(batch_shape, layer_kw={}):
    """Conv1D autoencoder"""
    dim = batch_shape[-1]
    bdim = dim // 2

    ipt = Input(batch_shape=batch_shape)
    x   = Conv1D(dim,  8, activation='relu',   **layer_kw)(ipt)
    x   = Conv1D(bdim, 1, activation='relu',   **layer_kw)(x)  # bottleneck
    out = Conv1D(dim,  8, activation='linear', **layer_kw)(x)

    model = Model(ipt, out)
    model.compile('adam', 'mse')
    return model

def make_data(batch_shape, n_batches):
    X = Y = np.random.randn(n_batches, *batch_shape)
    return X, Y

########### Train setup #######################################################
batch_shape = (32, 100, 64)
n_epochs = 5
n_batches = 200
wd = 2e-3
layer_kw = dict(padding='same', kernel_regularizer=l2(wd))

model = make_model(batch_shape, layer_kw)
X, Y  = make_data(batch_shape, n_batches)

## Train ####################
l2_stats = {}
for epoch in range(n_epochs):
    l2_stats[epoch] = {}
    for i, (x, y) in enumerate(zip(X, Y)):
        model.train_on_batch(x, y)
        print(end='.')

        verbose = bool(i == len(X) - 1)  # if last epoch iter, print last results
        if verbose:
            print()
        l2_stats[epoch] = weights_norm(model, [1, 3], l2_stats[epoch],
                                       omit_names='bias', verbose=verbose)
    print("Epoch", epoch + 1, "finished")
    print()

########### Preprocess funcs ##################################################
def _get_weight_names(model, layer_names, omit_names):
    weight_names= []
    for name in layer_names:
        layer = model.get_layer(name=name)
        for w in layer.weights:
            if not any(to_omit in w.name for to_omit in omit_names):
                weight_names.append(w.name)
    return weight_names

def _merge_layers_and_weights(l2_stats):
    stats_merged = []
    for stats in l2_stats.values():
        x = np.array(list(stats.values()))  # (layers, weights, stats, batches)
        x = x.reshape(-1, *x.shape[2:])     # (layers-weights, stats, batches)
        stats_merged.append(x)
    return stats_merged  # (epochs, layer-weights, stats, batches)

########### Plot setup ########################################################
ylim = 5
xlims = (.4, 1.2)
omit_names = 'bias'
suptitle = "wd={:.0e}".format(wd).replace('0', '')
side_annot = "EP"
configs = {'side_annot': dict(xy=(.9, .9))}

layer_names = list(l2_stats[0].keys())
weight_names = _get_weight_names(model, layer_names, omit_names)
stats_merged = _merge_layers_and_weights(l2_stats)

## Plot ########
features_hist_v2(stats_merged, colnames=weight_names, title=suptitle,
                 xlims=xlims, ylim=ylim, side_annot=side_annot, configs=configs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...