Scikit-learn中的特征生成处理

作者: 马力_Panotech | 来源:发表于2018-03-10 23:31 被阅读70次

    概要

    在scipy或者scikit-learn中已经具备某些功能的情况下,我们没有注意到而又独立去实现的事,时有发生。这种就是坊间所说的重新发明轮子,这种时间和精力浪费,其实应该尽力避免。下面就汇总一下数据在前处理完成后和被送到分类器之前的阶段中,能够使用,带来便利的各种轮子。

    LabelEncoder

    在将字符串转换成ID的时候可以使用。

    from sklearn.preprocessing import LabelEncoder
    le = LabelEncoder()
    le.fit(['beijing', 'shanghai', 'guangzhou', 'hangzhou', 'nanjing', 'wuhan'])
    
    le.classes_
      #=> array(['beijing', 'guangzhou', 'hangzhou', 'nanjing', 'shanghai', 'wuhan'], dtype='<U9')
    
    le.transform(['hangzhou', 'guangzhou', 'beijing', 'hangzhou', 'nanjing', 'guangzhou'])
      #=> array([2, 1, 0, 2, 3, 1], dtype=int64)
    
    le.inverse_transform([2, 1, 0, 2, 3, 1])
      #=> array(['hangzhou', 'guangzhou', 'beijing', 'hangzhou', 'nanjing', 'guangzhou'], dtype='<U9')
    

    生成的LabelEncoder暂时保存起来,其他地方也想使用的话,StackOverFlow上有一部分保存的解决方法:
    训练代码:

    encoder = LabelEncoder()
    encoder.fit(X)
    numpy.save('classes.npy', encoder.classes_)
    

    测试代码:

    encoder = LabelEncoder()
    encoder.classes_ = numpy.load('classes.npy')
    # Now you should be able to use encoder
    # as you would do after `fit`
    

    也可以用下面的方式简单的用pickle读写:

    import pickle
    with open('foo.p', 'wb') as f:
      pickle.dump(le, f)
    with open('foo.p', 'rb') as f:
      le2 = pickle.load(f)
    
    le2.inverse_transform([2, 1, 0, 2, 3, 1])
    #=> array(['hangzhou', 'guangzhou', 'beijing', 'hangzhou', 'nanjing', 'guangzhou'], dtype='<U9')
    

    LabelBinarizer

    LabelEncoder只是将字符串换成了数值。这些数值可能不能作为一个要素,而是要作为多个要素来处理。
    例如输入是[beijing, shanghai, guangzhou]这3个值的话,不要[1,2,3]而是想要[[1, 0, 0], [0, 1, 0]. [0, 0, 1]]。
    模式如下:

    # 目标不是变成这样
    pd.DataFrame([{'prefecture': 1}, {'prefecture': 2}, {'prefecture': 3}])
     
    
    # 而是要one-hot结果
     pd.DataFrame([
      {'beijing': 1, 'shanghai': 0, 'guangzhou': 0},
      {'beijing': 0, 'shanghai': 1, 'guangzhou': 0},
      {'beijing': 0, 'shanghai': 0, 'guangzhou': 1}])
    
    image.png

    这种情况下可以使用LabelBinarizer来完成。

    from sklearn.preprocessing import LabelBinarizer
    lb = LabelBinarizer()
    
    lb.fit(['beijing', 'guangzhou', 'shanghai'])
    lb.transform(['beijing', 'guangzhou', 'shanghai'])
    #=> array([[1, 0, 0],
      #=>        [0, 1, 0],
      #=>        [0, 0, 1]])
    

    对Pandas的DataFrame的列进行运算,运算结果想要放入相同的DataFrame的时候:

    df = pd.DataFrame([{'prefecture': 'beijing'}, {'prefecture': 'guangzhou'}, {'prefecture': 'shanghai'}, {'prefecture': 'beijing'}])
    lb.fit(df.prefecture)
    pd.concat([df, pd.DataFrame(lb.transform(df.prefecture), columns=lb.classes_)], axis=1)
    
    image.png

    上述只有三个列的情况下,用稠密的DataFrame其实也没有问题。如果值增加的话,就不得不使用稀疏方式了。
    如果在LabelBinarizer初始化时设定参数sparse_output,输出结果就变成稀疏结果。

    from sklearn.preprocessing import LabelBinarizer
    lb = LabelBinarizer(sparse_output=True)
    
    lb.fit(['beijing', 'guangzhou', 'shanghai'])
    lb.transform(['beijing', 'guangzhou', 'shanghai'])
      #=> <3x3 sparse matrix of type '' with 3 stored elements in Compressed Sparse Row format>
    

    MultiLabelBinarizer

    LabelBinarizer只适用于一列一列处理的情况。
    比如,处理电影的种类的时候,[action, horror]和[romance, commedy]这样有多个种类关联的场景。这时,将种类数组传递给MultiLabelBinarizer,可以很好的完成变换。

    from sklearn.preprocessing import MultiLabelBinarizer
    mlb = MultiLabelBinarizer()
    mlb.fit_transform([['action', 'adventure'], ['action'], ['action', 'war', 'commedy'], []])
      #=> array([[1, 1, 0, 0],
      #=>        [1, 0, 0, 0],
      #=>        [1, 0, 1, 1],
      #=>        [0, 0, 0, 0]])
    

    相关文章

      网友评论

        本文标题:Scikit-learn中的特征生成处理

        本文链接:https://www.haomeiwen.com/subject/jnqifftx.html