YOLOV7剪枝流程

YOLOV7剪枝流程

1、训练

1)划分数据集进行训练前的准备,按正常的划分流程即可

2)修改train.py文件

第一次处在参数列表里添加剪枝的参数,正常训练时设置为False,剪枝后微调时设置为True
parser.add_argument('--pruned', action='store_true', default=True, help='pruned model fine train')
第二处位置在
# Resume

下面修改代码,源代码为:

   # Resumestart_epoch, best_fitness = 0, 0.0if pretrained:# Optimizerif ckpt['optimizer'] is not None:optimizer.load_state_dict(ckpt['optimizer'])best_fitness = ckpt['best_fitness']# EMAif ema and ckpt.get('ema'):ema.ema.load_state_dict(ckpt['ema'].float().state_dict())ma.updates = ckpt['updates']# Resultsif ckpt.get('training_results') is not None:results_file.write_text(ckpt['training_results'])  # write results.txt

修改为:

   # Resumestart_epoch, best_fitness = 0, 0.0if pretrained:if not opt.pruned:# Optimizerif ckpt['optimizer'] is not None:optimizer.load_state_dict(ckpt['optimizer'])best_fitness = ckpt['best_fitness']# EMAif ema and ckpt.get('ema'):ema.ema.load_state_dict(ckpt['ema'].float().state_dict())ema.updates = ckpt['updates']# Resultsif ckpt.get('training_results') is not None:results_file.write_text(ckpt['training_results'])  # write results.txt
第三处位置在
# Epochs

源代码为:

         # Epochsstart_epoch = ckpt['epoch'] + 1if opt.resume:assert start_epoch > 0, '%s training to %g epochs is finished, nothing to resume.' % (weights, epochs)if epochs < start_epoch:logger.info('%s has been trained for %g epochs. Fine-tuning for %g additional epochs.' %(weights, ckpt['epoch'], epochs))epochs += ckpt['epoch']  # finetune additional epochsdel ckpt, state_dict

修改为

        # Epochsif not opt.pruned:start_epoch = ckpt['epoch'] + 1if opt.resume:assert start_epoch > 0, '%s training to %g epochs is finished, nothing to resume.' % (weights, epochs)elif opt.pruned:ckpt['epoch'] = 0start_epoch = ckpt['epoch'] + 1if epochs < start_epoch:logger.info('%s has been trained for %g epochs. Fine-tuning for %g additional epochs.' %(weights, ckpt['epoch'], epochs))epochs += ckpt['epoch']  # finetune additional epochsif not opt.pruned:del ckpt, state_dictelif opt.pruned:del ckpt
第四处位置在
# Save model

源代码为:

         # Save modelif (not opt.nosave) or (final_epoch and not opt.evolve):  # if saveckpt = {'epoch': epoch,'best_fitness': best_fitness,'training_results': results_file.read_text(),'model': deepcopy(model.module if is_parallel(model) else model).half(),'ema': deepcopy(ema.ema).half(),'updates': ema.updates,'optimizer': optimizer.state_dict(),'wandb_id': wandb_logger.wandb_run.id if wandb_logger.wandb else None}

修改为:

            # Save modelif (not opt.nosave) or (final_epoch and not opt.evolve):  # if saveif opt.pruned:ckpt = {'model': deepcopy(model.module if is_parallel(model) else model).half(),}elif not opt.pruned:ckpt = {'epoch': epoch,'best_fitness': best_fitness,'training_results': results_file.read_text(),'model': deepcopy(model.module if is_parallel(model) else model).half(),'ema': deepcopy(ema.ema).half(),'updates': ema.updates,'optimizer': optimizer.state_dict(),'wandb_id': wandb_logger.wandb_run.id if wandb_logger.wandb else None}
修改后的train.py整体代码如下:
import argparse
import logging
import math
import os
import random
import time
from copy import deepcopy
from pathlib import Path
from threading import Threadimport numpy as np
import torch.distributed as dist
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler
import torch.utils.data
import yaml
from torch.cuda import amp
from torch.nn.parallel import DistributedDataParallel as DDP
from torch.utils.tensorboard import SummaryWriter
from tqdm import tqdmimport test  # import test.py to get mAP after each epoch
from models.experimental import attempt_load
from models.yolo import Model
from utils.autoanchor import check_anchors
from utils.datasets import create_dataloader
from utils.general import labels_to_class_weights, increment_path, labels_to_image_weights, init_seeds, \fitness, strip_optimizer, get_latest_run, check_dataset, check_file, check_git_status, check_img_size, \check_requirements, print_mutation, set_logging, one_cycle, colorstr
from utils.google_utils import attempt_download
from utils.loss import ComputeLoss, ComputeLossOTA
from utils.plots import plot_images, plot_labels, plot_results, plot_evolution
from utils.torch_utils import ModelEMA, select_device, intersect_dicts, torch_distributed_zero_first, is_parallel
from utils.wandb_logging.wandb_utils import WandbLogger, check_wandb_resumelogger = logging.getLogger(__name__)def train(hyp, opt, device, tb_writer=None):logger.info(colorstr('hyperparameters: ') + ', '.join(f'{k}={v}' for k, v in hyp.items()))save_dir, epochs, batch_size, total_batch_size, weights, rank, freeze = \Path(opt.save_dir), opt.epochs, opt.batch_size, opt.total_batch_size, opt.weights, opt.global_rank, opt.freeze# Directorieswdir = save_dir / 'weights'wdir.mkdir(parents=True, exist_ok=True)  # make dirlast = wdir / 'last.pt'best = wdir / 'best.pt'results_file = save_dir / 'results.txt'# Save run settingswith open(save_dir / 'hyp.yaml', 'w') as f:yaml.dump(hyp, f, sort_keys=False)with open(save_dir / 'opt.yaml', 'w') as f:yaml.dump(vars(opt), f, sort_keys=False)# Configureplots = not opt.evolve  # create plotscuda = device.type != 'cpu'init_seeds(2 + rank)with open(opt.data) as f:data_dict = yaml.load(f, Loader=yaml.SafeLoader)  # data dictis_coco = opt.data.endswith('coco.yaml')# Logging- Doing this before checking the dataset. Might update data_dictloggers = {'wandb': None}  # loggers dictif rank in [-1, 0]:opt.hyp = hyp  # add hyperparametersrun_id = torch.load(weights, map_location=device).get('wandb_id') if weights.endswith('.pt') and os.path.isfile(weights) else Nonewandb_logger = WandbLogger(opt, Path(opt.save_dir).stem, run_id, data_dict)loggers['wandb'] = wandb_logger.wandbdata_dict = wandb_logger.data_dictif wandb_logger.wandb:weights, epochs, hyp = opt.weights, opt.epochs, opt.hyp  # WandbLogger might update weights, epochs if resumingnc = 1 if opt.single_cls else int(data_dict['nc'])  # number of classesnames = ['item'] if opt.single_cls and len(data_dict['names']) != 1 else data_dict['names']  # class namesassert len(names) == nc, '%g names found for nc=%g dataset in %s' % (len(names), nc, opt.data)  # check# Modelpretrained = weights.endswith('.pt')if pretrained:if opt.pruned:from models.yolo import attempt_load#model = attempt_load(weights,map_location=device)ckpt = torch.load(weights, map_location=device)model = ckpt['model']else:with torch_distributed_zero_first(rank):attempt_download(weights)  # download if not found locallyckpt = torch.load(weights, map_location=device)  # 加载模型# 模型的定义model = Model(opt.cfg or ckpt['model'].yaml, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device)  # createexclude = ['anchor'] if (opt.cfg or hyp.get('anchors'))else []  # exclude keysstate_dict = ckpt['model'].float().state_dict()  # to FP32 获得预权重的权值state_dict = intersect_dicts(state_dict, model.state_dict(), exclude=exclude)  # intersect# 将权重加载到模型内model.load_state_dict(state_dict, strict=False)  # loadlogger.info('Transferred %g/%g items from %s' % (len(state_dict), len(model.state_dict()), weights))  # report# with torch_distributed_zero_first(rank):#     attempt_download(weights)  # download if not found locally# ckpt = torch.load(weights, map_location=device)  # load checkpoint# model = Model(opt.cfg or ckpt['model'].yaml, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device)  # create# exclude = ['anchor'] if (opt.cfg or hyp.get('anchors')) and not opt.resume else []  # exclude keys# state_dict = ckpt['model'].float().state_dict()  # to FP32# state_dict = intersect_dicts(state_dict, model.state_dict(), exclude=exclude)  # intersect# model.load_state_dict(state_dict, strict=False)  # load# logger.info('Transferred %g/%g items from %s' % (len(state_dict), len(model.state_dict()), weights))  # reportelse:model = Model(opt.cfg, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device)  # createwith torch_distributed_zero_first(rank):check_dataset(data_dict)  # checktrain_path = data_dict['train']test_path = data_dict['val']# Freezefreeze = [f'model.{x}.' for x in (freeze if len(freeze) > 1 else range(freeze[0]))]  # parameter names to freeze (full or partial)for k, v in model.named_parameters():v.requires_grad = True  # train all layersif any(x in k for x in freeze):print('freezing %s' % k)v.requires_grad = False# Optimizernbs = 64  # nominal batch sizeaccumulate = max(round(nbs / total_batch_size), 1)  # accumulate loss before optimizinghyp['weight_decay'] *= total_batch_size * accumulate / nbs  # scale weight_decaylogger.info(f"Scaled weight_decay = {hyp['weight_decay']}")pg0, pg1, pg2 = [], [], []  # optimizer parameter groupsfor k, v in model.named_modules():if hasattr(v, 'bias') and isinstance(v.bias, nn.Parameter):pg2.append(v.bias)  # biasesif isinstance(v, nn.BatchNorm2d):pg0.append(v.weight)  # no decayelif hasattr(v, 'weight') and isinstance(v.weight, nn.Parameter):pg1.append(v.weight)  # apply decayif hasattr(v, 'im'):if hasattr(v.im, 'implicit'):           pg0.append(v.im.implicit)else:for iv in v.im:pg0.append(iv.implicit)if hasattr(v, 'imc'):if hasattr(v.imc, 'implicit'):           pg0.append(v.imc.implicit)else:for iv in v.imc:pg0.append(iv.implicit)if hasattr(v, 'imb'):if hasattr(v.imb, 'implicit'):           pg0.append(v.imb.implicit)else:for iv in v.imb:pg0.append(iv.implicit)if hasattr(v, 'imo'):if hasattr(v.imo, 'implicit'):           pg0.append(v.imo.implicit)else:for iv in v.imo:pg0.append(iv.implicit)if hasattr(v, 'ia'):if hasattr(v.ia, 'implicit'):           pg0.append(v.ia.implicit)else:for iv in v.ia:pg0.append(iv.implicit)if hasattr(v, 'attn'):if hasattr(v.attn, 'logit_scale'):   pg0.append(v.attn.logit_scale)if hasattr(v.attn, 'q_bias'):   pg0.append(v.attn.q_bias)if hasattr(v.attn, 'v_bias'):  pg0.append(v.attn.v_bias)if hasattr(v.attn, 'relative_position_bias_table'):  pg0.append(v.attn.relative_position_bias_table)if hasattr(v, 'rbr_dense'):if hasattr(v.rbr_dense, 'weight_rbr_origin'):  pg0.append(v.rbr_dense.weight_rbr_origin)if hasattr(v.rbr_dense, 'weight_rbr_avg_conv'): pg0.append(v.rbr_dense.weight_rbr_avg_conv)if hasattr(v.rbr_dense, 'weight_rbr_pfir_conv'):  pg0.append(v.rbr_dense.weight_rbr_pfir_conv)if hasattr(v.rbr_dense, 'weight_rbr_1x1_kxk_idconv1'): pg0.append(v.rbr_dense.weight_rbr_1x1_kxk_idconv1)if hasattr(v.rbr_dense, 'weight_rbr_1x1_kxk_conv2'):   pg0.append(v.rbr_dense.weight_rbr_1x1_kxk_conv2)if hasattr(v.rbr_dense, 'weight_rbr_gconv_dw'):   pg0.append(v.rbr_dense.weight_rbr_gconv_dw)if hasattr(v.rbr_dense, 'weight_rbr_gconv_pw'):   pg0.append(v.rbr_dense.weight_rbr_gconv_pw)if hasattr(v.rbr_dense, 'vector'):   pg0.append(v.rbr_dense.vector)if opt.adam:optimizer = optim.Adam(pg0, lr=hyp['lr0'], betas=(hyp['momentum'], 0.999))  # adjust beta1 to momentumelse:optimizer = optim.SGD(pg0, lr=hyp['lr0'], momentum=hyp['momentum'], nesterov=True)optimizer.add_param_group({'params': pg1, 'weight_decay': hyp['weight_decay']})  # add pg1 with weight_decayoptimizer.add_param_group({'params': pg2})  # add pg2 (biases)logger.info('Optimizer groups: %g .bias, %g conv.weight, %g other' % (len(pg2), len(pg1), len(pg0)))del pg0, pg1, pg2# Scheduler https://arxiv.org/pdf/1812.01187.pdf# https://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html#OneCycleLRif opt.linear_lr:lf = lambda x: (1 - x / (epochs - 1)) * (1.0 - hyp['lrf']) + hyp['lrf']  # linearelse:lf = one_cycle(1, hyp['lrf'], epochs)  # cosine 1->hyp['lrf']scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lf)# plot_lr_scheduler(optimizer, scheduler, epochs)# EMAema = ModelEMA(model) if rank in [-1, 0] else None# Resumestart_epoch, best_fitness = 0, 0.0if pretrained:if not opt.pruned:# Optimizerif ckpt['optimizer'] is not None:optimizer.load_state_dict(ckpt['optimizer'])best_fitness = ckpt['best_fitness']# EMAif ema and ckpt.get('ema'):ema.ema.load_state_dict(ckpt['ema'].float().state_dict())ema.updates = ckpt['updates']# Resultsif ckpt.get('training_results') is not None:results_file.write_text(ckpt['training_results'])  # write results.txt# Epochsif not opt.pruned:start_epoch = ckpt['epoch'] + 1if opt.resume:assert start_epoch > 0, '%s training to %g epochs is finished, nothing to resume.' % (weights, epochs)elif opt.pruned:ckpt['epoch'] = 0start_epoch = ckpt['epoch'] + 1if epochs < start_epoch:logger.info('%s has been trained for %g epochs. Fine-tuning for %g additional epochs.' %(weights, ckpt['epoch'], epochs))epochs += ckpt['epoch']  # finetune additional epochsif not opt.pruned:del ckpt, state_dictelif opt.pruned:del ckpt# start_epoch = ckpt['epoch'] + 1# if opt.resume:#     assert start_epoch > 0, '%s training to %g epochs is finished, nothing to resume.' % (weights, epochs)# if epochs < start_epoch:#     logger.info('%s has been trained for %g epochs. Fine-tuning for %g additional epochs.' %#                 (weights, ckpt['epoch'], epochs))#     epochs += ckpt['epoch']  # finetune additional epochs# del ckpt, state_dict# Image sizesgs = max(int(model.stride.max()), 32)  # grid size (max stride)nl = model.model[-1].nl  # number of detection layers (used for scaling hyp['obj'])imgsz, imgsz_test = [check_img_size(x, gs) for x in opt.img_size]  # verify imgsz are gs-multiples# DP modeif cuda and rank == -1 and torch.cuda.device_count() > 1:model = torch.nn.DataParallel(model)# SyncBatchNormif opt.sync_bn and cuda and rank != -1:model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(model).to(device)logger.info('Using SyncBatchNorm()')# Trainloaderdataloader, dataset = create_dataloader(train_path, imgsz, batch_size, gs, opt,hyp=hyp, augment=True, cache=opt.cache_images, rect=opt.rect, rank=rank,world_size=opt.world_size, workers=opt.workers,image_weights=opt.image_weights, quad=opt.quad, prefix=colorstr('train: '))mlc = np.concatenate(dataset.labels, 0)[:, 0].max()  # max label classnb = len(dataloader)  # number of batchesassert mlc < nc, 'Label class %g exceeds nc=%g in %s. Possible class labels are 0-%g' % (mlc, nc, opt.data, nc - 1)# Process 0if rank in [-1, 0]:testloader = create_dataloader(test_path, imgsz_test, batch_size * 2, gs, opt,  # testloaderhyp=hyp, cache=opt.cache_images and not opt.notest, rect=True, rank=-1,world_size=opt.world_size, workers=opt.workers,pad=0.5, prefix=colorstr('val: '))[0]if not opt.resume:labels = np.concatenate(dataset.labels, 0)c = torch.tensor(labels[:, 0])  # classes# cf = torch.bincount(c.long(), minlength=nc) + 1.  # frequency# model._initialize_biases(cf.to(device))if plots:#plot_labels(labels, names, save_dir, loggers)if tb_writer:tb_writer.add_histogram('classes', c, 0)# Anchorsif not opt.noautoanchor:check_anchors(dataset, model=model, thr=hyp['anchor_t'], imgsz=imgsz)model.half().float()  # pre-reduce anchor precision# DDP modeif cuda and rank != -1:model = DDP(model, device_ids=[opt.local_rank], output_device=opt.local_rank,# nn.MultiheadAttention incompatibility with DDP https://github.com/pytorch/pytorch/issues/26698find_unused_parameters=any(isinstance(layer, nn.MultiheadAttention) for layer in model.modules()))# Model parametershyp['box'] *= 3. / nl  # scale to layershyp['cls'] *= nc / 80. * 3. / nl  # scale to classes and layershyp['obj'] *= (imgsz / 640) ** 2 * 3. / nl  # scale to image size and layershyp['label_smoothing'] = opt.label_smoothingmodel.nc = nc  # attach number of classes to modelmodel.hyp = hyp  # attach hyperparameters to modelmodel.gr = 1.0  # iou loss ratio (obj_loss = 1.0 or iou)model.class_weights = labels_to_class_weights(dataset.labels, nc).to(device) * nc  # attach class weightsmodel.names = names# Start trainingt0 = time.time()nw = max(round(hyp['warmup_epochs'] * nb), 1000)  # number of warmup iterations, max(3 epochs, 1k iterations)# nw = min(nw, (epochs - start_epoch) / 2 * nb)  # limit warmup to < 1/2 of trainingmaps = np.zeros(nc)  # mAP per classresults = (0, 0, 0, 0, 0, 0, 0)  # P, R, mAP@.5, mAP@.5-.95, val_loss(box, obj, cls)scheduler.last_epoch = start_epoch - 1  # do not movescaler = amp.GradScaler(enabled=cuda)compute_loss_ota = ComputeLossOTA(model)  # init loss classcompute_loss = ComputeLoss(model)  # init loss classlogger.info(f'Image sizes {imgsz} train, {imgsz_test} test\n'f'Using {dataloader.num_workers} dataloader workers\n'f'Logging results to {save_dir}\n'f'Starting training for {epochs} epochs...')torch.save(model, wdir / 'init.pt')for epoch in range(start_epoch, epochs):  # epoch ------------------------------------------------------------------model.train()# Update image weights (optional)if opt.image_weights:# Generate indicesif rank in [-1, 0]:cw = model.class_weights.cpu().numpy() * (1 - maps) ** 2 / nc  # class weightsiw = labels_to_image_weights(dataset.labels, nc=nc, class_weights=cw)  # image weightsdataset.indices = random.choices(range(dataset.n), weights=iw, k=dataset.n)  # rand weighted idx# Broadcast if DDPif rank != -1:indices = (torch.tensor(dataset.indices) if rank == 0 else torch.zeros(dataset.n)).int()dist.broadcast(indices, 0)if rank != 0:dataset.indices = indices.cpu().numpy()# Update mosaic border# b = int(random.uniform(0.25 * imgsz, 0.75 * imgsz + gs) // gs * gs)# dataset.mosaic_border = [b - imgsz, -b]  # height, width bordersmloss = torch.zeros(4, device=device)  # mean lossesif rank != -1:dataloader.sampler.set_epoch(epoch)pbar = enumerate(dataloader)logger.info(('\n' + '%10s' * 8) % ('Epoch', 'gpu_mem', 'box', 'obj', 'cls', 'total', 'labels', 'img_size'))if rank in [-1, 0]:pbar = tqdm(pbar, total=nb)  # progress baroptimizer.zero_grad()for i, (imgs, targets, paths, _) in pbar:  # batch -------------------------------------------------------------ni = i + nb * epoch  # number integrated batches (since train start)imgs = imgs.to(device, non_blocking=True).float() / 255.0  # uint8 to float32, 0-255 to 0.0-1.0# Warmupif ni <= nw:xi = [0, nw]  # x interp# model.gr = np.interp(ni, xi, [0.0, 1.0])  # iou loss ratio (obj_loss = 1.0 or iou)accumulate = max(1, np.interp(ni, xi, [1, nbs / total_batch_size]).round())for j, x in enumerate(optimizer.param_groups):# bias lr falls from 0.1 to lr0, all other lrs rise from 0.0 to lr0x['lr'] = np.interp(ni, xi, [hyp['warmup_bias_lr'] if j == 2 else 0.0, x['initial_lr'] * lf(epoch)])if 'momentum' in x:x['momentum'] = np.interp(ni, xi, [hyp['warmup_momentum'], hyp['momentum']])# Multi-scaleif opt.multi_scale:sz = random.randrange(imgsz * 0.5, imgsz * 1.5 + gs) // gs * gs  # sizesf = sz / max(imgs.shape[2:])  # scale factorif sf != 1:ns = [math.ceil(x * sf / gs) * gs for x in imgs.shape[2:]]  # new shape (stretched to gs-multiple)imgs = F.interpolate(imgs, size=ns, mode='bilinear', align_corners=False)# Forwardwith amp.autocast(enabled=cuda):pred = model(imgs)  # forwardif 'loss_ota' not in hyp or hyp['loss_ota'] == 1:loss, loss_items = compute_loss_ota(pred, targets.to(device), imgs)  # loss scaled by batch_sizeelse:loss, loss_items = compute_loss(pred, targets.to(device))  # loss scaled by batch_sizeif rank != -1:loss *= opt.world_size  # gradient averaged between devices in DDP modeif opt.quad:loss *= 4.# Backwardscaler.scale(loss).backward()# Optimizeif ni % accumulate == 0:scaler.step(optimizer)  # optimizer.stepscaler.update()optimizer.zero_grad()if ema:ema.update(model)# Printif rank in [-1, 0]:mloss = (mloss * i + loss_items) / (i + 1)  # update mean lossesmem = '%.3gG' % (torch.cuda.memory_reserved() / 1E9 if torch.cuda.is_available() else 0)  # (GB)s = ('%10s' * 2 + '%10.4g' * 6) % ('%g/%g' % (epoch, epochs - 1), mem, *mloss, targets.shape[0], imgs.shape[-1])pbar.set_description(s)# Plotif plots and ni < 10:f = save_dir / f'train_batch{ni}.jpg'  # filenameThread(target=plot_images, args=(imgs, targets, paths, f), daemon=True).start()# if tb_writer:#     tb_writer.add_image(f, result, dataformats='HWC', global_step=epoch)#     tb_writer.add_graph(torch.jit.trace(model, imgs, strict=False), [])  # add model graphelif plots and ni == 10 and wandb_logger.wandb:wandb_logger.log({"Mosaics": [wandb_logger.wandb.Image(str(x), caption=x.name) for x insave_dir.glob('train*.jpg') if x.exists()]})# end batch ------------------------------------------------------------------------------------------------# end epoch ----------------------------------------------------------------------------------------------------# Schedulerlr = [x['lr'] for x in optimizer.param_groups]  # for tensorboardscheduler.step()# DDP process 0 or single-GPUif rank in [-1, 0]:# mAPema.update_attr(model, include=['yaml', 'nc', 'hyp', 'gr', 'names', 'stride', 'class_weights'])final_epoch = epoch + 1 == epochsif not opt.notest or final_epoch:  # Calculate mAPwandb_logger.current_epoch = epoch + 1results, maps, times = test.test(data_dict,batch_size=batch_size * 2,imgsz=imgsz_test,model=ema.ema,single_cls=opt.single_cls,dataloader=testloader,save_dir=save_dir,verbose=nc < 50 and final_epoch,plots=plots and final_epoch,wandb_logger=wandb_logger,compute_loss=compute_loss,is_coco=is_coco,v5_metric=opt.v5_metric)# Writewith open(results_file, 'a') as f:f.write(s + '%10.4g' * 7 % results + '\n')  # append metrics, val_lossif len(opt.name) and opt.bucket:os.system('gsutil cp %s gs://%s/results/results%s.txt' % (results_file, opt.bucket, opt.name))# Logtags = ['train/box_loss', 'train/obj_loss', 'train/cls_loss',  # train loss'metrics/precision', 'metrics/recall', 'metrics/mAP_0.5', 'metrics/mAP_0.5:0.95','val/box_loss', 'val/obj_loss', 'val/cls_loss',  # val loss'x/lr0', 'x/lr1', 'x/lr2']  # paramsfor x, tag in zip(list(mloss[:-1]) + list(results) + lr, tags):if tb_writer:tb_writer.add_scalar(tag, x, epoch)  # tensorboardif wandb_logger.wandb:wandb_logger.log({tag: x})  # W&B# Update best mAPfi = fitness(np.array(results).reshape(1, -1))  # weighted combination of [P, R, mAP@.5, mAP@.5-.95]if fi > best_fitness:best_fitness = fiwandb_logger.end_epoch(best_result=best_fitness == fi)# Save modelif (not opt.nosave) or (final_epoch and not opt.evolve):  # if saveif opt.pruned:ckpt = {'model': deepcopy(model.module if is_parallel(model) else model).half(),}elif not opt.pruned:ckpt = {'epoch': epoch,'best_fitness': best_fitness,'training_results': results_file.read_text(),'model': deepcopy(model.module if is_parallel(model) else model).half(),'ema': deepcopy(ema.ema).half(),'updates': ema.updates,'optimizer': optimizer.state_dict(),'wandb_id': wandb_logger.wandb_run.id if wandb_logger.wandb else None}# Save last, best and deletetorch.save(ckpt, last)if best_fitness == fi:torch.save(ckpt, best)if (best_fitness == fi) and (epoch >= 200):torch.save(ckpt, wdir / 'best_{:03d}.pt'.format(epoch))if epoch == 0:torch.save(ckpt, wdir / 'epoch_{:03d}.pt'.format(epoch))elif ((epoch+1) % 25) == 0:torch.save(ckpt, wdir / 'epoch_{:03d}.pt'.format(epoch))elif epoch >= (epochs-5):torch.save(ckpt, wdir / 'epoch_{:03d}.pt'.format(epoch))if wandb_logger.wandb:if ((epoch + 1) % opt.save_period == 0 and not final_epoch) and opt.save_period != -1:wandb_logger.log_model(last.parent, opt, epoch, fi, best_model=best_fitness == fi)del ckpt# end epoch ----------------------------------------------------------------------------------------------------# end trainingif rank in [-1, 0]:# Plotsif plots:plot_results(save_dir=save_dir)  # save as results.pngif wandb_logger.wandb:files = ['results.png', 'confusion_matrix.png', *[f'{x}_curve.png' for x in ('F1', 'PR', 'P', 'R')]]wandb_logger.log({"Results": [wandb_logger.wandb.Image(str(save_dir / f), caption=f) for f in filesif (save_dir / f).exists()]})# Test best.ptlogger.info('%g epochs completed in %.3f hours.\n' % (epoch - start_epoch + 1, (time.time() - t0) / 3600))if opt.data.endswith('coco.yaml') and nc == 80:  # if COCOfor m in (last, best) if best.exists() else (last):  # speed, mAP testsresults, _, _ = test.test(opt.data,batch_size=batch_size * 2,imgsz=imgsz_test,conf_thres=0.001,iou_thres=0.7,model=attempt_load(m, device).half(),single_cls=opt.single_cls,dataloader=testloader,save_dir=save_dir,save_json=True,plots=False,is_coco=is_coco,v5_metric=opt.v5_metric)# Strip optimizersfinal = best if best.exists() else last  # final modelfor f in last, best:if f.exists():strip_optimizer(f)  # strip optimizersif opt.bucket:os.system(f'gsutil cp {final} gs://{opt.bucket}/weights')  # uploadif wandb_logger.wandb and not opt.evolve:  # Log the stripped modelwandb_logger.wandb.log_artifact(str(final), type='model',name='run_' + wandb_logger.wandb_run.id + '_model',aliases=['last', 'best', 'stripped'])wandb_logger.finish_run()else:dist.destroy_process_group()torch.cuda.empty_cache()return resultsif __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument('--weights', type=str, default='my_dataset/layer_pruning.pt', help='initial weights path')parser.add_argument('--cfg', type=str, default='cfg/training/yolov7-tiny.yaml', help='model.yaml path')parser.add_argument('--data', type=str, default='my_dataset/coco.yaml', help='data.yaml path')parser.add_argument('--hyp', type=str, default='data/hyp.scratch.p5.yaml', help='hyperparameters path')parser.add_argument('--epochs', type=int, default=600)parser.add_argument('--batch-size', type=int, default=32, help='total batch size for all GPUs')parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes')parser.add_argument('--rect', action='store_true', help='rectangular training')parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')parser.add_argument('--notest', action='store_true', help='only test final epoch')parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--multi-scale', action='store_true', default=True, help='vary img-size +/- 50%%')parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')parser.add_argument('--workers', type=int, default=16, help='maximum number of dataloader workers')parser.add_argument('--project', default='runs/train', help='save to project/name')parser.add_argument('--entity', default=None, help='W&B entity')parser.add_argument('--name', default='exp', help='save to project/name')parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')parser.add_argument('--quad', action='store_true', help='quad dataloader')parser.add_argument('--linear-lr', action='store_true', help='linear LR')parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table')parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B')parser.add_argument('--save_period', type=int, default=2, help='Log model after every "save_period" epoch')parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used')parser.add_argument('--freeze', nargs='+', type=int, default=[0], help='Freeze layers: backbone of yolov7=50, first3=0 1 2')parser.add_argument('--v5-metric', action='store_true', help='assume maximum recall as 1.0 in AP calculation')parser.add_argument('--pruned', action='store_true', default=True, help='pruned model fine train')opt = parser.parse_args()# Set DDP variablesopt.world_size = int(os.environ['WORLD_SIZE']) if 'WORLD_SIZE' in os.environ else 1opt.global_rank = int(os.environ['RANK']) if 'RANK' in os.environ else -1set_logging(opt.global_rank)#if opt.global_rank in [-1, 0]:#    check_git_status()#    check_requirements()# Resumewandb_run = check_wandb_resume(opt)if opt.resume and not wandb_run:  # resume an interrupted runckpt = opt.resume if isinstance(opt.resume, str) else get_latest_run()  # specified or most recent pathassert os.path.isfile(ckpt), 'ERROR: --resume checkpoint does not exist'apriori = opt.global_rank, opt.local_rankwith open(Path(ckpt).parent.parent / 'opt.yaml') as f:opt = argparse.Namespace(**yaml.load(f, Loader=yaml.SafeLoader))  # replaceopt.save_dir = Path(ckpt).parent.parent  # increment runopt.cfg, opt.weights, opt.resume, opt.batch_size, opt.global_rank, opt.local_rank = '', ckpt, True, opt.total_batch_size, *apriori  # reinstatelogger.info('Resuming training from %s' % ckpt)else:# opt.hyp = opt.hyp or ('hyp.finetune.yaml' if opt.weights else 'hyp.scratch.yaml')opt.data, opt.cfg, opt.hyp = check_file(opt.data), check_file(opt.cfg), check_file(opt.hyp)  # check filesassert len(opt.cfg) or len(opt.weights), 'either --cfg or --weights must be specified'opt.img_size.extend([opt.img_size[-1]] * (2 - len(opt.img_size)))  # extend to 2 sizes (train, test)opt.name = 'evolve' if opt.evolve else opt.nameopt.save_dir = increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok | opt.evolve)  # increment run# DDP modeopt.total_batch_size = opt.batch_sizedevice = select_device(opt.device, batch_size=opt.batch_size)if opt.local_rank != -1:assert torch.cuda.device_count() > opt.local_ranktorch.cuda.set_device(opt.local_rank)device = torch.device('cuda', opt.local_rank)dist.init_process_group(backend='nccl', init_method='env://')  # distributed backendassert opt.batch_size % opt.world_size == 0, '--batch-size must be multiple of CUDA device count'opt.batch_size = opt.total_batch_size // opt.world_size# Hyperparameterswith open(opt.hyp) as f:hyp = yaml.load(f, Loader=yaml.SafeLoader)  # load hyps# Trainlogger.info(opt)if not opt.evolve:tb_writer = None  # init loggersif opt.global_rank in [-1, 0]:prefix = colorstr('tensorboard: ')logger.info(f"{prefix}Start with 'tensorboard --logdir {opt.project}', view at http://localhost:6006/")tb_writer = SummaryWriter(opt.save_dir)  # Tensorboardtrain(hyp, opt, device, tb_writer)# Evolve hyperparameters (optional)else:# Hyperparameter evolution metadata (mutation scale 0-1, lower_limit, upper_limit)meta = {'lr0': (1, 1e-5, 1e-1),  # initial learning rate (SGD=1E-2, Adam=1E-3)'lrf': (1, 0.01, 1.0),  # final OneCycleLR learning rate (lr0 * lrf)'momentum': (0.3, 0.6, 0.98),  # SGD momentum/Adam beta1'weight_decay': (1, 0.0, 0.001),  # optimizer weight decay'warmup_epochs': (1, 0.0, 5.0),  # warmup epochs (fractions ok)'warmup_momentum': (1, 0.0, 0.95),  # warmup initial momentum'warmup_bias_lr': (1, 0.0, 0.2),  # warmup initial bias lr'box': (1, 0.02, 0.2),  # box loss gain'cls': (1, 0.2, 4.0),  # cls loss gain'cls_pw': (1, 0.5, 2.0),  # cls BCELoss positive_weight'obj': (1, 0.2, 4.0),  # obj loss gain (scale with pixels)'obj_pw': (1, 0.5, 2.0),  # obj BCELoss positive_weight'iou_t': (0, 0.1, 0.7),  # IoU training threshold'anchor_t': (1, 2.0, 8.0),  # anchor-multiple threshold'anchors': (2, 2.0, 10.0),  # anchors per output grid (0 to ignore)'fl_gamma': (0, 0.0, 2.0),  # focal loss gamma (efficientDet default gamma=1.5)'hsv_h': (1, 0.0, 0.1),  # image HSV-Hue augmentation (fraction)'hsv_s': (1, 0.0, 0.9),  # image HSV-Saturation augmentation (fraction)'hsv_v': (1, 0.0, 0.9),  # image HSV-Value augmentation (fraction)'degrees': (1, 0.0, 45.0),  # image rotation (+/- deg)'translate': (1, 0.0, 0.9),  # image translation (+/- fraction)'scale': (1, 0.0, 0.9),  # image scale (+/- gain)'shear': (1, 0.0, 10.0),  # image shear (+/- deg)'perspective': (0, 0.0, 0.001),  # image perspective (+/- fraction), range 0-0.001'flipud': (1, 0.0, 1.0),  # image flip up-down (probability)'fliplr': (0, 0.0, 1.0),  # image flip left-right (probability)'mosaic': (1, 0.0, 1.0),  # image mixup (probability)'mixup': (1, 0.0, 1.0),   # image mixup (probability)'copy_paste': (1, 0.0, 1.0),  # segment copy-paste (probability)'paste_in': (1, 0.0, 1.0)}    # segment copy-paste (probability)with open(opt.hyp, errors='ignore') as f:hyp = yaml.safe_load(f)  # load hyps dictif 'anchors' not in hyp:  # anchors commented in hyp.yamlhyp['anchors'] = 3assert opt.local_rank == -1, 'DDP mode not implemented for --evolve'opt.notest, opt.nosave = True, True  # only test/save final epoch# ei = [isinstance(x, (int, float)) for x in hyp.values()]  # evolvable indicesyaml_file = Path(opt.save_dir) / 'hyp_evolved.yaml'  # save best result hereif opt.bucket:os.system('gsutil cp gs://%s/evolve.txt .' % opt.bucket)  # download evolve.txt if existsfor _ in range(300):  # generations to evolveif Path('evolve.txt').exists():  # if evolve.txt exists: select best hyps and mutate# Select parent(s)parent = 'single'  # parent selection method: 'single' or 'weighted'x = np.loadtxt('evolve.txt', ndmin=2)n = min(5, len(x))  # number of previous results to considerx = x[np.argsort(-fitness(x))][:n]  # top n mutationsw = fitness(x) - fitness(x).min()  # weightsif parent == 'single' or len(x) == 1:# x = x[random.randint(0, n - 1)]  # random selectionx = x[random.choices(range(n), weights=w)[0]]  # weighted selectionelif parent == 'weighted':x = (x * w.reshape(n, 1)).sum(0) / w.sum()  # weighted combination# Mutatemp, s = 0.8, 0.2  # mutation probability, sigmanpr = np.randomnpr.seed(int(time.time()))g = np.array([x[0] for x in meta.values()])  # gains 0-1ng = len(meta)v = np.ones(ng)while all(v == 1):  # mutate until a change occurs (prevent duplicates)v = (g * (npr.random(ng) < mp) * npr.randn(ng) * npr.random() * s + 1).clip(0.3, 3.0)for i, k in enumerate(hyp.keys()):  # plt.hist(v.ravel(), 300)hyp[k] = float(x[i + 7] * v[i])  # mutate# Constrain to limitsfor k, v in meta.items():hyp[k] = max(hyp[k], v[1])  # lower limithyp[k] = min(hyp[k], v[2])  # upper limithyp[k] = round(hyp[k], 5)  # significant digits# Train mutationresults = train(hyp.copy(), opt, device)# Write mutation resultsprint_mutation(hyp.copy(), results, yaml_file, opt.bucket)# Plot resultsplot_evolution(yaml_file)print(f'Hyperparameter evolution complete. Best results saved as: {yaml_file}\n'f'Command to train a new model with these hyperparameters: $ python train.py --hyp {yaml_file}')

2、剪枝

剪枝方法

YOLOv4剪枝【附代码】_strategy = tp.strategy.l1strategy()-CSDN博客参考此篇博文进行的通道剪枝。Pruning Filters for Efficient ConvNets这篇论文的技术

添加prunmodel.py文件

下载torch_pruning模块时一定要使用0.2.5版本,

pip install torch_pruning==0.2.7
pip install loguru

把训练好的模型路径放进去

layer_pruning('/home/jovyan/exp_3046/runs/train/best.pt')  

定义剪枝后保存的模型路径

torch.save(model_, '/home/jovyan/exp_3047/data/layer_pruning.pt')

修改prunmodel.py文件中需要剪枝的权重路径。重点修改58~62行。这里是以修改model的前10层为例。head层不能剪,我们选择backbone的层。

  included_layers = []for layer in model.model[:10]:  # 获取backboneif type(layer) is Conv:included_layers.append(layer.conv)included_layers.append(layer.bn)

下面代码是剪枝conv和BN层。【重点是tp.prune_conv】,自己修改amout也就是剪枝率。

        if isinstance(m, nn.Conv2d) and m in included_layers:# amount是剪枝率# 卷积剪枝pruning_plan = DG.get_pruning_plan(m, tp.prune_conv, idxs=strategy(m.weight, amount=0.8))logger.info(pruning_plan)# 执行剪枝pruning_plan.exec()if isinstance(m, nn.BatchNorm2d) and m in included_layers:# BN层剪枝pruning_plan = DG.get_pruning_plan(m, tp.prune_batchnorm, idxs=strategy(m.weight, amount=0.8))logger.info(pruning_plan)pruning_plan.exec()
出现以下内容说明剪枝成功
2023-03-15 14:57:40.825 | INFO     | __main__:layer_pruning:84 -   Params: 37196556 => 368397952023-03-15 14:57:41.176 | INFO     | __main__:layer_pruning:95 - 剪枝完成

代码如下:

import syssys.path.append("/home/jovyan/exp_3046")
# print(sys.path)import torch_pruning as tp
from loguru import logger
from models.common import *
from models.experimental import Ensemble
from utils.torch_utils import select_device"""
剪枝的时候根据模型结构去剪,不要盲目的猜
剪枝完需要进行一个微调训练
"""# 加载模型
def attempt_load(weights, map_location=None, inplace=True):from models.yolo import Detect, Modelmodel = Ensemble()ckpt = torch.load(weights, map_location=map_location)  # load weightsmodel.append(ckpt['ema' if ckpt.get('ema') else 'model'].float().eval())  # without layer fuse  权值的加载# Compatibility updatesfor m in model.modules():  # 取出每一层if type(m) in [nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU, Detect, Model]:m.inplace = inplace  # pytorch 1.7.0 compatibilityif type(m) is Detect:  # 判断是否为目标检测if not isinstance(m.anchor_grid, list):  # new Detect Layer compatibilitydelattr(m, 'anchor_grid')setattr(m, 'anchor_grid', [torch.zeros(1)] * m.nl)elif type(m) is Conv:  # 卷积层m._non_persistent_buffers_set = set()  # pytorch 1.6.0 compatibilityif len(model) == 1:return model[-1], ckpt  # return modelelse:print(f'Ensemble created with {weights}\n')for k in ['names']:setattr(model, k, getattr(model[-1], k))model.stride = model[torch.argmax(torch.tensor([m.stride.max() for m in model])).int()].stride  # max stridereturn model, ckpt  # return ensemble@logger.catch
def layer_pruning(weights):logger.add('../logs/layer_pruning.log', rotation='1 MB')device = select_device('cpu')model, ckpt = attempt_load(weights, map_location=device)for para in model.parameters():para.requires_grad = True# 创建输入样例,可在此修改输入大小x = torch.zeros(1, 3, 640, 640)# -----------------对整个模型的剪枝--------------------strategy = tp.strategy.L1Strategy()  # L1策略DG = tp.DependencyGraph()  # 依赖图DG = DG.build_dependency(model, example_inputs=x)"""这里写要剪枝的层这里以backbone为例"""included_layers = []for layer in model.model[:41]:  # 获取backboneif type(layer) is Conv:included_layers.append(layer.conv)included_layers.append(layer.bn)logger.info(included_layers)# 获取未剪枝之前的参数量num_params_before_pruning = tp.utils.count_params(model)# 模型遍历for m in model.modules():# 判断是否为卷积并且是否在需要剪枝的层里if isinstance(m, nn.Conv2d) and m in included_layers:# amount是剪枝率# 卷积剪枝# 层剪枝(需要筛选出不需要剪枝的层,比如yolo需要把头部的预测部分取出来,这个是不需要剪枝的) pruning_plan = DG.get_pruning_plan(m, tp.prune_conv, idxs=strategy(m.weight, amount=0.4))logger.info(pruning_plan)# 执行剪枝pruning_plan.exec()if isinstance(m, nn.BatchNorm2d) and m in included_layers:# BN层剪枝pruning_plan = DG.get_pruning_plan(m, tp.prune_batchnorm, idxs=strategy(m.weight, amount=0.3))logger.info(pruning_plan)pruning_plan.exec()# 获得剪枝以后的参数量num_params_after_pruning = tp.utils.count_params(model)# 输出一下剪枝前后的参数量logger.info("  Params: %s => %s\n" % (num_params_before_pruning, num_params_after_pruning))# 剪枝完以后模型的保存(不要用torch.save(model.state_dict(),...))model_ = {'model': model.half(),# 'optimizer': ckpt['optimizer'],# 'training_results': ckpt['training_results'],'epoch': ckpt['epoch']}torch.save(model_, '/home/jovyan/exp_3046/my_dataset/layer_pruning.pt')del model_, ckptlogger.info("剪枝完成\n")layer_pruning('/home/jovyan/exp_3046/runs/train/best.pt')  

3、微调

运行train.py

权重为剪枝之后的layer_pruning.pt

parser.add_argument('--pruned', action='store_true', default=True, help='pruned model fine train')

4、效果

使用初始训练好的权重进行预测用时 249.217s
在这里插入图片描述

使用剪枝之后的模型进行预测用时172.418s

在这里插入图片描述

p.prune_batchnorm, idxs=strategy(m.weight, amount=0.3))logger.info(pruning_plan)pruning_plan.exec()# 获得剪枝以后的参数量num_params_after_pruning = tp.utils.count_params(model)# 输出一下剪枝前后的参数量logger.info("  Params: %s => %s\n" % (num_params_before_pruning, num_params_after_pruning))# 剪枝完以后模型的保存(不要用torch.save(model.state_dict(),...))model_ = {'model': model.half(),# 'optimizer': ckpt['optimizer'],# 'training_results': ckpt['training_results'],'epoch': ckpt['epoch']}torch.save(model_, '/home/jovyan/exp_3046/my_dataset/layer_pruning.pt')del model_, ckptlogger.info("剪枝完成\n")layer_pruning('/home/jovyan/exp_3046/runs/train/best.pt')  

3、微调

运行train.py

权重为剪枝之后的layer_pruning.pt

parser.add_argument('--pruned', action='store_true', default=True, help='pruned model fine train')

4、效果

使用初始训练好的权重进行预测用时 249.217s

[外链图片转存中...(img-BIsS94eN-1705027254462)]

使用剪枝之后的模型进行预测用时172.418s

[外链图片转存中...(img-lLdHRbRI-1705027254463)]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/617939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux第28步_编译“正点原子的TF-A源码”

编译“正点原子的TF-A源码”&#xff0c;目的是想得到TF-A文件&#xff0c;即“tf-a-stm32mp157d-atk-trusted.stm32”。 在前27步的基础上&#xff0c;才可以学习本节内容&#xff0c;学习步骤如下&#xff1a; 1、创建“alientek_tf-a”目录&#xff1b; 2、复制正点原子的…

.【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)

概率图模型是一种用图形表示概率分布和条件依赖关系的数学模型。概率图模型可以分为两大类&#xff1a;有向图模型和无向图模型。有向图模型也叫贝叶斯网络&#xff0c;它用有向无环图表示变量之间的因果关系。无向图模型也叫马尔可夫网络&#xff0c;它用无向图表示变量之间的…

02.部署LVS-DR群集

技能展示&#xff1a; 了解LVS-DR群集的工作原理 会构建LVS-DR负载均衡群集 2.1 LVS-DR 集群 LVS-DR&#xff08; Linux Virtual Server Director Server &#xff09;工作模式&#xff0c;是生产环境中最常用的一种工作模式。 2.1.1&#xff0e;LVS-DR 工作原理 LVS-DR 模式&…

Spark---RDD持久化

文章目录 1.RDD持久化1.1 RDD Cache 缓存1.2 RDD CheckPoint 检查点1.3 缓存和检查点区别 1.RDD持久化 在Spark中&#xff0c;持久化是将RDD存储在内存中&#xff0c;以便在多次计算之间重复使用。这可以显著减少不必要的计算&#xff0c;提高Spark应用程序的性能。 val line…

蓝桥杯练习题(七)

&#x1f4d1;前言 本文主要是【算法】——蓝桥杯练习题&#xff08;七&#xff09;的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 …

kotlin运行

1.使用android studio 由于我本身是做android的&#xff0c;android studio本身有内置kotlin的插件。但若只是想跑kotlin的程序&#xff0c;并不像和android程序绑在一起&#xff0c;可以创建一个kt文件&#xff0c;在里面写一个main函数&#xff0c;就可以直接运行kotlin程序…

【机器学习 西瓜书】期末复习笔记整理

一些杂点&#xff1a; 测试集如何归一化&#xff1f; —— 不是用测试集的均值和标准差&#xff0c;而是用训练集的&#xff01; 机器学习&#xff1a; 对计算机一部分数据进行学习&#xff0c;然后对另外一些数据进行预测与判断。 参考计算例题&#xff1a; 机器学习【期末复习…

PyCharm安装使用教程2024

简介 PyCharm是一种PythonIDE&#xff08;Integrated Development Environment&#xff0c;集成开发环境&#xff09;&#xff0c;带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具&#xff0c;比如调试、语法高亮、项目管理、代码跳转、智能提示、自动完成、单…

[oeasy]python0004_游乐场_和python一起玩耍_python解释器_数学运算

和python玩耍 &#x1f94a; Python 回忆 上次 了解shell环境中的命令 命令作用whoami显示当前用户名pwd显示当前文件夹ls列出当前文件夹下的内容python3仿佛进入大于号黑洞 这python3 怎么玩啊&#xff01;&#x1f620; 说好的python教程呢&#xff1f;&#x1f914; 运…

vue2使用Lottie

文章目录 学习链接1.安装依赖2.创建lottie组件3.在相对应的页面应用4.相关data.json5.测试效果 学习链接 原文链接&#xff1a;lottie在vue中的使用 lottie官网&#xff1a;https://lottiefiles.com/ 1.安装依赖 npm install lottie-web2.创建lottie组件 <template>…

MetaGPT前期准备与快速上手

大家好&#xff0c;MetaGPT 是基于大型语言模型&#xff08;LLMs&#xff09;的多智能体协作框架&#xff0c;GitHub star数量已经达到31.3k。 接下来我们聊一下快速上手 这里写目录标题 一、环境搭建1.python 环境2. MetaGpt 下载 二、MetaGPT配置1.调用 ChatGPT API 服务2.简…

Maven的安装和配置

国内Maven仓库之阿里云Aliyun仓库地址及设置 用过Maven的都知道Maven的方便便捷&#xff0c;但由于某些网络原因&#xff0c;访问国外的Maven仓库不便捷&#xff0c;好在阿里云搭建了国内的maven仓库。 需要使用的话&#xff0c;要在maven的settings.xml 文件里配置mirrors的子…

HTTP 常见协议:选择正确的协议,提升用户体验(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

SQL语句详解二-DDL(数据定义语言)

文章目录 操作数据库创建&#xff1a;Create查询&#xff1a;Retrieve修改&#xff1a;Update删除&#xff1a;Delete使用数据库 操作表常见的几种数据类型创建&#xff1a;Create复制表 查询&#xff1a;Retrieve修改&#xff1a;Update删除&#xff1a;Delete 操作数据库 创…

Stable Diffusion XL Turbo 文生图和图生图实践

本篇文章聊聊&#xff0c;如何快速上手 Stable Diffusion XL Turbo 模型的文生图和图生图实战。 写在前面 分享一篇去年 11 月测试过模型&#xff0c;为月末分享的文章做一些技术铺垫&#xff0c;以及使用新的环境进行完整复现。 本篇文章相关的代码保存在 soulteary/docker…

【教学类-43-18】A4最终版 20240111 数独11.0 十宫格X*Y=Z套(n=10),套用没有分割行列的A4横版模板

作品展示&#xff1a; 撑满格子的10宫格数独50%难度 50空 背景需求&#xff1a; 大4班有3位男孩做9宫格数独&#xff08;81格子&#xff0c;30%难度 24空&#xff09;非常娴熟&#xff0c;我观察他们基本都在10分钟内完成&#xff0c;其中一位男孩把九宫格题目给我看时表达自…

使用 EmbeddingBag 和 Embedding 完成词嵌入

&#x1f368; 本文为[&#x1f517;365天深度学习训练营学习记录博客\n&#x1f366; 参考文章&#xff1a;365天深度学习训练营\n&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制]\n&#x1f680; 文章来源&#xff1a;[K同学的学习圈子](https://www.yuque.co…

移除两个双向链表中的重复元素,每个链表中的元素不重复

移除两个双向链表中的重复元素&#xff0c;每个链表中的元素不重复&#xff0c;请给出算法。 ans: 该问题比单向链表要更加复杂一些&#xff0c;必须考虑并更新前向节点的指向情况&#xff0c;具体编码中存在一些难度&#xff0c;加上链表调试相对不容易&#xff0c;因此难度系…

技术专栏——你所不知道的 RocketMQ 的集群管理:副本机制

这些精彩的技术类型的体系化文章&#xff0c;后面我会放到公众号上&#xff0c;并集中在合集“分布式消息中间件专栏”中&#xff0c;欢迎大家去订阅我的公众号和视频号“架构随笔录”&#xff0c;大家可以订阅合集&#xff0c;这样更加方便喔&#xff0c;后面会出电子版本&…

C++采集亚马逊amazon产品数据教程

最近亚马逊电商非常火爆&#xff0c;今天我将用C语言写一个亚马逊商品数据的爬虫程序&#xff0c;只要是用来收集一些产品相关信息。例如产品自身特性以及产品所对应的销量&#xff0c;为了后期布局亚马逊做一些参考&#xff0c;提供数据支持&#xff0c;同时另外我也会用C语言…