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

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

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

文章目录

  • 为特征向量数据(1D数组)叠加噪声实现数据增强
    • 背景介绍
    • 叠加噪声的主要方法
      • 高斯噪声(Gaussian Noise)
      • 均匀噪声(Uniform Noise)
      • 盐与胡椒噪声(Salt and Pepper Noise)
      • 随机遮挡噪声(Random Occlusion Noise)
      • 数据裁剪
    • 函数封装

背景介绍

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

  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

  • 基于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


均匀噪声(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
  • 基于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

盐与胡椒噪声(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
  • 基于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

随机遮挡噪声(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
  • 基于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

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

数据裁剪

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

noisy_vector = np.clip(noisy_vector, 0, 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)

你可能感兴趣的:(人工智能与机器学习,人工智能,数据增强,深度学习,机器学习,噪声注入)