Персональный сайт Red Stone:redstonewill.com
1. Что такое Софтмакс
Softmax имеет очень широкий спектр приложений в машинном обучении и глубоком обучении. Особенно при работе с задачами множественной классификации (C > 2) конечная единица вывода классификатора требует функции Softmax для числовой обработки. Определение функции Softmax выглядит следующим образом:
Среди них Vi является выходом предыдущего блока вывода классификатора. i представляет индекс категории, а общее количество категорий равно C. Si представляет собой отношение индекса текущего элемента к сумме индексов всех элементов. Softmax преобразует выходные значения нескольких классификаций в относительные вероятности, которые легче понять и сравнить. Давайте посмотрим на пример ниже.
Многоклассовая задача с C=4. Последний выходной слой модели линейного классификатора содержит четыре выходных значения:
После обработки Softmax значения конвертируются в относительные вероятности:
Понятно, что выходные данные Softmax представляют собой относительную вероятность между различными классами. Мы ясно видим, что S1 = 0,8390, соответствующая вероятность является наибольшей, можно более четко судить, что прогноз скорее относится к классу 1. Softmax преобразует непрерывные значения в относительные вероятности, что более удобно для нашего понимания.
В практических приложениях использование Softmax требует внимания к проблеме числового переполнения. Из-за экспоненциальной операции, если значение V велико, значение после экспоненциальной операции может часто переполняться. Таким образом, требуются некоторые числовые манипуляции с V: то есть каждый элемент в V минус максимальное значение в V.
Соответствующий пример кода Python выглядит следующим образом:
scores = np.array([123, 456, 789]) # example with 3 classes and each having large scores
scores -= np.max(scores) # scores becomes [-666, -333, 0]
p = np.exp(scores) / np.sum(np.exp(scores))
2. Функция потерь Softmax
Мы знаем, что выходом линейного классификатора является вход x, умноженный на матрицу весовых коэффициентов: s = Wx. Для задач с несколькими классами используйте Softmax для обработки линейного вывода. В этом разделе мы обсудим функцию потерь Softmax.
Среди них Syi — это функция линейной оценки, соответствующая правильной категории, а Si — результат Softmax, соответствующий правильной категории.
Поскольку лог-оператор не влияет на монотонность функции, записываем Si:
Мы надеемся, что чем больше Si, тем лучше, то есть чем больше относительная вероятность, соответствующая правильной категории, тем лучше, тогда мы можем добавить знак минус перед Si для представления функции потерь:
Дальнейшая обработка приведенной выше формулы приводит к уменьшению показателя степени:
Таким образом, функция потерь Softmax преобразуется в простую форму.
В качестве простого примера линейный вывод, полученный в предыдущем подразделе, выглядит следующим образом:
Предполагая, что i = 1 является реальной выборкой, функция потерь рассчитывается как:
3. Обратный градиент Softmax
После получения функции потерь Softmax перейдите к обратному выводу весовых параметров.
В линейном классификаторе Softmax линейный вывод:
где индекс i представляет i-ю выборку.
Программирование процесса вывода делится на два метода: один заключается в использовании вложенных циклов for, а другой — в непосредственном использовании матричных операций.
Используя вложенные циклы for, производная функция для весов W определяется следующим образом:
def softmax_loss_naive(W, X, y, reg):
"""
Softmax loss function, naive implementation (with loops)
Inputs have dimension D, there are C classes, and we operate on minibatches
of N examples.
Inputs:
- W: A numpy array of shape (D, C) containing weights.
- X: A numpy array of shape (N, D) containing a minibatch of data.
- y: A numpy array of shape (N,) containing training labels; y[i] = c means
that X[i] has label c, where 0 <= c < C.
- reg: (float) regularization strength
Returns a tuple of:
- loss as single float
- gradient with respect to weights W; an array of same shape as W
"""
# Initialize the loss and gradient to zero.
loss = 0.0
dW = np.zeros_like(W)
num_train = X.shape[0]
num_classes = W.shape[1]
for i in xrange(num_train):
scores = X[i,:].dot(W)
scores_shift = scores - np.max(scores)
right_class = y[i]
loss += -scores_shift[right_class] + np.log(np.sum(np.exp(scores_shift)))
for j in xrange(num_classes):
softmax_output = np.exp(scores_shift[j]) / np.sum(np.exp(scores_shift))
if j == y[i]:
dW[:,j] += (-1 + softmax_output) * X[i,:]
else:
dW[:,j] += softmax_output * X[i,:]
loss /= num_train
loss += 0.5 * reg * np.sum(W * W)
dW /= num_train
dW += reg * W
return loss, dW
Используя матричные операции, производная функция для веса W определяется следующим образом:
def softmax_loss_vectorized(W, X, y, reg):
"""
Softmax loss function, vectorized version.
Inputs and outputs are the same as softmax_loss_naive.
"""
# Initialize the loss and gradient to zero.
loss = 0.0
dW = np.zeros_like(W)
num_train = X.shape[0]
num_classes = W.shape[1]
scores = X.dot(W)
scores_shift = scores - np.max(scores, axis = 1).reshape(-1,1)
softmax_output = np.exp(scores_shift) / np.sum(np.exp(scores_shift), axis=1).reshape(-1,1)
loss = -np.sum(np.log(softmax_output[range(num_train), list(y)]))
loss /= num_train
loss += 0.5 * reg * np.sum(W * W)
dS = softmax_output.copy()
dS[range(num_train), list(y)] += -1
dW = (X.T).dot(dS)
dW = dW / num_train + reg * W
return loss, dW
Практическая проверка показывает, что матричные операции выполняются намного быстрее, чем вложенные циклы, особенно при большом количестве обучающих выборок. Мы используем около 5000 образцов в наборе данных CIFAR-10 для тестирования и сравнения двух методов деривации:
tic = time.time()
loss_naive, grad_naive = softmax_loss_naive(W, X_train, y_train, 0.000005)
toc = time.time()
print('naive loss: %e computed in %fs' % (loss_naive, toc - tic))
tic = time.time()
loss_vectorized, grad_vectorized = softmax_loss_vectorized(W, X_train, y_train, 0.000005)
toc = time.time()
print('vectorized loss: %e computed in %fs' % (loss_vectorized, toc - tic))
grad_difference = np.linalg.norm(grad_naive - grad_vectorized, ord='fro')
print('Loss difference: %f' % np.abs(loss_naive - loss_vectorized))
print('Gradient difference: %f' % grad_difference)
Результат отображается как:
naive loss: 2.362135e+00 computed in 14.680000s
vectorized loss: 2.362135e+00 computed in 0.242000s
Loss difference: 0.000000
Gradient difference: 0.000000
Очевидно, что матричная операция в этом примере выполняется в 60 раз быстрее, чем вложенный цикл. Поэтому, когда мы пишем модели алгоритмов машинного обучения, мы должны попытаться использовать матричные операции и использовать меньше вложенных циклов для повышения скорости работы.
4. Софтмакс и SVM
Функция потерь линейного классификатора Softmax вычисляет относительную вероятность, также известную как потеря перекрестной энтропии «Потеря перекрестной энтропии». Основное различие между линейными классификаторами SVM и линейными классификаторами Softmax заключается в функции потерь. SVM использует потерю шарнира и уделяет больше внимания расстоянию между правильным образцом и неправильным образцом «Δ = 1», пока расстояние больше, чем Δ, ему все равно, насколько расстояние отличается, игнорируя детали. . И функция оценки каждой категории в Softmax влияет на размер ее функции потерь. Например, количество категорий C = 3, функции оценки двух выборок — [10, -10, -10], [10, 9, 9], а истинная метка — 0-я категория. Для SVM оба Li равны 0, но для Softmax эти два Li равны 0,00 и 0,55 соответственно, что сильно отличается.
По поводу линейного классификатора SVM я представил его в прошлой статье портала:
Классификация наборов изображений CIFAR-10 на основе линейного SVM
Далее поговорим о влиянии параметра регуляризации λ на Softmax. Мы знаем, что целью регуляризации является ограничение размера весового параметра W для предотвращения переобучения. Чем больше параметр регуляризации λ, тем больше он ограничивает W. Например, линейный вывод 3-классификации равен [1, -2, 0], а соответствующий вывод Softmax — [0,7, 0,04, 0,26]. Предполагая, что положительный класс — это класс 0, очевидно, что 0,7 намного больше, чем 0,04 и 0,26.
Если используется параметр регуляризации λ, поскольку размер W ограничен, полученный линейный выход также будет пропорционально уменьшен: [0,5, -1, 0], а соответствующий выход Softmax равен [0,55, 0,12, 0,33]. Очевидно, что разрыв относительной вероятности между правильными выборками и неправильными выборками становится меньше.
Другими словами, чем больше параметр регуляризации λ, тем ближе результаты каждой категории Softmax. Большой λ фактически «гомогенизирует» относительную вероятность между правильными и неправильными выборками. Однако относительный порядок величин вероятности не меняется, что необходимо отметить. Следовательно, это не повлияет на алгоритм оптимизации Loss.
5. Практическое применение Softmax
Классифицируйте набор изображений CIFAR-10 с помощью линейного классификатора Softmax.
Используя перекрестную проверку, выберите лучший фактор обучения и параметр регуляризации:
# Use the validation set to tune hyperparameters (regularization strength and
# learning rate). You should experiment with different ranges for the learning
# rates and regularization strengths; if you are careful you should be able to
# get a classification accuracy of over 0.35 on the validation set.
results = {}
best_val = -1
best_softmax = None
learning_rates = [1.4e-7, 1.5e-7, 1.6e-7]
regularization_strengths = [8000.0, 9000.0, 10000.0, 11000.0, 18000.0, 19000.0, 20000.0, 21000.0]
for lr in learning_rates:
for reg in regularization_strengths:
softmax = Softmax()
loss = softmax.train(X_train, y_train, learning_rate=lr, reg=reg, num_iters=3000)
y_train_pred = softmax.predict(X_train)
training_accuracy = np.mean(y_train == y_train_pred)
y_val_pred = softmax.predict(X_val)
val_accuracy = np.mean(y_val == y_val_pred)
if val_accuracy > best_val:
best_val = val_accuracy
best_softmax = softmax
results[(lr, reg)] = training_accuracy, val_accuracy
# Print out results.
for lr, reg in sorted(results):
train_accuracy, val_accuracy = results[(lr, reg)]
print('lr %e reg %e train accuracy: %f val accuracy: %f' % (
lr, reg, train_accuracy, val_accuracy))
print('best validation accuracy achieved during cross-validation: %f' % best_val)
После обучения проверьте на тестовом наборе изображений:
# evaluate on test set
# Evaluate the best softmax on test set
y_test_pred = best_softmax.predict(X_test)
test_accuracy = np.mean(y_test == y_test_pred)
print('softmax on raw pixels final test set accuracy: %f' % (test_accuracy, ))
softmax on raw pixels final test set accuracy: 0.386000
Код визуализации весового параметра W выглядит следующим образом:
# Visualize the learned weights for each class
w = best_softmax.W[:-1,:] # strip out the bias
w = w.reshape(32, 32, 3, 10)
w_min, w_max = np.min(w), np.max(w)
classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
for i in range(10):
plt.subplot(2, 5, i + 1)
# Rescale the weights to be between 0 and 255
wimg = 255.0 * (w[:, :, :, i].squeeze() - w_min) / (w_max - w_min)
plt.imshow(wimg.astype('uint8'))
plt.axis('off')
plt.title(classes[i])
Ясно, что после обучения W содержит некоторые простые признаки оттенка и контура соответствующего класса.
Чтобы получить полный код этой статьи, нажмите «Исходный код».
использованная литература:
http://cs231n.github.io/linear-classify/