sklearn всегда предсказывает 1 при попытке предсказать цифры

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

матрица 2d (это похоже на круг, который у меня есть в блендере):

[[  0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.  25.  25.   0.   0.   0.]
 [  0.  25.  25.  25.   0.  25.  25.   0.]
 [  0.  25.   0.   0.   0.   0.  25.   0.]
 [  0.  25.   0.   0.   0.   0.  25.   0.]
 [  0.  25.   0.   0.   0.   0.  25.   0.]
 [  0.   0.  25.  25.  25.  25.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.]]

код:

import bpy
import numpy as np
from sklearn import datasets
from sklearn import svm
import scipy.misc

ob = bpy.context.object
assert ob.type == 'CURVE' # throw error if it's not a curve
curve = ob.data
spline = curve.splines.active # let's assume there's only one
assert spline.type == 'BEZIER' # throw error if it's not a bezier

shortest = None
shortestDist = 10000
shortest_x = None
shortestDist_x = 10000
result = []
for point in spline.bezier_points:
    dist = point.co.y
    dist_x = point.co.x
    if dist < shortestDist : #test if better so far
        shortest = point
        shortestDist = dist   
    if dist_x < shortestDist_x : #test if better so far
        shortest_x = point
        shortestDist_x = dist  

print(1 / abs(shortest.co.y))
result.append([shortest, shortestDist, dist, dist_x])
mult_y = 1 / abs(shortest.co.y)
mult_x = 1 / abs(shortest_x.co.x)
point_pos = []
for point in spline.bezier_points:
    loc = point.co.y
    loc_x = point.co.x
    max_y = loc * mult_y
    max_x = loc_x * mult_x
    point_pos.append([loc, loc_x])

matrix = np.zeros((8, 8))
pixel = []

for index in enumerate(matrix):
    matrix_to_co_y = 1 / len(matrix) * index[0]
    for index_y in enumerate(matrix[index[0]]):
        matrix_to_co_x = 1 / len(matrix) * index_y[0]
        #print(matrix_to_co_y)
        for point in point_pos:
            if matrix_to_co_y > point[0] > matrix_to_co_y - 1 / len(matrix):
                if matrix_to_co_x > point[1] > matrix_to_co_x - 1 / len(matrix):
                    pixel.append([index[0], index_y[0]])

for p in enumerate(pixel):
    matrix[p[1][0]][p[1][1]] = 25

flat = np.ravel(matrix)


digits = datasets.load_digits()

clf = svm.SVC(gamma=0.001, C=100)

x,y = digits.data[:-1], digits.target[:-1]
clf.fit(x,y)
print('Prediction:',clf.predict([flat]))

print(matrix)

Я не знаю, что я делаю неправильно. Любая помощь будет оценена


person Jonas Dichelle    schedule 22.11.2017    source источник
comment
Я бы посоветовал вам взглянуть на учебник scikit-learn. Там они показывают классификацию рукописных цифр. scikit-learn.org/stable/tutorial/basic/ Если вы можете ввести свой ввод в том же формате, что и набор данных Digits, вы сможете следовать учебному пособию точка за точкой.   -  person KPLauritzen    schedule 22.11.2017
comment
@KPLauritzen Я пробовал, матрица выглядит идентично матрицам из тренировочных данных.   -  person Jonas Dichelle    schedule 22.11.2017
comment
Что произойдет, если вы попытаетесь предсказать некоторые входные данные из набора данных digits? Кроме того, не могли бы вы попробовать использовать np.reshape или np.flatten вместо np.ravel. Я думаю, вы получаете плоский вектор из столбцов вместо строк из матрицы изображения.   -  person KPLauritzen    schedule 23.11.2017
comment
@KPLauritzen цифры из набора данных работают отлично, и мой массив имеет тот же формат, что и цифры, но всегда возвращает только 1 :(   -  person Jonas Dichelle    schedule 24.11.2017


Ответы (2)


Это может быть проблема либо с вашим входным изображением, либо с классификатором. Чтобы проверить, в чем проблема, вы можете

1) Попробуйте использовать более одного входного изображения. Попробуйте сделать по одному изображению для каждой цифры от 0 до 9. Если ваш классификатор предсказывает «1» для всех из них, проблема, вероятно, в классификаторе. Но если он может предсказать некоторые из них, то, скорее всего, именно ваше единственное входное изображение вызвало проблемы.

2) Попробуйте использовать другой классификатор. Почти все может дать вам достойную производительность в наборе данных digits. Я пробовал с RandomForestClassifier, и он правильно предсказывает ваше изображение как «0».

Доказательство концепции:

import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn import datasets
my_input = np.array(
 [[  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.],
 [  0.,   0.,   0.,  25.,  25.,   0.,   0.,   0.],
 [  0.,  25.,  25.,  25.,   0.,  25.,  25.,   0.],
 [  0.,  25.,   0.,   0.,   0.,   0.,  25.,   0.],
 [  0.,  25.,   0.,   0.,   0.,   0.,  25.,   0.],
 [  0.,  25.,   0.,   0.,   0.,   0.,  25.,   0.],
 [  0.,   0.,  25.,  25.,  25.,  25.,   0.,   0.],
 [  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.]])
iris = datasets.load_iris()
digits = datasets.load_digits()
clf = RandomForestClassifier()
clf.fit(digits.data, digits.target)
clf.predict(my_input.reshape(1, -1))
# Outputs array([0])
person KPLauritzen    schedule 04.12.2017

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

clf = svm.SVC(gamma=0.001, C=100) # This line of code is from your post
x,y = digits.data[:-1], digits.target[:-1] # This line of code is from your post
clf.fit(x,y)  # This line of code is from your post
y_pred=svc.predict_proba(flat) # Here, I predict the probabilities, using the test data you have named flat.

# The predicted probabilities are printed bellow
print(y_pred)

Конечно, вы взглянули на значения прогнозируемых вероятностей y_pred, напечатанные с помощью приведенного выше кода. Если все эти вероятности превышают 0,5, что является пороговым значением по умолчанию для бинарной классификации, следует использовать приведенный ниже код и изменить пороговое значение на значение, превышающее минимальное значение вероятностей, предсказанное выше. Например, предположим, что минимальное значение вероятностей равно 0,55, порог должен быть выше 0,55. Я выбираю 0,6. Однако если 0,6 выше максимального значения вероятности,

threshold=0.6    
ypred=(y_pred[:,1]>threshold).astype('int') 
print(ypred)

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

person Raulin Cadet    schedule 30.08.2019