前言
最近好久每更新过博客了,趁着今年的尾巴进行今年的最后一更,也算是为今年收个尾吧。之前写机器学习的博客都是直接对算法进行剖析与实现,今天我想分享的是机器学习中进行模型训练前常用的一些操作,希望能对大家有所帮助!!!
一.加载数据集
本文中使用的数据集为鸢尾花卉数据集,该数据集的介绍可以参考我之前的博客机器学习(三):一文读懂线性判别分析(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()
结语
以上便是本文的全部内容,如果发现有什么问题的话,敬请在评论区批评指正。要是觉得不错的话,可以点个赞或支持一下博主,你们的支持是博主继续创作的不竭动力!!!