PyTorch中形状为(N,1500,4)的数据集应在哪个位置做归一化?
归一化实现方案
你需要对最后一维的4个特征(Temp/Pre/Rev/Ph)分别做归一化,统计量仅用训练集计算,避免数据泄露,具体实现可以参考以下步骤:
1. 核心逻辑
你的数据形状为(N, 1500, 4),归一化时需要把所有样本的所有时间步的同特征值放在一起计算均值和标准差:
- 均值
mean形状为(4,),每个元素对应一个特征的全局平均值 - 标准差
std形状为(4,),每个元素对应一个特征的全局标准差 - 归一化公式:
x_norm = (x - mean) / std,可以加1e-6的极小值避免除0
2. 代码修改(内置在Dataset中,适合全训练集场景)
直接修改你的MyDataset类即可,修改后代码如下:
import numpy as np import torch from torch.utils import data as Data import pymssql class MyDataset(Data.Dataset): def __init__(self, is_train=True, train_mean=None, train_std=None, transform=None): # get the training data dataSource=[['xxxxxx'], ['xxxxxx'], ['xxxxxx']] conn=pymssql.connect( host='XXXXXXX', user='XXXX', password='XXXXXXXX', database='XXXXXXXX' ) featureDatas=[] for data in dataSource: oneDatas=[] cursor=conn.cursor(as_dict=True) sql='xxxxxxxxxxx' cursor.execute(sql) maxCount=1500 iCount=0 for row in cursor: if iCount<maxCount: oneDatas.append([row['Temp'],row['Pre'],row['Rev'],row['Ph']]) else: break iCount+=1 featureDatas.append(np.array(oneDatas).astype("float32")) cursor.close() conn.close() self.features = np.array(featureDatas) # 转成(N,1500,4)的numpy数组 labelDatas=[10,11,12] self.labels = np.array(labelDatas).astype("float32").reshape(-1,1) self.transform = transform # 归一化逻辑 if is_train: # 训练集:计算全局均值和标准差 self.mean = self.features.mean(axis=(0,1)) self.std = self.features.std(axis=(0,1)) # 避免标准差为0除错 self.std = np.where(self.std == 0, 1e-6, self.std) else: # 验证/测试集:用传入的训练集统计量 self.mean = train_mean self.std = train_std # 直接对所有特征做归一化,也可以放到__getitem__里动态做 self.features = (self.features - self.mean) / self.std def __len__(self): return len(self.features) def __getitem__(self, idx): if torch.is_tensor(idx): idx = idx.tolist() X = self.features[idx] Y = self.labels[idx] if self.transform: X = self.transform(X) # 标签如果不需要归一化就不要调用transform # Y = self.transform(Y) return X,Y # 调用示例 def toTensor(x): return torch.tensor(x) # 初始化训练集,自动计算统计量 train_dataset = MyDataset(is_train=True, transform=toTensor) # 打印训练集统计量,验证集/测试集初始化时传入这两个值即可 print("训练集特征均值:", train_dataset.mean) print("训练集特征标准差:", train_dataset.std) # 初始化验证/测试集示例 # val_dataset = MyDataset(is_train=False, train_mean=train_dataset.mean, train_std=train_dataset.std, transform=toTensor)
3. 注意事项
- 不要对单条样本单独计算统计量归一化,会丢失样本间的特征量级差异
- 如果是回归任务需要对标签归一化,训练完成后预测结果要做反归一化才能得到真实值:
y_real = y_pred * label_std + label_mean - 线上部署时需要把训练阶段得到的
mean和std固定下来,对新数据直接用这两个值做归一化即可
内容的提问来源于stack exchange,提问作者Epic Chen
相关产品推荐
相关产品推荐

