Изменение функции выполнения в Theano.tensor.nnet.softmax

Я только начал использовать лазанью и Theano для машинного обучения на Python.

Я пытаюсь изменить класс softmax в Theano. Я хочу изменить способ расчета функции активации (softmax). Вместо деления e_x на e_x.sum(ось=1) я хочу разделить e_x на сумму трех последовательных чисел.

Например, результат будет следующим:

sm[0] = e_x[0]/(e_x[0]+e_x[1]+e_x[2])
sm[1] = e_x[1]/(e_x[0]+e_x[1]+e_x[2])
sm[2] = e_x[2]/(e_x[0]+e_x[1]+e_x[2])
sm[3] = e_x[3]/(e_x[3]+e_x[4]+e_x[5])
sm[4] = e_x[4]/(e_x[3]+e_x[4]+e_x[5])
sm[5] = e_x[5]/(e_x[3]+e_x[4]+e_x[5])

и так далее...

Проблема в том, что я не совсем понимаю, как theano выполняет вычисления.

Вот мой главный вопрос. Достаточно ли просто изменить функцию Perform() в классе softmax?

Вот оригинальная функция Perform():

def perform(self, node, input_storage, output_storage):
    x, = input_storage
    e_x = numpy.exp(x - x.max(axis=1)[:, None])
    sm = e_x / e_x.sum(axis=1)[:, None]
    output_storage[0][0] = sm

Вот моя модифицированная функция Perform()

def myPerform(self, node, input_storage, output_storage):
    x, = input_storage
    e_x = numpy.exp(x - x.max(axis=1)[:, None])
    sm = numpy.zeros_like(e_x)
    for i in range(0,symbolCount):
        total = e_x[3*i] + e_x[3*i+1] + e_x[3*i+2]
        sm[3*i] = e_x[3*i]/total
        sm[3*i+1] = e_x[3*i+1]/total
        sm[3*i+2] = e_x[3*i+2]/total
    output_storage[0][0] = sm

С текущим кодом я получаю ошибку «неупорядоченные типы: int()>str()», когда использую метод прогнозирования в лазанье.


person Jin Hoon Jeffrey Bang    schedule 31.08.2015    source источник


Ответы (1)


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

Ваш пользовательский softmax может быть определен с точки зрения символических выражений. Делая это таким образом, вы получите градиенты (и другие части операции Theano) «бесплатно», но может работать немного медленнее, чем пользовательская операция.

Вот пример:

import numpy
import theano
import theano.tensor as tt

x = tt.matrix()

# Use the built in softmax operation
y1 = tt.nnet.softmax(x)

# A regular softmax operation defined via ordinary Theano symbolic expressions
y2 = tt.exp(x)
y2 = y2 / y2.sum(axis=1)[:, None]

# Custom softmax operation
def custom_softmax(a):
    b = tt.exp(a)
    b1 = b[:, :3] / b[:, :3].sum(axis=1)[:, None]
    b2 = b[:, 3:] / b[:, 3:].sum(axis=1)[:, None]
    return tt.concatenate([b1, b2], axis=1)
y3 = custom_softmax(x)

f = theano.function([x], outputs=[y1, y2, y3])

x_value = [[.1, .2, .3, .4, .5, .6], [.1, .3, .5, .2, .4, .6]]
y1_value, y2_value, y3_value = f(x_value)
assert numpy.allclose(y1_value, y2_value)
assert y3_value.shape == y1_value.shape
a = numpy.exp(.1) + numpy.exp(.2) + numpy.exp(.3)
b = numpy.exp(.4) + numpy.exp(.5) + numpy.exp(.6)
c = numpy.exp(.1) + numpy.exp(.3) + numpy.exp(.5)
d = numpy.exp(.2) + numpy.exp(.4) + numpy.exp(.6)
assert numpy.allclose(y3_value, [
    [numpy.exp(.1) / a, numpy.exp(.2) / a, numpy.exp(.3) / a, numpy.exp(.4) / b, numpy.exp(.5) / b, numpy.exp(.6) / b],
    [numpy.exp(.1) / c, numpy.exp(.3) / c, numpy.exp(.5) / c, numpy.exp(.2) / d, numpy.exp(.4) / d, numpy.exp(.6) / d]
]), y3_value
person Daniel Renshaw    schedule 31.08.2015
comment
Проблема в том, что я хотел бы изменить класс softmax, потому что класс используется несколько раз во время вычислений. Мне интересно, можно ли создать класс newSoftmax, используя символические выражения. Я не смог найти на него никакой документации. - person Jin Hoon Jeffrey Bang; 02.09.2015
comment
Просто создайте функцию Python, содержащую пользовательский код softmax. Затем вы можете вызывать эту функцию столько раз, сколько захотите. Простая операция Theano — это все, что можно вызывать в Python и что принимает и возвращает символьные переменные. - person Daniel Renshaw; 02.09.2015
comment
Можно ли создать класс вместо функции? Я не знаю, как работает лазанья. lasagne/nonlinearities.py def softmax(x): return theano.tensor.nnet.softmax(x) Мне приходится работать с этой функцией, которая просто возвращает класс. Должен ли я просто реализовать символические выражения внутри этой функции? Если да, то что он должен вернуть. - person Jin Hoon Jeffrey Bang; 03.09.2015
comment
theano.tensor.nnet.softmax возвращает объект, символьную переменную. То же самое делает custom_softmax. custom_softmax можно использовать как прямую замену функции softmax лазаньи. - person Daniel Renshaw; 03.09.2015