[ML]把机器学习数据特征缩放处理记录明白,详细记录BatchNorm1d层对于RNN 数据Shape的用法 用demo中实际例子说明

写在前面

12月10日更新:

对cnn可以用BN,而对于RNN 一般使用LN,其次数据的标准化一般在训练之前完成了,在模型结构之中的一起训练的是归一化层。

在学习数据处理时总是遇到几个不同的概念:
我的理解如下

  • 正则化,用来降低过拟合现象
  • L1 L2 :·对于损失函数使用,降低某个数据特征的依耐
  • 标准化:将数据缩放为平均为0方差1
  • 归一化:又分层归一 批次归一 :将数据集中在0-1之间,主要集中在激活函数敏感区域
    眼花缭乱。
    以上是我自己的理解。
    在这里插入图片描述深蓝老师的图

而后向GPT求证
A:你对这些概念的理解已经相当不错,让我帮你补充和澄清一些细节:

正则化:正则化是通过在损失函数中引入附加的惩罚项,以减小模型的复杂度,从而防止过拟合。正则化的目标是使模型的权重保持较小的值。最常见的正则化项有L1正则化和L2正则化。

L1正则化和L2正则化:
    L1正则化(Lasso):通过在损失函数中添加权重绝对值的总和来实现。它促使模型的某些权重趋向于零,从而实现特征选择。
    L2正则化(Ridge):通过在损失函数中添加权重平方的总和来实现。它使得所有权重都变得较小,但没有直接推动某些权重变为零,不具备特征选择的性质。

标准化(Standardization):标准化是一种处理数据的方法,目的是使数据的均值为0,标准差为1。这有助于处理特征之间的不同尺度,使得模型更容易收敛。标准化通常用于神经网络中的输入数据。

归一化:
    层归一化:这是一种归一化的方法,是对每个样本的每个特征在层内进行归一化。它不仅考虑了样本间的关系,还考虑了特征间的关系。
    批次归一化:这是对每个特征在批次内进行归一化,即对每个特征在每个小批量内进行归一化。批次归一化在训练神经网络时通常用于加速收敛,并有助于模型的泛化。在测试时,需要使用训练过程中计算得到的均值和方差进行归一化。

12月1日更新 用一个简单的例子 观察数据前后变化 数据shape用rnn输入情况

import torch
import torch.nn as nn

# 定义 BatchNorm1d
batch_norm = nn.BatchNorm1d(num_features=2, affine=False, track_running_stats=False)

# 模拟一个小批量的输入数据
#input_data = torch.randn((4, 2, 2))  # batch_size=5, sequence_length=5, feature_number=5

# [[[],[]],[[],[]]],[[[],[]],[[],[]]],[[[],[]],[[],[]]]

input_data =[[[1,5000],[2,10000]],[[0.5,2500],[0.1,500]],[[1,5000],[2,10000]],[[0.5,2500],[0.1,500]]]

input_data=torch.tensor(input_data)

# 将输入数据的形状调整为 (batch_size * sequence_length, feature_number)
input_data_reshaped = input_data.view(-1, 2)

# 使用 BatchNorm1d 处理输入数据
output_data_reshaped = batch_norm(input_data_reshaped)

# 将输出数据的形状调整回原来的形状
output_data = output_data_reshaped.view(4, 2, 2)

print("Input shape:", input_data.shape)
print("Output shape:", output_data.shape)
print(output_data)
##############################

Input shape: torch.Size([4, 2, 2])
Output shape: torch.Size([4, 2, 2])
tensor([[[ 0.1407,  0.1407],
         [ 1.5479,  1.5479]],

        [[-0.5629, -0.5629],
         [-1.1257, -1.1258]],

        [[ 0.1407,  0.1407],
         [ 1.5479,  1.5479]],

        [[-0.5629, -0.5629],
         [-1.1257, -1.1258]]])

Batch Normalization 将每个 feature 的数值进行标准化,使其均值接近 0,方差接近 1

用一个demo说明如何使用数据特征缩放

特征数量级差别大可能会导致神经网络训练困难,因为在反向传播过程中,梯度更新可能会因为某些特征的数量级远大于其他特征而变得不稳定。

比如原始数据为

data = [[170, 50], [180, 2000], [160, 30], [190, 5000000] 
dataset = CustomDataset(data)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)

我可以使用

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)
dataset = CustomDataset(data_scaled)

也可以使用pytorch库的torch.nn.functional.normalize 和 torch.nn.functional.min_max_scale
借助GPT展示两个例子

import torch
import torch.nn.functional as F

input_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=torch.float32)

# 使用 normalize 进行标准化
normalized_tensor = F.normalize(input_tensor, p=2, dim=1)

print("Original Tensor:")
print(input_tensor)
print("\nNormalized Tensor:")
print(normalized_tensor)

Original Tensor:
tensor([[1., 2., 3.],
        [4., 5., 6.]])

Normalized Tensor:
tensor([[0.2673, 0.5345, 0.8018],
        [0.4558, 0.5698, 0.6838]])
import torch
 
# 创建一个二维张量
x = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
 
# 沿着行的方向计算最小值和最大值
min_vals, _ = torch.min(x, dim=1, keepdim=True)
max_vals, _ = torch.max(x, dim=1, keepdim=True)
 
# 最小-最大缩放,将x的范围缩放到[0, 1]
scaled_x = (x - min_vals) / (max_vals - min_vals)
 
print(scaled_x)
 [https://blog.csdn.net/qq_36158230/article/details/120925154](https://blog.csdn.net/qq_36158230/article/details/120925154)

如果使用了BN层,BN说明 则可以不在数据使用之初使用这些办法,而建立在网络结构中。

一个简单的例子如下,
这个gpt的例子中,是用了一个全连接线性层前加一个bn,其参数和输入数据的特征维度保持一致,看起来可不一定能处理RNN 的数据shape:

import torch
import torch.nn as nn
from torch.utils.data import DataLoader, Dataset

class CustomDataset(Dataset):
    def __init__(self, data):
        self.data = data

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        return torch.tensor(self.data[idx], dtype=torch.float32)

class NeuralNetworkWithBatchNorm(nn.Module):
    def __init__(self):
        super(NeuralNetworkWithBatchNorm, self).__init__()
        self.fc1 = nn.Linear(2, 1)
        self.batch_norm = nn.BatchNorm1d(2)

    def forward(self, x):
        x = self.batch_norm(x)
        return self.fc1(x)

# 数据集
data = [[170, 50], [180, 2000], [160, 30], [190, 5000000]]
dataset = CustomDataset(data)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)

# 模型和优化器
model = NeuralNetworkWithBatchNorm()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

# 损失函数
criterion = nn.MSELoss()

# 训练模型
epochs = 1000
for epoch in range(epochs):
    for batch in dataloader:
        optimizer.zero_grad()
        output = model(batch)
        loss = criterion(output, torch.zeros_like(output))
        loss.backward()
        optimizer.step()

# 使用模型进行预测
sample_to_predict = torch.tensor([[175, 1000]], dtype=torch.float32)
predicted_value = model(sample_to_predict)
print("Predicted Value:", predicted_value.item())

继续提问
Q:BatchNorm1d可以处理的数据shape是什么
nn.BatchNorm1d 主要用于处理一维的输入,通常用在全连接层之后。具体而言,对于输入的 shape,应该是 (batch_size, num_features),其中 batch_size 是每个小批量的样本数,num_features 是每个样本的特征数。

例如,在一个简单的神经网络中,如果有两个特征,那么输入的 shape 就是 (batch_size, 2)。

下面是一个简单的示例:

python
import torch
import torch.nn as nn

# 定义 BatchNorm1d
batch_norm = nn.BatchNorm1d(num_features=2)

# 模拟一个小批量的输入数据
input_data = torch.randn((3, 2))  # 3个样本,每个样本有2个特征

# 使用 BatchNorm1d 处理输入数据
output_data = batch_norm(input_data)

在这个示例中,input_data 的 shape 是 (3, 2),表示有3个样本,每个样本有2个特征。BatchNorm1d 将在每个特征维度上进行标准化。

请注意,如果你的数据是多维的(比如图像数据),你可能需要使用 nn.BatchNorm2d 或 nn.BatchNorm3d,具体取决于数据的维度。nn.BatchNorm2d 用于处理二维输入,如图像数据,而 nn.BatchNorm3d 用于处理三维输入,比如视频数据。

也就是BN的参数仅仅与feature的维度有关。

那么RNN的数据结构类型为(batch_size,sequence_length,feature_number
)我该怎么使用他,

这个问题我在https://editor.csdn.net/md/?articleId=134698070的demo中遇到。
最后我理解,由于数据的维度是一维所以最好使用BN1d的方法,而只要把其他不是特征的维度,batch和seq length 乘在一起也正好就是本批次所有样本数量了,把时间序列拆开看

GPT回答
A:
对于 RNN 的输入数据形状为(5,5,5)(batch_size, sequence_length, feature_number),其中:

batch_size 是每个小批量的样本数。
sequence_length 是序列的长度,表示时间步的数量。
feature_number 是每个时间步的特征数。

在这种情况下,可以使用 nn.BatchNorm1d,但要确保在正确的维度上进行批归一化。由于输入数据是三维的,你需要在 nn.BatchNorm1d 中指定正确的 num_features 和 dim 参数。

以下是一个简单的示例:

python
import torch
import torch.nn as nn

# 定义 BatchNorm1d
batch_norm = nn.BatchNorm1d(num_features=5, affine=False, track_running_stats=False)

# 模拟一个小批量的输入数据
input_data = torch.randn((5, 5, 5))  # batch_size=5, sequence_length=5, feature_number=5

# 将输入数据的形状调整为 (batch_size * sequence_length, feature_number)
input_data_reshaped = input_data.view(-1, 5)

# 使用 BatchNorm1d 处理输入数据
output_data_reshaped = batch_norm(input_data_reshaped)

# 将输出数据的形状调整回原来的形状
output_data = output_data_reshaped.view(5, 5, 5)

在这个示例中,我们首先将输入数据的形状从(5,5,5)调整为(25,5),然后使用 nn.BatchNorm1d 对数据进行处理。最后,我们将输出数据的形状重新调整回原来的形状。这样,nn.BatchNorm1d 在每个时间步(sequence_length)上都会进行标准化

其中两个参数的作用如下;

affine 参数:
    当 affine=True 时,默认值,该层会学习两个可学习参数:拉伸(scale)和偏移(shift)。
    当 affine=False 时,不学习可学习参数,而是直接对输入进行标准化。

举个例子,假设 affine=True,那么 Batch Normalization 层会学习每个特征的缩放因子(scaling factor)和偏移量(shift factor),以便更灵活地适应数据。

track_running_stats 参数:
    当 track_running_stats=True 时,默认值,该参数允许在训练过程中追踪输入数据的全局均值和方差。
    当 track_running_stats=False 时,不追踪全局统计信息,在训练过程中使用批次的均值和方差进行归一化。

这两个参数的作用如下:

affine:
    如果你不想让 Batch Normalization 层学习额外的缩放和偏移参数(即使可能会降低模型的灵活性),可以将 affine 设为 False。
    在某些情况下,特别是在你对数据有较强先验知识或者希望减少模型参数数量时,可以选择禁用这些可学习的参数。

track_running_stats:
    如果你想要在训练过程中使用批次统计信息进行归一化,可以将 track_running_stats 设为 False。这对于小数据集或数据分布发生变化的情况很有用。
    如果你希望使用全局统计信息进行归一化(即使在训练期间也使用已经积累的整体统计数据),可以将 track_running_stats 设为 True。

以上,有新的理解再更新。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值