• 为特征向量数据(1D数组)叠加噪声实现数据增强


    为特征向量数据(1D数组)叠加噪声实现数据增强

    日期作者版本备注
    2023.09.11Dog TaoV1.0完成文档的初始版本。

    背景介绍

    数据增强(Data Augmentation)是一种在训练机器学习和深度学习模型时使用的技术,旨在通过对原始数据进行小的、随机的修改,来增加训练集的大小和多样性。这种增强的方法可以帮助模型学到更多的数据变化,从而增强模型的泛化能力,并减少过拟合。
    在这里插入图片描述
    根据数据的类型和特点,存在各种不同的数据增强技术。以下是针对不同类型数据的一些常见的数据增强方法:

    1. 图像数据:

      • 旋转、缩放、剪切
      • 色彩抖动(亮度、对比度、饱和度、色调变化)
      • 噪声注入(盐与胡椒噪声、高斯噪声)
      • 水平和垂直翻转
      • 仿射变换
      • 随机遮挡或模糊
    2. 时序数据/1D信号:

      • 噪声注入
      • 时间拉伸或压缩
      • 随机遮挡
      • 滑动窗口平均
      • 高频和低频滤波
    3. 文本数据:

      • 同义词替换
      • 随机删除、插入或交换单词
      • 句子重组
      • 回译(将文本翻译成另一种语言,然后再翻译回原语言)
    4. 音频数据:

      • 噪声注入(背景噪声、白噪声)
      • 变速不变调
      • 音高调整
      • 时间拉伸或压缩
      • 混响或其他音效添加
    5. 表格数据:

      • 抖动(对值进行轻微调整)
      • 特征交叉(组合两个或更多的特征)
      • 数据插补(使用统计方法或模型预测缺失值)
    6. 视频数据:

      • 与图像数据增强相似的技术,但在时间维度上应用
      • 帧间隔调整
      • 视频裁剪或切片

    当考虑数据增强技术时,重要的是确保增强方法不会破坏数据的原始语义或特征。此外,应始终在一个验证集上评估模型,该验证集没有应用相同的增强方法,以确保模型的泛化能力。

    叠加噪声的主要方法

    一般情况下,在机器学习中一个特征数据的表示形式为一个高维向量(例如时序数据、传感器数据或任何非结构化的一维数据)。为一个高维向量增加噪声以实现数据增强,可以考虑以下几种方法:

    高斯噪声(Gaussian Noise)

    高斯噪声是最常用的噪声类型,它的值是根据正态分布(高斯分布)来生成的。以下提供基于numpy.Array类型与torch.tensor类型的实现示例:

    • 基于numpy.Array类型
    import numpy as np
    
    def add_gaussian_noise_np(np_array, mean=0, std=1):
        """
        向numpy数组添加高斯噪声。
        
        参数:
            np_array (np.Array): 输入数组。
            mean (float): 高斯噪声的平均值。
            std (float): 高斯噪声的标准差。
            
        返回:
            np.Array: 添加了噪声的数组。
        """
        noise = np.random.normal(mean, std, np_array.shape)
        return np_array + noise
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 基于torch.tensor类型
    import torch
    
    def add_gaussian_noise_torch(tensor, mean=0, std=1):
        """
        向torch.tensor添加高斯噪声。
        
        参数:
            tensor (torch.Tensor): 输入张量。
            mean (float): 高斯噪声的平均值。
            std (float): 高斯噪声的标准差。
            
        返回:
            torch.Tensor: 添加了噪声的张量。
        """
        noise = torch.normal(mean, std, size=tensor.shape)
        return tensor + noise
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    均匀噪声(Uniform Noise)

    与高斯噪声不同,均匀噪声的值是从一个均匀分布中随机选取的。以下提供基于numpy.Array类型与torch.tensor类型的实现示例:

    • 基于numpy.Array类型
    import numpy as np
    
    def add_uniform_noise_np(array, low=-1, high=1):
        """
        向numpy数组添加均匀噪声。
        
        参数:
            array (np.Array): 输入数组。
            low (float): 均匀噪声的最小值。
            high (float): 均匀噪声的最大值。
            
        返回:
            np.Array: 添加了噪声的数组。
        """
        noise = np.random.uniform(low, high, array.shape)
        return array + noise
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 基于torch.tensor类型
    import torch
    
    def add_uniform_noise_torch(tensor, low=-1, high=1):
        """
        向torch.tensor添加均匀噪声。
        
        参数:
            tensor (torch.Tensor): 输入张量。
            low (float): 均匀噪声的最小值。
            high (float): 均匀噪声的最大值。
            
        返回:
            torch.Tensor: 添加了噪声的张量。
        """
        noise = torch.FloatTensor(tensor.size()).uniform_(low, high)
        return tensor + noise
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    盐与胡椒噪声(Salt and Pepper Noise)

    这种噪声会将向量中的某些元素设置为最大值(例如1)或最小值(例如0),模拟真实世界中的“损坏”数据。以下提供基于numpy.Array类型与torch.tensor类型的实现示例:

    • 基于numpy.Array类型
    import numpy as np
    
    def add_salt_pepper_noise_np(array, salt_prob=0.05, pepper_prob=0.05):
        """
        向numpy数组添加盐和胡椒噪声。
        
        参数:
            array (np.Array): 输入数组。
            salt_prob (float): 盐噪声的概率。
            pepper_prob (float): 胡椒噪声的概率。
            
        返回:
            np.Array: 添加了噪声的数组。
        """
        noise = np.random.choice([0, 1, 2], size=array.shape, p=[pepper_prob, salt_prob, 1 - salt_prob - pepper_prob])
        array[noise == 0] = 0
        array[noise == 1] = 1
        return array
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 基于torch.tensor类型
    import torch
    
    def add_salt_pepper_noise_torch(tensor, salt_prob=0.05, pepper_prob=0.05):
        """
        向torch.tensor添加盐和胡椒噪声。
        
        参数:
            tensor (torch.Tensor): 输入张量。
            salt_prob (float): 盐噪声的概率。
            pepper_prob (float): 胡椒噪声的概率。
            
        返回:
            torch.Tensor: 添加了噪声的张量。
        """
        noise = torch.multinomial(torch.tensor([pepper_prob, salt_prob, 1 - salt_prob - pepper_prob]), num_samples=tensor.numel(), replacement=True)
        tensor[noise == 0] = 0
        tensor[noise == 1] = 1
        return tensor
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    随机遮挡噪声(Random Occlusion Noise)

    随机遮挡噪声模拟真实情况中可能出现的部分损坏或遮挡的数据,以提高模型的泛化能力。以下提供基于numpy.Array类型与torch.tensor类型的实现示例:

    • 基于numpy.Array类型
    import numpy as np
    
    def add_random_block_noise_np(array, block_size=5):
        """
        向numpy数组添加随机遮挡噪声。
        
        参数:
            array (np.Array): 输入数组。
            block_size (int): 遮挡区域的长度。
            
        返回:
            np.Array: 添加了噪声的数组。
        """
        
        # 确定开始点,确保有足够的空间添加遮挡
        start_idx = np.random.randint(0, array.shape[0] - block_size)
        
        # 将遮挡区域设置为0
        array[start_idx:start_idx+block_size] = 0
        
        return array
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 基于torch.tensor类型
    import torch
    
    def add_random_block_noise_torch(tensor, block_size=5):
        """
        向torch.tensor添加随机遮挡噪声。
        
        参数:
            tensor (torch.Tensor): 输入张量。
            block_size (int): 遮挡区域的长度。
            
        返回:
            torch.Tensor: 添加了噪声的张量。
        """
        
        # 确定开始点,确保有足够的空间添加遮挡
        start_idx = torch.randint(0, tensor.size(0) - block_size, (1,)).item()
        
        # 将遮挡区域设置为0
        tensor[start_idx:start_idx+block_size] = 0
        
        return tensor
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这些函数中,我们选择了一个随机的开始点,并从该点开始将一维数组或张量中的连续数据设置为0,直到达到指定的block_size。

    数据裁剪

    当我们向向量添加噪声后,可能需要考虑是否需要对结果进行裁剪或归一化,以确保它们仍然在一个合理的范围内。例如,如果向量值的范围是[0, 1],那么在添加噪声后,可能需要执行以下操作来确保噪声后的向量仍然在这个范围内:

    noisy_vector = np.clip(noisy_vector, 0, 1)
    
    • 1

    函数封装

    我们设计一个函数来为特征数据叠加噪声,实现数据增强。将设计的函数命名为data_augmentation,该函数会接受以下参数:

    • xy:分别对应样本数据和标签数据。
    • augment_factor:增强数量,例如你想为每一组样本和标签生成10组样本和标签,那么这个值应设为10。
    • sigma:高斯噪声的标准偏差。
    • noise_range:均匀噪声的范围。
    • prob:盐与胡椒噪声的概率。

    函数会为每一组输入样本生成augment_factor个增强样本,并返回增强后的样本和标签集。例如令augment_factor=10,对于每个输入样本和标签,我们将获得30倍(3种噪声类型 ✖ augment_factor)的增强样本和标签。我们可以根据需要调整增强的数量和程度。

    import torch
    
    def add_gaussian_noise(tensor, sigma):
        """
        为给定的tensor添加高斯噪声。
        
        参数:
        tensor: torch.Tensor - 输入的张量。
        sigma: float - 高斯噪声的标准偏差。
        
        返回:
        torch.Tensor - 添加了高斯噪声的张量。
        """
        noise = torch.normal(mean=0., std=sigma, size=tensor.size())
        return tensor + noise
    
    def add_uniform_noise(tensor, noise_range):
        """
        为给定的tensor添加均匀噪声。
        
        参数:
        tensor: torch.Tensor - 输入的张量。
        noise_range: float - 均匀噪声的范围,噪声值将从[-noise_range, noise_range]选择。
        
        返回:
        torch.Tensor - 添加了均匀噪声的张量。
        """
        noise = torch.FloatTensor(tensor.size()).uniform_(-noise_range, noise_range)
        return tensor + noise
    
    def add_salt_and_pepper_noise(tensor, prob):
        """
        为给定的tensor添加盐与胡椒噪声。
        
        参数:
        tensor: torch.Tensor - 输入的张量。
        prob: float - 添加盐或胡椒的概率。
        
        返回:
        torch.Tensor - 添加了盐与胡椒噪声的张量。
        """
        noise = torch.FloatTensor(tensor.size()).uniform_(0, 1)
        salt_and_pepper = torch.where(noise < prob/2, torch.ones_like(tensor), torch.where(noise < prob, torch.zeros_like(tensor)-1, torch.zeros_like(tensor)))
        return tensor + salt_and_pepper
    
    def data_augmentation(x, y, augment_factor=10, sigma=0.1, noise_range=0.05, prob=0.01):
        """
        对给定的样本和标签进行数据增强。
        
        参数:
        x: torch.Tensor - 输入样本张量。
        y: torch.Tensor - 标签张量。
        augment_factor: int - 每种噪声类型的增强数量。
        sigma: float - 高斯噪声的标准偏差。
        noise_range: float - 均匀噪声的范围。
        prob: float - 盐与胡椒噪声的概率。
        
        返回:
        torch.Tensor, torch.Tensor - 增强后的样本和标签张量。
        """
        augmented_x, augmented_y = [], []
    
        # 为每个输入样本添加高斯噪声
        for _ in range(augment_factor):
            augmented_x.append(add_gaussian_noise(x, sigma))
            augmented_y.append(y)  # 噪声仅影响输入数据,不影响标签
    
        # 为每个输入样本添加均匀噪声
        for _ in range(augment_factor):
            augmented_x.append(add_uniform_noise(x, noise_range))
            augmented_y.append(y)
    
        # 为每个输入样本添加盐与胡椒噪声
        for _ in range(augment_factor):
            augmented_x.append(add_salt_and_pepper_noise(x, prob))
            augmented_y.append(y)
    
        # 返回堆叠后的增强样本和标签
        return torch.stack(augmented_x), torch.stack(augmented_y)
    
    
    if __name__ == "__main__":
    	# 使用示例
    	x = torch.rand((1024,))
    	y = torch.tensor([1])  # 假设这是一个标签
    	augmented_x, augmented_y = data_augmentation(x, y, augment_factor=10, sigma=0.1, noise_range=0.05, prob=0.01)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
  • 相关阅读:
    kafka的安装和使用
    Express--是第三方的框架、
    2.1.4 面向对象:类的继承(Python)
    C++程序设计期末考试复习试题及解析 3(自用~)
    【Designing ML Systems】第 4 章 :训练数据
    多版本node的安装与切换详细操作
    Angular中懒加载一个模块并动态创建显示该模块下声明的组件
    AnimalTFDB v4.0 | OMG!我最爱的转录因子数据库更新啦!~(附使用指南)(二)
    基于缓冲原理计算轨迹相似度
    宜搭,怎么在公式编辑中计算百分比的和?
  • 原文地址:https://blog.csdn.net/u013441358/article/details/132810898