為什么政府網(wǎng)站做的很爛網(wǎng)絡(luò)培訓(xùn)平臺(tái)有哪些
1、緒論
1.1 KerasCV簡(jiǎn)介
KerasCV是一個(gè)專注于計(jì)算機(jī)視覺(jué)任務(wù)的模塊化組件庫(kù),基于Keras構(gòu)建,可與TensorFlow、JAX或PyTorch等框架配合使用。
-
概念與定位:
- KerasCV是Keras API的水平擴(kuò)展,提供了一系列新的第一方Keras對(duì)象,這些對(duì)象過(guò)于專業(yè)化,無(wú)法添加到核心Keras中。
- 它獲得了與核心Keras API相同級(jí)別的完善和向后兼容性保證,并由Keras團(tuán)隊(duì)維護(hù)。
-
功能與應(yīng)用:
- KerasCV的API協(xié)助執(zhí)行常見(jiàn)的計(jì)算機(jī)視覺(jué)任務(wù),如數(shù)據(jù)增強(qiáng)、分類、對(duì)象檢測(cè)、分割、圖像生成等。
- 它包括針對(duì)流行計(jì)算機(jī)視覺(jué)數(shù)據(jù)集的預(yù)訓(xùn)練模型,例如ImageNet、COCO和Pascal VOC,可用于遷移學(xué)習(xí)。
- KerasCV還提供了一系列可視化工具,用于檢查模型學(xué)習(xí)的中間表示以及可視化對(duì)象檢測(cè)和分割任務(wù)的結(jié)果。
-
框架兼容性:
- 雖然KerasCV主要支持TensorFlow框架,但由于其模塊化設(shè)計(jì),一些組件和功能可能也可以與其他兼容Keras的框架(如JAX或某些版本的PyTorch)一起使用。
- 這些模型、層、指標(biāo)、回調(diào)等基于Keras Core構(gòu)建,可以在任何框架中進(jìn)行訓(xùn)練和序列化,并在另一個(gè)框架中重復(fù)使用,而無(wú)需進(jìn)行昂貴的遷移。
-
應(yīng)用場(chǎng)景:
- 應(yīng)用計(jì)算機(jī)視覺(jué)工程師可以利用KerasCV為常見(jiàn)的計(jì)算機(jī)視覺(jué)任務(wù)快速組裝生產(chǎn)級(jí)、最先進(jìn)的訓(xùn)練和推理管道。
- 在多個(gè)領(lǐng)域中都有廣泛應(yīng)用,例如自動(dòng)駕駛、醫(yī)學(xué)影像處理、視頻監(jiān)控等。
KerasCV是一個(gè)功能強(qiáng)大、靈活且易于使用的計(jì)算機(jī)視覺(jué)庫(kù),為開(kāi)發(fā)者提供了豐富的工具和資源來(lái)構(gòu)建和優(yōu)化各種計(jì)算機(jī)視覺(jué)模型。
1.2 YOLOV8簡(jiǎn)介
YOLOV8(You Only Look Once version 8)是一個(gè)深度學(xué)習(xí)框架,專門用于實(shí)現(xiàn)實(shí)時(shí)對(duì)象檢測(cè)。
-
算法思想:
- YOLO(You Only Look Once)算法的核心思想是只需要瀏覽一次圖像,就可以識(shí)別出圖像中物體的類別和位置。它采用了一種Region-free(無(wú)區(qū)域)或單階段(1-stage)的方法,與需要兩階段(2-stage)的Region-based方法不同。
-
性能特點(diǎn):
- 實(shí)時(shí)性能:YOLOV8繼承了YOLO系列的實(shí)時(shí)檢測(cè)特性,即使在較低的硬件配置上也能達(dá)到很高的幀率(FPS)。
- 高準(zhǔn)確度:通過(guò)更深更復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)和改進(jìn)的訓(xùn)練技巧,YOLOV8在保持高速度的同時(shí),也大幅提高了檢測(cè)的準(zhǔn)確度。
- 多尺度預(yù)測(cè):YOLOV8引入了改進(jìn)的多尺度預(yù)測(cè)技術(shù),能夠更好地檢測(cè)不同大小的對(duì)象。
- 自適應(yīng)錨框:新版在自適應(yīng)調(diào)整錨框方面做了優(yōu)化,可以更準(zhǔn)確地預(yù)測(cè)對(duì)象的位置和大小。
- 更強(qiáng)的特征提取器:YOLOV8使用了更先進(jìn)的特征提取網(wǎng)絡(luò),有助于從圖像中提取出更豐富、更有區(qū)分度的特征。
-
功能與應(yīng)用:
- YOLOV8不僅是一個(gè)目標(biāo)檢測(cè)算法,還結(jié)合了多算法實(shí)現(xiàn)多目標(biāo)追蹤、實(shí)例分割和姿態(tài)估計(jì)功能。
- 它在計(jì)算機(jī)視覺(jué)領(lǐng)域具有廣泛的應(yīng)用前景,如智能監(jiān)控、自動(dòng)駕駛、人機(jī)交互等領(lǐng)域。
-
創(chuàng)新點(diǎn):
- YOLOV8是在Yolo系列歷史版本的基礎(chǔ)上推出的最新版本,引入了新的功能和改進(jìn)點(diǎn),如新的骨干網(wǎng)絡(luò)、新的Ancher-Free檢測(cè)頭和一個(gè)新的損失函數(shù)。
- 它的可擴(kuò)展性允許它不僅僅用于Yolo系列模型,還能支持非Yolo模型以及分類、分割、姿態(tài)估計(jì)等各類任務(wù)。
-
模型評(píng)估:
- 在COCO Val 2017數(shù)據(jù)集上,YOLOV8相比前代模型如YOLOV5,在精度上有所提升,但模型參數(shù)量和FLOPs(浮點(diǎn)運(yùn)算次數(shù))也相應(yīng)增加。然而,與YOLOV5相比,大部分模型的推理速度可能會(huì)變慢。
YOLOV8是一個(gè)功能強(qiáng)大、性能優(yōu)越的實(shí)時(shí)對(duì)象檢測(cè)算法,具有廣泛的應(yīng)用前景和強(qiáng)大的擴(kuò)展能力。
1.3 圖像目標(biāo)識(shí)別概述
圖像目標(biāo)識(shí)別是計(jì)算機(jī)視覺(jué)領(lǐng)域中的一個(gè)重要任務(wù),旨在從給定的圖像中自動(dòng)識(shí)別和定位出其中的目標(biāo)物體。
-
定義:
- 圖像目標(biāo)識(shí)別是利用計(jì)算機(jī)對(duì)圖像進(jìn)行處理、分析和理解,以識(shí)別各種不同模式的目標(biāo)和對(duì)象的技術(shù)。
-
主要步驟:
- 圖像預(yù)處理:對(duì)圖像進(jìn)行平移、旋轉(zhuǎn)和縮放等幾何規(guī)范,使圖像識(shí)別能夠更快速、準(zhǔn)確。同時(shí),圖像濾波用于消除噪聲,保持圖像特征。
- 圖像分割:是實(shí)現(xiàn)機(jī)器視覺(jué)圖像自動(dòng)識(shí)別與分析的關(guān)鍵步驟,其分割質(zhì)量對(duì)后續(xù)圖像的分析具有重要意義。
- 目標(biāo)檢測(cè):在圖像中定位出目標(biāo)的位置,通常使用邊界框來(lái)表示目標(biāo)的位置和大小。
- 目標(biāo)分類:在檢測(cè)到目標(biāo)后,對(duì)其進(jìn)行分類,識(shí)別出目標(biāo)的類別。
-
技術(shù)特點(diǎn):
- 圖像目標(biāo)識(shí)別通過(guò)存儲(chǔ)的信息(記憶中存儲(chǔ)的信息)與當(dāng)前的信息(當(dāng)時(shí)進(jìn)入感官的信息)進(jìn)行比較實(shí)現(xiàn)對(duì)圖像的識(shí)別。
- 前提是圖像描述,即使用數(shù)字或符號(hào)表示圖像或景物中各個(gè)目標(biāo)的相關(guān)特征,甚至目標(biāo)之間的關(guān)系。
- 圖像識(shí)別技術(shù)對(duì)圖像中個(gè)性特征進(jìn)行提取時(shí),可以采用模板匹配模型等方法。
-
應(yīng)用領(lǐng)域:
- 圖像識(shí)別技術(shù)已廣泛應(yīng)用于多個(gè)領(lǐng)域,包括生物醫(yī)學(xué)、衛(wèi)星遙感、機(jī)器人視覺(jué)、貨物檢測(cè)、目標(biāo)跟蹤、自主車導(dǎo)航、公安、銀行、交通、軍事、電子商務(wù)和多媒體網(wǎng)絡(luò)通信等。
-
技術(shù)發(fā)展:
- 隨著技術(shù)的發(fā)展,出現(xiàn)了基于機(jī)器視覺(jué)的目標(biāo)識(shí)別、基于深度學(xué)習(xí)的目標(biāo)識(shí)別等,這些方法大大提高了圖像識(shí)別的準(zhǔn)確度和識(shí)別效率。
圖像目標(biāo)識(shí)別是一個(gè)復(fù)雜的任務(wù),涉及多個(gè)步驟和技術(shù)方法。通過(guò)不斷的研究和技術(shù)創(chuàng)新,圖像目標(biāo)識(shí)別的性能正在不斷提高,為各個(gè)領(lǐng)域的應(yīng)用提供了有力的支持。
2、圖像物體識(shí)別過(guò)程
2.1軟件安裝及設(shè)置
KerasCV 是 Keras 在計(jì)算機(jī)視覺(jué)任務(wù)上的擴(kuò)展。在本文中我們將看到如何使用 KerasCV 訓(xùn)練 YOLOv8 目標(biāo)檢測(cè)模型。在進(jìn)行訓(xùn)練之前,將簡(jiǎn)要介紹軟件的安裝和設(shè)置。
2.1.1 軟件安裝
!pip install --upgrade git+https://github.com/keras-team/keras-cv -q
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
2.1.2 設(shè)置
import os
from tqdm.auto import tqdm
import xml.etree.ElementTree as ETimport tensorflow as tf
from tensorflow import kerasimport keras_cv
from keras_cv import bounding_box
from keras_cv import visualization
2.2 數(shù)據(jù)預(yù)處理
2.2.1 數(shù)據(jù)加載
本文我們將使用從 roboflow 獲取的自動(dòng)駕駛汽車數(shù)據(jù)集。為了使數(shù)據(jù)集更易于管理,我已經(jīng)提取了較大數(shù)據(jù)集的一個(gè)子集,該數(shù)據(jù)集原本包含15,000個(gè)數(shù)據(jù)樣本。在此子集中,我選擇了7,316個(gè)樣本用于模型訓(xùn)練。
為了簡(jiǎn)化手頭的任務(wù)并集中我們的努力,我們將使用減少數(shù)量的對(duì)象類別。具體來(lái)說(shuō),我們將考慮五個(gè)主要類別進(jìn)行檢測(cè)和分類:汽車、行人、交通燈、摩托車手和卡車。這些類別代表了自動(dòng)駕駛汽車環(huán)境中遇到的一些最常見(jiàn)和最重要的對(duì)象。
通過(guò)將數(shù)據(jù)集縮小到這些特定類別,我們可以集中精力構(gòu)建一個(gè)能夠準(zhǔn)確識(shí)別和分類這些重要對(duì)象的強(qiáng)大目標(biāo)檢測(cè)模型。
TensorFlow 數(shù)據(jù)集庫(kù)提供了一種方便的方式來(lái)下載和使用各種數(shù)據(jù)集,包括目標(biāo)檢測(cè)數(shù)據(jù)集。對(duì)于想要快速開(kāi)始使用數(shù)據(jù)而無(wú)需手動(dòng)下載和預(yù)處理的人來(lái)說(shuō),這是一個(gè)很好的選擇。
程序員可以在這里查看各種目標(biāo)檢測(cè)數(shù)據(jù)集:TensorFlow 數(shù)據(jù)集
然而,在本文的代碼示例中,我們將演示如何從頭開(kāi)始使用 TensorFlow 的 tf.data
管道加載數(shù)據(jù)集。這種方法提供更多的靈活性,并允許程序員根據(jù)需要自定義預(yù)處理步驟。
使用 tf.data
管道加載在 TensorFlow 數(shù)據(jù)集庫(kù)中不可用自定義數(shù)據(jù)集是使用 tf.data
管道的一個(gè)主要優(yōu)勢(shì)。這種方法允許程序員創(chuàng)建一個(gè)定制的數(shù)據(jù)預(yù)處理管道,以滿足程序員對(duì)數(shù)據(jù)集的特定需求和要求。
2.2.2 設(shè)置超參數(shù)
SPLIT_RATIO = 0.2
BATCH_SIZE = 4
LEARNING_RATE = 0.001
EPOCH = 5
GLOBAL_CLIPNORM = 10.0
2.2.3 創(chuàng)建數(shù)據(jù)字典
在圖像目標(biāo)識(shí)別任務(wù)中,建立一個(gè)詳細(xì)的數(shù)據(jù)字典是一個(gè)至關(guān)重要的步驟,它確保了模型能夠準(zhǔn)確地將圖像中的目標(biāo)映射到對(duì)應(yīng)的類別。數(shù)據(jù)字典,通常被稱為標(biāo)簽字典或類別字典,是一個(gè)將目標(biāo)類別名稱與唯一標(biāo)識(shí)符相關(guān)聯(lián)的集合。以下是建立和使用數(shù)據(jù)字典的詳細(xì)過(guò)程:
首先,需要明確你的數(shù)據(jù)集中包含哪些目標(biāo)類別。這些類別通常是根據(jù)你的具體應(yīng)用場(chǎng)景和需求來(lái)定義的,例如,在自動(dòng)駕駛系統(tǒng)中,類別可能包括“汽車”、“行人”、“交通燈”等;在動(dòng)物識(shí)別應(yīng)用中,類別可能包括“貓”、“狗”、“鳥”等。
接下來(lái),你需要列出所有的目標(biāo)類別,并確保每個(gè)類別名稱都是唯一的,沒(méi)有拼寫錯(cuò)誤或混淆的可能性。這一步是為了確保在后續(xù)的數(shù)據(jù)處理和模型訓(xùn)練過(guò)程中,每個(gè)類別都能夠被正確地識(shí)別和區(qū)分。
然后,為每個(gè)類別分配一個(gè)唯一的標(biāo)識(shí)符。這個(gè)標(biāo)識(shí)符通常是一個(gè)整數(shù)或字符串,用于在數(shù)據(jù)處理和模型訓(xùn)練過(guò)程中代替類別名稱。整數(shù)標(biāo)識(shí)符在處理速度和內(nèi)存使用方面通常更具優(yōu)勢(shì),因此在大多數(shù)圖像目標(biāo)識(shí)別任務(wù)中更為常用。你可以按照某種順序(如字母順序或自定義順序)為類別分配標(biāo)識(shí)符,只要確保每個(gè)類別都有一個(gè)唯一的標(biāo)識(shí)符即可。
現(xiàn)在,你可以創(chuàng)建一個(gè)數(shù)據(jù)字典,將類別名稱作為鍵,將對(duì)應(yīng)的標(biāo)識(shí)符作為值。在創(chuàng)建數(shù)據(jù)字典時(shí),可以使用編程語(yǔ)言(如Python)中的字典數(shù)據(jù)結(jié)構(gòu)來(lái)實(shí)現(xiàn)。這個(gè)數(shù)據(jù)字典將成為你在整個(gè)項(xiàng)目過(guò)程中處理類別標(biāo)簽的參考依據(jù)。
在訓(xùn)練、驗(yàn)證和測(cè)試過(guò)程中,你需要使用數(shù)據(jù)字典來(lái)編碼和解碼類別標(biāo)簽。編碼是指將類別名稱轉(zhuǎn)換為對(duì)應(yīng)的標(biāo)識(shí)符,以便模型能夠處理這些標(biāo)簽。解碼是指將模型輸出的標(biāo)識(shí)符轉(zhuǎn)換回可讀的類別名稱,以便你能夠理解模型的預(yù)測(cè)結(jié)果。在編碼和解碼過(guò)程中,你只需要查找數(shù)據(jù)字典中相應(yīng)的鍵值對(duì)即可。
需要注意的是,在整個(gè)項(xiàng)目過(guò)程中,你需要確保始終使用相同的數(shù)據(jù)字典。不要更改字典中的映射關(guān)系,除非你有充分的理由這樣做。此外,如果你的數(shù)據(jù)集將來(lái)需要添加新的類別,你需要確保你的數(shù)據(jù)字典可以輕松地?cái)U(kuò)展以包含新的映射關(guān)系。一種常見(jiàn)的做法是在數(shù)據(jù)字典中預(yù)留一些額外的標(biāo)識(shí)符,以便將來(lái)添加新的類別時(shí)使用。
通過(guò)建立和使用一個(gè)詳細(xì)的數(shù)據(jù)字典,你可以確保在圖像目標(biāo)識(shí)別任務(wù)中準(zhǔn)確地處理類別標(biāo)簽,從而提高模型的識(shí)別精度和性能。
物體類別映射
class_ids = ["car","pedestrian","trafficLight","biker","truck",
]
class_mapping = dict(zip(range(len(class_ids)), class_ids))# 圖像和注釋的路徑
path_images = "/kaggle/input/dataset/data/images/"
path_annot = "/kaggle/input/dataset/data/annotations/"# 獲取 path_annot 中所有 XML 文件路徑并排序
xml_files = sorted([os.path.join(path_annot, file_name)for file_name in os.listdir(path_annot)if file_name.endswith(".xml")]
)# 獲取 path_images 中所有 JPEG 圖像文件路徑并排序
jpg_files = sorted([os.path.join(path_images, file_name)for file_name in os.listdir(path_images)if file_name.endswith(".jpg")]
)
下面定義的函數(shù)讀取 XML 文件,找到圖像名稱和路徑,然后遍歷 XML 文件中的每個(gè)對(duì)象,提取每個(gè)對(duì)象的邊界框坐標(biāo)和類別標(biāo)簽。
該函數(shù)返回三個(gè)值:圖像路徑、邊界框列表(每個(gè)邊界框表示為四個(gè)浮點(diǎn)數(shù)的列表:xmin, ymin, xmax, ymax),以及與每個(gè)邊界框?qū)?yīng)的類別 ID 列表(表示為整數(shù))。類別 ID 是通過(guò)使用名為 class_mapping
的字典將類別標(biāo)簽映射到整數(shù)值來(lái)獲得的。
def parse_annotation(xml_file):tree = ET.parse(xml_file)root = tree.getroot()image_name = root.find("filename").textimage_path = os.path.join(path_images, image_name)boxes = []classes = []for obj in root.iter("object"):cls = obj.find("name").textclasses.append(cls)bbox = obj.find("bndbox")xmin = float(bbox.find("xmin").text)ymin = float(bbox.find("ymin").text)xmax = float(bbox.find("xmax").text)ymax = float(bbox.find("ymax").text)boxes.append([xmin, ymin, xmax, ymax])class_ids = [list(class_mapping.keys())[list(class_mapping.values()).index(cls)]for cls in classes]return image_path, boxes, class_idsimage_paths = []
bbox = []
classes = []
for xml_file in tqdm(xml_files):image_path, boxes, class_ids = parse_annotation(xml_file)image_paths.append(image_path)bbox.append(boxes)classes.append(class_ids)
建立張量
這里我們使用 tf.ragged.constant
從 bbox
和 classes
列表創(chuàng)建不規(guī)則張量。不規(guī)則張量是一種可以處理一個(gè)或多個(gè)維度上長(zhǎng)度不等數(shù)據(jù)的張量類型。這在處理具有可變長(zhǎng)度序列的數(shù)據(jù)時(shí)非常有用,例如文本或時(shí)間序列數(shù)據(jù)。
classes = [[8, 8, 8, 8, 8], # 5 classes[12, 14, 14, 14], # 4 classes[1], # 1 class[7, 7], # 2 classes...
]bbox = [[[199.0, 19.0, 390.0, 401.0],[217.0, 15.0, 270.0, 157.0],[393.0, 18.0, 432.0, 162.0],[1.0, 15.0, 226.0, 276.0],[19.0, 95.0, 458.0, 443.0]], # 第一張圖有 4 個(gè)對(duì)象[[52.0, 117.0, 109.0, 177.0]], # 第二張圖有 1 個(gè)對(duì)象[[88.0, 87.0, 235.0, 322.0],[113.0, 117.0, 218.0, 471.0]], # 第三張圖有 2 個(gè)對(duì)象...
]
在這個(gè)例子中,bbox
和 classes
列表對(duì)每個(gè)圖像的長(zhǎng)度不同,這取決于圖像中的對(duì)象數(shù)量以及相應(yīng)的邊界框和類別。為了處理這種可變性,我們使用不規(guī)則張量而不是常規(guī)張量。
稍后,這些不規(guī)則張量被用來(lái)創(chuàng)建一個(gè) tf.data.Dataset
,使用 from_tensor_slices
方法。該方法通過(guò)沿第一維切分輸入張量來(lái)創(chuàng)建數(shù)據(jù)集。通過(guò)使用不規(guī)則張量,數(shù)據(jù)集可以處理每個(gè)圖像長(zhǎng)度不等的數(shù)據(jù),并為進(jìn)一步處理提供靈活的輸入管道。
bbox = tf.ragged.constant(bbox)
classes = tf.ragged.constant(classes)
image_paths = tf.ragged.constant(image_paths)data = tf.data.Dataset.from_tensor_slices((image_paths, classes, bbox))
2.2.4 分割訓(xùn)練和驗(yàn)證數(shù)據(jù)
在圖像目標(biāo)識(shí)別任務(wù)中,分割訓(xùn)練和驗(yàn)證數(shù)據(jù)是確保模型性能評(píng)估和避免過(guò)擬合的關(guān)鍵步驟。
首先,你需要明確你的數(shù)據(jù)集,包括圖像的總數(shù)、每個(gè)類別的圖像數(shù)量以及標(biāo)簽的詳細(xì)程度。接著,大部分?jǐn)?shù)據(jù)(通常70%到80%)被用作訓(xùn)練集,用于訓(xùn)練模型學(xué)習(xí)如何從圖像中識(shí)別目標(biāo)。剩余的數(shù)據(jù)(20%到30%)則被用作驗(yàn)證集,它不參與訓(xùn)練過(guò)程,但用于在訓(xùn)練過(guò)程中評(píng)估模型的性能,以便調(diào)整超參數(shù)或提前停止訓(xùn)練。
在分割數(shù)據(jù)時(shí),必須確保訓(xùn)練集和驗(yàn)證集中的類別分布相似,這有助于確保模型在驗(yàn)證集上的性能能夠反映其在未見(jiàn)過(guò)的數(shù)據(jù)上的性能。同時(shí),要特別注意避免數(shù)據(jù)泄露,即確保驗(yàn)證集中的圖像在訓(xùn)練過(guò)程中是完全不可見(jiàn)的。任何形式的數(shù)據(jù)泄露都可能導(dǎo)致模型在驗(yàn)證集上表現(xiàn)出過(guò)高的性能,但在實(shí)際應(yīng)用中表現(xiàn)不佳。
為了提高模型的泛化能力,可以考慮對(duì)訓(xùn)練集進(jìn)行數(shù)據(jù)增強(qiáng),如旋轉(zhuǎn)、縮放、翻轉(zhuǎn)等操作。然而,驗(yàn)證集應(yīng)保持原始狀態(tài),以便準(zhǔn)確評(píng)估模型的性能。在多次實(shí)驗(yàn)或研究中,為了獲得更穩(wěn)定的驗(yàn)證結(jié)果,可以考慮多次隨機(jī)分割數(shù)據(jù)集并計(jì)算平均驗(yàn)證性能。
最后,務(wù)必記錄你如何分割數(shù)據(jù)的信息,包括分割的比例、使用的隨機(jī)數(shù)種子等,以便其他人能夠復(fù)現(xiàn)你的結(jié)果或進(jìn)行進(jìn)一步的研究。
合理分割訓(xùn)練和驗(yàn)證數(shù)據(jù)是圖像目標(biāo)識(shí)別任務(wù)中不可或缺的一環(huán),它有助于確保模型能夠在未見(jiàn)過(guò)的數(shù)據(jù)上展現(xiàn)出良好的性能。
數(shù)據(jù)分割
# 確定驗(yàn)證樣本的數(shù)量
num_val = int(len(xml_files) * SPLIT_RATIO)# 將數(shù)據(jù)集分割為訓(xùn)練集和驗(yàn)證集
val_data = data.take(num_val)
train_data = data.skip(num_val)
邊界框格式化
讓我們來(lái)談?wù)剶?shù)據(jù)加載和邊界框格式化,以啟動(dòng)事情。KerasCV 中的邊界框有一個(gè)預(yù)定的格式。為此,你必須將你的邊界框捆綁成一個(gè)字典,該字典符合下面列出的要求:
bounding_boxes = {# num_boxes 可能是一個(gè)不規(guī)則維度'boxes': Tensor(shape=[batch, num_boxes, 4]),'classes': Tensor(shape=[batch, num_boxes])
}
字典有兩個(gè)鍵,'boxes'
和 'classes'
,每個(gè)鍵都映射到一個(gè) TensorFlow 不規(guī)則張量或張量對(duì)象。'boxes'
張量的形狀為 [batch, num_boxes, 4]
,其中 batch 是批次中的圖像數(shù)量,num_boxes 是任何圖像
中邊界框的最大數(shù)量。4 表示定義邊界框所需的四個(gè)值:xmin, ymin, xmax, ymax。
'classes'
張量的形狀為 [batch, num_boxes]
,其中的每個(gè)元素代表 'boxes'
張量中相應(yīng)邊界框的類別標(biāo)簽。num_boxes 維度可能是不規(guī)則的,這意味著批次中圖像的數(shù)量可能不同。
最終的字典應(yīng)該是:
{"images": images, "bounding_boxes": bounding_boxes}
def load_image(image_path):image = tf.io.read_file(image_path)image = tf.image.decode_jpeg(image, channels=3)return imagedef load_dataset(image_path, classes, bbox):# 讀取圖像image = load_image(image_path)bounding_boxes = {"classes": tf.cast(classes, dtype=tf.float32),"boxes": bbox,}return {"images": tf.cast(image, tf.float32), "bounding_boxes": bounding_boxes}
在這里,我們創(chuàng)建一個(gè)層,將圖像調(diào)整為 640x640 像素,同時(shí)保持原始縱橫比。與圖像相關(guān)聯(lián)的邊界框指定為 xyxy
格式。如果需要,調(diào)整大小的圖像將用零填充,以保持原始縱橫比。
KerasCV 支持的邊界框格式:
- CENTER_XYWH
- XYWH
- XYXY
- REL_XYXY
- REL_XYWH
- YXYX
- REL_YXYX
格式轉(zhuǎn)換方法
此外,可以在任何兩對(duì)格式之間執(zhí)行格式轉(zhuǎn)換:
boxes = keras_cv.bounding_box.convert_format(bounding_box,images=image,source="xyxy", # 原始格式target="xywh", # 目標(biāo)格式(我們要轉(zhuǎn)換的格式)
)
2.2.5 數(shù)據(jù)增強(qiáng)
構(gòu)建目標(biāo)檢測(cè)管道時(shí)最具挑戰(zhàn)性的任務(wù)之一是數(shù)據(jù)增強(qiáng)。它涉及對(duì)輸入圖像應(yīng)用各種轉(zhuǎn)換,以增加訓(xùn)練數(shù)據(jù)的多樣性,并提高模型的泛化能力。然而,當(dāng)處理目標(biāo)檢測(cè)任務(wù)時(shí),情況變得更加復(fù)雜,因?yàn)檫@些轉(zhuǎn)換需要了解底層的邊界框,并相應(yīng)地更新它們。
KerasCV 提供了對(duì)邊界框增強(qiáng)的原生支持。KerasCV 提供了一系列專門設(shè)計(jì)用于處理邊界框的數(shù)據(jù)增強(qiáng)層。這些層在圖像轉(zhuǎn)換時(shí)智能地調(diào)整邊界框坐標(biāo),確保邊界框保持準(zhǔn)確并與增強(qiáng)圖像對(duì)齊。
通過(guò)利用 KerasCV 的功能,開(kāi)發(fā)人員可以方便地將邊界框友好的數(shù)據(jù)增強(qiáng)集成到他們的目標(biāo)檢測(cè)管道中。通過(guò)在 tf.data 管道中執(zhí)行即時(shí)增強(qiáng),該過(guò)程變得無(wú)縫高效,從而實(shí)現(xiàn)更好的訓(xùn)練和更準(zhǔn)確的目標(biāo)檢測(cè)結(jié)果。
augmenter = keras.Sequential(layers=[keras_cv.layers.RandomFlip(mode="horizontal", bounding_box_format="xyxy"),keras_cv.layers.RandomShear(x_factor=0.2, y_factor=0.2, bounding_box_format="xyxy"),keras_cv.layers.JitteredResize(target_size=(640, 640), scale_factor=(0.75, 1.3), bounding_box_format="xyxy"),]
)
2.2.6 創(chuàng)建訓(xùn)練數(shù)據(jù)集
在圖像目標(biāo)識(shí)別任務(wù)中,對(duì)訓(xùn)練數(shù)據(jù)集進(jìn)行適當(dāng)?shù)念A(yù)處理和增強(qiáng)是至關(guān)重要的步驟。以下代碼片段展示了如何使用TensorFlow的tf.data
API對(duì)train_data
數(shù)據(jù)集進(jìn)行一系列的處理,以準(zhǔn)備用于模型訓(xùn)練。
首先,train_data.map(load_dataset, num_parallel_calls=tf.data.AUTOTUNE)
這行代碼將load_dataset
函數(shù)應(yīng)用于train_data
數(shù)據(jù)集中的每一個(gè)元素,該函數(shù)通常負(fù)責(zé)讀取圖像文件、解碼圖像數(shù)據(jù)、進(jìn)行必要的預(yù)處理(如歸一化、裁剪等)以及加載標(biāo)簽等操作。通過(guò)num_parallel_calls=tf.data.AUTOTUNE
,TensorFlow會(huì)自動(dòng)決定并行調(diào)用load_dataset
函數(shù)的最佳數(shù)量,以優(yōu)化性能。
接著,train_ds.shuffle(BATCH_SIZE * 4)
對(duì)數(shù)據(jù)集進(jìn)行隨機(jī)打亂,以防止模型在訓(xùn)練過(guò)程中記住數(shù)據(jù)的特定順序,從而提高模型的泛化能力。打亂緩沖區(qū)的大小設(shè)置為BATCH_SIZE * 4
,這意味著TensorFlow會(huì)從數(shù)據(jù)集中隨機(jī)選擇BATCH_SIZE * 4
個(gè)元素放入緩沖區(qū),并從該緩沖區(qū)中隨機(jī)選擇一個(gè)元素作為下一個(gè)輸出。
然后,train_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
將數(shù)據(jù)集分割成大小為BATCH_SIZE
的批次。由于使用ragged_batch
,這個(gè)方法可以處理可能具有不同長(zhǎng)度的元素(如不同大小的圖像)。但是,由于drop_remainder=True
,如果數(shù)據(jù)集中的元素?cái)?shù)量不能被BATCH_SIZE
整除,那么剩余的元素將被丟棄。
最后,train_ds.map(augmenter, num_parallel_calls=tf.data.AUTOTUNE)
這行代碼將augmenter
函數(shù)應(yīng)用于數(shù)據(jù)集的每一個(gè)批次,進(jìn)行數(shù)據(jù)增強(qiáng)操作,如隨機(jī)旋轉(zhuǎn)、縮放、翻轉(zhuǎn)等,以增加模型的泛化能力。同樣,num_parallel_calls=tf.data.AUTOTUNE
允許TensorFlow自動(dòng)決定并行調(diào)用augmenter
函數(shù)的最佳數(shù)量。
整個(gè)處理流程的目的是生成一個(gè)適用于圖像目標(biāo)識(shí)別模型訓(xùn)練的、經(jīng)過(guò)預(yù)處理和增強(qiáng)的數(shù)據(jù)集train_ds
。
train_ds = train_data.map(load_dataset, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.shuffle(BATCH_SIZE * 4)
train_ds = train_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
train_ds = train_ds.map(augmenter, num_parallel_calls=tf.data.AUTOTUNE)
2.2.7 創(chuàng)建驗(yàn)證數(shù)據(jù)集
在圖像目標(biāo)識(shí)別任務(wù)中,對(duì)驗(yàn)證數(shù)據(jù)集(val_data
)進(jìn)行適當(dāng)?shù)念A(yù)處理和增強(qiáng)是評(píng)估模型性能的關(guān)鍵步驟。以下代碼片段使用keras_cv.layers.JitteredResize
層和其他tf.data
API方法來(lái)處理驗(yàn)證數(shù)據(jù)集val_data
。
首先,定義了一個(gè)JitteredResize
層resizing
,用于在驗(yàn)證數(shù)據(jù)集中隨機(jī)調(diào)整圖像的大小。該層將圖像的目標(biāo)大小設(shè)置為640x640像素,并通過(guò)scale_factor
參數(shù)在0.75到1.3的范圍內(nèi)隨機(jī)縮放圖像,以此作為數(shù)據(jù)增強(qiáng)的一種手段。這種隨機(jī)縮放有助于模型學(xué)習(xí)對(duì)尺度變化的魯棒性。此外,bounding_box_format="xyxy"
指定了邊界框的格式,確保在縮放過(guò)程中邊界框的位置和大小得到正確的調(diào)整。
接下來(lái),通過(guò)val_data.map(load_dataset, num_parallel_calls=tf.data.AUTOTUNE)
,load_dataset
函數(shù)被應(yīng)用于驗(yàn)證數(shù)據(jù)集的每個(gè)元素。這個(gè)函數(shù)負(fù)責(zé)加載圖像文件、解碼圖像數(shù)據(jù),并進(jìn)行必要的預(yù)處理(如解碼標(biāo)簽、歸一化等)。num_parallel_calls=tf.data.AUTOTUNE
允許TensorFlow自動(dòng)確定并行調(diào)用的最佳數(shù)量,以提高數(shù)據(jù)加載的效率。
然后,val_ds.shuffle(BATCH_SIZE * 4)
對(duì)驗(yàn)證數(shù)據(jù)集進(jìn)行隨機(jī)打亂。打亂操作有助于防止模型在評(píng)估過(guò)程中受到數(shù)據(jù)順序的影響,從而得到更準(zhǔn)確的評(píng)估結(jié)果。打亂緩沖區(qū)的大小設(shè)置為BATCH_SIZE * 4
,意味著TensorFlow將從數(shù)據(jù)集中隨機(jī)選擇BATCH_SIZE * 4
個(gè)元素進(jìn)行打亂。
接著,val_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
將打亂后的數(shù)據(jù)集分割成大小為BATCH_SIZE
的批次。由于使用了ragged_batch
,這個(gè)方法可以處理可能具有不同長(zhǎng)度的元素(盡管在驗(yàn)證集中這種情況可能較少見(jiàn))。drop_remainder=True
確保如果數(shù)據(jù)集中的元素?cái)?shù)量不能被BATCH_SIZE
整除,則剩余的元素將被丟棄,以確保每個(gè)批次的大小一致。
最后,通過(guò)val_ds.map(resizing, num_parallel_calls=tf.data.AUTOTUNE)
,resizing
層被應(yīng)用于驗(yàn)證數(shù)據(jù)集的每個(gè)批次。這個(gè)步驟將前面定義的隨機(jī)大小調(diào)整操作應(yīng)用于驗(yàn)證集中的每個(gè)圖像,以實(shí)現(xiàn)數(shù)據(jù)增強(qiáng)。同樣,num_parallel_calls=tf.data.AUTOTUNE
允許TensorFlow自動(dòng)確定并行調(diào)用的最佳數(shù)量,以提高處理效率。
整個(gè)處理流程的目的是生成一個(gè)經(jīng)過(guò)適當(dāng)預(yù)處理和增強(qiáng)的驗(yàn)證數(shù)據(jù)集val_ds
,以便在模型訓(xùn)練過(guò)程中用于評(píng)估模型的性能。
resizing = keras_cv.layers.JitteredResize(target_size=(640, 640),scale_factor=(0.75, 1.3),bounding_box_format="xyxy",
)val_ds = val_data.map(load_dataset, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.shuffle(BATCH_SIZE * 4)
val_ds = val_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
val_ds = val_ds.map(resizing, num_parallel_calls=tf.data.AUTOTUNE)
2.2.8 可視化
以下碼定義了一個(gè)名為visualize_dataset
的函數(shù),該函數(shù)用于可視化數(shù)據(jù)集中的圖像及其對(duì)應(yīng)的邊界框。隨后,該函數(shù)被用于可視化訓(xùn)練數(shù)據(jù)集train_ds
和驗(yàn)證數(shù)據(jù)集val_ds
。
在visualize_dataset
函數(shù)中,首先通過(guò)next(iter(inputs.take(1)))
從輸入的數(shù)據(jù)集inputs
中取出一個(gè)批次的數(shù)據(jù)。這個(gè)批次的數(shù)據(jù)通常是一個(gè)字典,包含了圖像(images
)和對(duì)應(yīng)的邊界框(bounding_boxes
)。
接下來(lái),函數(shù)使用visualization.plot_bounding_box_gallery
來(lái)繪制一個(gè)包含多個(gè)圖像的網(wǎng)格(或稱為畫廊),每個(gè)圖像上都標(biāo)出了邊界框。value_range
參數(shù)定義了圖像像素值的范圍(在此例中為0到255,對(duì)應(yīng)于標(biāo)準(zhǔn)的8位RGB圖像),而rows
和cols
參數(shù)定義了網(wǎng)格中的行數(shù)和列數(shù)。y_true
參數(shù)是真實(shí)的邊界框數(shù)據(jù),用于在圖像上繪制邊界框。scale
和font_scale
參數(shù)分別用于控制圖像大小和字體大小。bounding_box_format
參數(shù)定義了邊界框的格式(在這里使用"xyxy"格式,表示邊界框由左上角的(x, y)坐標(biāo)和右下角的(x, y)坐標(biāo)定義)。class_mapping
參數(shù)用于將類別索引映射到實(shí)際的類別名稱,但在這個(gè)函數(shù)定義中并未給出class_mapping
的具體內(nèi)容或傳遞方式,我們假設(shè)它在使用該函數(shù)之前已經(jīng)被定義或作為全局變量存在。
在函數(shù)定義之后,visualize_dataset
函數(shù)被兩次調(diào)用,分別用于可視化train_ds
和val_ds
數(shù)據(jù)集。在這兩個(gè)調(diào)用中,除了數(shù)據(jù)集本身外,其他參數(shù)都相同:邊界框格式設(shè)置為"xyxy",像素值范圍設(shè)置為0到255,網(wǎng)格的行數(shù)和列數(shù)都設(shè)置為2。這意味著每個(gè)網(wǎng)格將包含2x2=4個(gè)圖像。
代碼的目的是為了直觀地展示訓(xùn)練數(shù)據(jù)集和驗(yàn)證數(shù)據(jù)集中的圖像及其對(duì)應(yīng)的邊界框,以便于開(kāi)發(fā)者檢查數(shù)據(jù)的質(zhì)量和預(yù)處理效果。
def visualize_dataset(inputs, value_range, rows, cols, bounding_box_format):inputs = next(iter(inputs.take(1)))images, bounding_boxes = inputs["images"], inputs["bounding_boxes"]visualization.plot_bounding_box_gallery(images,value_range=value_range,rows=rows,cols=cols,y_true=bounding_boxes,scale=5,font_scale=0.7,bounding_box_format=bounding_box_format,class_mapping=class_mapping,)visualize_dataset(train_ds, bounding_box_format="xyxy", value_range=(0, 255), rows=2, cols=2
)visualize_dataset(val_ds, bounding_box_format="xyxy", value_range=(0, 255), rows=2, cols=2
)
然后通過(guò)使用map和prefetch函數(shù)對(duì)訓(xùn)練數(shù)據(jù)集train_ds和驗(yàn)證數(shù)據(jù)集val_ds進(jìn)行了優(yōu)化處理。首先,通過(guò)map函數(shù)將數(shù)據(jù)集中的每個(gè)字典項(xiàng)轉(zhuǎn)換為元組形式,簡(jiǎn)化了數(shù)據(jù)格式并提高了模型訪問(wèn)數(shù)據(jù)的效率。然后,使用prefetch函數(shù)在后臺(tái)異步地加載數(shù)據(jù),以便在模型需要新的數(shù)據(jù)批次時(shí)能夠立即提供,從而減少了數(shù)據(jù)加載的時(shí)間,提高了整體的訓(xùn)練性能。在這個(gè)過(guò)程中,tf.data.AUTOTUNE被用于自動(dòng)選擇最佳的預(yù)取緩沖區(qū)大小,以在可用資源之間達(dá)到最佳平衡。
def dict_to_tuple(inputs):return inputs["images"], inputs["bounding_boxes"]train_ds = train_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.prefetch(tf.data.AUTOTUNE)val_ds = val_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.prefetch(tf.data.AUTOTUNE)
2.3 創(chuàng)建模型
YOLOv8 是一種用于各種計(jì)算機(jī)視覺(jué)任務(wù)的最新 YOLO 模型,如目標(biāo)檢測(cè)、圖像分類和實(shí)例分割。Ultraalytics,YOLOv5 的創(chuàng)建者,也開(kāi)發(fā)了 YOLOv8,它在架構(gòu)和開(kāi)發(fā)者體驗(yàn)方面相比前身進(jìn)行了多項(xiàng)改進(jìn)和變更。YOLOv8 是業(yè)界高度評(píng)價(jià)的最新技術(shù)模型。
下面的表格比較了五種不同大小(以像素為單位)的 YOLOv8 模型的性能指標(biāo):YOLOv8n、YOLOv8s、YOLOv8m、YOLOv8l 和 YOLOv8x。指標(biāo)包括不同交并比(IoU)閾值下驗(yàn)證數(shù)據(jù)的平均精度均值(mAP)值、CPU 上 ONNX 格式的推理速度和 A100 TensorRT 的速度、參數(shù)數(shù)量和浮點(diǎn)運(yùn)算次數(shù)(FLOPs)(分別為百萬(wàn)和十億)。
模型 | 大小 (像素) | mAPval 50-95 | 速度 CPU ONNX (ms) | 速度 A100 TensorRT (ms) | 參數(shù) (M) | FLOPs (B) |
---|---|---|---|---|---|---|
YOLOv8n | 640 | 37.3 | 80.4 | 0.99 | 3.2 | 8.7 |
YOLOv8s | 640 | 44.9 | 128.4 | 1.20 | 11.2 | 28.6 |
YOLOv8m | 640 | 50.2 | 234.7 | 1.83 | 25.9 | 78.9 |
YOLOv8l | 640 | 52.9 | 375.2 | 2.39 | 43.7 | 165.2 |
YOLOv8x | 640 | 53.9 | 479.1 | 3.53 | 68.2 | 257.8 |
2.3.1 創(chuàng)建backbone 實(shí)例
在圖像目標(biāo)識(shí)別任務(wù)中,當(dāng)使用KerasCV這樣的框架時(shí),為YOLOV8選擇一個(gè)合適的backbone并加載COCO預(yù)訓(xùn)練權(quán)重是構(gòu)建高效模型的關(guān)鍵步驟。首先,你需要從KerasCV中選擇一個(gè)經(jīng)過(guò)預(yù)訓(xùn)練的backbone,這個(gè)backbone通?;谏疃染矸e神經(jīng)網(wǎng)絡(luò)(CNN)如ResNet、EfficientNet等,并已經(jīng)針對(duì)圖像分類或目標(biāo)檢測(cè)任務(wù)進(jìn)行了優(yōu)化。其次,確保這個(gè)backbone提供了COCO數(shù)據(jù)集的預(yù)訓(xùn)練權(quán)重,因?yàn)檫@將有助于加速訓(xùn)練過(guò)程并提高模型的性能。
在選定backbone后,你可以使用KerasCV提供的工具或API來(lái)加載這個(gè)backbone以及對(duì)應(yīng)的COCO預(yù)訓(xùn)練權(quán)重。這個(gè)步驟將確保backbone中的權(quán)重已經(jīng)被正確地初始化為經(jīng)過(guò)大量數(shù)據(jù)訓(xùn)練得到的值,從而提高了模型在目標(biāo)識(shí)別任務(wù)上的泛化能力。
一旦backbone被加載并初始化,你可以將其整合到Y(jié)OLOV8模型中。YOLOV8是一個(gè)流行的目標(biāo)檢測(cè)算法,它依賴于backbone來(lái)提取圖像中的特征。將backbone整合到Y(jié)OLOV8模型中時(shí),需要確保backbone的輸出與YOLOV8的輸入要求相匹配,以便能夠正確地處理這些特征并輸出目標(biāo)邊界框和類別。
最后,你可以使用整合了backbone的YOLOV8模型進(jìn)行訓(xùn)練和評(píng)估。通過(guò)調(diào)整模型的參數(shù)和配置,你可以進(jìn)一步優(yōu)化模型的性能,以滿足特定應(yīng)用場(chǎng)景的需求。在整個(gè)過(guò)程中,保持對(duì)backbone和YOLOV8模型的理解和熟悉將是非常重要的,這將有助于你更好地利用這些工具來(lái)解決圖像目標(biāo)識(shí)別任務(wù)。KerasCV 中可用的 YOLOV8 Backbones:
無(wú)權(quán)重:
1. yolo_v8_xs_backbone
2. yolo_v8_s_backbone
3. yolo_v8_m_backbone
4. yolo_v8_l_backbone
5. yolo_v8_xl_backbone
帶有預(yù)訓(xùn)練 coco 權(quán)重:
backbone = keras_cv.models.YOLOV8Backbone.from_preset("yolo_v8_s_backbone_coco" # 我們將使用帶有 coco 權(quán)重的 yolov8 小型 backbone
)
Downloading data from https://storage.googleapis.com/keras-cv/models/yolov8/coco/yolov8_s_backbone.h5
20596968/20596968 [==============================] - 0s 0us/step
2.3.2 構(gòu)建YOLOV8 模型
接下來(lái),讓我們使用 YOLOV8Detector
構(gòu)建一個(gè) YOLOV8 模型,它接受一個(gè)特征提取器作為 backbone
參數(shù),一個(gè) num_classes
參數(shù),該參數(shù)根據(jù) class_mapping
列表的大小指定要檢測(cè)的目標(biāo)類別數(shù)量,一個(gè) bounding_box_format
參數(shù),該參數(shù)告知模型數(shù)據(jù)集中邊界框的格式,最后,特征金字塔網(wǎng)絡(luò)(FPN)深度由 fpn_depth
參數(shù)指定。
在 KerasCV中,使用上述任何一個(gè) backbone 構(gòu)建 YOLOV8 都非常簡(jiǎn)單。
yolo = keras_cv.models.YOLOV8Detector(num_classes=len(class_mapping),bounding_box_format="xyxy",backbone=backbone,fpn_depth=1,
)
2.4 編譯模型
2.4.1YOLOV8 使用的損失函數(shù):
-
分類損失:此損失函數(shù)計(jì)算預(yù)期類別概率和實(shí)際類別概率之間的差異。在這種情況下,使用了
binary_crossentropy
,這是解決二元分類問(wèn)題的著名解決方案。我們使用二元交叉熵,因?yàn)槊總€(gè)被識(shí)別的對(duì)象要么被歸類為某個(gè)特定類別(如人、汽車等),要么不是。 -
邊界框損失:
box_loss
是用來(lái)衡量預(yù)測(cè)邊界框和真實(shí)邊界框之間差異的損失函數(shù)。在這種情況下,使用了完整的 IoU(CIoU)指標(biāo),它不僅衡量預(yù)測(cè)和真實(shí)邊界框之間的重疊,還考慮了縱橫比、中心距離和框大小的差異。這些損失函數(shù)共同幫助優(yōu)化模型的目標(biāo)檢測(cè),通過(guò)最小化預(yù)測(cè)和真實(shí)類別概率以及邊界框之間的差異。
在以下的Python代碼中,配置一個(gè)用于訓(xùn)練YOLOv8模型的優(yōu)化器,并編譯模型以使用特定的損失函數(shù)。
-
優(yōu)化器配置:
tf.keras.optimizers.Adam(...)
:這里您正在創(chuàng)建一個(gè)Adam優(yōu)化器的實(shí)例,它通常用于深度學(xué)習(xí)中參數(shù)的優(yōu)化。learning_rate=LEARNING_RATE
:學(xué)習(xí)率決定了參數(shù)更新的步長(zhǎng)。LEARNING_RATE
應(yīng)該是一個(gè)預(yù)先定義的變量,表示您想要設(shè)置的學(xué)習(xí)率值。global_clipnorm=GLOBAL_CLIPNORM
:這是梯度裁剪的一個(gè)參數(shù)。它用于確保梯度的L2范數(shù)不會(huì)超過(guò)指定的閾值,從而避免梯度爆炸的問(wèn)題。GLOBAL_CLIPNORM
應(yīng)該是一個(gè)預(yù)先定義的變量,表示您想要設(shè)置的梯度裁剪閾值。
-
模型編譯:
yolo.compile(...)
:這是Keras模型的一個(gè)方法,用于配置訓(xùn)練過(guò)程。在編譯時(shí),您需要指定損失函數(shù)和優(yōu)化器(以及其他可選的參數(shù),如指標(biāo))。optimizer=optimizer
:這里您傳遞了之前創(chuàng)建的Adam優(yōu)化器實(shí)例。classification_loss="binary_crossentropy"
:對(duì)于分類任務(wù),您使用了二元交叉熵?fù)p失(binary crossentropy)。這是因?yàn)閅OLOv8為每個(gè)類別都使用了一個(gè)獨(dú)立的sigmoid分類器,因此每個(gè)類別的預(yù)測(cè)都可以被視為一個(gè)二分類問(wèn)題。box_loss="ciou"
:對(duì)于邊界框的回歸,您選擇了CIOU(Complete Intersection over Union)損失。CIOU是IOU的一個(gè)擴(kuò)展,它增加了寬度、高度比的損失以及預(yù)測(cè)框和目標(biāo)框中心點(diǎn)距離的懲罰項(xiàng),從而提高了邊界框回歸的精度。
optimizer = tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE,global_clipnorm=GLOBAL_CLIPNORM,
)yolo.compile(optimizer=optimizer, classification_loss="binary_crossentropy", box_loss="ciou"
)
2.4.2 COCO 指標(biāo)回調(diào)
我們將使用 KerasCV 中的 BoxCOCOMetrics
來(lái)評(píng)估模型并計(jì)算平均精度均值(Map)得分、召回率和精確度。當(dāng) mAP 分?jǐn)?shù)提高時(shí),我們還會(huì)保存我們的模型。
示例代碼定義了一個(gè)名為 EvaluateCOCOMetricsCallback
的類,它繼承自 Keras 的 Callback
類,用于在 Keras 模型訓(xùn)練過(guò)程中評(píng)估模型在 COCO 數(shù)據(jù)集上的指標(biāo),并在 mAP(mean Average Precision)提高時(shí)保存模型。以下是對(duì)代碼的詳細(xì)解讀:
- 導(dǎo)入依賴:
雖然代碼中沒(méi)有直接顯示導(dǎo)入的依賴,但我們可以假設(shè)已經(jīng)導(dǎo)入了 keras
和 keras_cv.metrics.BoxCOCOMetrics
。其中,keras
是深度學(xué)習(xí)庫(kù) Keras,而 keras_cv.metrics.BoxCOCOMetrics
可能是一個(gè)第三方庫(kù)或自定義庫(kù),用于計(jì)算 COCO 數(shù)據(jù)集上的目標(biāo)檢測(cè)指標(biāo)。
-
類定義:
EvaluateCOCOMetricsCallback(keras.callbacks.Callback)
:定義了一個(gè)繼承自 Keras Callback 的類,用于在模型訓(xùn)練過(guò)程中執(zhí)行特定的操作。
-
初始化方法:
__init__(self, data, save_path)
:初始化方法接受兩個(gè)參數(shù),data
和save_path
。其中,data
是用于評(píng)估的數(shù)據(jù)集,而save_path
是保存最佳模型的路徑。self.metrics = keras_cv.metrics.BoxCOCOMetrics(...)
:創(chuàng)建一個(gè)BoxCOCOMetrics
對(duì)象,用于計(jì)算 COCO 數(shù)據(jù)集上的指標(biāo)。這里設(shè)置bounding_box_format
為 “xyxy”,表示邊界框的格式是 (x1, y1, x2, y2),其中 (x1, y1) 是左上角坐標(biāo),(x2, y2) 是右下角坐標(biāo)。evaluate_freq=1e9
表示每次更新都會(huì)計(jì)算指標(biāo),但通常這個(gè)參數(shù)應(yīng)該設(shè)置為一個(gè)較小的值,如 1,表示每個(gè)批次都計(jì)算指標(biāo),但在這種情況下,由于我們?cè)?on_epoch_end
中手動(dòng)處理,所以這個(gè)值設(shè)置為 1e9 是合適的。self.best_map = -1.0
:初始化最佳 mAP 值為 -1.0,用于后續(xù)比較。
-
on_epoch_end 方法:
- 這個(gè)方法在每個(gè)訓(xùn)練周期結(jié)束時(shí)被調(diào)用。
self.metrics.reset_state()
:重置指標(biāo)的狀態(tài),為新的評(píng)估周期做準(zhǔn)備。- 遍歷
self.data
中的每個(gè)批次,使用模型進(jìn)行預(yù)測(cè),并使用self.metrics.update_state(y_true, y_pred)
更新指標(biāo)的狀態(tài)。 metrics = self.metrics.result(force=True)
:計(jì)算并獲取最終的指標(biāo)結(jié)果。force=True
表示強(qiáng)制計(jì)算結(jié)果,即使沒(méi)有達(dá)到evaluate_freq
指定的更新頻率。logs.update(metrics)
:將計(jì)算得到的指標(biāo)結(jié)果更新到 Keras 的日志中,這樣可以在訓(xùn)練過(guò)程中跟蹤這些指標(biāo)。- 檢查當(dāng)前的 mAP 值是否比之前保存的最佳 mAP 值高,如果是,則保存模型并更新最佳 mAP 值。
class EvaluateCOCOMetricsCallback(keras.callbacks.Callback):def __init__(self, data, save_path):super().__init__()self.data = dataself.metrics = keras_cv.metrics.BoxCOCOMetrics(bounding_box_format="xyxy",evaluate_freq=1e9,)self.save_path = save_pathself.best_map = -1.0def on_epoch_end(self, epoch, logs):self.metrics.reset_state()for batch in self.data:images, y_true = batch[0], batch[1]y_pred = self.model.predict(images, verbose=0)self.metrics.update_state(y_true, y_pred)metrics = self.metrics.result(force=True)logs.update(metrics)current_map = metrics["MaP"]if current_map > self.best_map:self.best_map = current_mapself.model.save(self.save_path) # 當(dāng) mAP 提高時(shí)保存模型return logs
2.5 訓(xùn)練模型
示例代碼使用YOLO的fit
方法來(lái)訓(xùn)練模型。
yolo.fit(train_ds,validation_data=val_ds,epochs=3,callbacks=[EvaluateCOCOMetricsCallback(val_ds, "model.h5")],
)
yolo.fit(...)
:
- 這表明你正在調(diào)用一個(gè)名為
yolo
的對(duì)象的fit
方法。這個(gè)對(duì)象很可能是一個(gè)深度學(xué)習(xí)模型(如Keras的Model
類或其子類)。
train_ds
:
- 這是
fit
方法的第一個(gè)參數(shù),代表訓(xùn)練數(shù)據(jù)集。train_ds
很可能是一個(gè)數(shù)據(jù)加載器或數(shù)據(jù)生成器,它為模型提供訓(xùn)練時(shí)所需的輸入數(shù)據(jù)和對(duì)應(yīng)的標(biāo)簽。
validation_data=val_ds
:
- 這是一個(gè)關(guān)鍵字參數(shù),用于指定驗(yàn)證數(shù)據(jù)集。在訓(xùn)練過(guò)程中,模型會(huì)使用
val_ds
來(lái)評(píng)估其在驗(yàn)證集上的性能,但不會(huì)基于驗(yàn)證集的數(shù)據(jù)來(lái)更新權(quán)重。這有助于監(jiān)控模型是否出現(xiàn)過(guò)擬合。
epochs=3
:
- 這指定了訓(xùn)練的輪數(shù)(或迭代次數(shù))。在這里,模型將遍歷整個(gè)
train_ds
數(shù)據(jù)集3次。
callbacks=[EvaluateCOCOMetricsCallback(val_ds, "model.h5")]
:
callbacks
是一個(gè)列表,其中可以包含多個(gè)回調(diào)函數(shù)。這些回調(diào)函數(shù)在訓(xùn)練的不同階段(如每個(gè)epoch結(jié)束后)被調(diào)用,以執(zhí)行某些操作,如保存模型、記錄日志等。- 在這里,你定義了一個(gè)名為
EvaluateCOCOMetricsCallback
的回調(diào)函數(shù),并將其實(shí)例化,傳遞了val_ds
(驗(yàn)證數(shù)據(jù)集)和"model.h5"
(可能是模型權(quán)重文件的保存路徑)作為參數(shù)。 - 我們可以猜測(cè)
EvaluateCOCOMetricsCallback
可能是一個(gè)自定義的回調(diào)函數(shù),用于在每個(gè)epoch結(jié)束后評(píng)估模型在COCO數(shù)據(jù)集上的某些指標(biāo)(如mAP,即平均精度均值)。這些指標(biāo)是目標(biāo)檢測(cè)任務(wù)中常用的性能度量標(biāo)準(zhǔn)。
2.6 可視化預(yù)測(cè)結(jié)果
當(dāng)使用深度學(xué)習(xí)模型(如YOLO)進(jìn)行目標(biāo)檢測(cè)時(shí),我們通常希望可視化模型的預(yù)測(cè)結(jié)果以評(píng)估其性能。以下是一個(gè)步驟說(shuō)明,描述了如何執(zhí)行這一過(guò)程:
首先,我們定義一個(gè)名為visualize_detections
的函數(shù),該函數(shù)接受三個(gè)參數(shù):model
(訓(xùn)練好的模型),dataset
(用于獲取輸入圖像的數(shù)據(jù)集)以及bounding_box_format
(邊界框的格式,如"xyxy")。
在函數(shù)內(nèi)部,我們使用next(iter(dataset.take(1)))
從數(shù)據(jù)集中獲取一個(gè)批次的圖像和對(duì)應(yīng)的真實(shí)標(biāo)簽。然后,我們利用model.predict(images)
對(duì)圖像進(jìn)行預(yù)測(cè),得到預(yù)測(cè)的邊界框信息。
接下來(lái),我們可能需要將預(yù)測(cè)的邊界框信息轉(zhuǎn)換為一種可視化工具所需的格式。但請(qǐng)注意,這一步的具體實(shí)現(xiàn)取決于你使用的可視化庫(kù)或方法。假設(shè)這里存在一個(gè)bounding_box
模塊,它有一個(gè)to_ragged
方法可以將預(yù)測(cè)結(jié)果轉(zhuǎn)換為所需的格式(盡管在標(biāo)準(zhǔn)的深度學(xué)習(xí)庫(kù)中并沒(méi)有直接這樣的方法)。
一旦我們有了可視化所需的圖像、真實(shí)標(biāo)簽和預(yù)測(cè)邊界框,我們就可以調(diào)用一個(gè)可視化函數(shù)(如visualization.plot_bounding_box_gallery
)來(lái)繪制包含真實(shí)邊界框和預(yù)測(cè)邊界框的圖像。這個(gè)函數(shù)通常接受一系列參數(shù),如圖像、真實(shí)標(biāo)簽、預(yù)測(cè)標(biāo)簽、邊界框格式等,并生成一個(gè)可視化結(jié)果。
最后,我們調(diào)用visualize_detections
函數(shù),傳入已訓(xùn)練的YOLO模型、驗(yàn)證數(shù)據(jù)集以及邊界框格式(“xyxy”)。這將觸發(fā)上述過(guò)程,生成一個(gè)可視化結(jié)果,顯示模型在驗(yàn)證數(shù)據(jù)集上的預(yù)測(cè)效果。
def visualize_detections(model, dataset, bounding_box_format):images, y_true = next(iter(dataset.take(1)))y_pred = model.predict(images)y_pred = bounding_box.to_ragged(y_pred)visualization.plot_bounding_box_gallery(images,value_range=(0, 255),bounding_box_format=bounding_box_format,y_true=y_true,y_pred=y_pred,scale=4,rows=2,cols=2,show=True,font_scale=0.7,class_mapping=class_mapping,)visualize_detections(yolo, dataset=val_ds, bounding_box_format="xyxy")
3、總結(jié)
本文介紹了如何使用 KerasCV 庫(kù)來(lái)訓(xùn)練 YOLOv8 目標(biāo)檢測(cè)模型。KerasCV 是 Keras 的擴(kuò)展,專為計(jì)算機(jī)視覺(jué)任務(wù)設(shè)計(jì),提供了預(yù)訓(xùn)練模型、可視化工具以及對(duì)遷移學(xué)習(xí)的支持。
- 環(huán)境設(shè)置與數(shù)據(jù)準(zhǔn)備
首先,安裝了 KerasCV 庫(kù),并導(dǎo)入了必要的 TensorFlow 和 KerasCV 模塊。接著,定義了超參數(shù),包括數(shù)據(jù)集分割比例、批量大小、學(xué)習(xí)率、訓(xùn)練周期數(shù)和全局剪切范數(shù)。為了處理 PASCAL VOC 數(shù)據(jù)集,編寫了解析 XML 注釋文件的函數(shù),用于提取圖像路徑、邊界框和類別 ID。
- 數(shù)據(jù)處理
利用 TensorFlow 的 tf.data
API 加載和處理數(shù)據(jù),創(chuàng)建了不規(guī)則張量來(lái)處理邊界框和類別標(biāo)簽的不同長(zhǎng)度,并劃分了訓(xùn)練集和驗(yàn)證集。
- 數(shù)據(jù)增強(qiáng)
介紹了數(shù)據(jù)增強(qiáng)的重要性,并展示了 KerasCV 提供的數(shù)據(jù)增強(qiáng)層,這些層能夠智能調(diào)整邊界框坐標(biāo),以適應(yīng)圖像變換。
- 模型構(gòu)建
詳細(xì)描述了 YOLOv8 模型的不同變體(YOLOv8n、YOLOv8s、YOLOv8m、YOLOv8l 和 YOLOv8x)的性能指標(biāo),包括平均精度均值(mAP)、推理速度、參數(shù)數(shù)量和浮點(diǎn)運(yùn)算次數(shù)。然后,使用 KerasCV 的 YOLOV8Detector
類構(gòu)建了 YOLOv8 模型,指定了類別數(shù)量、邊界框格式、backbone 和 FPN 深度。
- 模型編譯與訓(xùn)練
討論了用于 YOLOv8 的損失函數(shù),包括分類損失和邊界框損失,并編譯了模型。使用自定義的回調(diào)函數(shù) EvaluateCOCOMetricsCallback
訓(xùn)練模型,并在每個(gè)周期結(jié)束時(shí)評(píng)估 mAP 分?jǐn)?shù),還在 mAP 提高時(shí)保存模型。
- 結(jié)果可視化
提供了可視化訓(xùn)練和驗(yàn)證數(shù)據(jù)集的函數(shù),以及可視化模型預(yù)測(cè)結(jié)果的函數(shù),這有助于理解模型性能和進(jìn)行故障排除。
通過(guò)本教程,讀者可以了解到如何從頭開(kāi)始使用 KerasCV 訓(xùn)練定制的 YOLOv8 目標(biāo)檢測(cè)模型,包括數(shù)據(jù)準(zhǔn)備、增強(qiáng)、模型構(gòu)建、編譯、訓(xùn)練和結(jié)果可視化的完整流程。