Распознавание рукописных цифр с использованием алгоритма SVM

искусственный интеллект Идентификация изображения
Распознавание рукописных цифр с использованием алгоритма SVM

«Это 23-й день моего участия в ноябрьском испытании обновлений. Подробную информацию об этом событии см.:Вызов последнего обновления 2021 г."

предисловие

Машины опорных векторов (Support Vector Machine, SVM) — это метод обучения с учителем, который строит гиперплоскость или набор гиперплоскостей в многомерном пространстве путем оптимального разделения обучающих данных в соответствии с указанными классами. существуетOpenCVмогут быть реализованы и обученыSVMалгоритм, в этой статье мы научимся использоватьSVMКлассификатор выполняет распознавание рукописных цифр, а также исследует влияние различных параметров на производительность модели для достижения наилучшей производительности.SVMКлассификатор.

Распознавание рукописных цифр с помощью SVM

мы уже«Распознавание рукописных цифр с помощью алгоритма KNN»введен вMNISTНабор данных рукописных цифр и как его использоватьKNNАлгоритмы распознают рукописные цифры. А предварительно обработав цифровое изображение (desew()функцию) и использовать высокоуровневые дескрипторы (HOGдескриптор) в качестве вектора признаков, используемого для описания каждой цифры для получения наилучшей точности классификации. Поэтому один и тот же контент не будет повторяться и будет использоваться непосредственно в следующих«Распознавание рукописных цифр с помощью алгоритма KNN»Предварительная обработка иHOGособенность, использованиеSVMАлгоритмы классифицируют цифровые изображения.

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

# 加载数据
(train_dataset, train_labels), (test_dataset, test_labels) = keras.datasets.mnist.load_data()
SIZE_IMAGE = train_dataset.shape[1]
train_labels = np.array(train_labels, dtype=np.int32)
# 预处理函数
def deskew(img):
    m = cv2.moments(img)
    if abs(m['mu02']) < 1e-2:
        return img.copy()
    skew = m['mu11'] / m['mu02']
    M = np.float32([[1, skew, -0.5 * SIZE_IMAGE * skew], [0, 1, 0]])
    img = cv2.warpAffine(img, M, (SIZE_IMAGE, SIZE_IMAGE), flags=cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)

    return img
# HOG 高级描述符
def get_hog():
    hog = cv2.HOGDescriptor((SIZE_IMAGE, SIZE_IMAGE), (8, 8), (4, 4), (8, 8), 9, 1, -1, 0, 0.2, 1, 64, True)

    print("hog descriptor size: {}".format(hog.getDescriptorSize()))

    return hog
# 数据打散
shuffle = np.random.permutation(len(train_dataset))
train_dataset, train_labels = train_dataset[shuffle], train_labels[shuffle]

hog = get_hog()

hog_descriptors = []
for img in train_dataset:
    hog_descriptors.append(hog.compute(deskew(img)))
hog_descriptors = np.squeeze(hog_descriptors)

results = defaultdict(list)
# 数据划分
split_values = np.arange(0.1, 1, 0.1)

Далее инициализируйтеSVMи обучить его:

# 模型初始化函数
def svm_init(C=12.5, gamma=0.50625):
    model = cv2.ml.SVM_create()
    model.setGamma(gamma)
    model.setC(C)
    model.setKernel(cv2.ml.SVM_RBF)
    model.setType(cv2.ml.SVM_C_SVC)
    model.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6))

    return model
# 模型训练函数
def svm_train(model, samples, responses):
    model.train(samples, cv2.ml.ROW_SAMPLE, responses)
    return model
# 模型预测函数
def svm_predict(model, samples):
    return model.predict(samples)[1].ravel()
# 模型评估函数
def svm_evaluate(model, samples, labels):
    predictions = svm_predict(model, samples)
    acc = (labels == predictions).mean()
    print('Percentage Accuracy: %.2f %%' % (acc * 100))
    return acc *100
# 使用不同训练集、测试集划分方法进行训练和测试
for split_value in split_values:
    partition = int(split_value * len(hog_descriptors))
    hog_descriptors_train, hog_descriptors_test = np.split(hog_descriptors, [partition])
    labels_train, labels_test = np.split(train_labels, [partition])

    print('Training SVM model ...')
    model = svm_init(C=12.5, gamma=0.50625)
    svm_train(model, hog_descriptors_train, labels_train)

    print('Evaluating model ... ')
    acc = svm_evaluate(model, hog_descriptors_test, labels_test)
    results['svm'].append(acc)

使用 SVM 进行手写数字识别

На изображении выше, используя параметры по умолчаниюSVMМодель может достичь точности 98,60% при использовании 70% цифровых изображений для обучения алгоритма.Далее мы изменимSVMПараметры C и γ модели для проверки возможности улучшения модели.

Влияние параметров C и γ на точность распознавания рукописных цифр

SVMмодель в использованииRBFПри использовании ядра есть два важных параметра — C и γ, в приведенном выше примере мы используемC=12.5иγ=0.50625Как значения параметров, настройки C и γ зависят от конкретного набора данных. Следовательно, необходимо использовать какой-либо метод поиска параметров, в данном случае поиск по сетке подходящих параметров C и γ.

for C in [1, 10, 100, 1000]:
    for gamma in [0.1, 0.15, 0.25, 0.3, 0.35, 0.45, 0.5, 0.65]:
        model = svm_init(C, gamma)
        svm_train(model, hog_descriptors_train, labels_train)
        acc = svm_evaluate(model, hog_descriptors_test, labels_test)
        print(" {}".format("%.2f" % acc))
        results[C].append(acc)

Наконец, визуализируйте результаты:

fig = plt.figure(figsize=(10, 6))
plt.suptitle("SVM handwritten digits recognition", fontsize=14, fontweight='bold')
ax = plt.subplot(1, 1, 1)
ax.set_xlim(0, 0.65)
dim = [0.1, 0.15, 0.25, 0.3, 0.35, 0.45, 0.5, 0.65]

for key in results:
    ax.plot(dim, results[key], linestyle='--', marker='o', label=str(key))

plt.legend(loc='upper left', title="C")
plt.title('Accuracy of the SVM model varying both C and gamma')
plt.xlabel("gamma")
plt.ylabel("accuracy")
plt.show()

Результат работы программы следующий:

参数 C 和 γ 对识别手写数字精确度的影响

Как показано на рисунке, при использовании различных параметров точность может достигать 99,25%. По сравнениюKNNклассификатор иSVMПроизводительность классификатора в задаче распознавания рукописных цифр, можно сделать вывод, что в задаче распознавания рукописных цифрSVMлучше чемKNNЗаключение классификатора.

Ссылки по теме

Распознавание рукописных цифр с помощью алгоритма KNN