onehot在python(sklearn)中的使用方法,示例,代码实现

首先强调一下,本篇博客是我实验得出来的结论,要是错了,可以在评论区指正,嘻嘻

接下来我会介绍以下三个内容

  • 为什么要用onehot
  • 怎么用

为什么要用onehot:

 假设你有一个这样的数据集,格式是csv或者arff格式:

体重 身高 ... class
1 5 0 ... 不好看
1 6 0 ... 还可以
有点胖 1 8 0 ...
有点瘦 1 5 0 ... 还可以

你现在需要对这个数据构建一个分类器,挖掘一些有用的信息,此时你想到了sklearn(真是个错误的决定),你会发现如果你把这个数据集直接当成数据矩阵numpy,输入sklearn中的分类器中,编译器会提示你,类型错误,无法把string(或者btype)类型转成float....

经过我查阅多方资料,我才明白,原来sklearn中的数据默认得是全数值类型。一个非常好又不方便的设定,在:统一数据类型,不方便在:有得时候我们的数据就是数值,离散值,string类型混合的。那我们就来解决吧(当然,如果你换weka(java)这个机器学习库就没有这种奇怪的问题)


怎么用:

在讲怎么写onehot代码之前,我先简单介绍一下onehot方法,简单地说,onehot方法可以把刚刚上面的这个数据变成这个样子:

 

是否胖 是否瘦 是否有点胖 是否有点瘦 身高 ... class
1 0 0 1 5 0 ... 不好看
0 1 0 0 1 6 0 ... 还可以
0 0 1 0 1 8 0 ...
0 0 0 1 1 5 0 ... 还可以

从上面的数据,我们可以发现,onehot方法就是把离散取值(取名词)的属性裂变成多个属性(取值为01),这样就可以给sklearn计算了。

好的,接下来,我展示一下,具体的代码(使用onehot重新编码,并进行knn分类,然后返回十折交叉验证结果的代码)调用示例:

def do_knn(fea,lab,k):
    # sdata=fea+lab
    auc=0
    #x是个矩阵
    #arffdata = imp.fit_transform(arffdata)
    #lab.reshape(-1,1).reshape(-1)#?????去掉它的多余括号
    flo = []  # 存放数值型属性
    str = []  # 存放名词性属性
    colmn = fea.shape[1]  # 存放列数
    raw = fea.shape[0]  # 存放行数
    strnumber = 0#判断是否存在名词性属性
    flonumber=0
    for i in range(colmn):
        if type(fea[0][i]) == bytes or type(fea[0][i]) == np.bytes_:
            str.append(fea[:, i])
            strnumber += 1
        else:
            flo.append(fea[:, i])
            flonumber+=1
    flo = np.array(flo).T
    str = np.array(str).T

    features=np.random.rand(1)#之后重新赋值
    if strnumber != 0 and flonumber != 0:
        enc = OneHotEncoder()
        enc.fit(str)
        str = enc.transform(str).toarray()
        str = np.array(str)
        features = np.concatenate((flo, str), 1)
    if strnumber==0:
        features = flo
    if flonumber==0:
        enc = OneHotEncoder()
        enc.fit(str)
        str = enc.transform(str).toarray()
        features = np.array(str)
    knn = KNeighborsClassifier(n_neighbors=k)
    scores = cross_val_score(knn, features, lab, cv=5, scoring='accuracy')
    auc=sum(scores)/len(scores)
    #print(lab)#似乎是因为btype类型的原因
    return auc###auc有时居然是空的

代码片段有点长,那是因为这个方法用起来真的不方便(以前的版本是很方便,只需要一行就能实现,后来sklearn把一个关键的函数去掉了。。)

代码解释说明:这个函数是计算一组数据进行knn分类方法并返回十折交叉验证的平均auc的函数。输入的fea是数据的特征(属性),输入的lab是数据的类别,所以这段代码是对fea进行数值化处理的。

关键的代码是这个:

enc = OneHotEncoder()
enc.fit(str)
str = enc.transform(str).toarray()
features = np.array(str)

首先,创建一个onehotencoder对象(方法),然后让这个方法去学str(把fea的所有非数值类取出来,存放在str中)矩阵中的信息(每个属性的取值有几种),再通过transfrom函数就可以把非数值得矩阵转成纯数值的数据矩阵。


补充说明:

上面的代码中,我先对数据集的属性矩阵进行了一个评定,看看这个数据的属性含不含非数值类型,并把数值型属性和非数值属性分开,最后调用onehot方法把非数值属性的矩阵转成纯数值矩阵,最后再把这两个矩阵拼接,构成数据集的完整属性矩阵features,最后利用这个featurs和lab得到了分类的结果。

我这么做的原因是因为,onehot方法以前的版本是可以选择哪一列需要数值化 的,方法是这样 enc=onehotencoder(categories
_featuires=[1,2]),这样的onehot就可以一行实现一个数据矩阵中的第一列和第二列数值化,真的是很方便,但是,不知道为什么,我这个版本把这种这么好的输入参数去掉了。。。。。。。所以他默认就是全部数值化,这样就会导致,如果你有一个属性是身高,取值有148.2,145.6,170.9等等,那么他就会裂变出 是否148.2,是否145.6.......这么多属性。。。。。所以我才做得这么麻烦。

要是你们知道怎么快速进行onehot方法(可以选择那一列裂变),可以在评论区告诉我呀,感谢感谢

 


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章