Продолжим наше обсуждение темы «Основы глубокого обучения» и обсудим кросс-энтропийную функцию ошибок. Не волнуйтесь по поводу такого названия, в действительности суть очень проста. Напомним, что в наших прошедших статьях по логистической регрессии мы рассматривали квадратичную функцию ошибок:
Применительно к регрессии, это менее универсальная функция, поскольку она предполагает, что наша ошибка имеет гауссово распределение.
Содержание страницы
Кросс-энтропийная функция ошибок. Теория
Разумеется, при логистической регрессии ошибка не может иметь гауссова распределения, так как результат находится между нулём и единицей, а целевая переменная принимает значения только 0 и 1. Именно поэтому нам и нужна другая функция ошибок.
Что нам нужно от функции ошибок?
Прежде всего, она должна равняться нулю, если ошибок нет, и иметь тем большее значение, чем больше оказывается ошибок. Итак, посмотрим, как кросс-энтропийная функция со всем этим справляется.
Кросс-энтропийная функция ошибок определяется так:
где t – целевая переменная, y – результат логистической регрессии.
Прежде всего отметим, что существенным является только один член уравнения. Это происходит потому, что целевая переменная t принимает значения лишь 0 и 1. Если t = 1, существенным является первый член, если t = 0, – то второй.
Далее, поскольку y – исходящая переменная логистической регрессии, принимающая значение от нуля до единицы, то логарифм этой величины принимает значения от нуля до минус бесконечности. Но обратите внимание на знак «минус» в формуле. Таким образом, получив минус бесконечность, в конечном результате у нас получится плюс бесконечность.
Рассмотрим теперь несколько примеров. Пусть у нас t = 1, y = 1. В результате получим единицу, умноженную на нуль, то есть нуль. Таким образом, ошибка равна нулю. Замечательно. Обратите внимание, что если t = 0, y = 0, то получится такой же результат.
Пусть теперь t = 1, y = 0,9, то есть модель почти правильная. В результате получим 0,11, – весьма небольшая ошибка, так что тут тоже всё замечательно. Если мы установим t = 1, y = 0,5, то есть модель находится на грани корректности, то в качестве результата функции ошибок получим 0,69 – это куда большая ошибка, свидетельствующая, что модель работает так себе. Пусть теперь t = 0, y = 0,1, то есть мы очень сильно ошибаемся. В результате получим значение функции ошибки 2,3 – это ещё большее значение.
Таким образом, кросс-энтропийная функция ошибок работает, как и предполагалось.
Наконец, обратите внимание, что нам нужно рассчитать общую ошибку, чтобы одновременно оптимизировать параметры модели по всему набору данных. Для этого мы суммируем значения всех отдельных ошибок от 1 до N, что и даёт нам общую кросс-энтропийную функцию ошибок:
Кросс-энтропийная функция ошибок. Код
Теперь рассмотрим вычисление кросс-энтропийной функции ошибок в коде.
Сначала мы перенесём часть кода из предыдущего файла.
import numpy as np
N = 100
D = 2
X = np.random.randn(N,D)
Теперь создадим два наших класса, причём первые 50 точек будут концентрироваться в районе с центром (-2; -2), а вторые 50 – в районе с центром (+2; +2).
X[:50, :] = X[:50, :] – 2*np.ones((50, D))
X[:50, :] = X[:50, :] + 2*np.ones((50, D))
Создадим массив целевых переменных, причём первые 50 будут относиться к классу 0, а вторые 50 – классу 1.
T = np.array([0]*50 + [1]*50)
Создание столбца из единиц мы тоже можем скопировать из предыщуего кода, как и часть кода, посвящённая вычислению сигмоиды.
ones = np.array([[1]*N]).T
Xb = np.concatenate((ones, X), axis=1)
w = np.random.randn(D + 1)
z = Xb.dot(w)
def sigmoid(z):
return 1/(1 + np.exp(-z))
Y = sigmoid(z)
Теперь напишем функцию для вычисления кросс-энтропийной функции ошибок. Она зависит от значения целевой переменной и исходящей переменной логистической регрессии.
def cross_entropy(T, Y):
E = 0
for i in xrange(N):
если T[i] == 1:
E -= np.log(Y[i])
еще:
E -= np.log(1 – Y[i])
return E
print cross_entropy (T, Y)
Запустим программу. Наша кросс-энтропийная ошибка составляет 52,1763501199.
Было бы неплохо заодно найти уже рассматривавшееся частное решение для логистической регрессии. Его использование правомерно, поскольку наши данные имеют одинаковую дисперсию в обоих классах. Мы рекомендуем вам самостоятельно вычислить, что смещение равно нулю, а оба весовых коэффициента равны 4, чтобы понимать, откуда взялись именно такие цифры.
w = np.array([0, 4, 4])
z = Xb.dot(w)
Y = sigmoid(z)
print cross_entropy(T, Y)
Запустив программу, вы можете убедиться, что при использовании частного решения логистической регрессии кросс-энтропийная ошибка становится значительно меньше.
Визуализация линейного разделителя
В этом разделе статьи мы графически изобразим решение для байесовского классификатора, найденное нами выше.
Скопируем код из предыдущей статьи. Единственное отличие – на этот раз мы импортируем ещё и библиотеку Matplotlib.
import numpy as np
import matplotlib.pyplot as plt
N = 100
D = 2
X = np.random.randn(N,D)
У нас уже есть код для создания данных, которые составляют два гауссовых облака, одно из которых имеет центром точку (-2; -2), а второе – точку (+2; +2).
X[:50, :] = X[:50, :] – 2*np.ones((50, D))
X[:50, :] = X[:50, :] + 2*np.ones((50, D))
T = np.array([0]*50 + [1]*50)
У нас есть также целевая переменная, принимающая значение нуль и единица. Кроме того, мы вычислили байесовский классификатор и сигмоиду.
ones = np.array([[1]*N]).T
Xb = np.concatenate((ones, X), axis=1)
def sigmoid(z):
return 1/(1 + np.exp(-z))
Мы уже знаем, что решением для байесовского классификатора являются 0, 4, 4, где 0 – это точка пересечения с осью y. Следовательно, искомая прямая имеет вид y = -x. Установим цвета для диаграммы рассеяния наших целевых переменных, установим количество точек, равное 100, и α = 0,5.
plt.scatter(X[:,0], X[:,1] c=T, s=100, alpha=0.5)
Прорисовав точки, изобразим теперь прямую. Установим для x начальную точку (-6; -6) и прорисуем ещё 100 точек прямой.
x_axis = np.linspace(-6, 6, 100)
y_axis = -x_axis
plt.plot(x_axis, y_axis)
plt.show
Запустим программу.
Итак, мы можем видеть два гауссова облака данных и разделяющую линию.