【问题标题】:sklearn always predicts 1 when trying to predict digitssklearn 在尝试预测数字时总是预测 1
【发布时间】:2017-11-22 02:29:30
【问题描述】:

我正在尝试编写从搅拌机中的曲线预测数字的代码。 所以我将曲线转换为 sklearn 使用的矩阵,并尝试预测数字,不幸的是,无论我做什么,预测总是 1。

二维矩阵(它看起来像我在搅拌机中的圆圈):

[[  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)

我不知道我做错了什么。 任何帮助将不胜感激

【问题讨论】:

  • 我建议你看看 scikit-learn 教程。在那里,他们展示了手写数字的分类。 scikit-learn.org/stable/tutorial/basic/…如果你能把你的输入变成与数字数据集相同的格式,你应该能够按照教程点对点
  • @KPLauritzen 我试过了,矩阵看起来与训练数据中的矩阵相同
  • 如果您尝试预测来自digits 数据集的一些输入会发生什么?另外,您能否尝试使用np.reshapenp.flatten 而不是np.ravel。我认为您从列而不是图像矩阵中的行中获取平面向量
  • @KPLauritzen 数据集中的数字工作得很好,我的数组与数字的格式完全相同,但它只返回 1 :(

标签: python machine-learning scikit-learn blender scikits


【解决方案1】:

这可能是您的输入图像或分类器的问题。 要测试问题出在哪里,您可以

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])

【讨论】:

    【解决方案2】:

    您应该验证预测的概率是否高于默认阈值。如果是这种情况,你会发现总是 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)
    

    您可以尝试多个阈值值并测试哪一个产生您感兴趣的最佳指标(准确度得分、召回率、精度等)。

    【讨论】:

      猜你喜欢
      • 2020-07-14
      • 2019-09-07
      • 2019-03-17
      • 2019-01-28
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 2016-03-22
      相关资源
      最近更新 更多