如何在Scikit-learn中对属性为字符串的二分类器应用?

1 投票
1 回答
5494 浏览
提问于 2025-04-18 17:57

我有一个人名的列表,包括他们的名字和姓氏,还有一个二元语言分类(会说英语或不会说英语)。

这里有一个示例文件(我把名字换成了假名,以保护个人隐私):

name1,name2,0
name3,name4,0
name5,name6,1
name7,name2,0
name8,name3,0
name9,name10,1
name11,name5,1

我想用机器学习算法,比如支持向量机(SVM)和朴素贝叶斯,利用Scikit-learn来评估这个二元分类任务。因为Scikit不允许属性是字符串,所以我把它们转换成了整数。转换后的示例文件是这样的:

1,2,0
3,4,0
5,6,1
7,2,0
8,3,0
9,10,1
11,5,1

我想问一下,SVM和朴素贝叶斯在处理名字的输入值时,是把它们当作独立的值来看待,还是这些数字之间有某种关系?换句话说,数字5比2大这个事实重要吗,还是这些数字只是被当作独特的值来看,而不考虑它们的大小?

我问这个问题的原因是,如果我先按语言排序(比如先把会说英语的人放在前面),然后再把名字换成整数,算法的结果会非常好(准确率和F值都超过97%)。但是如果我把列表打乱顺序后再换成整数,结果就会很差。

总的来说,当属性值是字符串时,使用Scikit进行分类的解决方案是什么?

附注1:我用Weka测试了同样的数据集,没有遇到这样的问题,因为Weka使用arff文件,并且会自动进行必要的转换。

附注2:这是我用来读取文件并应用算法的代码(运行良好,没有错误):

#read file into numpy array format
path = "/path/to/csv/file/BinaryClassification.csv"
import numpy as np
lstAttributes = np.loadtxt(path, delimiter=',')[:,0:2]
lstLabels = np.loadtxt(path, delimiter=',')[:,2:3]
tempArr = []
for v in lstLabels:
    tempArr.append(float(v))
from numpy import array
lstLabels = array(tempArr)

#trains and test algorithms (uses whole data as training and test set)
from sklearn import naive_bayes
classifier = naive_bayes.GaussianNB()
model = classifier.fit(lstAttributes, lstLabels)
prediction = model.predict(lstAttributes)
from sklearn.metrics import confusion_matrix
print confusion_matrix(lstLabels, prediction)

#Use 5 fold cross validation to evaluate the algorithms
from sklearn import cross_validation
scores = cross_validation.cross_val_score(classifier, lstAttributes, lstLabels, cv=5, scoring='f1')
print("cross validation: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

1 个回答

2

一般来说,你需要了解字符串的含义,这样才能把它们转换成数字特征值。同时,你还得考虑这些结果要用到哪个学习算法。在这种情况下,最好的尝试是使用一种叫做“一热编码”的方法。DictVectorizer 就是用来实现这个的。最终的结果会是一个稀疏矩阵,里面包含了一些指示变量,所以你最好把算法从 GaussianNB 换成 BernoulliNB(因为 GaussianNB 对于你现在的编码方式并不合适)。

撰写回答