[ad_1]
Đào tạo Mô hình Phân đoạn Bất kỳ (SAM) của Meta để phân đoạn mặt nạ có độ trung thực cao cho bất kỳ miền nào
Việc phát hành một số mô hình nền tảng mã nguồn mở mạnh mẽ cùng với những tiến bộ trong việc tinh chỉnh đã mang lại một mô hình mới trong học máy và trí tuệ nhân tạo. Trung tâm của cuộc cách mạng này là mô hình máy biến áp.
Trong khi các mô hình chuyên biệt có độ chính xác cao trước đây nằm ngoài tầm với của hầu hết mọi người, ngoại trừ các tập đoàn được tài trợ tốt nhất, thì ngày nay, mô hình nền tảng cho phép ngay cả những nguồn lực khiêm tốn dành cho sinh viên hoặc các nhà nghiên cứu độc lập cũng có thể đạt được kết quả ngang bằng với các mô hình độc quyền hiện đại.
Bài viết này khám phá ứng dụng của Mô hình phân đoạn bất kỳ (SAM) của Meta vào nhiệm vụ cảm biến từ xa của phân đoạn pixel sông. Nếu bạn muốn tham gia ngay vào mã, tệp nguồn cho dự án này có sẵn tại GitHub và dữ liệu đang bật Ôm mặtmặc dù vậy, bạn nên đọc toàn bộ bài viết trước.
Bước đầu tiên là tìm hoặc tạo một tập dữ liệu phù hợp. Dựa trên tài liệu hiện có, một bộ dữ liệu tinh chỉnh tốt cho SAM sẽ có ít nhất 200–800 hình ảnh. Bài học quan trọng trong thập kỷ qua về tiến bộ học tập sâu là càng nhiều dữ liệu thì càng tốt, vì vậy bạn không thể sai lầm với một tập dữ liệu tinh chỉnh lớn hơn. Tuy nhiên, mục tiêu đằng sau các mô hình cơ bản là cho phép các bộ dữ liệu tương đối nhỏ cũng đủ để có hiệu suất mạnh mẽ.
Cũng cần phải có tài khoản HuggingFace, có thể được tạo ra ở đây. Khi sử dụng HuggingFace, chúng ta có thể dễ dàng lưu trữ và truy xuất tập dữ liệu của mình bất kỳ lúc nào từ bất kỳ thiết bị nào, giúp việc cộng tác và tái tạo dễ dàng hơn.
Yêu cầu cuối cùng là một thiết bị có GPU mà chúng ta có thể chạy quy trình đào tạo. GPU Nvidia T4, có sẵn miễn phí thông qua Google Colabđủ mạnh để huấn luyện điểm kiểm tra mô hình SAM lớn nhất (sam-vit-huge) trên 1000 hình ảnh trong 50 kỷ nguyên trong vòng chưa đầy 12 giờ.
Để tránh mất tiến trình do giới hạn sử dụng trên thời gian chạy được lưu trữ, bạn có thể gắn Google Drive và lưu từng điểm kiểm tra mô hình ở đó. Ngoài ra, hãy triển khai và kết nối với Máy ảo GCP để vượt qua giới hạn hoàn toàn. Nếu bạn chưa bao giờ sử dụng GCP trước khi đủ điều kiện nhận khoản tín dụng 300 đô la miễn phí, số tiền này đủ để đào tạo mô hình ít nhất hàng chục lần.
Trước khi bắt đầu đào tạo, chúng ta cần hiểu kiến trúc của SAM. Mô hình bao gồm ba thành phần: một bộ mã hóa hình ảnh từ một bộ mã hóa được sửa đổi tối thiểu bộ mã hóa tự động đeo mặt nạ, bộ mã hóa lời nhắc linh hoạt có khả năng xử lý các loại lời nhắc đa dạng và bộ giải mã mặt nạ nhanh chóng và nhẹ. Một động lực đằng sau thiết kế này là cho phép phân đoạn nhanh, theo thời gian thực trên các thiết bị biên (ví dụ: trong trình duyệt) vì việc nhúng hình ảnh chỉ cần được tính toán một lần và bộ giải mã mặt nạ có thể chạy trong ~50 mili giây trên CPU.
Về mặt lý thuyết, bộ mã hóa hình ảnh đã học được cách tối ưu để nhúng hình ảnh, xác định hình dạng, cạnh và các đặc điểm trực quan chung khác. Tương tự như vậy, về mặt lý thuyết, bộ mã hóa lời nhắc đã có thể mã hóa lời nhắc một cách tối ưu. Bộ giải mã mặt nạ là một phần của kiến trúc mô hình, lấy các nhúng hình ảnh và lời nhắc này và thực sự tạo mặt nạ bằng cách vận hành trên các nhúng hình ảnh và lời nhắc.
Do đó, một cách tiếp cận là cố định các tham số mô hình được liên kết với bộ mã hóa hình ảnh và dấu nhắc trong quá trình đào tạo và chỉ cập nhật trọng số của bộ giải mã mặt nạ. Cách tiếp cận này có lợi ích là cho phép cả các tác vụ xuôi dòng được giám sát và không giám sát, vì các lời nhắc về điểm điều khiển và hộp giới hạn đều có thể tự động hóa và có thể sử dụng được bởi con người.
Một cách tiếp cận khác là làm quá tải bộ mã hóa dấu nhắc, đóng băng bộ mã hóa hình ảnh và bộ giải mã mặt nạ và đơn giản là không sử dụng bộ mã hóa mặt nạ SAM gốc. Ví dụ: kiến trúc AutoSAM sử dụng mạng dựa trên Harmonic Dense Web để tạo ra các phần nhúng nhanh chóng dựa trên chính hình ảnh. Trong hướng dẫn này, chúng tôi sẽ đề cập đến cách tiếp cận đầu tiên, đóng băng hình ảnh và bộ mã hóa lời nhắc cũng như chỉ đào tạo bộ giải mã mặt nạ, nhưng bạn có thể tìm thấy mã cho phương pháp thay thế này trong AutoSAM GitHub Và giấy.
Bước tiếp theo là xác định loại lời nhắc nào mà mô hình sẽ nhận được trong thời gian suy luận, để chúng ta có thể cung cấp loại lời nhắc đó tại thời điểm đào tạo. Cá nhân tôi sẽ không khuyên bạn sử dụng lời nhắc văn bản cho bất kỳ quy trình xử lý thị giác máy tính nghiêm túc nào, vì bản chất không thể đoán trước/không nhất quán của quá trình xử lý ngôn ngữ tự nhiên. Điều này để lại các điểm và hộp giới hạn, với sự lựa chọn cuối cùng phụ thuộc vào bản chất cụ thể của tập dữ liệu cụ thể của bạn, mặc dù tài liệu đã phát hiện ra rằng các hộp giới hạn hoạt động tốt hơn các điểm kiểm soát khá nhất quán.
Lý do cho điều này không hoàn toàn rõ ràng nhưng có thể là bất kỳ yếu tố nào sau đây hoặc sự kết hợp nào đó của chúng:
- Các điểm kiểm soát tốt khó lựa chọn hơn tại thời điểm suy luận (khi mặt nạ sự thật cơ bản không được biết) so với các hộp giới hạn.
- Không gian của các dấu nhắc điểm có thể có là các bậc có độ lớn lớn hơn không gian của các dấu nhắc hộp giới hạn có thể có nên nó chưa được đào tạo kỹ lưỡng.
- Các tác giả SAM ban đầu đã tập trung vào khả năng bắn không và bắn ít (được tính theo tương tác nhanh chóng của con người) của mô hình, do đó, quá trình đào tạo trước có thể tập trung nhiều hơn vào các hộp giới hạn.
Bất kể thế nào, phân đoạn sông thực sự là một trường hợp hiếm hoi mà các điểm nhắc nhở thực sự vượt trội hơn các hộp giới hạn (mặc dù chỉ một chút, ngay cả với một miền cực kỳ thuận lợi). Vì trong bất kỳ hình ảnh nào của một con sông, khối nước sẽ trải dài từ đầu này đến đầu kia của hình ảnh, bất kỳ hộp giới hạn bao quanh nào cũng sẽ gần như luôn bao phủ hầu hết hình ảnh. Do đó, các hộp giới hạn nhắc nhở cho các phần rất khác nhau của con sông có thể trông cực kỳ giống nhau, về mặt lý thuyết có nghĩa là các hộp giới hạn cung cấp cho mô hình ít thông tin hơn đáng kể so với các điểm kiểm soát và do đó dẫn đến hiệu suất kém hơn.
Lưu ý trong hình minh họa ở trên, mặc dù mặt nạ phân đoạn thực sự cho hai phần sông là hoàn toàn khác nhau, nhưng các hộp giới hạn tương ứng của chúng gần như giống hệt nhau, trong khi các điểm nhắc của chúng lại khác nhau (tương đối) nhiều hơn.
Yếu tố quan trọng khác cần xem xét là mức độ dễ dàng tạo ra lời nhắc nhập liệu tại thời điểm suy luận. Nếu bạn mong đợi có một con người trong vòng lặp, thì cả hộp giới hạn và điểm kiểm soát đều khá dễ dàng để có được tại thời điểm suy luận. Tuy nhiên, trong trường hợp bạn có ý định có một đường ống hoàn toàn tự động, việc trả lời những câu hỏi này trở nên phức tạp hơn.
Cho dù sử dụng điểm kiểm soát hay hộp giới hạn, việc tạo dấu nhắc trước tiên thường liên quan đến việc ước tính mặt nạ thô cho đối tượng quan tâm. Khi đó, các hộp giới hạn có thể chỉ là hộp tối thiểu bao bọc mặt nạ thô, trong khi các điểm kiểm soát cần được lấy mẫu từ mặt nạ thô. Điều này có nghĩa là các hộp giới hạn sẽ dễ dàng có được hơn khi không xác định được mặt nạ sự thật mặt đất, vì mặt nạ ước tính cho đối tượng quan tâm chỉ cần khớp gần giống với cùng kích thước và vị trí của đối tượng thực, trong khi đối với các điểm kiểm soát, mặt nạ ước tính sẽ cần để phù hợp hơn với các đường viền của đối tượng.
Đối với phân đoạn sông, nếu chúng ta có thể truy cập cả RGB và NIR, thì chúng ta có thể sử dụng các phương pháp ngưỡng chỉ số phổ để có được mặt nạ thô của mình. Nếu chúng ta chỉ có thể truy cập RGB, chúng ta có thể chuyển đổi hình ảnh sang HSV và ngưỡng tất cả các pixel trong một phạm vi sắc thái, độ bão hòa và giá trị nhất định. Sau đó, chúng ta có thể loại bỏ các thành phần được kết nối dưới một ngưỡng kích thước nhất định và sử dụng erosion
từ skimage.morphology
để đảm bảo chỉ có 1 pixel trong mặt nạ của chúng ta là những pixel nằm về phía tâm của các đốm màu xanh lớn.
Để đào tạo mô hình của chúng tôi, chúng tôi cần một trình tải dữ liệu chứa tất cả dữ liệu đào tạo mà chúng tôi có thể lặp lại cho mỗi kỷ nguyên đào tạo. Khi chúng tôi tải tập dữ liệu của mình từ HuggingFace, nó có dạng datasets.Dataset
lớp học. Nếu tập dữ liệu ở chế độ riêng tư, trước tiên hãy đảm bảo cài đặt HuggingFace CLI và đăng nhập bằng !huggingface-cli login
.
from datasets import load_dataset, load_from_disk, Datasethf_dataset_name = "stodoran/elwha-segmentation-v1"
training_data = load_dataset(hf_dataset_name, break up="prepare")
validation_data = load_dataset(hf_dataset_name, break up="validation")
Sau đó, chúng tôi cần mã hóa lớp tập dữ liệu tùy chỉnh của riêng mình để trả về không chỉ hình ảnh và nhãn cho bất kỳ chỉ mục nào mà còn cả lời nhắc. Dưới đây là cách triển khai có thể xử lý cả lời nhắc điểm điều khiển và hộp giới hạn. Để được khởi tạo, cần có HuggingFace datasets.Dataset
và một phiên bản bộ xử lý SAM.
from torch.utils.information import Datasetclass PromptType:
CONTROL_POINTS = "pts"
BOUNDING_BOX = "bbox"
class SAMDataset(Dataset):
def __init__(
self,
dataset,
processor,
prompt_type = PromptType.CONTROL_POINTS,
num_positive = 3,
num_negative = 0,
erode = True,
multi_mask = "imply",
perturbation = 10,
image_size = (1024, 1024),
mask_size = (256, 256),
):
# Asign all values to self
...
def __len__(self):
return len(self.dataset)
def __getitem__(self, idx):
datapoint = self.dataset(idx)
input_image = cv2.resize(np.array(datapoint("picture")), self.image_size)
ground_truth_mask = cv2.resize(np.array(datapoint("label")), self.mask_size)
if self.prompt_type == PromptType.CONTROL_POINTS:
inputs = self._getitem_ctrlpts(input_image, ground_truth_mask)
elif self.prompt_type == PromptType.BOUNDING_BOX:
inputs = self._getitem_bbox(input_image, ground_truth_mask)
inputs("ground_truth_mask") = ground_truth_mask
return inputs
Chúng ta cũng phải xác định SAMDataset._getitem_ctrlpts
Và SAMDataset._getitem_bbox
các hàm, mặc dù nếu bạn chỉ có kế hoạch sử dụng một loại dấu nhắc thì bạn có thể cấu trúc lại mã để chỉ xử lý trực tiếp loại đó SAMDataset.__getitem__
và loại bỏ chức năng trợ giúp.
class SAMDataset(Dataset):
...def _getitem_ctrlpts(self, input_image, ground_truth_mask):
# Get management factors immediate. See the GitHub for the supply
# of this operate, or exchange with your individual level choice algorithm.
input_points, input_labels = generate_input_points(
num_positive=self.num_positive,
num_negative=self.num_negative,
masks=ground_truth_mask,
dynamic_distance=True,
erode=self.erode,
)
input_points = input_points.astype(float).tolist()
input_labels = input_labels.tolist()
input_labels = ((x) for x in input_labels)
# Put together the picture and immediate for the mannequin.
inputs = self.processor(
input_image,
input_points=input_points,
input_labels=input_labels,
return_tensors="pt"
)
# Take away batch dimension which the processor provides by default.
inputs = {okay: v.squeeze(0) for okay, v in inputs.objects()}
inputs("input_labels") = inputs("input_labels").squeeze(1)
return inputs
def _getitem_bbox(self, input_image, ground_truth_mask):
# Get bounding field immediate.
bbox = get_input_bbox(ground_truth_mask, perturbation=self.perturbation)
# Put together the picture and immediate for the mannequin.
inputs = self.processor(input_image, input_boxes=((bbox)), return_tensors="pt")
inputs = {okay: v.squeeze(0) for okay, v in inputs.objects()} # Take away batch dimension which the processor provides by default.
return inputs
Kết hợp tất cả lại với nhau, chúng ta có thể tạo một hàm tạo và trả về bộ tải dữ liệu PyTorch dựa trên sự phân chia của tập dữ liệu HuggingFace. Viết các hàm trả về bộ nạp dữ liệu thay vì chỉ thực thi các ô có cùng mã không chỉ là cách thực hành tốt để viết mã linh hoạt và có thể bảo trì mà còn cần thiết nếu bạn định sử dụng HuggingFace Tăng tốc để thực hiện đào tạo phân tán.
from transformers import SamProcessor
from torch.utils.information import DataLoaderdef get_dataloader(
hf_dataset,
model_size = "base", # Considered one of "base", "giant", or "enormous"
batch_size = 8,
prompt_type = PromptType.CONTROL_POINTS,
num_positive = 3,
num_negative = 0,
erode = True,
multi_mask = "imply",
perturbation = 10,
image_size = (256, 256),
mask_size = (256, 256),
):
processor = SamProcessor.from_pretrained(f"fb/sam-vit-{model_size}")
sam_dataset = SAMDataset(
dataset=hf_dataset,
processor=processor,
prompt_type=prompt_type,
num_positive=num_positive,
num_negative=num_negative,
erode=erode,
multi_mask=multi_mask,
perturbation=perturbation,
image_size=image_size,
mask_size=mask_size,
)
dataloader = DataLoader(sam_dataset, batch_size=batch_size, shuffle=True)
return dataloader
Sau đó, việc huấn luyện chỉ đơn giản là tải mô hình, đóng băng hình ảnh và bộ mã hóa lời nhắc cũng như huấn luyện số lần lặp mong muốn.
mannequin = SamModel.from_pretrained(f"fb/sam-vit-{model_size}")
optimizer = AdamW(mannequin.mask_decoder.parameters(), lr=learning_rate, weight_decay=weight_decay)# Prepare solely the decoder.
for identify, param in mannequin.named_parameters():
if identify.startswith("vision_encoder") or identify.startswith("prompt_encoder"):
param.requires_grad_(False)
Dưới đây là phác thảo cơ bản của mã vòng lặp đào tạo. Lưu ý rằng forward_pass
, calculate loss
, evaluate_model
Và save_model_checkpoint
các hàm đã được bỏ qua vì lý do ngắn gọn, nhưng các triển khai có sẵn trên GitHub. Mã chuyển tiếp sẽ khác đôi chút dựa trên loại dấu nhắc và phép tính mất mát cũng cần một trường hợp đặc biệt dựa trên loại dấu nhắc; khi sử dụng dấu nhắc điểm, SAM trả về một mặt nạ dự đoán cho mọi điểm đầu vào đơn lẻ, do đó, để có được một mặt nạ duy nhất có thể so sánh với giá trị thực tế, thì các mặt nạ dự đoán cần được tính trung bình hoặc mặt nạ dự đoán tốt nhất cần được chọn (xác định dựa trên điểm IoU dự đoán của SAM).
train_losses = ()
validation_losses = ()
epoch_loop = tqdm(whole=num_epochs, place=epoch, go away=False)
batch_loop = tqdm(whole=len(train_dataloader), place=0, go away=True)whereas epoch < num_epochs:
epoch_losses = ()
batch_loop.n = 0 # Loop Reset
for idx, batch in enumerate(train_dataloader):
# Ahead Move
batch = {okay: v.to(accelerator.system) for okay, v in batch.objects()}
outputs = forward_pass(mannequin, batch, prompt_type)
# Compute Loss
ground_truth_masks = batch("ground_truth_mask").float()
train_loss = calculate_loss(outputs, ground_truth_masks, prompt_type, loss_fn, multi_mask="greatest")
epoch_losses.append(train_loss)
# Backward Move & Optimizer Step
optimizer.zero_grad()
accelerator.backward(train_loss)
optimizer.step()
lr_scheduler.step()
batch_loop.set_description(f"Prepare Loss: {train_loss.merchandise():.4f}")
batch_loop.replace(1)
validation_loss = evaluate_model(mannequin, validation_dataloader, accelerator.system, loss_fn)
train_losses.append(torch.imply(torch.Tensor(epoch_losses)))
validation_losses.append(validation_loss)
if validation_loss < best_loss:
save_model_checkpoint(
accelerator,
best_checkpoint_path,
mannequin,
optimizer,
lr_scheduler,
epoch,
train_history,
validation_loss,
train_losses,
validation_losses,
loss_config,
model_descriptor=model_descriptor,
)
best_loss = validation_loss
epoch_loop.set_description(f"Greatest Loss: {best_loss:.4f}")
epoch_loop.replace(1)
epoch += 1
Đối với dự án sông Elwha, thiết lập tốt nhất đạt được là đào tạo mô hình “sam-vit-base” bằng cách sử dụng tập dữ liệu gồm hơn 1k mặt nạ phân đoạn bằng cách sử dụng phiên bản GCP trong vòng chưa đầy 12 giờ.
So với SAM cơ bản, việc tinh chỉnh đã cải thiện hiệu suất đáng kể, với mặt nạ trung bình chuyển từ không sử dụng được sang có độ chính xác cao.
Một thực tế quan trọng cần lưu ý là tập dữ liệu huấn luyện của hình ảnh sông 1k không hoàn hảo, với các nhãn phân đoạn khác nhau rất nhiều về số lượng pixel được phân loại chính xác. Do đó, số liệu hiển thị ở trên được tính toán trên tập dữ liệu hoàn hảo về pixel gồm 225 hình ảnh dòng sông.
Một hành vi quan sát thú vị là mô hình đã học cách khái quát hóa từ dữ liệu đào tạo không hoàn hảo. Khi đánh giá trên các điểm dữ liệu mà ví dụ đào tạo chứa các phân loại sai rõ ràng, chúng ta có thể quan sát thấy rằng dự đoán của mô hình tránh được lỗi. Lưu ý cách các hình ảnh ở hàng trên cùng hiển thị các mẫu đào tạo chứa các mặt nạ không lấp đầy toàn bộ dòng sông cho đến tận bờ, trong khi hàng dưới cùng hiển thị các dự đoán của mô hình phân đoạn ranh giới sông chặt chẽ hơn.
[ad_2]
Source link