离散属性连续化

2019-07-29  本文已影响0人  白老包

本来要写神经网络中前向传播和反向传播的一些东西。准备使用西瓜数据集建立一个超级简单的两层MLP进行分析。但是着手动键盘以后发现西瓜数据集是一个离散数据集,而传统的神经网络输入的是是一个连续值。so存在一个步骤把离散变量转为连续变量。
针对这个问题,网上的资料并不多,一些学者把离散和连续变量转换成统一形式的方法,如(胡巍. 面向格结构的机器学习[D].上海交通大学,2009.)。周志华《机器学习》中对这个问题有简要的介绍(其实也不简要)。我结合西瓜数据集简单记录一下这个问题。
离散数据分为两类,分别为有序序列和无序序列。
我认为西瓜数据集中的条件属性均为有序序列。有序序列的特点是离散的数据之间存在序,换句话说不同离散属性存在大小关系。例如在数据集中:

ID,色泽,根蒂,敲声,纹理,脐部,触感,好瓜
1,青绿,蜷缩,浊响,清晰,凹陷,硬滑,好瓜
2,乌黑,蜷缩,沉闷,清晰,凹陷,硬滑,好瓜
3,乌黑,蜷缩,浊响,清晰,凹陷,硬滑,好瓜
4,青绿,蜷缩,沉闷,清晰,凹陷,硬滑,好瓜
5,浅白,蜷缩,浊响,清晰,凹陷,硬滑,好瓜
6,青绿,稍蜷,浊响,清晰,稍凹,软粘,好瓜
7,乌黑,稍蜷,浊响,稍糊,稍凹,软粘,好瓜
8,乌黑,稍蜷,浊响,清晰,稍凹,硬滑,好瓜
9,乌黑,稍蜷,沉闷,稍糊,稍凹,硬滑,坏瓜
10,青绿,硬挺,清脆,清晰,平坦,软粘,坏瓜
11,浅白,硬挺,清脆,模糊,平坦,硬滑,坏瓜
12,浅白,蜷缩,浊响,模糊,平坦,软粘,坏瓜
13,青绿,稍蜷,浊响,稍糊,凹陷,硬滑,坏瓜
14,浅白,稍蜷,沉闷,稍糊,凹陷,硬滑,坏瓜
15,乌黑,稍蜷,浊响,清晰,稍凹,软粘,坏瓜
16,浅白,蜷缩,浊响,模糊,平坦,硬滑,坏瓜
17,青绿,蜷缩,沉闷,稍糊,稍凹,硬滑,坏瓜

色泽属性可以按照深浅对其进行排序。浅白>青绿>乌黑。当然反过来也可以。可以将{浅白,青绿,乌黑}连续化为{1,0.5,0}。
决策属性则无法转换为连续形式,是无序序列。这类例子还有{牛,马,人}等。如果强行连续则会对一些利用距离进行学习的机器学习算法造成误导。书中的原话是对这些属性转换为k维向量。k为属性的总数。例如转换为{(0,0,1),(0,1,0),(0,0,1)}.对这个叙述我不太理解。一个属性只能是一个数,如果是向量如何参与计算?我的理解是将一个属性转化为k个属性,这些属性只有0和1两个值。但是这样会造成特征维度的增长,对算法也不利。对这类问题我以后还会继续关注。
西瓜数据集还算温柔,只有6个属性,如果属性的数量增多,手工排序的工作会变得很繁琐。所以我使用一个小工具辅助人工排序。
PS,在实现的过程中,我突然发现一个问题。我使用tf实现mlp的时候标签使用的是one_hot编码,也就是一个向量,但是用pytorch和sklearn实现的时候用的是数字????????查了一下官方教程的demo,这样使用没错,难道在框架内部自动进行了转换?
转换工具的代码如下:PS,汪师说我代码的临时变量应该取个名字,so,对此进行了更改。

# -*- coding: utf-8 -*-
"""
Created on Sun Jul 28 09:20:21 2019

@author: BHN
"""

import pandas as pd
import numpy as np
import os

class Deal_data:
#    主要功能是把数据集连续化
    def __init__(self, data_root):
#        参数意义数据集的路径
        self.df=pd.read_csv(data_root, encoding='gb18030')
        self.sort_file_name = r"attribute_sort.csv"
        self.label_file_name = r"label_sort.csv"
        
    def Attribute_2_csv(self):
#        主要功能去重每个属性,并存到csv文件中,
        if os.path.exists(self.sort_file_name):#如果文件存在就不需要重新排序
            return
        answer = {}
        for attribute_name in list(self.df.columns[1:-1]): #删除第一列的序数和最后一列的决策属性
            attribute = pd.Series(list(set(self.df[attribute_name].values)))#DataFrame对应转成numpy的是to_numpy()
#            answer.append(attribute)
            answer[attribute_name] = attribute
        answer = pd.DataFrame(answer)
        answer.to_csv(self.sort_file_name,index=False)
        print(answer)
            
    def Attribute_read_sort(self):
#        读取手工拍好的顺序属性
        df=pd.read_csv(self.sort_file_name)#这里的编码经过了转换
        continuing_table = {}
        for attribute_name in list(df.columns):#保存的时候删除了序号,所以从0开始
#            print(df[attribute_name].dropna().values)
            continuing_table[attribute_name]=dict(zip(\
                           df[attribute_name].dropna().values,\
                           range(len(df[attribute_name].dropna().values))))
#        print(self.df.values)
        answer = []
        for attribute_name in list(self.df.columns[1:-1]):
            answer_attribute = []
            for single_attribute in self.df[attribute_name]:
                answer_attribute.append(continuing_table[attribute_name][single_attribute])
#                print(answer_attribute)
            answer.append(answer_attribute)
        answer = np.array(answer).T
        return answer
            
    def Label_2_csv(self):
#        label属性其实不需要排列,主要防止有多个label,方便数字化
        if os.path.exists(self.label_file_name):#如果文件存在就不需要重新排序
            return
        answer = {}
        for attribute_name in list([self.df.columns[-1]]):
            attribute = pd.Series(list(set(self.df[attribute_name].values)))#查看最后一列,也就是label
            answer[attribute_name] = attribute
        answer = pd.DataFrame(answer)
        answer.to_csv(self.label_file_name,index=False)
        print(answer)
        
    def Label_read_sort(self):
#        读取离散label的顺序,label属性其实不需要排列,但是因为要数字化,所以干脆一起做了
        df=pd.read_csv(self.label_file_name)#这里的编码经过了转换
        continuing_table = {}
        answer = []
        for attribute_name in list(df.columns):
            continuing_table=dict(zip(\
                                      df[attribute_name].dropna().values,\
                                      range(len(df[attribute_name].dropna().values))))
            answer_attribute = []

            for single_attribute in self.df[attribute_name]:
                answer_attribute.append(continuing_table[single_attribute])
#                print(answer_attribute)
            answer.append(answer_attribute)
        answer = np.array(answer).T
        return answer
        
if __name__ =='__main__':
    a = Deal_data('data//watermelon.csv')
    a.Attribute_2_csv()
    a.Attribute_read_sort()
    a.Label_2_csv()
    a.Label_read_sort()

使用方法,运行一次会生成两个文件。


QQ截图20190729223643.jpg

打开文件,对每一列的属性进行排序,保存即可。第二次运行会直接使用排列好的顺序进行连续化。

上一篇 下一篇

猜你喜欢

热点阅读