Нейронная сеть: персептрон для угадывания положения точки относительно функции.

Я создаю простой персептрон с 3 входами (x, y, смещение = 1).

Он должен угадать, находится ли заданная точка (x,y) под или под заданной функцией.

По сути, он был вдохновлен этой статьей.

Для обучения сети используется контролируемая модель обучения, и формула следующая:

learningConst = 0.01
error = desired - neuralAnswer
new_weights[i] = old_weights[i] + error * inputs[i] * learningConst

Тем не менее, после 100000 обучающих тестов он делает ошибки даже на простой функции (2x+1)

Вот код:

import numpy as np
import matplotlib.pyplot as plt

class Perceptron:
    def __init__(self, n):
        self.n = n #n is 2 in this case. 2 inputs [ x, y ] 
        self.weights = [np.random.uniform(-1, 1) for x in range(n)]
        self.learningConstant = 0.05

    # 1 added to the sum is the bias input    
    def feedForward(self, inputs):
        return 1 + sum([self.weights[i]*inputs[i] for i in range(self.n)])

    def activate(self, result):
        if result >= 0:
            return 1
        elif result < 0:
            return -1

    def train(self, inputs, expected):
        prediction = self.feedForward(inputs)
        answer = self.activate(prediction)
        error = expected - answer

        self.weights = [
            self.weights[i] + error * inputs[i] * self.learningConstant 
            for i in range(self.n)
        ]
        #print(self.weights)

    def predict(self, inputs):
        prediction = self.feedForward(inputs)
        return self.activate(prediction)

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

Что мне сделать, чтобы улучшить программу?

Результаты персептрона

ПОЛНЫЙ КОД: НАЖМИТЕ

РЕШЕНИЕ

Моя проблема заключалась в том, что ввод смещения использовался как грубая константа (строка 14 полного кода), не позволяя алгоритму учиться на нем. Итак, мои входные данные теперь равны [смещение, x, y], а веса равны [w1, w3, w3] — вход смещения теперь имеет свой вес.

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

2x + 1 Изображение

x^2 - 2x + 1 введите здесь описание изображения


person Denis Rozimovschii    schedule 14.05.2016    source источник
comment
Я не вижу смысла использовать numpy только для создания случайных чисел... используйте массивы numpy и векторные операции: self.weigths = np.random.uniform(-1, 1, size=n), а также np.sum(self.weigths * inputs) и self.weights = self.weights + error*inputs*self.learningConstant.   -  person Bakuriu    schedule 14.05.2016
comment
Не могли бы вы опубликовать код, который также использует ваш Perceptron, чтобы мне не пришлось его придумывать :)   -  person bakkal    schedule 14.05.2016


Ответы (2)


Основная проблема с вашим решением заключается в том, что ваше смещение всегда равно 1. Это не параметр - он постоянен. Так что это может быть проблемой, потому что ваша модель намного слабее, чем классическая модель персептрона.

person Marcin Możejko    schedule 14.05.2016
comment
Это хорошая идея! Вход смещения может изменить ответ. Но разве нейронная сеть не должна адаптировать свои веса к входному смещению после некоторых тестов? - person Denis Rozimovschii; 14.05.2016
comment
Да, должен, но как бы они ни адаптировались, ваш уклон всегда будет положительным. Это может серьезно повредить вашему прогнозу. - person Marcin Możejko; 14.05.2016
comment
Как мне его изменить? Пробовал снять и понизить до 0.01 - практически никакого эффекта - person Denis Rozimovschii; 14.05.2016
comment
Попробуйте использовать -1. Или лучше - просто измените свои веса на трехмерные [w1, w2, w3] и сделайте ввод равным [1,x,y]. Тогда без предвзятости должно работать хорошо. - person Marcin Możejko; 14.05.2016
comment
Но что, если есть другая функция? Есть ли какой-либо общий ввод смещения? - person Denis Rozimovschii; 14.05.2016
comment
@MarcinMożejko Что такое мы и ж? Вы имели в виду, что вес одного соединения должен быть списком из 3-х чисел? - person Denis Rozimovschii; 14.05.2016
comment
@MarcinMożejko Прямо сейчас у меня есть [x, y] и [w1, w2]. Поэтому я должен добавить часть смещения и обновить ее при обучении. - person Denis Rozimovschii; 14.05.2016
comment
Ух ты! Я сделал [bias, x, y] и [w1, w2, w3], и, похоже, это работает! - person Denis Rozimovschii; 14.05.2016
comment
Да. Точно. И в этом случае хардкод 1 не подходит. - person Marcin Możejko; 14.05.2016

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

person Octoplus    schedule 14.05.2016
comment
Вы должны случайным образом выбрать неправильно классифицированный пример и обновить вес с помощью ответа (который неверен). Действительно, если вы умножаете для каждого примера, это не сработает. - person Octoplus; 14.05.2016
comment
Я обновил ответ, потому что похоже, что обновление с ошибкой было правильным. Чтобы иметь линейно разделимый набор случайных точек, сгенерируйте, например, случайный набор положительных примеров и случайный набор отрицательных примеров. - person Octoplus; 14.05.2016
comment
Я имею в виду... если у меня есть набор случайных 2D-точек - он всегда отделяется линией (по крайней мере, одна вертикальная линия всегда жизнеспособна) - person Denis Rozimovschii; 14.05.2016
comment
Не могли бы вы уточнить утверждение о генерации разделимого набора тестов? - person Denis Rozimovschii; 14.05.2016
comment
@DenisRozimovschii Ваш тренировочный набор в порядке, поскольку по их определению они будут либо на линии, либо над ней, либо ниже, следовательно, их можно разделить линией. - person bakkal; 14.05.2016
comment
@bakkal Может быть, мне нужно увеличить количество тренировочных тестов? Но... кажется, что веса не сходятся к какому-то значению, они всегда меняются - person Denis Rozimovschii; 14.05.2016