使用Sci-kit Learn SVM时预测始终相同

时间:2017-02-03 09:03:05

标签: python pandas numpy scikit-learn sklearn-pandas

我有一个数据集,我试图预测数据输入来自DNA构成的DNA类型。例如,字符串ATTAG...ACGAT可能会转换为EI。可能的输出是EIIEN。可以进一步调查数据集here。我尝试将内核从linear切换到rbf,但结果是一样的。 SVM分类器似乎每次都输出N。有什么想法吗?我是Sci-kit Learn的初学者。

import pandas as pd
# 3190 total
training_data = pd.read_csv('new_training.csv')
test_data = pd.read_csv('new_test.csv')
frames = [training_data, test_data]
data = pd.concat(frames)
x = data.iloc[:, 0:59]
y = data.iloc[:, 60]

x = pd.get_dummies(x)
train_x = x.iloc[0:3000, :]
train_y = y.iloc[0:3000]
test_x = x.iloc[3000:3190, :]
test_y = y.iloc[3000:3190]

from sklearn import svm
from sklearn import preprocessing

clf = svm.SVC(kernel="rbf")
label_encoder = preprocessing.LabelEncoder()
label_encoder.fit(y)

print(label_encoder.transform(train_y))
clf.fit(train_x, label_encoder.transform(train_y))

for u in train_y.unique():
    print(u)

predictions = clf.predict(test_x)

correct = 0
total = len(predictions)
for i in range(total):
    prediction = label_encoder.inverse_transform(predictions[i])
    print('predicted %s and actual %s' % (prediction, test_y[i]))
    print(len(prediction))
    if prediction == test_y[i]:
        correct += 1

print('correct %d out of %d' % (correct, total))

首先,我导入训练和测试数据,将其组合并将其拆分为x(输入)或y(输出标签)。然后我将x转换为原始60列的虚拟变量版本,就像300~列一样,因为每个DNA点可以是ATGC,有时候N。基本上每个输入的所有可能输入都有0或1。 (有更好的方法吗?Sci-kit学习并不支持分类编码,我尽力从this完成。)然后我再次分离数据(我必须合并以便我可以在整个数据空间上生成假人。)

从这里开始,我只运行svm内容以适合xy标签,然后预测test_x。我还必须编码/标记y,从字符串版本到数字版本。但是,它总是产生N,我觉得这是错的。我该如何解决?谢谢!

1 个答案:

答案 0 :(得分:2)

我认为问题在于数据被分解为训练和测试的方式。您已经采用了前3000个样本进行培训,其余190个样本进行了测试。我发现通过这样的训练,分类器为所有测试样本产生真正的类标签(得分 = 1.0)。我还注意到数据集的最后190个样本具有相同的类标签,即'N'。因此,您获得的结果是正确的。

我建议您将数据集拆分为火车并通过test_size=.06 test_size=.01进行测试(这大致相当于190/3190,但为了使结果更容易,我使用了import numpy as np from sklearn.preprocessing import OneHotEncoder, LabelEncoder from sklearn.model_selection import ShuffleSplit from sklearn import svm data = np.loadtxt(r'splice.data', delimiter=',', dtype='string') bases = {'A': 0, 'C': 1, 'D': 2, 'G': 3, 'N': 4, 'R': 5, 'S': 6, 'T': 7} X_base = np.asarray([[bases[c] for c in seq.strip()] for seq in data[:, 2]]) y_class = data[:, 0] enc = OneHotEncoder(n_values=len(bases)) lb = LabelEncoder() enc.fit(X_base) lb.fit(y_class) X = enc.transform(X_base).toarray() y = lb.transform(y_class) rs = ShuffleSplit(n_splits=1, test_size=.01, random_state=0) train_index, test_index = rs.split(X).next() train_X, train_y = X[train_index], y[train_index] test_X, test_y = X[test_index], y[test_index] clf = svm.SVC(kernel="rbf") clf.fit(train_X, train_y) predictions = clf.predict(test_X) 样品在下面运行)。为简单起见,我还建议您使用ShuffleSplit对要素的分类值进行编码。

这是完整的代码(我冒昧地执行了一些重构):

Out[2]: 
array(['IE', 'EI', 'EI', 'EI', 'EI', 'IE', 'N', 'N', 'EI', 'N', 'N', 'IE',
       'IE', 'N', 'N', 'IE', 'EI', 'N', 'N', 'EI', 'IE', 'EI', 'IE', 'N',
       'EI', 'N', 'IE', 'N', 'EI', 'N', 'N', 'EI'], 
      dtype='|S79')

In [3]: y_class[test_index]
Out[3]: 
array(['IE', 'EI', 'EI', 'EI', 'EI', 'IE', 'N', 'N', 'EI', 'N', 'N', 'IE',
       'IE', 'N', 'N', 'IE', 'EI', 'N', 'N', 'EI', 'IE', 'EI', 'IE', 'N',
       'IE', 'N', 'IE', 'N', 'EI', 'N', 'N', 'EI'], 
      dtype='|S79')

In [4]: clf.score(test_X, test_y)
Out[4]: 0.96875

演示:

import wikipedia
import json
wikipedia.search('Barack Obama ')

注意:确保您的sklearn版本为0.18.1,否则上述代码可能无效。