какую функцию активации я должен использовать для принудительного округления, подобного поведению

Мне нужна функция активации, которая округляет мои тензоры.

производная (градиенты) функции round() равна 0 (или None в тензорном потоке), что делает ее непригодной для использования в качестве функции активации.

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

Я знаю, что формула: tanh ○ сигмовидная использовалась для обеспечения того, чтобы числа {-1, 0, 1} проходили только через модель, поэтому существует ли какая-то комбинация выводимых функций, которые имитируют поведение округления?


person Tissuebox    schedule 07.08.2018    source источник
comment
у вас есть конечное число лейблов, известных заранее? Или это открытые целые домены.   -  person modesitt    schedule 07.08.2018
comment
нет, это не конечное количество ярлыков   -  person Tissuebox    schedule 07.08.2018
comment
Если вы пишете свою собственную функцию активации, вы можете указать свой собственный градиент. Вычисление градиента функции округления не является тривиальной задачей, но тщательные размышления помогут вам в этом.   -  person PMende    schedule 07.08.2018
comment
Округление @PMende по своей сути недифференцируемо< /б>. Совершенно не согласен с тем, что OP может каким-то образом написать значимую функцию для этого. Его/ее лучший шанс - округлить результат и использовать какую-то функцию MSE/Huber Loss.   -  person modesitt    schedule 07.08.2018
comment
Функция округления не дифференцируема. Дифференцируемая функция, в частности, непрерывна, и если вы начертите свою функцию округления, вы увидите, что она прерывиста.   -  person antonioACR1    schedule 07.08.2018
comment
@modesitt По этой логике ReLU также не дифференцируем. Ты не прав.   -  person PMende    schedule 07.08.2018
comment
@PMende А? ReLU указывает, что производная в 0 (это единственная недифференцируемая точка) равна 0. Это не математика - это обычай. Невозможно сделать это с помощью round (ноль везде — лучшее, что вы можете сделать) и если бы вы немного подумали / знали вводное исчисление, это было бы ясно.   -  person modesitt    schedule 07.08.2018
comment
@PMende Производная ReLU существует для x<0 и x>0, есть только одно исключение в x=0, и производная в этот момент определяется как 0 просто по соглашению, а не потому, что она дифференцируема в x=0   -  person antonioACR1    schedule 07.08.2018
comment
@modesitt Если бы вы немного подумали и поняли сложные вычисления и концепцию распределений, было бы ясно, что существуют производные. Использование распределений как функций не работает в простом приложении, но можно создавать приближения, если это действительно желаемое поведение.   -  person PMende    schedule 07.08.2018
comment
@PMende А, часть 2? Пожалуйста, объясните, как вы считаете, что это связано со стохастическим исчислением. Если вы так уверены, что существует производная... приведите ее ;). Подсказка... вы не правы.   -  person modesitt    schedule 07.08.2018
comment
@modesitt Производная от round - это гребенка Дирака с частотой 1 и фазой 0,5. Каждую дельта-функцию Дирака можно рассматривать как предел гауссовой функции, становящейся бесконечно тонкой и бесконечно высокой. Если вам нужно поведение округления и градиент такой функции, вы можете выбрать подходящую дисперсию для вашего нормализованного гауссова. Я не говорю, что это будет эффективно с точки зрения вычислений, но если это действительно то, чего кто-то хочет, то это выполнимо.   -  person PMende    schedule 07.08.2018
comment
@PMende на самом деле я думаю о том, чтобы приблизить * поведение округления к непрерывной функции, которую я сделаю сам. Я проверю дисперсию нормализованного гауссова, спасибо за это.   -  person Tissuebox    schedule 07.08.2018
comment
Все это приводит к тому, что везде есть нули, кроме чисел, которые являются нечетными кратными 1/2, где ваша причудливая «гребенка Дирака» с некоторой «выбранной дисперсией» является просто несколько большим числом, выбранным произвольно. Кроме того, решение сделать это совершенно произвольно и совершенно бесполезно для обучения нейронной сети.   -  person modesitt    schedule 07.08.2018
comment
@Tissuebox Если вам действительно нравится такое поведение в открытой области вещественных чисел, вы можете аппроксимировать округление как бесконечную серию ступенчатых функций, а затем использовать логистическую аппроксимацию (en.wikipedia.org/wiki/), аналогично ответу user322778. В этом случае, чтобы определить производную, вы должны взять свои входные данные, x, и по модулю 1 их (т.е. excess = x %1). Конкретная логистическая функция, которую вы выберете, будет иметь центр 0,5, и вам нужно только выбрать соответствующий параметр, чтобы указать крутизну (которая будет гиперпараметром).   -  person PMende    schedule 07.08.2018
comment
Это именно то, что я хочу сделать, аппроксимируя округление как бесконечный ряд ступенчатых функций. Вопросы, если у вас есть время: как перевести эту логистическую (или сигмовидную) функцию в центр на 0,5? как сделать его бесконечным?   -  person Tissuebox    schedule 07.08.2018
comment
@Tissuebox Что если вы определите производную вашей функции округления в x=0.5 как 0 или 1 просто как соглашение (аналогично для x=1.5, x=2.5 и т. д.)? Я думаю, что вы слишком усложняете ситуацию, пытаясь аппроксимировать функцию, которая сама по себе НЕ дифференцируема...   -  person antonioACR1    schedule 07.08.2018
comment
Я думаю, что в keras и tensorflow вывод происходит автоматически и не может быть установлен вручную.   -  person Tissuebox    schedule 07.08.2018
comment
Я почти уверен, что его можно установить (каким-то образом) вручную, однако было бы неплохо, если бы вы включили исходный код и воспроизводимый пример перед   -  person antonioACR1    schedule 07.08.2018
comment
простой модели keras? В противном случае я не знаю, какой код вы ищете, мне нужна дифференцируемая функция, похожая на маршрутизацию, я не знаю, какой код вы ищете   -  person Tissuebox    schedule 07.08.2018
comment
@Tissuebox я тоже :), поэтому я сказал, что было бы неплохо, если бы вы включили исходный код и воспроизводимый пример раньше.   -  person antonioACR1    schedule 08.08.2018


Ответы (2)


Если вы хотите аппроксимировать округление на реальной линии, вы можете сделать что-то вроде следующего:

def approx_round(x, steepness=1):
    floor_part = tf.floor(x)
    remainder = tf.mod(x, 1)
    return floor_part + tf.sigmoid(steepness*(remainder - 0.5))

На самом деле есть способы зарегистрировать собственные градиенты в Tensorflow (см., например, этот вопрос). Однако я не так знаком с этой частью, так как не так часто использую Keras/TensorFlow.

С точки зрения функции, которая даст вам градиент этого приближения, это будет следующее:

def approx_round_grad(x, steepness=1):
    remainder = tf.mod(x, 1)
    sig = tf.sigmoid(steepness*(remainder - 0.5))
    return sig*(1 - sig)

Чтобы было ясно, это приближение предполагает, что вы используете «достаточно крутой» параметр steepness, поскольку сигмовидная функция не достигает точно 0 или 1, за исключением предела больших аргументов.

Чтобы сделать что-то вроде приближения полусинуса, вы можете использовать следующее:

def approx_round_sin(x, width=0.1):
    if width > 1 or width <= 0:
        raise ValueError('Width must be between zero (exclusive) and one (inclusive)')
    floor_part = tf.floor(x)
    remainder = tf.mod(x, 1)
    return (floor_part + clipped_sin(remainder, width))

def clipped_sin(x, width):
    half_width = width/2
    sin_part = (1 + tf.sin(np.pi*((x-0.5)/width)))/2
    whole = sin_part*tf.cast(tf.abs(x - 0.5) < half_width, tf.float32)
    whole += tf.cast(x > 0.5 + half_width, tf.float32)
    return whole

def approx_round_grad_sin(x, width=0.1):
    if width > 1 or width <= 0:
        raise ValueError('Width must be between zero (exclusive) and one (inclusive)')
    remainder = tf.mod(x, 1)
    return clipped_cos(remainder, width)

def clipped_cos(x, width):
    half_width = width/2
    cos_part = np.pi*tf.cos(np.pi*((x-0.5)/width))/(2*width)
    return cos_part*tf.cast(tf.abs(x - 0.5) < half_width, dtype=tf.float32)
person PMende    schedule 07.08.2018
comment
Поскольку я не очень хорошо знаком с API Keras/Tensorflow, мне сложно дать рекомендации по инкапсуляции этой функциональности. В принципе, вы, вероятно, захотите определить функцию каким-то образом, чтобы вам не нужно было постоянно передавать гиперпараметр steepness как базовой функции, так и ее градиенту. Возможно, вы могли бы сделать это, определив третью функцию, которая, например, возвращает как базовую функцию, так и ее градиент в виде кортежа. - person PMende; 08.08.2018
comment
Будь осторожен. Ваша функция также не дифференцируема при целочисленных значениях. - person antonioACR1; 08.08.2018
comment
Я проверил, и это работает, чем выше значение крутизны, тем меньше разница с фактической функцией round() (пробовал до 100), хотя, когда я пробовал слишком большое число во время фактического обучения (например, 100), градиенты отсутствуют, он работает только тогда, когда он ниже, мне еще предстоит сравнить результат, я попробовал его в сети LSTM, пытаясь предсказать число после того, которое я даю. (например, если я ввожу 23, он должен вывести 24) - person Tissuebox; 08.08.2018
comment
@Tissuebox Это работает, приближая круглую функцию, да, но с математической точки зрения она не дифференцируема. Пожалуйста, прочтите формальное определение дифференцируемости. - person antonioACR1; 08.08.2018
comment
следует отметить, что никакая функция активации не дает лучшего результата в этом конкретном случае, и что более низкое значение крутизны также дает лучший результат, даже если разница между фактической функцией round() и аппроксимацией увеличивается, когда крутизна ниже - person Tissuebox; 08.08.2018
comment
@user322778 user322778, может быть, я плохо разбираюсь в деривативах, так как мне еще предстоит поступить в колледж, но это не должно иметь значения, верно? кроме того, в моей модели нет целочисленного потока - person Tissuebox; 08.08.2018
comment
@ user322778 Да, это очень грубое приближение. Что касается определения дифференцируемого, это действительно зависит от вашего определения. Рекомендую почитать теорию распределений. - person PMende; 08.08.2018
comment
@PMende Спасибо. Я приму это во внимание. Однако всякий раз, когда вы пытаетесь применить теорию распределений или любой другой инструмент, который вы предпочитаете, вам необходимо установить, что именно вы понимаете под дифференцируемым. Как математик, важно делать определения и утверждения точными, иначе это приведет к долгим дискуссиям, как описано выше, из-за недопонимания. - person antonioACR1; 08.08.2018
comment
@PMende Я не знаю, интересно ли вам это, но эта функция активации дала мне результаты, которых я никогда раньше не видел, и не могу воссоздать их ни с какими другими: она изучает линейные отношения, такие как математика. Я тестировал только сложение и умножение, но я даю только 100 данных признаков, и они могут правильно складываться (например, с 0,0006 или разницей каждый раз) в тысячах. Я даже пытался умножить на два с 50 данными признаков в отрицательном и 50 в положительном для обучения, и он, черт возьми, научился умножать реальные числа на два. Я попробовал ВСЕ функции активации в keras, и ни одна из них не смогла - person Tissuebox; 08.08.2018
comment
@PMende, если быть точным, я знаю, что это было сделано раньше, но я еще не нашел источника, который хотя бы близок к моему результату за пределами диапазона обучения, я даю ему только 100 примеров маленьких чисел (от -50 до 50 в моих случаях ) и обобщает до тысяч без ошибок - person Tissuebox; 08.08.2018
comment
@Tissuebox Это супер круто! Рад слышать, что это было успешным для вас. Действительно, отсутствие обобщения вне поддержки обучающих данных является распространенной проблемой в нейтральных сетях. Интересно слышать, что ваша архитектура работает за пределами вашего диапазона обучающих данных! Хотя, учитывая природу функции активации и ее производной, для меня это имеет некоторый интуитивный смысл. Если вы опубликуете статью, пожалуйста, не стесняйтесь упоминать меня в своих благодарностях. :П - person PMende; 08.08.2018
comment
Я должен сказать конкретно, что нейронные сети часто испытывают трудности с обобщением за пределами диапазона обучающих данных, если вы используете ограниченные функции активации. - person PMende; 08.08.2018
comment
да, это правда, я не использовал ни сигмоид, ни тан, только relu и функцию rouding для последнего слоя, мне не удалось заставить его выучить десятичные точки, потому что лучший результат был только тогда, когда rouding был в последнем слое. Я попробую другое, например, использовать половину цикла функции sin или cos вместо сигмоида. Я все еще ищу последние достижения в области математики для создания нейронных сетей, по этому вопросу мало литературы, поэтому я вполне мог бы опубликовать свою первую статью! Я хотел спросить вас, могу ли я, потому что вы действительно сделали функцию, я отдам вам должное и скажу, что вы помогли! - person Tissuebox; 08.08.2018

Возможно, вам нужна потеря перекрестной энтропии с функцией softmax tf.nn.softmax_cross_entropy_with_logits_v2, см.

https://www.tensorflow.org/api_docs/python/tf/nn/softmax_cross_entropy_with_logits_v2

Также взгляните на

https://deepnotes.io/softmax-crossentropy

person antonioACR1    schedule 07.08.2018
comment
Если я не понял, что сказано в ссылке на заметки, эта функция потерь не является лучшей для целых чисел открытого домена (частью которых являются мои метки) - person Tissuebox; 07.08.2018
comment
Что вы подразумеваете под целыми числами открытого домена? Если вы имеете в виду, что у вас может быть буквально любое целое число в качестве метки, то я не думаю, что вы найдете подходящую функцию потерь. Когда вы подгоняете модель к набору данных, у вас уже должны быть доступны все ваши метки. В противном случае подгоночная часть не имеет смысла в первую очередь - person antonioACR1; 07.08.2018
comment
ну, я искал не функцию потерь, а функцию активации - person Tissuebox; 07.08.2018