Пожалуйста, вставьте и скопируйте быстро, это полезный набор кодов TensorFlow.

TensorFlow глубокое обучение
TensorFlowХотя в настоящее время это самая популярная структура нейронной сети, она известна как «сложная для начала» (Джефф Дин: вини меня). Бывают случаи, когда нам нужен краткий код, чтобы вести нас. Недавно Джунхо Ким из исследовательского отдела искусственного интеллекта NCsoft выпустил такой набор кодов TensorFlow. Он похож на мини-версию Keras, за исключением того, что исходный код намного легче читать из-за его простоты.

Ссылка на проект: https://github.com/taki0112/Tensorflow-Cookbook

В этом проекте автор подчеркивает, что это простой в использовании набор кодов TensorFlow, который включает в себя общую регуляризацию,Операция сверткиархитектурные модули и т. д. На самом деле, когда мы создаем свои собственные модели или системы, просто скопируйте и вставьте этот код. Они определяют различные функциональные модули в канонической форме, поэтому они идеально вписываются в наш проект всего с несколькими параметрами и изменениями кода.

В настоящее время проект содержит код, необходимый для общей архитектуры глубокого обучения, такой как инициализация и регуляризация, различные операции свертки, базовая сетевая архитектура и модули.функция потерьи другие процедуры предварительной обработки данных. Кроме того, автор также специально добавил поддержку GAN, что в основном отражается в функции потерь, где потери генератора и потери дискриминатора могут использовать расстояние бульдозера, расстояние наименьших квадратов и расхождение KL и т. д.

инструкции

На самом деле есть два способа его использования.Во-первых, мы можем скопировать и вставить код, что очень удобно для настройки модуля. Во-вторых, мы можем напрямую вызывать операции и модули, как с помощью API, что делает модель очень лаконичной, а импортированный исходный код также легко понять. Прежде всего, для второго метода прямого импорта мы можем импортировать часть операции с моделью и процесс предварительной обработки изображения из файлов ops.py и utils.py соответственно.

  • from ops import *

  • from utils import *

from ops import convx = conv(x, channels=64, kernel=3, stride=2, pad=1, pad_type='reflect', use_bias=True, sn=True, scope='conv')

Для первого копирования и вставки мы можем изменить некоторые параметры и структуры в соответствии с реальной ситуацией, но это намного проще, чем писать с нуля. Как показано ниже, для общей нейронной сети потребуется следующий структурный шаблон:

def network(x, is_training=True, reuse=False, scope="network"):    with tf.variable_scope(scope, reuse=reuse):        x = conv(...)        ...return logit

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

Каталог наборов кодов

Страница проекта:woohoo.notion.so/простые-десятки…

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

пример кода

Далее в основном представлены несколько примеров кода, включая наиболее распространенные операции свертки и остаточные модули. Каждый пример кода можно назвать стилем API или скопировать-вставить, поэтому они не только быстры в использовании, но и являются отличным ресурсом для изучения того, как реализуются различные операции.

свертка

Я полагаю, что все знакомы с принципом свертки, так что просто посмотрите на вызывающий код:

x = conv(x, channels=64, kernel=3, stride=2, pad=1, pad_type='reflect', use_bias=True, sn=True, scope='conv')

Код, который реализует вышеуказанный API, показан ниже, вместо прямого использования padding='SAME', также полезно знать, как вручную дополнять изображение нулями. Кроме того, этот кусок кода включает в себя спектральную нормализацию (spectral_normalization/sn), и мы даже можем перехватить эту маленькую часть и встроить ее в наш собственный код.

# padding='SAME' ======> pad = ceil[ (kernel - stride) / 2 ]def conv(x, channels, kernel=4, stride=2, pad=0, pad_type='zero', use_bias=True, sn=False, scope='conv_0'):    with tf.variable_scope(scope):        if pad > 0:            h = x.get_shape().as_list()[1]            if h % stride == 0:                pad = pad * 2            else:                pad = max(kernel - (h % stride), 0)            pad_top = pad // 2            pad_bottom = pad - pad_top            pad_left = pad // 2            pad_right = pad - pad_left            if pad_type == 'zero':                x = tf.pad(x, [[0, 0], [pad_top, pad_bottom], [pad_left, pad_right], [0, 0]])            if pad_type == 'reflect':                x = tf.pad(x, [[0, 0], [pad_top, pad_bottom], [pad_left, pad_right], [0, 0]], mode='REFLECT')        if sn:            w = tf.get_variable("kernel", shape=[kernel, kernel, x.get_shape()[-1], channels], initializer=weight_init,                                regularizer=weight_regularizer)            x = tf.nn.conv2d(input=x, filter=spectral_norm(w),                             strides=[1, stride, stride, 1], padding='VALID')            if use_bias:                bias = tf.get_variable("bias", [channels], initializer=tf.constant_initializer(0.0))                x = tf.nn.bias_add(x, bias)        else:            x = tf.layers.conv2d(inputs=x, filters=channels,                                 kernel_size=kernel, kernel_initializer=weight_init,                                 kernel_regularizer=weight_regularizer,                                 strides=stride, use_bias=use_bias)        return x

Частичная свертка

Частичная свертка — это операция свертки, представленная NVIDIA для отрисовки изображения, которая позволяет модели отрисовывать произвольные нецентральные, нерегулярные области. В статье Изображение Inpainting для неправильных отверстий с использованием частичных сверток реализация частичной свертки очень важна.Простой процесс вызова показан ниже:

x = partial_conv(x, channels=64, kernel=3, stride=2, use_bias=True, padding='SAME', sn=True, scope='partial_conv')        

Читатели могут понять конкретную информацию о реализации в соответствии со следующим кодом, определяющим PConv:

def partial_conv(x, channels, kernel=3, stride=2, use_bias=True, padding='SAME', sn=False, scope='conv_0'):    with tf.variable_scope(scope):        if padding.lower() == 'SAME'.lower():            with tf.variable_scope('mask'):                _, h, w, _ = x.get_shape().as_list()                slide_window = kernel * kernel                mask = tf.ones(shape=[1, h, w, 1])                update_mask = tf.layers.conv2d(mask, filters=1,                                               kernel_size=kernel, kernel_initializer=tf.constant_initializer(1.0),                                               strides=stride, padding=padding, use_bias=False, trainable=False)                mask_ratio = slide_window / (update_mask + 1e-8)                update_mask = tf.clip_by_value(update_mask, 0.0, 1.0)                mask_ratio = mask_ratio * update_mask            with tf.variable_scope('x'):                if sn:                    w = tf.get_variable("kernel", shape=[kernel, kernel, x.get_shape()[-1], channels],                                        initializer=weight_init, regularizer=weight_regularizer)                    x = tf.nn.conv2d(input=x, filter=spectral_norm(w), strides=[1, stride, stride, 1], padding=padding)                else:                    x = tf.layers.conv2d(x, filters=channels,                                         kernel_size=kernel, kernel_initializer=weight_init,                                         kernel_regularizer=weight_regularizer,                                         strides=stride, padding=padding, use_bias=False)                x = x * mask_ratio                if use_bias:                    bias = tf.get_variable("bias", [channels], initializer=tf.constant_initializer(0.0))                    x = tf.nn.bias_add(x, bias)                    x = x * update_maskelse:            if sn:                w = tf.get_variable("kernel", shape=[kernel, kernel, x.get_shape()[-1], channels],                                    initializer=weight_init, regularizer=weight_regularizer)                x = tf.nn.conv2d(input=x, filter=spectral_norm(w), strides=[1, stride, stride, 1], padding=padding)                if use_bias:                    bias = tf.get_variable("bias", [channels], initializer=tf.constant_initializer(0.0))                    x = tf.nn.bias_add(x, bias)            else:                x = tf.layers.conv2d(x, filters=channels,                                     kernel_size=kernel, kernel_initializer=weight_init,                                     kernel_regularizer=weight_regularizer,                                     strides=stride, padding=padding, use_bias=use_bias)        return x   

остаточный модуль

Самая большая особенность ResNet заключается в том, что он решает проблему исчезновения градиента во время обратного распространения, поэтому он может обучать очень глубокие сети без добавления сети классификации посередине для предоставления дополнительных градиентов, таких как GoogLeNet. ResNet состоит из остаточных модулей.Как правило, при необходимости можно определить несколько различных остаточных модулей:

x = resblock(x, channels=64, is_training=is_training, use_bias=True, sn=True, scope='residual_block')x = resblock_down(x, channels=64, is_training=is_training, use_bias=True, sn=True, scope='residual_block_down')x = resblock_up(x, channels=64, is_training=is_training, use_bias=True, sn=True, scope='residual_block_up')

Три остаточных модуля показаны выше, где «вниз» означает понижение дискретизации, а длина и ширина входной карты объектов будут уменьшены вдвое, а «вверх» означает повышение дискретизации, а длина и ширина входной карты объектов будут удвоены. В каждом остаточном блоке остаточное соединение напрямую суммирует вход и выход блока. Следовательно, при обратном распространении градиенты, передаваемые по остаточному соединению, не могут проходить через несколько сверточных слоев внутри остаточного модуля, таким образом сохраняя достаточно информации о градиенте для предыдущего слоя.

Общий resblock и апсемплинг resblock_up просто определяются следующим образом, потому что такие функции, как conv(), deconv() и batch_norm(), которые они вызывают, являются разными модулями вычислений, определенными ранее, поэтому общий код выглядит очень кратким.

def resblock(x_init, channels, use_bias=True, is_training=True, sn=False, scope='resblock'):    with tf.variable_scope(scope):        with tf.variable_scope('res1'):            x = conv(x_init, channels, kernel=3, stride=1, pad=1, use_bias=use_bias, sn=sn)            x = batch_norm(x, is_training)            x = relu(x)        with tf.variable_scope('res2'):            x = conv(x, channels, kernel=3, stride=1, pad=1, use_bias=use_bias, sn=sn)            x = batch_norm(x, is_training)        return x + x_initdef resblock_up(x_init, channels, use_bias=True, is_training=True, sn=False, scope='resblock_up'):    with tf.variable_scope(scope):        with tf.variable_scope('res1'):            x = deconv(x_init, channels, kernel=3, stride=2, use_bias=use_bias, sn=sn)            x = batch_norm(x, is_training)            x = relu(x)        with tf.variable_scope('res2') :            x = deconv(x, channels, kernel=3, stride=1, use_bias=use_bias, sn=sn)            x = batch_norm(x, is_training)        with tf.variable_scope('skip') :            x_init = deconv(x_init, channels, kernel=3, stride=2, use_bias=use_bias, sn=sn)

Здесь показана только реализация кода трех функциональных блоков, и мы можем почувствовать, что проект похож на мини-Keras. Но поскольку операции, реализованные в этом проекте, относительно просты и распространены, исходный код будет намного проще читать, чем большая библиотека, такая как Keras, которая более удобна для встроенного использования или обучения.