参考:
量化剪枝:YOLO落地部署,一文尽览YOLOv5最新剪枝、量化进展
robflow 漂浮物数据集:buoy Computer Vision Dataset by ai
yolo5 :https://github.com/ultralytics/yolov5
克隆代码:
git clone https://github.com/ultralytics/yolov5 # clone
cd yolov5
pip install -r requirements.txt # install
import torch
# 检查是否有可用的GPU
if torch.cuda.is_available():
print("GPU is available.")
else:
print("GPU is not available.")
python train.py --img 640 --epochs 3 --data coco128.yaml --weights yolov5s.pt
调参适应场景和优化效果:
--weights: 初始权重文件的路径,默认值是 ROOT / 'yolov5s.pt'。
--data: 数据集配置文件 dataset.yaml 的路径,默认值是 ROOT / 'data/coco128.yaml'。
--epochs
: 总的训练轮数,默认值是 100。
--batch-size
: 所有 GPU 上的总批量大小,-1 表示自动确定,默认值是 16。
--imgsz
: 训练和验证图像大小(像素),默认值是 640。
--device
: 指定使用的设备,如 'cuda:0' 表示使用第一个 GPU,'cpu' 表示使用 CPU。
--project
: 保存结果的项目路径,默认值是ROOT / 'runs/train'
--name
: 保存结果的名称,默认值是 'exp'。
python train.py --img 640 --epochs 3 --data ../float_data/data.yaml --weights yolov5s.pt --device cuda:0
# 使用V100的训练参数
python train.py --data coco.yaml --epochs 300 --weights '' --cfg yolov5n.yaml --batch-size 128
使用torch.hub.load()加载我们训练好的模型,如下,通过torch.hub.load进行加载模型,将图片导入,得到的results。可以通过results.pandas().xyxy[0]解读,结果是个张量,前四列为目标框的左上角和右下角,confidence为置信度,class为类别编号,name为类别名称。
import torch
from utils.torch_utils import prune
import cv2
import time
import torch
model = torch.hub.load('../yolov5', 'custom', path='./runs/train/exp2/weights/best.pt', source='local')
model.eval()
model.conf = 0.4
cap = cv2.VideoCapture(0)
fps_time = time.time()
while True:
ret, frame = cap.read()
frame = cv2.flip(frame, 1)
img_cvt = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = model(img_cvt)
# print(results.pandas().xyxy[0].to_numpy())# tensor-to-numpy
results_ = results.pandas().xyxy[0].to_numpy()
i = 0
for box in results_:
l, t, r, b = box[:4].astype('int')
confidence = str(round(box[4] * 100, 2)) + "%"
cls_name = box[6]
if cls_name == "person":
i += 1
cv2.rectangle(frame, (l, t), (r, b), (0, 255, 0), 2)
cv2.putText(frame, cls_name + "-" + confidence, (l, t), cv2.FONT_ITALIC, 1, (255, 0, 0), 2)
cv2.putText(frame, "person:" + str(i), (10, 20), cv2.FONT_ITALIC, 1, (0, 0, 0), 2)
now = time.time()
fps_txt = 1 / (now - fps_time)
fps_time = now
cv2.putText(frame, str(round(fps_txt, 2)), (50, 50), cv2.FONT_ITALIC, 1, (0, 255, 0), 2)
cv2.imshow("result", frame)
if cv2.waitKey(10) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
import glob
import cv2
import time
import torch
from utils.torch_utils import prune
# 从本地目录加载自定义的YOLOv5模型
model = torch.hub.load('../yolov5', 'custom', path='./runs/train/exp2/weights/best.pt', source='local')
# model.eval()
# 设置置信度阈值
# model.conf = 0.4
# 图片文件夹路径
folder_path = '../float_data/valid/images/'
# 获取文件夹中所有图片的路径
image_paths = glob.glob(folder_path + '*.jpg')
for image_path in image_paths:
frame = cv2.imread(image_path)
img_cvt = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 进行目标检测
results = model(img_cvt)
print(f'img_name_result,name:{image_path},results:{results}\n')
# 将结果转换为numpy数组
results_ = results.pandas().xyxy[0].to_numpy()
i = 0
# 处理并在图像上绘制边界框
for box in results_:
i += 1
l, t, r, b = box[:4].astype('int')
confidence = str(round(box[4] * 100, 2)) + "%"
cls_name = box[6]
cv2.rectangle(frame, (l, t), (r, b), (0, 255, 0), 2)
# cv2.putText(frame, cls_name + "-" + confidence, (l, t), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.putText(frame, 'floating' + "-" + confidence, (l, t), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.putText(frame, "floating number: " + str(i), (30, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
# 显示图片
cv2.imshow("result", frame)
if cv2.waitKey(10000) & 0xFF == ord("q"):
continue
cv2.destroyAllWindows()
量化剪枝效果不好,直接选用了一个小一点的模型,重新进行了训练。
神经网络剪枝 最初是在Optimal Brain Damage和Optimal Brain Surgeon中提出的。它们都依赖于二阶泰勒展开来估计剪枝的参数重要性。也就是说,在这些方法中,Hessian矩阵应该部分或完全地被计算。然而,其他标准可以用于识别参数的重要性,也称为显著性。
显著性标准是指根据网络的某些特性或属性来确定神经网络中 个别权重、神经元、滤波器 或一组权重的重要性或相关性的度量或指标。
剪枝的粒度 定义了对模型的哪种参数 进行剪枝。广义上,剪枝可以以结构化或非结构化的方式进行。
神经网络量化旨在用 比其原始精度(通常为32位单精度浮点数FP32)更少的位数表示深度神经网络的 权重和激活。这一过程在尽量保持模型性能/准确性的同时完成。通过利用更快的硬件整数指令,量化可以减小模型的大小并提高推理时间。
在[A survey of quantization methods for efficient neural network inference]中,Gholami等人对神经网络量化的不同方面进行了调查,其中包括这一主题的理论细节。在这里,作者将简要介绍和讨论关键要点。不失一般性,作者解释量化概念时使用一个实际的有限变量,它可以表示神经网络中的权重或激活。
一旦模型被量化,它可以使用虚伪量化(也称为模拟量化)或仅整数量化(也称为定点量化)进行部署。在前者中,权重和激活以低精度存储,但从加法到矩阵乘法的所有操作都在浮点精度下执行。虽然这种方法在浮点运算之前和之后需要不断的解量化和量化,但它有利于模型的准确性。
与常规CNN不同,对YOLOv5进行剪枝面临一些挑战,因为其复杂且高度优化的深度神经网络架构。YOLOv5使用CSP-Darknet53神经网络架构作为Backbone网络,使用PANet作为neck,两者都由许多卷积层紧密连接和连接组成。此外,Backbone网络和neck之间的互连增加了模型的复杂性。总体而言,这些层的结构复杂性妨碍了在不对网络整体性能产生不利影响的情况下移除不必要的滤波器。否则,与连接相关的特征图的空间分辨率将不匹配。因此,在剪枝YOLOv5之前需要进行一些补偿。例如,[Pruned-yolo: Learning efficient object detector using model pruning]不考虑剪枝上采样层、连接层和YOLOv5的head。
量化的问题,尽管与YOLO无关,从FP32到INT8的量化不是一种平滑的转换,如果梯度景观比较恶劣,可能会阻碍结果的最优性。此外,使用PTQ实现低位(<4位)精度几乎是不可能的,因为它很可能会破坏模型的性能。
python train.py --img 2048 --data ../float_data/data.yaml --weights yolov5m.pt --device cuda:0 --batch-size 2 --workers 12 --epochs 500 # 41M 第三次训练
原模型太大,使用较小的预训练模型,效果好像差不多,从验证数据效果来看。