想要将YOLOv5-v7.0(python语言)中的数据增强中的Mixup替换为FMix。遂在“utils.augmentations.py”中加入FMix函数,在“utils.dataloaders.py”编改编原先的Mixup调用函数,改成FMix调用。现出现调用错误,请路过的各位大神帮忙看看!!!已经困惑多日了,这个Fmix就是不运行。
def FMix(self,
index,
im,
labels,
im2,
labels2,
mask,
decay = 3.0,
alpha=1,
shape=(416,416),
max_soft=0.0
):
self.im2 = im2
self.labels = labels2
mask = make_low_freq_image(decay, shape)
mask = binarise_mask(mask, lam, shape, max_soft)
im = (im * mask + im2 * (1 - mask)).astype(np.uint8)
labels = np.concatenate((labels, labels2), 0)
return im, labels
#计算lamba值
def lam(alpha, reformulate=False):
if reformulate:
lam = beta.rvs(alpha+1, alpha)
else:
lam = beta.rvs(alpha, alpha)
return lam
# 从傅里叶空间采样一个低频图像
def make_low_freq_image(decay, shape, ch=1):
freqs = fftfreqnd(*shape)
spectrum = get_spectrum(freqs, decay, ch, *shape)#.reshape((1, *shape[:-1], -1))
spectrum = spectrum[:, 0] + 1j * spectrum[:, 1]
mask = np.real(np.fft.irfftn(spectrum, shape))
if len(shape) == 1:
mask = mask[:1, :shape[0]]
if len(shape) == 2:
mask = mask[:1, :shape[0], :shape[1]]
if len(shape) == 3:
mask = mask[:1, :shape[0], :shape[1], :shape[2]]
mask = mask
mask = (mask - mask.min())
mask = mask / mask.max()
return mask
def fftfreqnd(h, w=None, z=None):
fz = fx = 0
fy = np.fft.fftfreq(h)
if w is not None:
fy = np.expand_dims(fy, -1)
if w % 2 == 1:
fx = np.fft.fftfreq(w)[: w // 2 + 2]
else:
fx = np.fft.fftfreq(w)[: w // 2 + 1]
if z is not None:
fy = np.expand_dims(fy, -1)
if z % 2 == 1:
fz = np.fft.fftfreq(z)[:, None]
else:
fz = np.fft.fftfreq(z)[:, None]
return np.sqrt(fx * fx + fy * fy + fz * fz)
#获取傅里叶图像
def get_spectrum(freqs, decay_power, ch, h, w=0, z=0):
scale = np.ones(1) / (np.maximum(freqs, np.array([1. / max(w, h, z)])) ** decay_power)
param_size = [ch] + list(freqs.shape) + [2]
param = np.random.randn(*param_size)
scale = np.expand_dims(scale, -1)[None, :]
return scale * param
def binarise_mask(mask, lam, in_shape, max_soft=0.0):
idx = mask.reshape(-1).argsort()[::-1]
mask = mask.reshape(-1)
num = math.ceil(lam * mask.size) if random.random() > 0.5 else math.floor(lam * mask.size)
eff_soft = max_soft
if max_soft > lam or max_soft > (1-lam):
eff_soft = min(lam, 1-lam)
soft = int(mask.size * eff_soft)
num_low = num - soft
num_high = num + soft
mask[idx[:num_high]] = 1
mask[idx[num_low:]] = 0
mask[idx[num_low:num_high]] = np.linspace(1, 0, (num_high - num_low))
mask = mask.reshape((1, *in_shape))
return mask
2.bug报告:
看看 hyp 那个数据是什么
参考GPT和自己的思路:根据你提供的代码,可能有以下原因导致调用错误:
1 FMix 函数缺少参数 im2, labels2, mask。
2 调用 FMix 函数时,缺少参数 index。
3 make_low_freq_image() 函数返回的 mask 是一个浮点型数组,但是在 FMix 函数中,mask 被用作一个布尔值的数组进行操作,可能导致类型不匹配的错误。
4 在 binarise_mask() 函数中,返回的 mask 是一个 Numpy 数组,但是在 FMix 函数中,使用了 Python 自带的 bool 类型作为数组类型,可能导致类型不匹配的错误。
你需要仔细检查以上问题,并对代码进行相应的更改,以确保正确调用 FMix 函数。
参考GPT和自己的思路,在utils.dataloaders.py中,需要将原来的Mixup替换为FMix,可以先将Mixup调用函数复制一份并将函数名改为FMix,同时对于FMix函数的参数需要按照新的定义进行修改,具体如下:
def FMixBatch(self, batch, alpha=1, decay=3.0, max_soft=0.0):
lam = np.random.beta(alpha, alpha)
index = torch.randperm(batch.size(0)).to(batch.device)
self.mix_decision = np.random.rand()
if self.mix_decision < 0.5:
# Mixup
batch = batch * lam + batch[index] * (1 - lam)
self.y_a, self.y_b = self.y_a.to(batch.device), self.y_b.to(batch.device)
labels = torch.cat([self.y_a, self.y_b], dim=0)
else:
# FMix
im2, labels2 = self._batch_transform(batch)
batch, labels = self.FMix(index, batch, self.y_a, im2, self.y_b, decay, alpha=batch.shape[-2:], max_soft=max_soft)
labels = torch.from_numpy(labels).to(batch.device)
return batch, labels
此外,还需要在utils.datasets.py文件中修改调用数据增强的函数,将原来的mixup_batch替换为FMixBatch即可,具体如下:
class LoadImagesAndLabels(Dataset):
def __init__(self, path, img_size=640, augment=False, hyp=None, rect=False, cache=False, single_cls=False):
self.img_files = sorted(glob.glob('%s/*.*' % path))
self.label_files = [x.replace('images', 'labels').replace('.png', '.txt').replace('.jpg', '.txt') for x in self.img_files]
self.img_size = img_size
self.augment = augment
self.hyp = hyp
self.rect = rect
self.cache = cache
self.mosaic = self.augment and not self.rect and not single_cls # load 4 images at a time into a mosaic (only during training)
self.single_cls = single_cls
self.n = len(self.img_files)
self.shapes = None
self.indices = range(self.n)
self.label_cache = {}
def __getitem__(self, index):
if self.cache:
img, label = self.imgs[index], self.labels[index]
else:
img_path = self.img_files[index]
label_path = self.label_files[index]
with open(label_path, 'r') as f:
label = np.array([x.split() for x in f.read().strip().splitlines()], dtype=np.float32)
# if label.ndim == 1:
# label = label.reshape(-1, 5) # make sure it's 2D
# Load image
img = cv2.imread(img_path) # BGR
assert img is not None, 'Image Not Found ' + img_path
# Padded resize
h0, w0 = img.shape[:2]
img, ratio, pad = resize_square(img, self.img_size, pad=self.rect)
label[:, 1:] = xyxy2xywh(label[:, 1:]) # xywh
label[:, 1:] = (label[:, 1:] * ratio + pad) / self.img_size # normalized xywh
label[:, [0, 2, 6]] = label[:, [0, 2, 6]] * ratio + pad # normalized xyxy
# FMix augmentation
if self.fmix and np.random.rand() < self.fmix_prob:
lam = self.sample_lambda()
fmix_ix = np.random.choice(self.num_samples, size=1)[0]
img2, label2 = self.load_image_and_label(fmix_ix)
img2, _, _ = resize_square(img2, self.img_size, pad=self.rect)
label2[:, 1:] = xyxy2xywh(label2[:, 1:]) # xywh
img, label = self.fmix(img, label, img2, label2, lam=lam)
# MixUp augmentation
elif self.mixup and np.random.rand() < self.mixup_prob:
lam = np.random.beta(self.mixup_alpha, self.mixup_alpha)
mix_ix = np.random.choice(self.num_samples, size=1)[0]
img2, label2 = self.load_image_and_label(mix_ix)
img2, _, _ = resize_square(img2, self.img_size, pad=self.rect)
label2[:, 1:] = xyxy2xywh(label2[:, 1:]) # xywh
img, label = self.mixup(img, label, img2, label2, lam=lam)
# Apply augmentations
img, label = self.transforms(img, label)
return img, label
具体来说,使用Fmix进行数据增强可以帮助模型更好地处理复杂场景下的物体,并提高模型的泛化性能。Fmix会随机选取两张图片进行融合,并利用一个掩码函数来生成新的训练样本。这个掩码函数是用于像素级别的数据操作,使得原始图像的部分区域被覆盖或消除,从而让模型不依赖于特定的背景或位置信息,增强模型的鲁棒性。
在YOLOv5中应用Fmix技术,主要可以通过以下步骤实现:
准备数据集:首先需要为目标检测模型准备一个数据集,包含了多个类别的物体样本图片,同时需要安装Fmix库。
数据增强:针对每个批次的训练数据,利用Fmix库生成额外的训练样本,扩充数据量以及增强模型鲁棒性。
训练模型:将经过Fmix增强的新数据集输入到YOLOv5模型里进行训练,更新权重和偏差。此时,模型可以更好地处理复杂的场景和物体,在训练过程中快速适应新图像的变化。
模型评估:训练完成后,可以对模型进行评估和调试,根据评估结果对模型参数进行优化和改进。
总之,将YOLOv5和Fmix技术结合起来,可以帮助我们设计出更精准、鲁棒性更强的目标检测模型,适用于各种任务场景。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
首先请确认报错信息是什么,以便更好地排查问题。
另外,您应该在更改“utils.dataloaders.py”中的Mixup调用函数之前,确保您已成功在训练集中使用FMix函数进行数据增强,并且使用FMix函数的代码没有问题。
在您进行“utils.dataloaders.py”中的更改时,您需要将原来的Mixup函数调用替换为FMix函数调用。以下是一个示例代码片段,其中Mixup被替换为FMix:
from utils.augmentations import FMix # 导入FMix函数
class LoadImages: # 更改LoadImages类,以使用FMix函数
...
def __iter__(self):
self.count = -1
self.cutoff = self.n - self.img_size * 2 # 最大迭代次数
self.shuffled = self.randomize and not self.not_rand_crop # 是否要打乱顺序
self.infinite = self.infinite_samples
return self
def __next__(self):
self.count += 1
if self.count == self.n:
if self.infinite:
self.count = 0
else:
raise StopIteration
if self.shuffled and self.count % self.n == 0:
self.indices = random.sample(range(self.n), self.n)
img_path = self.img_files[self.indices[self.count]]
img = cv2.imread(img_path) # 加载图像
...
if self.augment: # 数据增强
...
if self.mixup == 1:
img, labels = mixup(img, labels, self.smooth_labels)
elif self.mixup == 2:
img, labels = cutmix(img, labels, self.smooth_labels)
elif self.mixup == 3:
img, labels = mosaic(imgs, labels, self.cfg['mosaic']['mosaic_min'], self.img_size)
elif self.mixup == 4:
# 替换Mixup为FMix
img, labels = FMix(img, labels, self.img_size)
...
return img, labels, img_path, (h, w)
请注意,在这个示例代码片段中,我们已经从“utils.augmentations”导入了FMix函数。我们还检查了我们原来的Mixup函数调用的选项(即self.mixup的值)并相应地替换了它们。
希望这可以帮助到您!
如果我的回答解决了您的问题,请采纳!