Scikit-узнайте распознавание знака SVM

Я хочу, чтобы программа распознала цифру в изображении. Я следую учебному курсу в scikit learn .

Я могу обучать и сопоставлять классификатор svm следующим образом.

Во-первых, я импортирую библиотеки и набор данных

from sklearn import datasets, svm, metrics digits = datasets.load_digits() n_samples = len(digits.images) data = digits.images.reshape((n_samples, -1)) 

Во-вторых, я создаю модель SVM и тренирую ее с помощью набора данных.

 classifier = svm.SVC(gamma = 0.001) classifier.fit(data[:n_samples], digits.target[:n_samples]) 

И затем, я пытаюсь прочитать свое собственное изображение и использовать функцию predict() чтобы распознать цифру.

Вот мое изображение: введите описание изображения здесь

Я преобразую изображение в (8, 8), а затем преобразую его в 1D-массив.

 img = misc.imread("w1.jpg") img = misc.imresize(img, (8, 8)) img = img[:, :, 0] 

Наконец, когда я распечатываю прогноз , он возвращает [1]

 predicted = classifier.predict(img.reshape((1,img.shape[0]*img.shape[1] ))) print predicted 

Независимо от того, что я сделал другим пользователям, он все равно возвращает [1]

введите описание изображения здесь введите описание изображения здесь

Когда я распечатываю «набор данных по умолчанию» с номером «9», он выглядит так: введите описание изображения здесь

Мой номер изображения «9»:

введите описание изображения здесь

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

Я не знаю, почему. Я ищу помощь для решения моей проблемы. благодаря

Моя лучшая ставка будет заключаться в том, что есть проблемы с вашими типами данных и формами массива.

Похоже, вы тренируетесь по массивам numpy, которые имеют тип np.float64 (или, возможно, np.float32 на 32-битных системах, я не помню) и где каждое изображение имеет форму (64,) .

Между тем ваше входное изображение для предсказания после операции изменения размера в вашем коде имеет тип uint8 и форму (1, 64) .

Сначала я попытался бы изменить форму вашего входного изображения, так как преобразования dtype часто работают так, как вы ожидали. Поэтому измените эту строку:

predicted = classifier.predict(img.reshape((1,img.shape[0]*img.shape[1] )))

к этому:

predicted = classifier.predict(img.reshape(img.shape[0]*img.shape[1]))

Если это не исправить, вы всегда можете попробовать перепрофилировать тип данных, а также

img = img.astype(digits.images.dtype) .

Надеюсь, это поможет. Отладка через прокси намного сложнее, чем на самом деле сидеть перед вашим компьютером 🙂

Изменить: согласно документации SciPy, данные обучения содержат целочисленные значения от 0 до 16. Значения в вашем исходном изображении должны масштабироваться так, чтобы они соответствовали одному и тому же интервалу. ( http://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_digits.html#sklearn.datasets.load_digits )

1) Вам необходимо создать свой собственный набор тренировок – на основе данных, аналогичных тем, что вы будете делать прогнозы. Призыв к datasets.load_digits() в scikit-learn загружает предварительно обработанную версию набора данных MNIST Digits, которая, насколько нам известно, может иметь очень разные изображения для тех, которые вы пытаетесь распознать.

2) Вам необходимо правильно установить параметры вашего классификатора. Вызов svm.SVC(gamma = 0.001) – это просто выбор произвольного значения параметра гамма в SVC, что может быть не лучшим вариантом. Кроме того, вы не настраиваете параметр C, что очень важно для SVM. Я бы сказал, что это одна из причин, почему ваш вывод «всегда 1».

3) Независимо от того, какие конечные настройки вы выберете для своей модели, вам необходимо использовать схему перекрестной проверки, чтобы гарантировать, что алгоритм эффективно изучает

За этим стоит много теории машинного обучения, но, как хорошее начало, я бы порекомендовал взглянуть на SVM-scikit-learn для более подробного описания того, как работает реализация SVC в работе с болезнью, и GridSearchCV для простой методики настройки параметров.

Это всего лишь предположение, но … Набор для обучения Sk-Learn – это черные цифры на белом фоне . И вы пытаетесь предсказать цифры, белые на черном фоне …

Я думаю, вам нужно либо тренироваться на тренировочном наборе, либо тренироваться в негативной версии ваших фотографий.

Надеюсь, эта помощь!

Если вы посмотрите на: http://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_digits.html#sklearn.datasets.load_digits

вы можете видеть, что каждая точка в матрице равна 0-16.

Вы можете попытаться преобразовать значения изображения между 0-16. Я сделал это, и теперь прогноз хорошо подходит для цифры 9, но не для 8 и 6. Это больше не дает 1.

 from sklearn import datasets, svm, metrics import cv2 import numpy as np # Load digit database digits = datasets.load_digits() n_samples = len(digits.images) data = digits.images.reshape((n_samples, -1)) # Train SVM classifier classifier = svm.SVC(gamma = 0.001) classifier.fit(data[:n_samples], digits.target[:n_samples]) # Read image "9" img = cv2.imread("w1.jpg") img = img[:,:,0]; img = cv2.resize(img, (8, 8)) # Normalize the values in the image to 0-16 minValueInImage = np.min(img) maxValueInImage = np.max(img) normaliizeImg = np.floor(np.divide((img - minValueInImage).astype(np.float),(maxValueInImage-minValueInImage).astype(np.float))*16) # Predict predicted = classifier.predict(normaliizeImg.reshape((1,normaliizeImg.shape[0]*normaliizeImg.shape[1] ))) print predicted 

Я решил эту проблему, используя ниже методы:

  1. проверьте количество атрибутов, слишком большое или слишком маленькое.

  2. проверьте масштаб вашего серого значения, я перехожу на [0,16].

  3. проверьте тип данных, я меняю его на uint8.

  4. проверьте количество данных обучения, слишком малое или нет.

Я надеюсь, что это помогает. ^. ^

Привет, в дополнение к @carrdelling, я добавлю, что вы можете использовать один и тот же набор упражнений, если вы нормализуете свои изображения, чтобы иметь тот же диапазон значений. Например, вы можете использовать ваши данные (1, если> 0, 0 else), или вы можете разделить на максимальную интенсивность изображения, чтобы иметь произвольный интервал [0; 1].

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

surf = cv2.SURF(400) kp, des = surf.detectAndCompute(img,None)

Но функции SURF могут быть не самыми полезными или важными для вашего набора данных и задачи обучения. Вы должны также попробовать других, таких как HOG или другие.

Помните, что на более высоком уровне функции, которые вы извлекаете, более общая / устойчивая к ошибкам ваша модель будет заключаться в невидимых изображениях. Тем не менее, вы можете жертвовать точностью в своих известных образцах и тестовых случаях.