机器学习(四):数据集中常用的骚操作

前言

最近好久每更新过博客了,趁着今年的尾巴进行今年的最后一更,也算是为今年收个尾吧。之前写机器学习的博客都是直接对算法进行剖析与实现,今天我想分享的是机器学习中进行模型训练前常用的一些操作,希望能对大家有所帮助!!!

一.加载数据集

本文中使用的数据集为鸢尾花卉数据集,该数据集的介绍可以参考我之前的博客机器学习(三):一文读懂线性判别分析(LDA),后面的所有操作都是基于该数据集的。首先利用pandas库加载该数据集,为了方便理解,我还额外输出了该数据集的一些常规属性:

import pandas as pd

iris = pd.read_csv('iris.csv')
print(iris.head())
print(iris.shape)
print(iris.dtypes)
"""
#输出该数据集的前5行
   sepal.length  sepal.width  petal.length  petal.width variety
0           5.1          3.5           1.4          0.2  Setosa
1           4.9          3.0           1.4          0.2  Setosa
2           4.7          3.2           1.3          0.2  Setosa
3           4.6          3.1           1.5          0.2  Setosa
4           5.0          3.6           1.4          0.2  Setosa
#输出该数据集的维度
(150, 5)
#输出该数据集各列的数据类型
sepal.length    float64
sepal.width     float64
petal.length    float64
petal.width     float64
variety          object
dtype: object
"""

然后我们需要从该数据集中获取特征标签(target):

x,y = iris.iloc[:,0:3].values,iris.iloc[:,[-1]].values
print(x.shape)
print(y.shape)
"""
(150, 3)
(150, 1)
"""

#获取样本数,后面的操作会用到
m = x.shape[0]

二.数据集的常用操作

2.1 打乱数据集

打乱数据集可以消除数据间的相关性,在一定程度上可以减少过拟合,提升模型的泛化能力。对数据集的打乱可以对数据集的索引进行打乱,然后利用打乱的索引重新对原来的数据进行索引,需要注意特征和标签的打乱需要绑定在一起。

2.1.1 方法一:基于random库

首先需要根据数据集样本数创建索引数组,然后利用 random.shuffle()函数来打乱索引,最后利用新索引数组重新索引数据集。

#建立样本索引
indices = [i for i in range(m)]
#打乱索引
random.shuffle(indices)
#对数据集进行打乱
x,y = x[indices,:],y[indices,:]

2.1.2 方法二:基于numpy库

该方法其实和使用random库类似,只不过是换成了 numpy.random.shuffle()函数来进行索引打乱。

#建立样本索引
indices = np.arange(m)
#打乱索引
np.random.shuffle(indices)
print(indices)
#对数据集进行打乱
x,y = x[indices,:],y[indices,:]

2.2 划分训练集与测试集

在机器学习的过程中,我们一般都会将数据集划分为训练集测试集(也有的划分为训练集验证集测试集),其中训练集用于模型的训练,而测试集用于评估训练出的模型的泛化能力。下面将会展示对鸢尾花数据集的划分,由于该数据集比较小,按照常规思路训练集与测试集的划分比例为 7 : 3 7:3 7:3

2.2.1 方法一:基于numpy库

要实现数据集划分其实很简单只需要计算出训练集的样本数 n n n,然后索引出前 n n n个数据集即可。

#获取训练集样本数
train_nums = int(m * 0.7)
#划分
train_x,train_y = x[:train_nums,:],y[:train_nums,:]
test_x,test_y = x[train_nums:,:],y[train_nums:,:]
#分别输出训练集和测试集的特征与标签的维度
print(train_x.shape,train_y.shape,test_x.shape,test_y.shape)
"""
(105, 3) (105, 1) (45, 3) (45, 1)
"""

2.2.2 方法二:基于sklearn库

通过sklearn.model_selection.train_test_split(X,Y,test_size,random_state,shuffle=True)函数也能实现数据集的划分,其中:

  • X:数据特征;
  • Y:标签;
  • test_size:测试集所占的比例,取值 ∈ ( 0 , 1 ) \in (0,1) (0,1)
  • random_state:int,随机数种子;
  • shuffle:bool,是否打乱数据集;
from sklearn.model_selection import train_test_split

#这里只需数据集划分,因此将打乱数据集设置为不需要
train_x,test_x,train_y,test_y = train_test_split(x,y,test_size=0.3,shuffle=False)
print(train_x.shape,train_y.shape,test_x.shape,test_y.shape)
"""
(105, 3) (105, 1) (45, 3) (45, 1)
"""

2.3 划分数据集为mini-batch

在机器学习中利用数据集的子训练集进行梯度下降被称为mini-batch梯度下降,利用整个数据集进行梯度下降被称为batch梯度下降,每次利用数据集中的一个样本进行梯度下降被称为随机梯度下降。其中mini-batch梯度下降在数据集比较大时更为高效,另外当数据集特别大时进行batch梯度下降是不现实的,这时将数据集划分为一个个的batch进行学习是一个比较好的选择。

对于数据集划分为batches其实很简单:首先需要求出能划分多少个batch,然后进行索引取出各个batch即可,需要注意的是数据集的样本数不一定能被batch的大小整除,因此对于数据集后面的尾巴需要进行额外的处理。

def divideIntoBatches(X, Y, mini_batch_size = 32):
    """
    将数据集划分为mini-batch
    """
    #获取样本数
    m = X.shape[0]
    #获取数据batch数量
    batch_nums = m // mini_batch_size
    for i in range(batch_nums + 1):
        #获取本次batch的起始索引
        start = i*mini_batch_size
        if i < batch_nums:
            yield X[start:start + mini_batch_size,:],Y[start:start + mini_batch_size,:]
        else:
            #将数据集后的尾巴全部取出为一个batch
            yield X[start:,:],Y[start:,:]

for x_b,y_b in divideIntoBatches(x,y,mini_batch_size=32):
    print(x_b.shape,y_b.shape)
"""
(32, 3) (32, 1)
(32, 3) (32, 1)
(32, 3) (32, 1)
(32, 3) (32, 1)
(22, 3) (22, 1)
"""

当然数据集划分为batches还可以通过深度学习框架Tensorflow或者Pytorch中的API函数。

2.4 数据集的one-hot编码

one-hot编码(独热码)是指用二进制向量来表示分类变量。这首先要将分类值映射到整数值,然后每个整数值用一个二进制向量代表,在二进制向量中除了整数索引标记为1,其它都标记为0。要进行one-hot编码的属性必须满足属性间不存在序关系,且为离散型变量。在鸢尾花数据集中,标签就满足进行one-hot编码的条件。

2.4.1 方法一:基于numpy库

首先是根据one-hot编码的定义中的方法来实现。

#初始化one-hot编码全为0
#标签种类数为3,因此onehot编码的shape为(样本数,3)
target = np.zeros(shape=(m,3))
#将标签映射为整数值
y[y == 'Setosa'] = 0
y[y == 'Versicolor'] = 1
y[y == 'Virginica'] = 2
#行索引为行号
row_indexs = [i for i in range(m)]
#列索引为标签的应设置
column_indexs = y.flatten().tolist()
#根据行索引和列索引将对应位置的值置为1
target[row_indexs,column_indexs] = 1

2.4.2 方法二:基于sklearn库

通过sklearn.preprocessing.OneHotEncoder类就可以直接实现one-hot编码。

from sklearn.preprocessing import OneHotEncoder

#设置不反悔稀疏矩阵形式
enc = OneHotEncoder(sparse=False,handle_unknown='ignore')
#直接根据标签数组构造one-hot编码
target = enc.fit_transform(y)

2.4.3 方法三:基于pandas库

通过pandas.get_dummies()函数也可实现one-hot编码。

target = pd.get_dummies(y.flatten())

2.5 数据集的降维操作

在机器学习中对数据集进行降维也是一个常用的操作,倘若你不了解为什么需要降维可以去看看这篇博客常用降维方法-常用降维方法的目的。另外,降维除了这篇博客介绍的那些好处外,还可以方便对数据集进行可视化。目前常用的两种降维方法分别为LDA和PCA。对于这两种降维方法sklearn库已经帮我们实现了相应的方法,我们只需要会调用即可。

from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

#将标签数组转换为整数(方便后面可视化)
y[y == 'Setosa'] = 0
y[y == 'Versicolor'] = 1
y[y == 'Virginica'] = 2

#转换标签数组的数据类型(LDA降维要求其数据类型不能为object)
y = y.astype(np.float32)

#进行PCA降维
pca = PCA(n_components=2)
x_new = pca.fit(x).transform(x)
plt.title('PCA')
plt.scatter(x_new[:,0],x_new[:,1],c=y)
plt.show()

#进行LDA降维
lda = LinearDiscriminantAnalysis(n_components=2)
x_new1 = lda.fit(x,y).transform(x)
plt.title('LDA')
plt.scatter(x_new1[:,0],x_new1[:,1],c=y)
plt.show()

PCA

图1:PCA降维可视化

LDA

图2:LDA降维可视化

结语

以上便是本文的全部内容,如果发现有什么问题的话,敬请在评论区批评指正。要是觉得不错的话,可以点个赞或支持一下博主,你们的支持是博主继续创作的不竭动力!!!

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯曦巍峨

码文不易,有条件的可以支持一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值