Python 在Sklearn中运行SVM时出现值错误

Python 在Sklearn中运行SVM时出现值错误,python,numpy,scikit-learn,Python,Numpy,Scikit Learn,我有下面的问题,用numpy数组做支持向量机 import numpy as np from sklearn import svm 我有3个类别/标签(男性,女性,na),表示如下: labels = [0,1,2] In [19]: clf = svm.SVC() In [20]: y = ["male"] * 5 + ["female"] * 5 + ["na"] * 5 In [21]: X = np.vstack([males, females, nas]) In [22]:

我有下面的问题,用numpy数组做支持向量机

import numpy as np
from sklearn import svm
我有3个类别/标签(
男性
女性
na
),表示如下:

labels = [0,1,2]
In [19]: clf = svm.SVC()

In [20]: y = ["male"] * 5 + ["female"] * 5 + ["na"] * 5

In [21]: X = np.vstack([males, females, nas])

In [22]: clf.fit(X, y)
Out[22]: 
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,
  kernel='rbf', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)

In [23]: height_weight_age = [100,100,100]

In [24]: clf.predict(height_weight_age)
Out[24]: 
array(['female'], 
      dtype='|S6')
每个班级由3个变量(
身高
体重
年龄
)定义为训练数据:

male_height = np.array([111,121,137,143,157])
male_weight = np.array([60,70,88,99,75])
male_age = np.array([41,32,73,54,35])

males = np.hstack([male_height,male_weight,male_age])

female_height = np.array([91,121,135,98,90])
female_weight = np.array([32,67,98,86,56])
female_age = np.array([51,35,33,67,61])

females = np.hstack([female_height,female_weight,female_age])

na_height = np.array([96,127,145,99,91])
na_weight = np.array([42,97,78,76,86])
na_age = np.array([56,35,49,64,66])

nas = np.hstack([na_height,na_weight,na_age])
现在,我必须为训练数据拟合支持向量机方法,以预测给定这三个变量的类:

height_weight_age = [100,100,100]

clf = svm.SVC()
trainingData = np.vstack([males,females,nas])

clf.fit(trainingData, labels)

result = clf.predict(height_weight_age)

print result
不幸的是,出现以下错误:

  ValueError: X.shape[1] = 3 should be equal to 15, the number of features at training time

如何修改
培训数据
标签
,以获得正确答案?

hstack
给出了一维数组。您需要形状的二维数组
(n个样本,n个特征)
,您可以从
vstack
中获得

In [7]: males = np.hstack([male_height,male_weight,male_age])

In [8]: males
Out[8]: 
array([111, 121, 137, 143, 157,  60,  70,  88,  99,  75,  41,  32,  73,
        54,  35])

In [9]: np.vstack([male_height,male_weight,male_age])
Out[9]: 
array([[111, 121, 137, 143, 157],
       [ 60,  70,  88,  99,  75],
       [ 41,  32,  73,  54,  35]])

In [10]: np.vstack([male_height,male_weight,male_age]).T
Out[10]: 
array([[111,  60,  41],
       [121,  70,  32],
       [137,  88,  73],
       [143,  99,  54],
       [157,  75,  35]])
您还需要传递反映每个样本标签的标签列表/数组,而不仅仅是枚举存在的标签。修正所有变量后,我可以训练SVM并按如下方式应用它:

labels = [0,1,2]
In [19]: clf = svm.SVC()

In [20]: y = ["male"] * 5 + ["female"] * 5 + ["na"] * 5

In [21]: X = np.vstack([males, females, nas])

In [22]: clf.fit(X, y)
Out[22]: 
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,
  kernel='rbf', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)

In [23]: height_weight_age = [100,100,100]

In [24]: clf.predict(height_weight_age)
Out[24]: 
array(['female'], 
      dtype='|S6')

(请注意,我使用的是字符串标签而不是数字标签。我还建议您标准化特征值,因为它们的范围非常不同。)

@jornsharpe感谢您如此巧妙地编辑了我的原始问题!我一直认为,当特征值按数量级变化时,我需要进行标准化……即使在这样的情况下,如果差异在一个(小的)常量的数量级上,你也会发现这很有用吗?@Fred这当然值得一试。它还更改了
C
(正则化)参数的比例,使其进入一个更容易处理的范围。@Fred什么是标准化?我怎么做?请举个例子@larsmans@bercik:使用
生成管道(StandardScaler(),clf)
而不是
clf
。有关详细信息,请参阅scikit学习文档。