1. Introduction

1.1 Fine-tuning là gì ?

Chắc hẳn đông đảo ai thao tác làm việc với các Model vào deep learning phần lớn sẽ nghe/quen với quan niệm Transfer learningFine tuning. Khái niệm tổng quát: Transfer learning là tận dụng tối đa trí thức học tập được từ một vụ việc nhằm áp dụng vào 1 sự việc tất cả liên quan không giống. Một ví dụ đối chọi giản: gắng bởi vì train 1 Model bắt đầu hoàn toàn đến bài tân oán phân nhiều loại chó/mèo, người ta rất có thể tận dụng tối đa 1 Mã Sản Phẩm đã làm được train vào ImageNet datamix cùng với hằng triệu hình ảnh. Pre-trained model này sẽ tiến hành train tiếp trên tập datamix chó/mèo, quy trình train này ra mắt nkhô hanh rộng, tác dụng thường xuyên xuất sắc hơn. Có không ít thứ hạng Transfer learning, các bạn có thể xem thêm trong bài bác này: Tổng đúng theo Transfer learning. Trong bài bác này, bản thân sẽ viết về 1 dạng transfer learning phổ biến: Fine-tuning.

Bạn đang xem: Fine tuning là gì

Quý Khách đang xem: Fine tuning là gì

Hiểu dễ dàng, fine-tuning là các bạn rước 1 pre-trained mã sản phẩm, tận dụng một phần hoặc tổng thể các layer, thêm/sửa/xoá 1 vài ba layer/nhánh để tạo thành 1 mã sản phẩm mới. Thường các layer đầu của Model được freeze (đóng góp băng) lại - tức weight những layer này sẽ không xẩy ra thay đổi quý hiếm vào quy trình train. Lý bởi vì vì chưng các layer này đã có công dụng trích xuất biết tin nút trìu tượng rẻ , năng lực này được học từ quá trình training trước kia. Ta freeze lại để tận dụng tối đa được năng lực này cùng góp vấn đề train ra mắt nkhô hanh hơn (Model chỉ yêu cầu update weight sinh sống những layer cao). Có tương đối nhiều những Object detect model được xây dựng dựa trên những Classifier model. VD Retina model (Object detect) được sản xuất với backbone là Resnet.

*

1.2 Tại sao pytorch núm vì Keras ?

Chủ đề bài viết lúc này, mình đang gợi ý fine-tuning Resnet50 - 1 pre-trained Model được hỗ trợ sẵn vào torchvision của pytorch. Tại sao là pytorch nhưng không hẳn Keras ? Lý bởi vì chưng vấn đề fine-tuning mã sản phẩm vào keras siêu đơn giản dễ dàng. Dưới đấy là 1 đoạn code minc hoạ cho vấn đề xây cất 1 Unet dựa trên Resnet vào Keras:

from tensorflow.keras import applicationsresnet = applications.resnet50.ResNet50()layer_3 = resnet.get_layer("activation_9").outputlayer_7 = resnet.get_layer("activation_21").outputlayer_13 = resnet.get_layer("activation_39").outputlayer_16 = resnet.get_layer("activation_48").output#Adding outputs decoder with encoder layersfcn1 = Conv2D(...)(layer_16)fcn2 = Conv2DTranspose(...)(fcn1)fcn2_skip_connected = Add()()fcn3 = Conv2DTranspose(...)(fcn2_skip_connected)fcn3_skip_connected = Add()()fcn4 = Conv2DTranspose(...)(fcn3_skip_connected)fcn4_skip_connected = Add()()fcn5 = Conv2DTranspose(...)(fcn4_skip_connected)Unet = Model(inputs = resnet.đầu vào, outputs=fcn5)quý khách hoàn toàn có thể thấy, fine-tuning model vào Keras thực thụ hết sức dễ dàng và đơn giản, dễ làm, dễ nắm bắt. Việc add thêm các nhánh rất đơn giản bởi vì cú pháp đơn giản. Trong pytorch thì ngược trở lại, desgin 1 model Unet tựa như sẽ tương đối vất vả với phức tạp. Người new học sẽ chạm mặt khó khăn vì trên mạng hiếm hoi những trả lời mang lại bài toán này. Vậy bắt buộc bài này mình đang giải đáp chi tiết giải pháp fine-tune vào pytorch nhằm áp dụng vào bài tân oán Visual Saliency prediction

2. Visual Saliency prediction

2.1 What is Visual Saliency ?


*

khi chú ý vào 1 tấm hình, đôi mắt thông thường sẽ có xu hướng triệu tập quan sát vào 1 vài chủ thể chính. Hình ảnh bên trên đấy là 1 minc hoạ, màu đá quý được sử dụng nhằm biểu hiện mức độ quyến rũ. Saliency prediction là bài bác tân oán mô rộp sự triệu tập của mắt bạn Lúc quan lại gần kề 1 tấm hình. Cụ thể, bài bác toán yên cầu thi công 1 mã sản phẩm, model này thừa nhận hình họa đầu vào, trả về 1 mask mô rộp cường độ duyên dáng. do vậy, Mã Sản Phẩm nhấn vào 1 đầu vào image với trả về 1 mask gồm kích cỡ tương tự.

Để rõ hơn về bài bác toán này, chúng ta cũng có thể gọi bài: Visual Saliency Prediction with Contextual Encoder-Decoder Network.Datamix thông dụng nhất: SALICON DATASET

2.2 Unet

Note: Quý Khách rất có thể bỏ qua mất phần này trường hợp vẫn biết về Unet

Đây là một trong bài xích toán thù Image-to-Image. Để giải quyết và xử lý bài bác toán này, bản thân sẽ xây dựng 1 Model theo bản vẽ xây dựng Unet. Unet là 1 trong kiến trúc được sử dụng nhiều trong bài xích toán thù Image-to-image như: semantic segmentation, tự động color, super resolution ... Kiến trúc của Unet tất cả điểm giống như với phong cách xây dựng Encoder-Decoder đối xứng, có thêm các skip connection tự Encode quý phái Decode tương ứng. Về cơ bạn dạng, các layer càng cao càng trích xuất báo cáo ở mức trìu tượng cao, điều này đồng nghĩa với câu hỏi các lên tiếng nút trìu tượng rẻ như mặt đường nét, Màu sắc, độ sắc nét... có khả năng sẽ bị mất đuối đi trong quy trình lan truyền. Người ta thêm các skip-connection vào để giải quyết vấn đề này.

Với phần Encode, feature-map được downscale bởi những Convolution. Ngược lại, ở trong phần decode, feature-maps được upscale bởi các Upsampling layer, vào bài xích này bản thân thực hiện những Convolution Transpose.

*

2.3 Resnet

Để giải quyết bài xích toán, mình sẽ xây dựng dựng mã sản phẩm Unet với backbone là Resnet50. quý khách đề xuất mày mò về Resnet ví như chưa biết về kiến trúc này. Hãy quan tiền giáp hình minh hoạ sau đây. Resnet50 được tạo thành các khối to . Unet được kiến tạo với Encoder là Resnet50. Ta đã lấy ra output của từng kăn năn, sản xuất những skip-connection kết nối từ bỏ Encoder sang Decoder. Decoder được chế tạo vì chưng những Convolution Transpose layer (xen kẽ trong các số ấy là những lớp Convolution nhằm mục đích mục đích sút số chanel của feature map -> bớt số lượng weight cho model).

Theo quan điểm cá thể, pytorch rất dễ code, dễ hiểu rộng tương đối nhiều đối với Tensorflow 1.x hoặc ngang ngửa Keras. Tuy nhiên, vấn đề fine-tuning model vào pytorch lại cạnh tranh rộng không hề ít so với Keras. Trong Keras, ta ko bắt buộc thừa quan tâm cho tới bản vẽ xây dựng, luồng giải pháp xử lý của Model, chỉ việc kéo ra những output trên 1 số ít layer khăng khăng làm cho skip-connection, ghép nối và tạo ra Model mới.

Xem thêm: Thiết Kế & Đồ Họa - Download Xilisoft Video Converter Ultimate 7


*

3. Code

Tất cả code của bản thân được đóng gói trong file notebook Salicon_main.ipynb. Quý khách hàng có thể thiết lập về và run code theo links github: github/trungthanhnguyen0502 . Trong nội dung bài viết mình đã chỉ đưa ra các đoạn code chính.

Import những package

import albumentations as Aimport numpy as npimport torchimport torchvisionimport torch.nn as nn import torchvision.transforms as Timport torchvision.models as modelsfrom torch.utils.data import DataLoader, Datasetimport ....

3.1 utils functions

Trong pytorch, dữ liệu có máy tự dimension không giống với Keras/TF/numpy. thường thì với numpy tốt keras, hình ảnh có dimension theo sản phẩm công nghệ tự (batchkích thước,h,w,chanel)(batchkích thước, h, w, chanel)(batchkích thước,h,w,chanel). Thứ tự vào Pytorch ngược lại là (batchsize,chanel,h,w)(batchkích thước, chanel, h, w)(batchkích thước,chanel,h,w). Mình sẽ xây dựng 2 hàm toTensor cùng toNumpy nhằm đổi khác qua lại thân nhị format này.

def toTensor(np_array, axis=(2,0,1)): return torch.tensor(np_array).permute(axis)def toNumpy(tensor, axis=(1,2,0)): return tensor.detach().cpu().permute(axis).numpy() ## display one image in notebookdef plot_img(img): ... ## display multi imagedef plot_imgs(imgs): ...

3.2 Define model

3.2.1 Conv và Deconv

Mình sẽ xây dựng dựng 2 function trả về module Convolution cùng Convolution Transpose (Deconv)

def Deconv(n_input, n_output, k_size=4, stride=2, padding=1): Tconv = nn.ConvTranspose2d( n_input, n_output, kernel_size=k_form size, stride=stride, padding=padding, bias=False) bloông chồng = return nn.Sequential(*block) def Conv(n_đầu vào, n_output, k_size=4, stride=2, padding=0, bn=False, dropout=0): conv = nn.Conv2d( n_input, n_output, kernel_size=k_kích cỡ, stride=stride, padding=padding, bias=False) blochồng = return nn.Sequential(*block)

3.2.2 Unet model

Init function: ta đang copy những layer đề nghị giữ lại từ resnet50 vào unet. Sau đó khởi chế tạo các Conv / Deconv layer và các layer quan trọng.

Forward function: cần bảo vệ luồng cách xử trí của resnet50 được không thay đổi tương tự code gốc (trừ Fully-connected layer). Sau kia ta ghnghiền nối các layer lại theo phong cách thiết kế Unet đang diễn đạt trong phần 2.

Xem thêm: Wondershare Mobiletrans 7 - Download Wondershare Mobiletrans 8

class Unet(nn.Module): def __init__(self, resnet): super().__init__() self.conv1 = resnet.conv1 self.bn1 = resnet.bn1 self.relu = resnet.relu self.maxpool = resnet.maxpool self.tanh = nn.Tanh() self.sigmoid = nn.Sigmoid() # get some layer from resnet to lớn make skip connection self.layer1 = resnet.layer1 self.layer2 = resnet.layer2 self.layer3 = resnet.layer3 self.layer4 = resnet.layer4 # convolution layer, use to lớn reduce the number of channel => reduce weight number self.conv_5 = Conv(2048, 512, 1, 1, 0) self.conv_4 = Conv(1536, 512, 1, 1, 0) self.conv_3 = Conv(768, 256, 1, 1, 0) self.conv_2 = Conv(384, 128, 1, 1, 0) self.conv_1 = Conv(128, 64, 1, 1, 0) self.conv_0 = Conv(32, 1, 3, 1, 1) # deconvolution layer self.deconv4 = Deconv(512, 512, 4, 2, 1) self.deconv3 = Deconv(512, 256, 4, 2, 1) self.deconv2 = Deconv(256, 128, 4, 2, 1) self.deconv1 = Deconv(128, 64, 4, 2, 1) self.deconv0 = Deconv(64, 32, 4, 2, 1) def forward(self, x): x = self.conv1(x) x = self.bn1(x) x = self.relu(x) skip_1 = x x = self.maxpool(x) x = self.layer1(x) skip_2 = x x = self.layer2(x) skip_3 = x x = self.layer3(x) skip_4 = x x5 = self.layer4(x) x5 = self.conv_5(x5) x4 = self.deconv4(x5) x4 = torch.cat(, dim=1) x4 = self.conv_4(x4) x3 = self.deconv3(x4) x3 = torch.cat(, dim=1) x3 = self.conv_3(x3) x2 = self.deconv2(x3) x2 = torch.cat(, dim=1) x2 = self.conv_2(x2) x1 = self.deconv1(x2) x1 = torch.cat(, dim=1) x1 = self.conv_1(x1) x0 = self.deconv0(x1) x0 = self.conv_0(x0) x0 = self.sigmoid(x0) return x0 device = torch.device("cuda")resnet50 = models.resnet50(pretrained=True)mã sản phẩm = Unet(resnet50)mã sản phẩm.to(device)## Freeze resnet50"s layers in Unetfor i, child in enumerate(Mã Sản Phẩm.children()): if i 7: for param in child.parameters(): param.requires_grad = False

3.3 Dataset and Dataloader

Dataset trả thừa nhận 1 danh mục các image_path cùng mask_dir, trả về image với mask khớp ứng.

Define MaskDataset

class MaskDataset(Dataset): def __init__(self, img_fns, mask_dir, transforms=None): self.img_fns = img_fns self.transforms = transforms self.mask_dir = mask_dir def __getitem__(self, idx): img_path = self.img_fns img_name = img_path.split("/").split(".") mask_fn = f"self.mask_dir/img_name.png" img = cv2.imread(img_path) mask = cv2.imread(mask_fn) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY) if self.transforms: sample = "image": img, "mask": mask sample = self.transforms(**sample) img = sample mask = sample # lớn Tensor img = img/255.0 mask = np.expand_dims(mask, axis=-1)/255.0 mask = toTensor(mask).float() img = toTensor(img).float() return img, mask def __len__(self): return len(self.img_fns)Test dataset

img_fns = glob("./Salicon_dataset/image/train/*.jpg")mask_dir = "./Salicon_dataset/mask/train"train_transkhung = A.Compose(, height=256, width=256, p=0.4), A.HorizontalFlip(p=0.5), A.Rotate(limit=(-10,10), p=0.6),>)train_dataphối = MaskDataset(img_fns, mask_dir, train_transform)train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True, drop_last=True)# Test datasetimg, mask = next(iter(train_dataset))img = toNumpy(img)mask = toNumpy(mask)img = (img*255.0).astype(np.uint8)mask = (mask*255.0).astype(np.uint8)heatmap_img = cv2.applyColorMap(mask, cv2.COLORMAP_JET)combine_img = cv2.addWeighted(img, 0.7, heatmap_img, 0.3, 0)plot_imgs(

3.4 Train model

Vì bài toán đơn giản dễ dàng cùng khiến cho dễ hiểu, mình vẫn train theo cách đơn giản dễ dàng nhất, ko validate trong qúa trình train mà chỉ lưu giữ Model sau một số ít epoch tuyệt nhất định

train_params = optimizer = torch.optyên.Adam(train_params, lr=0.001, betas=(0.9, 0.99))epochs = 5Model.train()saved_dir = "model"os.makedirs(saved_dir, exist_ok=True)loss_function = nn.MSELoss(reduce="mean")for epoch in range(epochs): for imgs, masks in tqdm(train_loader): imgs_gpu = imgs.to(device) outputs = model(imgs_gpu) masks = masks.to(device) loss = loss_function(outputs, masks) loss.backward() optimizer.step()

3.5 Test model

img_fns = glob("./Salicon_dataset/image/val/*.jpg")mask_dir = "./Salicon_dataset/mask/val"val_transsize = A.Compose()model.eval()val_dataphối = MaskDataset(img_fns, mask_dir, val_transform)val_loader = DataLoader(val_dataphối, batch_size=4, shuffle=False, drop_last=True)imgs, mask_targets = next(iter(val_loader))imgs_gpu = imgs.to(device)mask_outputs = model(imgs_gpu)mask_outputs = toNumpy(mask_outputs, axis=(0,2,3,1))imgs = toNumpy(imgs, axis=(0,2,3,1))mask_targets = toNumpy(mask_targets, axis=(0,2,3,1))for i, img in enumerate(imgs): img = (img*255.0).astype(np.uint8) mask_output = (mask_outputs*255.0).astype(np.uint8) mask_target = (mask_targets*255.0).astype(np.uint8) heatmap_label = cv2.applyColorMap(mask_target, cv2.COLORMAP_JET) heatmap_pred = cv2.applyColorMap(mask_output, cv2.COLORMAP_JET) origin_img = cv2.addWeighted(img, 0.7, heatmap_label, 0.3, 0) predict_img = cv2.addWeighted(img, 0.7, heatmap_pred, 0.3, 0) result = np.concatenate((img,origin_img, predict_img),axis=1) plot_img(result)Kết quả thu được:

Bài viết liên quan

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *