进击的机器学习 First Day——数据预处理

作者: 焜俞 | 来源:发表于2019-11-02 22:25 被阅读0次

    在入门机器学习之前必须要知道,很多的数据并不会照我们想的那样十分完美,比如数据残缺,单位不统一等都会使我们的机器无法完成正常的学习,甚至会出现程序的报错。因此,学习如何对数据进行预处理是很有必要的。以下文章就是对预处理的一些代码的实现和讲解。
    数据的下载地址点击下载 提取码 t6if

    第一个:调包侠专用(纯属调侃啊,用起来比较方便)基于sklearn和pandas库

    导入数据

       Country   Age   Salary Purchased
    0   France  44.0  72000.0         0
    1    Spain  27.0  48000.0         1
    2  Germany  30.0  54000.0         0
    3    Spain  38.0  61000.0         0
    4  Germany  40.0      NaN         1
    5   France  35.0  58000.0         1
    6    Spain   NaN  52000.0         0
    7   France  48.0  79000.0         1
    8  Germany  50.0  83000.0         0
    9   France  37.0  67000.0         1
    #数据长这样:不同国家,年龄,收入的人对这件商品是否购买,0表示不购买,1表示购买
    #我们要处理什么呢:第一个NaN的缺失值该怎么做掉
    第二个这些国家的名字作为自变量对机器学习来说无法进行学习,该怎样把他们变成数据让数据学习
    
    import pandas as pd #导入Pandas库
    dataset=pd.read_csv(path)#读取数据到dataset,path是文件路径
    x=dataset.iloc[:,0:3].values#pandas的一个iloc属性,选择x数据的范围
    #注意:values一定要加上,否则数据数据只是可看不可读写
    #x一定是一个二维数组哦,类似[[],]这种,否则sklearn会处理报错
    y=dataset.iloc[:,3].values
    

    处理丢失的数据

    from sklearn.preprocessing import Imputer,LabelEncoder,OneHotEncoder
    #从preprocessing里面导入Imputer(处理丢失数据)
    #LabelEncoder(将一些属性标签化,不懂的话往后看)
    #OneHotEncoder将标签化的数据再进一步处理为one-hot编码(不懂会有解答)
    imputer=Imputer(missing_values='NaN',strategy='mean',axis=0)
    #首先将Imputer实例化,参数missing_values顾名思义
    #strategy是将缺失值修复的方法,这里mean是平均值,还有median(中值)
    #抑或是most-frequent(众数)
    #axis的0按列处理,1是按行处理
    imputer.fit(x[:,1:])#让imputer去处理x的第二列以后的丢失的数据
    x[:,1:]=imputer.transform(x[:,1:])#将处理后的数据转化给原来的x
    

    将特定属性标签化

    LE=LabelEncoder()#实例化标签化 类
    x[:,0]=LE.fit_transform(x[:,0])
    y[:]=LE.fit_transform(y[:])
    #以上就是LE如何将指定的列的数据进行标签化
    #下一步将标签化的数据进行one-hot编码
    onehotencoder=OneHotEncoder(categorical_features = [0])
    #同样先实例化,里面参数可要可不要
    X = onehotencoder.fit_transform(X).toarray()
    #将属性X进行转化,完成one-hot编码
    

    数据打散为训练集和测试集

    from sklearn.model_selection import train_test_split
    #废话不多说,导入包就完事了
    x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=0)
    #首先参数x,y是数组格式,要和前面一一对应
    #test_size指定测试集的占比,如果是整数的化就是指定数据数量
    #random_state指定随机数种子,实验具有可复性
    

    最后一步,数据归一化

    from sklearn.preprocessing import StandardScaler
    sd=StandardScaler()#还是先进行实例化
    x_train=sd.fit_transform(x_train)
    x_test=sd.fit_transform(x_test)
    #数据归一化处理完毕
    

    以上就是调包侠处理数据的过程,有sklearn我就是个爸爸,不服咬我啊
    问题解答:

    1、Q:为什么对一些特征标签化呢?
    A:因为我们给出的数据比如说国家名称,机器无法进行运算,我们将它标签化为0,1,2等与国家相对应,机器就可以处理了。进一步one-hot编码更适合机器使用
    2、Q:为什么要将数据进行归一化处理呢?
    A:为了使数据更加的平稳,减少噪声
    3、Q:如何理解onehot编码呢?
    A:比如说有3个国家['中国','日本','美国','中国'],显然这样机器学习算法无法进行运算学习,于是呢我们就一个国家给他们分配一个标签,依次是[0,1,2,0],代表与之相应的国家。但是仅仅是进行这种编码,机器就会认为1代表的美国大于0表的中国,但是我们实际上没那个意思啊。这时进行onehot编码就可以避免这个问题,这里共3个国家,于是创建一个1*3的数值都是0的行向量[0,0,0]。因为0代表中国,那么行向量索引为0的值变为1,即中国的onehot编码就是[1,0,0]。同理日本是[0,1,0],美国是[0,0,1]。这样就没大小比较啦!

    第二个 自己动手实现数据的预处理(请喊我埼玉sai sai) numpy埼玉

    在接下来的教程中我们仅仅使用numpy,pandas,matplotlib,机器学习基础工具来实现上述一系列对数据的预处理。有的人可能要嘲讽了:我是想不开了吗?sklearn它不香吗? 其实并不香
    sklearn确实是机器学习的一个强大工具,但是要知道它只是一个黑盒子,你不知道原理是什么,只知道调用其中的这个函数会这种效果,这其实是不利于我们机器学习的。好,废话不多说,开始发车。

    导入数据 还是和之前一样

    import numpy as np
    import pandas as pd
    import math
    dataset=pd.read_csv(path)#传入文件地址
    #分别导入数据
    x=dataset.iloc[:,0:3].values
    y=dataset.iloc[:,3].values
    

    导入数据完毕

    创建数据丢失处理函数

    #目前我只做了平均值和列方向的处理方式。欢迎大家完善啊
    def PreMissValues(x=np.zeros((3,3)),axis=1,strategy='mean'):
        rows,columns=x.shape#获取传入的x形状
        if axis==1:#传入对列的操作指令
            for j in range(columns):#对列进行迭代
                column_sum=0#列的和
                sign_position=[]#丢失值的位置
                num=0#除去丢失值,某列的元素个数
                for i in range(rows):#对行进行迭代
                    if type(x[i][j])==str:
                        continue#如果是非数值型的数据,我们直接跳过
                    if not math.isnan(x[i,j]):#这是判断数据是否是NaN型丢失数据
                        column_sum+=x[i][j]#不是的话,求和
                        num+=1#元素个数记录,为了求均值。(所以其他策略都是可以实现的)
                    else:
                        sign_position.append((i,j))#如果是丢失数据类型,记录它的位置
                        continue
                    for position in sign_position:
                        x_p,y_p=position
                        x[x_p][y_p]=column_sum/num#将丢失数据的值按平均值赋给它
        return x
    

    处理丢失值数据函数构建完毕

    数据标签化

    def label_to_values(x=np.zeros((3,3)),axis=1,ohe='y'):
    #是否进行onehot编码(ohe)
        if len(list(x.shape))==2:#判断传入的数组是特征值,还是目标值(所以我说x是[[]]类型,而y是[]类型)
            rows,columns=x.shape#获取形状
            if axis==1:#对列处理
                for j in range(columns):#对列进行迭代
                    label={}#获取标签字典,并用自然数指代
                    num=0#字典的自然数
                    for i in range(rows):#对行进行迭代
                        if x[i][j] in label.keys():#判断元素是否已经存在在字典中
                            continue
                        if type(x[i,j])==str:#判断元素是否是非数值型
                            key=x[i,j]#是的话,获取作为键值
                            label[key]=num#键值对应的标签
                            num+=1
                    for i in range(rows):#对行进行迭代
                        if type(x[i,j])==str:
                            x[i,j]=label.get(x[i,j])#将键值替换为其对的值,完成标签化
                    if ohe=='y':#是否onehot编码
                        x=x.tolist()#首先将x转换为列表,便于处理
                        for a in range(rows):#沿着上面对行迭代
                            onehot=[]#初始onehot的列表
                            for m in range(len(label)):
                                onehot.append(0)#赋值onehot的0
                            if not onehot:
                                break
                            pop=x[a].pop(j)#删除标签值,并获取标签值,作为索引
                            onehot[pop]=1#指定onehot索引值处为1
                            onehot.reverse()#时onehot颠倒位置好加入到x中
                            for element in onehot:
                                x[a].insert(0,element)#将onehot元素插入x中
                        x=np.array(x)#再将x转化为nump数组,onehot编码完毕
    #同理下面是对一维数组的处理,不再赘述
        if len(list(x.shape))==1:
            rows=list(x.shape)[0]
            label={}
            num=0
            for i in range(rows):
                if x[i] in label.keys():
                            continue
                if type(x[i])==str:
                            key=x[i]
                            label[key]=num
                            num+=1
            for i in range(rows):
                        if type(x[i])==str:
                            x[i]=label.get(x[i])
        return x
    

    数据标签化函数构建完毕

    将数据处理为训练集和测试集

    #指定传入参数有拆分比例
    def Train_Test_split(x=np.zeros((3,3)),y=np.zeros(3),test_size=0.2):
        length=len(x)#获取传入数组的长度,行数(一行一个训练数据嘛)
        random_index=np.random.permutation(length)#获取随机的索引
        test_position=int(length*test_size)#获取拆分的位置
        x_train=[]
        x_test=[]
        y_train=[]
        y_test=[]#构建训练集和测试集
        for i in range(test_position):
            sign=random_index[i]#获取要分为测试集的索引
            x_test.append(x[sign].tolist())#添加进入测试集
            y_test.append(y[sign])
        for j in range(test_position,length):#将剩下的元素加入训练集
            sign=random_index[j]
            x_train.append(x[sign].tolist())
            y_train.append(y[sign])
        x_train=np.array(x_train)
        x_test=np.array(x_test)
        y_train=np.array(y_train)
        y_test=np.array(y_test)
        return (x_train,x_test,y_train,y_test)#返回一个元组
    

    数据拆分函数构建完毕

    数据归一化

    def standard_scaler(x=np.zeros((3,3))):
        mean=x.mean()#获取数组的平均值
        std=x.std()#获取数组的标准差
        shape=x.shape#获取数组的形状
        mean_array=np.tile(mean,shape)#构建一个元素都等于平均值,但是形状和x一样的数组
        x=(x-mean_array)/std#数据归一化公式(x-u)/std,这里面用到了矩阵的减法和除法
        return x
    

    数据归一化函数构建完毕
    以上的内容就是用基础函数库实现数据的预处理


    Python再好也怕买菜
    1、Q:math.isnan()是干啥的?
    A:判断数据类型是否是NaN
    2、Q:np.random.permutation(n)有啥用?
    A:生成一个从零0到n-1数组,但是顺序是打乱的,自己尝试一下就懂了
    3、Q:np.tile(n,(a,b))用来做什么?
    A:生成一个(a,b)数组,元素都是n

    机器学习第一课数据预处理到这里就应该结束了,欢迎大家学习交流啊!

    机器学习使我快乐,呵呵

    相关文章

      网友评论

        本文标题:进击的机器学习 First Day——数据预处理

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