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.rhkb.cn/news/241149.html

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

相关文章

Linux安装ossutil工具且在Jenkins中执行shell脚本下载文件

测试中遇到想通过Jenkins下载OSS桶上的文件&#xff0c;要先在linux上安装ossutil工具&#xff0c;记录安装过程如下&#xff1a; 一、下载安装ossutil&#xff0c;使用命令 1.下载&#xff1a;wget https://gosspublic.alicdn.com/ossutil/1.7.13/ossutil64 2.一定要赋权限…

不同波段的热红外相机特点与应用

热红外相机通常分为三个主要波段&#xff1a; 长波红外 (LWIR) 波段&#xff1a;这个波段的范围大约在8-14微米。长波红外相机主要用于工业、安全监控和夜视设备。这个波段的特点是对温度变化非常敏感&#xff0c;能够在没有任何光源的情况下工作。 中波红外 (MWIR) 波段&…

使用的uview 微信高版本 头像昵称填写能力

<template><view><button class"cu-btn block bg-blue margin-tb-sm lg" tap"wxGetUserInfo">一键登录</button><view><!-- 提示窗示例 --><u-popup :show"show" background-color"#fff">&…

小程序开发实战案例五 | 小程序如何嵌入H5页面

在接入小程序过程中会遇到需要将 H5 页面集成到小程序中情况&#xff0c;今天我们就来聊一聊怎么把 H5 页面塞到小程序中。 本篇文章将会从下面这几个方面来介绍&#xff1a; 小程序承载页面的前期准备小程序如何承载 H5小程序和 H5 页面如何通讯小程序和 H5 页面的相互跳转 小…

Ubuntu重启后进入initramfs导致无法开机

今晚&#xff0c;我的电脑意外关机&#xff0c;重新开机后打开了虚拟机后出现initramfs&#xff0c;一直无法开机。该虚拟机使用的是 vm17,系统是ubuntu20, 解决方案 使用如下命令查看和识别磁盘、分区或文件系统的信息 在initramfs后面输入 fsck /dev/sdb4 ,即修复上面损坏的…

WINCC读写EXCEL-VBS

原创 RENHQ WINCC 关于VBS操作EXCEL的文档不管在论坛上还是在网上&#xff0c;相关的脚本已经很多&#xff0c;但是依然有很多人在问这个问题&#xff0c;于是把我以前在论坛上发的一个集合帖子的脚本拿来&#xff0c;重新开个帖子&#xff0c;如果再有人问的话&#xff0c;可…

kali下-MSF-ftp_login模块破解FTP账号及密码

一、环境准备 两台设备在同一个网络内 一台kali系统&#xff1a;192.168.10.128 一台winserver2016&#xff1a;192.168.10.132 二、MSF介绍 metasploit 全称是The Metasploit Framework&#xff0c;又称MSF&#xff0c;是Kali 内置的一款渗透测试框架&#xff0c;也是全球…

MySQL中锁的概述

按照锁的粒度来分可分为&#xff1a;全局锁&#xff08;锁住当前数据库的所有数据表&#xff09;&#xff0c;表级锁&#xff08;锁住对应的数据表&#xff09;&#xff0c;行级锁&#xff08;每次锁住对应的行数据&#xff09; 加全局锁&#xff1a;flush tables with read lo…

基于springboot+vue的图书个性化推荐系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

线程同步--生产者消费者模型

文章目录 一.条件变量pthread线程库提供的条件变量操作 二.生产者消费者模型生产者消费者模型的高效性基于环形队列实现生产者消费者模型中的数据容器 一.条件变量 条件变量是线程间共享的全局变量,线程间可以通过条件变量进行同步控制条件变量的使用必须依赖于互斥锁以确保线…

数据结构之栈的基本操作

该顺序栈涉及到了存储整型数据的顺序栈还有存储字符型数据的顺序栈 实现的功能有&#xff1a;入栈、出栈、判断是否为空栈、求栈的长度、清空栈、销毁栈、得到栈顶元素 此外根据上述功能&#xff0c;编写了数值转换&#xff08;十进制转化八进制&#xff09;方法、括号匹配方法…

服务器变矿机,该如何应对?

开始 恶意的挖矿程序会导致服务器cpu的异常占用&#xff0c;很让人讨厌。起初&#xff0c;我只是使用top命令显示出占用cpu不正常的进程&#xff0c;发现其中一个进程占用了百分之九十九点几&#xff0c;然后通过kill -9 <PID>命令干掉它。但总是过不了几天&#xff0c;…

深度学习:探索人工智能的前沿

1. 引言 1.1 人工智能的演进 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一门研究如何使计算机能够执行通常需要人类智能的任务的领域。从早期的符号推理到现代的深度学习&#xff0c;人工智能经历了漫长的发展过程。 20世纪50年代&#xff…

MySQL 基于创建时间进行RANGE分区

MySQL是一款广泛使用的关系型数据库。在MySQL中&#xff0c;大量数据场景提高查询效率是非常关键的&#xff0c;所以&#xff0c;对数据表进行分区是一个很好的选择。 在创建分区表之前&#xff0c;需要了解一下MySQL分区的基本概念。MySQL分区可以将一个大表分成多个小表&…

K8s 网关选型血泪史

Sealos 公有云几乎打爆了市面上所有主流的开源网关&#xff0c;本文可以给大家很好的避坑&#xff0c;在网关选型方面做一些参考。 Sealos Cloud 的复杂场景 Sealos 公有云上线以来&#xff0c;用户呈爆发式增长&#xff0c;目前总共注册用户 8.7w&#xff0c;每个用户都去创…

FFmpeg之AVFormat

文章目录 一、概述二、解封装流程三、重要结构体3.1、AVFormatContext3.2、AVInputFormat3.3、AVOutputFormat3.4、AVStream 四、重要函数分析4.1、avformat_alloc_context4.2、avformat_open_input4.2.1、init_input4.2.2、av_probe_input_format2 4.3、avformat_find_stream_…

Flutter开发之蓝牙链接传输数据

本文使用的是flutter_blue_plus插件来实现链接蓝牙之后&#xff0c;和设备直接实现数据互相传输的功能。 1、配置蓝牙权限 iOS权限设置<key>NSBluetoothAlwaysUsageDescription</key><string>App需要您的同意,才能访问蓝牙,进行设备连接,数据通讯服务</…

LeetCode 热题 100 | 双指针(上)

目录 1 283. 移动零 2 11. 盛最多水的容器 3 15. 三数之和 菜鸟做题第一周&#xff0c;语言是 C 1 283. 移动零 解题思路&#xff1a; 两个指针一前一后遍历数组前者永远指向 0&#xff0c;后者永远在寻找非 0 数的路上后者找到一个非 0 数就和前者进行一个数值交换 …

Qt应用开发(安卓篇)——Hello Qt On Android

一、前言 这一篇从实际出发&#xff0c;讲述如何创建、编译和部署Qt On Android项目。 二、ADB调试 ADB的全称为Android Debug Bridge&#xff0c;就是起到调试桥的作用&#xff0c;主要用于连接计算机与Android 设备&#xff0c;以便进行调试和数据传输。ADB 可以实现以下主要…

分享一个美美的html模板

在这个万物vue的年代&#xff0c;网页设计越来越框架化。 上网搜个资料学习学习吧&#xff0c;咵咵咵&#xff0c;“游泳健身&#xff0c;vue了解一下” 我只是想简单地学个html&#xff0c;js啊&#xff01;怎么就这么复杂&#xff01; 曾几何时&#xff0c;在网上找个网页…