深度神经网络在机器学习中应用时面临两类主要问题:优化问题和泛化问题。
优化问题:深度神经网络的优化具有挑战性。
泛化问题:由于深度神经网络的复杂度较高且具有强大的拟合能力,很容易在训练集上产生过拟合现象。因此,在训练深度神经网络时需要采用一定的正则化方法来提高网络的泛化能力。
目前,研究人员通过大量实践总结了一些经验方法,以在神经网络的表示能力、复杂度、学习效率和泛化能力之间取得良好的平衡,从而得到良好的网络模型。本系列文章将从网络优化和网络正则化两个方面来介绍如下方法:
本文将介绍神经网络中的数据预处理方法
本系列实验使用了PyTorch深度学习框架,相关操作如下:
conda create -n DL python=3.7
conda activate DL
pip install torch==1.8.1+cu102 torchvision==0.9.1+cu102 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
conda install matplotlib
conda install scikit-learn
软件包 | 本实验版本 | 目前最新版 |
---|---|---|
matplotlib | 3.5.3 | 3.8.0 |
numpy | 1.21.6 | 1.26.0 |
python | 3.7.16 | |
scikit-learn | 0.22.1 | 1.3.0 |
torch | 1.8.1+cu102 | 2.0.1 |
torchaudio | 0.8.1 | 2.0.2 |
torchvision | 0.9.1+cu102 | 0.15.2 |
神经网络的参数学习是一个非凸优化问题.当使用梯度下降法来进行优化网络参数时,参数初始值的选取十分关键,关系到网络的优化效率和泛化能力.参数初始化的方式通常有以下三种:
from torch import nn
随机梯度下降(Stochastic Gradient Descent,SGD)是一种常用的优化算法,用于训练深度神经网络。在每次迭代中,SGD通过随机均匀采样一个数据样本的索引,并计算该样本的梯度来更新网络参数。具体而言,SGD的更新步骤如下:
Pytorch官方教程
optimizer = torch.optim.SGD(model.parameters(), lr=0.2)
【深度学习实验】前馈神经网络(final):自定义鸢尾花分类前馈神经网络模型并进行训练及评价
传统的SGD在某些情况下可能存在一些问题,例如学习率选择困难和梯度的不稳定性。为了改进这些问题,提出了一些随机梯度下降的改进方法,其中包括学习率的调整和梯度的优化。
【深度学习实验】网络优化与正则化(一):优化算法:使用动量优化的随机梯度下降算法(Stochastic Gradient Descent with Momentum)
【深度学习实验】网络优化与正则化(二):基于自适应学习率的优化算法详解:Adagrad、Adadelta、RMSprop
Adam算法(Adaptive Moment Estimation Algorithm)[Kingma et al., 2015]可以看作动量法和 RMSprop 算法的结合,不但使用动量作为参数更新方向,而且可以自适应调整学习率。
【深度学习实验】网络优化与正则化(三):随机梯度下降的改进——Adam算法详解(Adam≈梯度方向优化Momentum+自适应学习率RMSprop)
【深度学习实验】网络优化与正则化(四):参数初始化及其Pytorch实现——基于固定方差的初始化(高斯、均匀分布),基于方差缩放的初始化(Xavier、He),正交初始化
除了参数初始化比较困难之外,不同输入特征的尺度差异比较大时,梯度下降法的效率也会受到影响。一般而言,样本特征由于来源以及度量单位不同,它们的尺度(Scale)(即取值范围)往往差异很大.以描述长度的特征为例,当用“米”作单位时令其值为,那么当用“厘米”作单位时其值为100.
对于尺度不同的特征,不同的机器学习模型对其敏感程度不同。尺度不变性是指机器学习算法在缩放全部或部分特征后仍能保持学习和预测性能的性质。例如,线性分类器具有尺度不变性,而最近邻分类器则对特征尺度敏感。当计算不同样本之间的欧氏距离时,尺度大的特征会起到主导作用。因此,对于尺度敏感的模型,需要对样本进行预处理,将各个特征转换到相同的取值区间,并消除不同特征之间的相关性,以获得更好的结果。
理论上,神经网络应该具有尺度不变性,可以通过参数的调整来适应不同特征的尺度。然而,尺度不同的输入特征会增加训练的难度。以一个只有一层的神经网络为例,如果输入特征的尺度差异很大,那么tanh函数在区间[-2, 2]上的导数会很敏感,而在其他区间上接近于0。因此,如果参数11 + 22 + 过大或过小,梯度会变得很小,导致难以训练。为了提高训练效率,可以将1设为较小的值(例如[-0.1, 0.1]之间),从而使11 + 22 + 在[-2, 2]区间内。然而,当数据维度很多时,手动选择每个参数变得困难。因此,如果每个特征的尺度相似(例如[0, 1]或[-1, 1]),就可以减少人工干预,简化训练过程。
数据预处理方法是在训练神经网络之前对数据进行处理,以提高模型的性能和训练效果。常见的数据预处理方法包括标准化、归一化、白化等操作。
将数据按照特征列进行均值为0,标准差为1的标准化处理。这种方法可以使得数据的分布更加接近正态分布,有助于提高模型的训练效果。
import torch
from sklearn.preprocessing import StandardScaler
# 假设有一个名为data的张量,形状为(100, 10)
data = torch.randn(100, 10)
# 创建StandardScaler对象
scaler = StandardScaler()
# 对数据进行标准化
normalized_data = scaler.fit_transform(data)
# 打印标准化后的数据
print(normalized_data)
将数据按照特征列进行线性变换,将数据的取值范围缩放到0到1之间。这种方法可以将不同特征的数据统一到同一个尺度上,避免不同特征之间的差异对模型的影响。
import torch
from sklearn.preprocessing import MinMaxScaler
# 假设有一个名为data的张量,形状为(100, 10)
data = torch.randn(100, 10)
# 创建MinMaxScaler对象
scaler = MinMaxScaler()
# 对数据进行最小最大值归一化
normalized_data = scaler.fit_transform(data)
# 打印归一化后的数据
print(normalized_data)
白化(Whitening)是一种重要的预处理方法,用来降低输入数据特征之间的冗余性。输入数据经过白化处理后,特征之间相关性较低,并且所有特征具有相同的方差。白化的一个主要实现方式是使用主成分分析(Principal Component Analysis,PCA)方法去除掉各个成分之间的相关性。
import numpy as np
from sklearn.decomposition import PCA
# 假设有一个名为data的数组,形状为(100, 10)
data = np.random.randn(100, 10)
# 计算数据的协方差矩阵
covariance_matrix = np.cov(data, rowvar=False)
# 使用PCA方法进行白化处理
pca = PCA(whiten=True)
whitened_data = pca.fit_transform(data)
# 打印白化后的数据
print(whitened_data)
将数据中的异常值进行处理或去除,避免异常值对模型的影响,可以考虑以下几种常见方法:
删除异常值:将数据中的异常值直接删除或忽略。这种方法适用于异常值对整体数据影响较小的情况,但需要注意可能会导致数据的信息损失。
替换异常值:将异常值替换为合理的数值。可以使用均值、中位数、众数等统计量来替换异常值,或者使用插值法进行填充。这种方法适用于异常值数量较少且可以通过合理的替换来保持数据整体分布特征的情况。
离散化处理:将连续型的异常值转化为离散型数据,例如将连续的数值分桶为不同的类别。这种方法适用于异常值呈现明显分布特征的情况。
使用统计方法:使用统计方法来识别和处理异常值,例如Z-score方法或箱线图方法等。这些方法可以通过计算数据的偏差程度来确定异常值,并进一步进行处理。
对于数据中存在的缺失值,可以通过填充、删除或插值等方法进行处理。
import torch
import pandas as pd
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.impute import SimpleImputer
import numpy as np
# 假设有一个名为data的张量,形状为(100, 10),其中含有缺失值和异常值
data = torch.randn(100, 10)
data[0, 0] = torch.tensor(float('nan')) # 添加一个缺失值
data[1, 1] = 1000 # 添加一个异常值
# 缩放
scaler = MinMaxScaler() # 最小最大值缩放
scaled_data = scaler.fit_transform(data)
scaler = StandardScaler() # 标准化
scaled_data = scaler.fit_transform(data)
# 去除异常值
std = torch.std(data)
mean = torch.mean(data)
data[(data - mean).abs() > 3 * std] = float('nan') # 使用3倍标准差去除异常值
# 处理缺失值
data = pd.DataFrame(data.numpy()) # 转换为DataFrame
imputer = SimpleImputer(strategy='mean') # 使用均值插补缺失值
imputed_data = imputer.fit_transform(data)
imputed_data = torch.tensor(imputed_data) # 转换为Tensor
# 打印处理后的数据
print(imputed_data)