Классификация наборов изображений CIFAR-10 на основе линейного SVM

машинное обучение искусственный интеллект алгоритм регулярное выражение

Персональный сайт Red Stone:redstonewill.com

Ранее я использовал шесть статей для подробного ознакомления с теорией алгоритмов и моделью метода опорных векторов SVM по следующим ссылкам:

1. Линейная машина опорных векторов LSVM

2. Двойная машина опорных векторов DSVM

3. Машина опорных векторов ядра KSVM

4. Машина опорных векторов мягких полей

5. Логистическая регрессия ядра KLR

6. Поддержка векторной регрессии SVR

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

После изучения сложных теоретических знаний многие друзья могут очень захотеть написать программу SVM на практическом примере и применить ее на практике. Затем эта статья поможет вам написать собственную программу SVM и применить ее к задаче классификации изображений. Мы выполним проверку программы SVM на классическом наборе данных изображений CIFAR10.

Без лишних слов, давайте начнем!

1. Основная идея SVM

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

Взяв в качестве примера двумерную плоскость, определите прямую линию для классификации положительных и отрицательных образцов, как показано на следующем рисунке:

这里写图片描述

Очевидно, что хотя классификационные строки H1, H2, H3 могут полностью разделять положительные и отрицательные образцы, несомненно, что H3 лучше. Причина в том, что положительные и отрицательные образцы находятся достаточно далеко от H3, то есть интервал «маржа» самый большой. Это основная идея SVM: постарайтесь сделать все выборки как можно дальше от гиперплоскости классификации.

2. Линейная классификация и функция оценки

В алгоритме линейного классификатора входом является x, выходом является y, пусть весовой коэффициент равен W, а коэффициент постоянного члена равен b. Мы определяем функцию оценки s как:

s=Wx+b

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

Если взять в качестве примера распознавание изображений, то есть 3 категории «кошка, собака, корабль». Пусть размер объекта ввода x равен 4, «то есть он содержит 4 значения пикселей», размер W равен 3x4, а размер b равен 3x1. После того, как W и b определены, функция оценки s каждой категории получается как:

这里写图片描述

Как видно из рисунка выше, поскольку всегда есть 3 категории, функция оценки s представляет собой вектор 3x1. Среди них оценка кошки = -96,8, оценка собаки = 437,9, оценка корабля = 61,95. Исходя из значения s, если оценка собаки самая высокая, а оценка кошки самая низкая, вероятность быть предсказанным собакой выше. А реальная метка картинки — кошка.Очевидно, что с точки зрения функции оценки s результат предсказания линейного классификатора неверен.

Обычно, чтобы упростить вычисления, мы напрямую интегрируем W и b в матрицу и добавляем к x дополнительное измерение всех единиц. Таким образом, выражение функции оценки s упрощается:

W:=[W\ \ b]
x:=[x;\ 1]
s=Wx

Примерная схема выглядит следующим образом:

这里写图片描述

3. Стратегия оптимизации и функция потерь

Вообще говоря, стратегия оптимизации SVM состоит в том, чтобы максимизировать расстояние выборки до гиперплоскости классификации. Другими словами, постарайтесь, чтобы положительные и отрицательные образцы имели достаточно широкий интервал от гиперплоскости классификации, что является методом оптимизации измерения на основе расстояния. Для упомянутого выше примера истинная метка изображения — кошка, но полученное значение s — самое низкое, что явно не то, что мы хотим видеть. В лучшем случае должен быть самый высокий балл кошки. Это гарантирует, что вероятность предсказания кошки выше. В настоящее время, используя идею максимизации интервала SVM, требуется, чтобы оценка кота была не только больше, чем значение s других категорий, но и достигала определенного уровня, о котором можно сказать, что он имеет минимальный порог.

Следовательно, эту новую стратегию оптимизации SVM можно понимать следующим образом: функция оценки s, соответствующая правильной категории, должна быть больше, чем функция оценки s других категорий на пороговое значение.\Delta:

s_{y_i}\geq s_j+\Delta

Далее мы можем определить функцию потерь SVM в соответствии с этой идеей:

L_i=\sum_{j\neq y_i}max(0,s_j-s_{y_i}+\Delta )

в,y_iпредставляет правильный класс, а j представляет неправильный класс. отL_iИз выражения видно, что только приs_{y_i}Сравниватьs_jвыше порога\Deltaчас,L_iравен нулю, иначеL_iБольше нуля. Эта стратегия аналогична стратегии максимизации расстояния.

приведите пример, чтобы объяснитьL_iПроцесс расчета: например, функция оценки s=[-1, 5, 4],y_1реальный образец, пусть\Delta=3,но:

L_i=max(0,-1-5+3)+max(0,4-5+3)=0+2=2

Эта функция потерь состоит из двух частей:y_1иy_0,y_1иy_2. так какy_1иy_0разница больше порога\Delta, то его функция потерь равна 0, хотяy_1Сравниватьy_2Большая, но разница меньше порога\Delta, то функция потерь равна 2. Функция общих потерь равна 2.

Выражение такого рода функции потерь обычно называется функцией потерь шарнира «Функция потерь шарнира»:

这里写图片描述

Очевидно, только когдаs_j-s_{y_i} + \Delta < 0, функция потерь равна нулю.

Преимущество этой функции потерь шарнира в том, что она воплощает идею максимизации расстояния SVM, более того, когда функция потерь больше нуля, она является линейной функцией, что удобно для вывода алгоритма градиентного спуска.

В дополнение к этой SVM с линейными потерями в шарнирах существует также SVM с квадратичными потерями в шарнирах, который принимает форму квадрата:

L_i=\sum_{j\neq y_i}max(0,s_j-s_{y_i}+\Delta )^2

По сравнению с SVM с линейными потерями в шарнирах, SVM с квадратичными потерями в шарнирах характеризуется усилением штрафа за точки, которые нарушают пороговые требования интервала.Чем больше нарушение, тем больше штраф. В некоторых практических приложениях SVM с квадратичными потерями в шарнире работает лучше. Какой из них использовать, можно определить путем перекрестной проверки в соответствии с реальными проблемами.

Для пороговых значений гиперпараметров\Delta, общие настройки\Delta=1. Поскольку весовой коэффициент W является масштабируемым, он напрямую влияет на размер функции оценки s. так,\Delta=1или\Delta=10, по сути разницы нет, расширение и сжатие W можно полностью компенсировать\Deltaчисловое воздействие. Поэтому обычно\DeltaУстановите его на 1. Функция потерь в это время:

L_i=\sum_{j\neq y_i}max(0,s_j-s_{y_i}+1 )

В SVM для предотвращения переобучения модели можно использовать метод регуляризации «Regularization». Например, используя регуляризацию L2:

R(W)=\sum_k\sum_lw_{k,l }^2

Функция потерь после введения члена регуляризации:

L=\frac1NL_i+\lambda R(W)

где N — количество обучающих выборок,\lambda– параметр регуляризации, регулируемый. Вообще говоря,\lambdaЧем больше значение, тем больше штраф за вес W;\lambdaЧем меньше штраф, тем меньше штраф за вес W.\lambdaФактически взвешивается соотношение между первым и вторым членами функции потерь:\lambdaЧем больше значение, тем больше штраф за W, принося в жертву интервал между положительными и отрицательными образцами, что может привести к недообучению «недообучения»;\lambdaЧем меньше значение, тем больше получается интервал между положительными и отрицательными выборками, но значение W станет больше, что может привести к переоснащению. В практических приложениях соответствующие параметры регуляризации могут быть выбраны с помощью перекрестной проверки.\lambda.

Нуждается ли постоянный член b в регуляризации? На самом деле то, является ли b регуляризованным или нет, мало влияет на модель. b может быть регуляризованным или нет. В практических приложениях обычно регуляризуется только весовой коэффициент W.

4. Линейный бой SVM

Во-первых, краткое введение в классический набор данных, который мы будем использовать: CIFAR-10.

Набор данных CIFAR-10 состоит из 60 000 цветных изображений RGB 3×32×32, в общей сложности 10 категорий. 50 000 изображений для обучения, 10 000 изображений для тестирования (перекрестная проверка). Самая большая особенность этого набора данных заключается в том, что распознавание переносится на универсальные объекты и применяется к мультиклассификации, Это очень классический и широко используемый набор данных.

这里写图片描述

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

Ссылка: https://pan.baidu.com/s/1iZPwt72j-EpVUbLKgEpYMQ

Пароль: vy1e

Следующий код случайным образом выбирает 5 изображений в каждой категории и отображает:

# Visualize some examples from the dataset.
# We show a few examples of training images from each class.
classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
num_classes = len(classes)
samples_per_class = 7
for y, cls in enumerate(classes):
   idxs = np.flatnonzero(y_train == y)
   idxs = np.random.choice(idxs, samples_per_class, replace=False)
   for i, idx in enumerate(idxs):
       plt_idx = i * num_classes + y + 1
       plt.subplot(samples_per_class, num_classes, plt_idx)
       plt.imshow(X_train[idx].astype('uint8'))
       plt.axis('off')
       if i == 0:
           plt.title(cls)
plt.show()

这里写图片描述

Затем рассчитайте потери шарнира для SVM, включая регуляризацию L2, код выглядит следующим образом:

scores = X.dot(W) 
correct_class_score = scores[range(num_train), list(y)].reshape(-1,1) # (N,1)
margin = np.maximum(0, scores - correct_class_score + 1)
margin[range(num_train), list(y)] = 0
loss = np.sum(margin) / num_train + 0.5 * reg * np.sum(W * W)

Код для вычисления градиента W выглядит следующим образом:

num_classes = W.shape[1]
inter_mat = np.zeros((num_train, num_classes))
inter_mat[margin > 0] = 1
inter_mat[range(num_train), list(y)] = 0
inter_mat[range(num_train), list(y)] = -np.sum(inter_mat, axis=1)

dW = (X.T).dot(inter_mat)
dW = dW/num_train + reg*W

Согласно алгоритму SGD, W обновляется после каждой итерации:

W -=  learning_rate * dW

В процессе обучения используйте метод перекрестной проверки, чтобы выбрать лучший фактор обучения learning_rate и параметр регуляризации reg. Код выглядит следующим образом:

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]

results = {}
best_lr = None
best_reg = None
best_val = -1   # The highest validation accuracy that we have seen so far.
best_svm = None # The LinearSVM object that achieved the highest validation rate.

for lr in learning_rates:
   for reg in regularization_strengths:
       svm = LinearSVM()
       loss_history = svm.train(X_train, y_train, learning_rate = lr, reg = reg, num_iters = 2000)
       y_train_pred = svm.predict(X_train)
       accuracy_train = np.mean(y_train_pred == y_train)
       y_val_pred = svm.predict(X_val)
       accuracy_val = np.mean(y_val_pred == y_val)
       if accuracy_val > best_val:
           best_lr = lr
           best_reg = reg
           best_val = accuracy_val
           best_svm = svm
       results[(lr, reg)] = accuracy_train, accuracy_val
       print('lr: %e reg: %e train accuracy: %f val accuracy: %f' %
             (lr, reg, results[(lr, reg)][0], results[(lr, reg)][1]))
print('Best validation accuracy during cross-validation:\nlr = %e, reg = %e, best_val = %f' %
     (best_lr, best_reg, best_val))

После обучения выберите лучший фактор обучения learning_rate и параметр регуляризации reg и проверьте его на наборе тестовых изображений.Код выглядит следующим образом:

# Evaluate the best svm on test set
y_test_pred = best_svm.predict(X_test)
test_accuracy = np.mean(y_test == y_test_pred)
print('linear SVM on raw pixels final test set accuracy: %f' % test_accuracy)

linear SVM on raw pixels final test set accuracy: 0.384000

Наконец, есть более интересная операция, мы можем визуализировать тренированный вес W:

# Visualize the learned weights for each class.
# Depending on your choice of learning rate and regularization strength, these may
# or may not be nice to look at.
w = best_svm.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, имеют сходство в классе отсчетов, к которому они принадлежат, что и учит линейный SVM.

5. Резюме

Линейный SVM, описанный в этой статье, использует идею наибольшего интервала расстояния и стратегию оптимизации потери шарнира для построения модели машинного обучения и применяет эту простую модель к набору изображений CIFAR-10 для обучения и тестирования. Фактическая точность теста составляет около 40%. Хотя показатель точности не очень высок, эта SVM является линейной моделью, она не вводит функцию ядра для построения нелинейной модели и не использует сверточные сети, такие как AlexNet, VGG, GoogLeNet и ResNet. Результат теста намного лучше, чем случайное угадывание 10%, и это хорошая практичная и интересная модель.

Чтобы получить полный код, нажмите «Источник».

исходный код


Использованная литература:

http://cs231n.github.io/linear-classify/