Автоэнкодер с использованием обратного распространения

Я пытаюсь реализовать автоэнкодер, используя этот ресурс, который реализует алгоритм обратного распространения. Я использую тот же алгоритм прямой связи, реализованный там, но, тем не менее, он дает мне большую ошибку. В автоэнкодерах - сигмоидальная функция, применяемая к скрытому для кодирования и снова к выходному сигналу для декодирования.

def feedForwardPropagation(network, row, output=False):
currentInput = row
if not output:
    layer = network[0]
else:
    layer = network[1]
layer_output = []
for neuron in layer:
    activation = neuron_activation(neuron['weights'], currentInput)
    neuron['output'] = neuron_transfer(activation)
    layer_output.append(neuron['output'])
currentInput = layer_output
return currentInput

def backPropagationNetworkErrorUpdate(network, expected):
for i in reversed(range(len(network))):
    layer = network[i]
    errors = list()
    if i != len(network) - 1:
        # Hidden Layers weight error compute
        for j in range(len(layer)):
            error = 0.0
            for neuron in network[i + 1]:  # It starts with computing weight error of output neuron.
                error += (neuron['weights'][j] * neuron['delta'])
            errors.append(error)
    else:
        # Output layer error computer
        for j in range(len(layer)):
            neuron = layer[j]
            error = expected[j] - neuron['output']
            errors.append(error)
    for j in range(len(layer)):
        neuron = layer[j]
        transfer = neuron['output'] * (1.0 - neuron['output'])
        neuron['delta'] = errors[j] * transfer

def updateWeights(network, row, l_rate, momentum=0.5):
for i in range(len(network)):
    inputs = row[:-1]
    if i != 0:
        inputs = [neuron['output'] for neuron in network[i - 1]]
    for neuron in network[i]:
        for j in range(len(inputs)):
            neuron['velocity'][j] = momentum * neuron['velocity'][j] + l_rate * neuron['delta'] * inputs[j]
            neuron['weights'][j] += neuron['velocity'][j]
        neuron['velocity'][-1] = momentum * neuron['velocity'][-1] + l_rate * neuron['delta'] * inputs[j]
        neuron['weights'][-1] += neuron['velocity'][-1]


def trainNetwork(network, train, l_rate, n_epoch, n_outputs, test_set):
hitrate = list()
errorRate = list()
epoch_step = list()
for epoch in range(n_epoch):
    sum_error = 0
    np.random.shuffle(train)
    for row in train:
        outputs = feedForwardPropagation(network, row)
        outputs = feedForwardPropagation(network, outputs)
        expected = row
        sum_error += sum([(expected[i] - outputs[i]) ** 2 for i in range(len(expected))])
        backPropagationNetworkErrorUpdate(network, expected)
        updateWeights(network, row, l_rate)
    if epoch % 10 == 0:
        errorRate.append(sum_error)
        epoch_step.append(epoch)
        log = '>epoch=%d, lrate=%.3f, error=%.3f' % (epoch, l_rate, sum_error)
        print(log, n_epoch, len(network[1][0]['weights']) - 1, l_rate)
return epoch_step, errorRate

Для автокодирования я использую один скрытый слой, n входов и n выходов. Я считаю, что ошибся с реализацией прямой связи. Будем очень признательны за любые предложения.

Изменить: я попытался вычислить веса после первого слоя (продолжайте комментировать в методе прямой связи), а затем декодировал вывод с помощью сигмоидной функции, прокомментированной в методе trainNetwork. Однако через 100 эпох ошибка не изменилась.


person Jaswanth Kumar    schedule 13.11.2017    source источник


Ответы (1)


Характеристики вашей проблемы (например, ошибка, которая едва меняется в течение 100 эпох и остается с большой ошибкой) предполагают, что проблема может быть (и, вероятно, такова) вызвана порядком размера ваших входных данных и тем фактом, что вы используете сигмоиды как функция активации. Приведу простой пример:

Предположим, я хочу восстановить значение x=100. Если я тренирую его с помощью автокодировщика на одном нейроне, восстановленный вывод будет дан как r = sigmoid(w*x), где ошибка - это разница между фактическим вводом и реконструкцией, то есть e = x - r. Обратите внимание, что, поскольку сигмовидная функция ограничена между -1 и 1, минимальная ошибка, которую вы можете получить в этом случае, составляет e = 100-1 = 99. Независимо от того, насколько хорошо вы тренируете вес w в этом случае, r=sigmoid(w*x) всегда будет ограничен единицей.

Это означает, что функция активации сигмоида не может представить ваши данные в этом случае. Чтобы решить эту проблему, либо:

  1. Уменьшите масштаб или нормализуйте ваши входные данные до размера от -1 до 1, или
  2. Измените сигмоид на другую функцию активации, которая может фактически восстановить правильный размер порядка ваших данных.

Надеюсь это поможет.

person BlueRine S    schedule 11.01.2018