Как мы знаем, атомы являются строительными блоками материи, а микропроцессоры — строительными блоками компьютера, а персептрон — строительными блоками нейронных сетей.

Если вы видите слово Perceptron, оно состоит из двух слов:

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

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

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

Для приведенного выше примера препятствия являются входными данными, а решение повернуть налево или направо — выходным сигналом.

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

Представление Perceptron

Персептрон состоит из трех основных компонентов:

  • Входные данные. Каждый ввод соответствует функции. Например, в случае человека признаками могут быть возраст, рост, вес и т. д.
  • Вес. Каждый ввод также имеет вес. Вес означает определенную степень важности входных данных. Если вес входа велик, то это означает, что этот вход играет большую роль в определении выхода.
  • Вывод. Наконец, персептрон использует входные данные и веса для получения выходных данных. Тип вывода зависит от характера проблемы. Например, чтобы предсказать, будет ли дождь, выходные данные должны быть двоичными — 1 для «Да» и 0 для «Нет». Однако, чтобы предсказать температуру на следующий день, диапазон выходных данных должен быть больше, например число от -5 до 50.
class Perceptron:
   def __init__(self, num_inputs=2, weights=[1,1]):
      self.num_inputs = num_inputs
      self.weights = weights
cool_perceptron = Perceptron()

В приведенном выше коде мы создали класс Perceptron, в котором мы инициализировали два аргумента num_inputs и weights. num_inputs указывает количество входных данных, а weights указывает вес каждого входного параметра.

Шаг 1. Взвешенная сумма

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

взвешенная сумма=x1​w1​+x2​w2​+…+xnwn

здесь x — это входы, а w — веса каждого из входов.

Для расчета взвешенной суммы:

  1. Начните с взвешенной суммы 0. Назовем ее weighted_sum.
  2. Начните с первого входа и умножьте его на соответствующий вес. Добавьте этот результат к weighted_sum.
  3. Перейдите к следующему входу и умножьте его на соответствующий вес. Добавьте этот результат к weighted_sum.
  4. Повторите этот процесс для всех входов.
class Perceptron:
  def __init__(self, num_inputs=2, weights=[2,1]):
    self.num_inputs = num_inputs
    self.weights = weights
    
  def weighted_sum(self, inputs):
    # create variable to store weighted sum
    weighted_sum = 0
    for i in range(self.num_inputs):
      weighted_sum += inputs[i] * self.weights[i]
    
    return weighted_sum
      
cool_perceptron = Perceptron()
print(cool_perceptron.weighted_sum([24,55]))

Шаг 2. Активация функции

После вычисления взвешенной суммы вторым шагом является ограничение взвешенной суммы для получения желаемого результата.

Представьте, если персептрон имеет входные данные в диапазоне от 100 до 1000, но наша цель — предсказать, произойдет что-то или нет, то есть 1 для «Да» или 0 для «Нет». Это приведет к очень большой взвешенной сумме.

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

Например, вы хотите научить персептрон определять, находится ли точка ниже или выше линии. Мы хотим, чтобы на выходе была метка +1 или -1. Для этого мы используем функцию активации знака, чтобы помочь персептрону принять решение.

  • Если взвешенная сумма положительна, вернуть +1
  • Если взвешенная сумма отрицательна, вернуть -1
class Perceptron:
  def __init__(self, num_inputs=2, weights=[1,1]):
    self.num_inputs = num_inputs
    self.weights = weights
    
  def weighted_sum(self, inputs):
    weighted_sum = 0
    for i in range(self.num_inputs):
      weighted_sum += self.weights[i]*inputs[i]
    return weighted_sum
  
  def activation(self, weighted_sum):
    if weighted_sum >= 0:
      return 1
    if weighted_sum < 0:
      return -1
cool_perceptron = Perceptron()
print(cool_perceptron.weighted_sum([24, 55]))
print(cool_perceptron.activation(52))

Наш персептрон теперь может прогнозировать входные данные, но как мы узнаем, что прогноз правильный?

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

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

В этом примере мы создадим наши собственные обучающие наборы, используя случайные числа.

import random
def generate_training_set(num_points):
   x_coordinates = [random.randint(0, 50) for i in range(num_points)]
   y_coordinates = [random.randint(0, 50) for i in range(num_points)]
   training_set = dict()
   for x, y in zip(x_coordinates, y_coordinates):
      if x <= 45-y:
        training_set[(x,y)] = 1
      elif x > 45-y:
        training_set[(x,y)] = -1
   return training_set
training_set = generate_training_set(5)

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

class Perceptron:
  def __init__(self, num_inputs=2, weights=[1,1]):
    self.num_inputs = num_inputs
    self.weights = weights
    
  def weighted_sum(self, inputs):
    weighted_sum = 0
    for i in range(self.num_inputs):
      weighted_sum += self.weights[i]*inputs[i]
    return weighted_sum
  
  def activation(self, weighted_sum):
    if weighted_sum >= 0:
      return 1
    if weighted_sum < 0:
      return -1
    
  def training(self, training_set):
    for inputs in training_set:
      prediction = self.activation(self.weighted_sum(inputs))
      actual = training_set[inputs]
      error = actual - prediction
      
cool_perceptron = Perceptron()
print(cool_perceptron.weighted_sum([24, 55]))
print(cool_perceptron.activation(52))

Теперь у нас есть ошибки тренировочных наборов, так что же нам с этим делать? Мы медленно подталкиваем персептрон к лучшей версии самого себя, которая в конечном итоге имеет нулевую ошибку.

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

Цель состоит в том, чтобы найти оптимальные комбинации весов, которые дают правильный результат.

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

Важной частью алгоритма является то, где обновить вес.

вес = вес + (ошибка * ввод)

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

class Perceptron:
  def __init__(self, num_inputs=2, weights=[1,1]):
    self.num_inputs = num_inputs
    self.weights = weights
    
  def weighted_sum(self, inputs):
    weighted_sum = 0
    for i in range(self.num_inputs):
      weighted_sum += self.weights[i]*inputs[i]
    return weighted_sum
  
  def activation(self, weighted_sum):
    if weighted_sum >= 0:
      return 1
    if weighted_sum < 0:
      return -1
    
  def training(self, training_set):
    foundLine = False
    while not foundLine:
      total_error = 0
      for inputs in training_set:
        prediction = self.activation(self.weighted_sum(inputs))
        actual = training_set[inputs]
        error = actual - prediction
        total_error += abs(error)
        for i in range(self.num_inputs):
          self.weights[i] += error*inputs[i]
      if total_error == 0:
        foundLine = True
      
cool_perceptron = Perceptron()
small_training_set = {(0,3):1, (3,0):-1, (0,-3):-1, (-3,0):1}
cool_perceptron.training(small_training_set)
print(cool_perceptron.weights)

Теперь мы знаем, как можно научить персептрон выдавать правильные результаты путем настройки весов.

Однако много раз нам требовалась небольшая корректировка нашего персептрона. Воспользуемся помощью весов смещения. Это играет вспомогательную роль для нашего персептрона. Его входное значение по умолчанию равно 1.

Итак, теперь наша новая оценка взвешенной суммы:

взвешенная сумма=x1​w1​+x2​w2​+…+xnwn​+1wb

И теперь наш код будет обновлен до такого вида:

class Perceptron:
  def __init__(self, num_inputs=3, weights=[1,1,1]):
    self.num_inputs = num_inputs
    self.weights = weights
    
  def weighted_sum(self, inputs):
    weighted_sum = 0
    for i in range(self.num_inputs):
      weighted_sum += self.weights[i]*inputs[i]
    return weighted_sum
  
  def activation(self, weighted_sum):
    if weighted_sum >= 0:
      return 1
    if weighted_sum < 0:
      return -1
    
  def training(self, training_set):
    foundLine = False
    while not foundLine:
      total_error = 0
      for inputs in training_set:
        prediction = self.activation(self.weighted_sum(inputs))
        actual = training_set[inputs]
        error = actual - prediction
        total_error += abs(error)
        for i in range(self.num_inputs):
          self.weights[i] += error*inputs[i]
      if total_error == 0:
        foundLine = True
      
cool_perceptron = Perceptron()