1. Introduction

1.1 Fine-tuning là gì ?

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

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

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

*

1.2 Tại sao pytorch cố do Keras ?

Chủ đề bài viết bây giờ, mình đã hướng dẫn fine-tuning Resnet50 - 1 pre-trained Model được cung ứng sẵn vào torchvision của pytorch. Tại sao là pytorch mà chưa hẳn Keras ? Lý bởi vày bài toán fine-tuning mã sản phẩm vào keras khôn xiết đơn giản và dễ dàng. Dưới đó là 1 đoạn code minh hoạ mang đến việc kiến thiết 1 Unet dựa vào 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.input, outputs=fcn5)Quý Khách rất có thể thấy, fine-tuning Model trong Keras thực thụ khôn cùng đơn giản dễ dàng, dễ dàng có tác dụng, dễ hiểu. Việc add thêm các nhánh rất dễ do cú pháp đơn giản và dễ dàng. Trong pytorch thì ngược lại, tạo ra 1 mã sản phẩm Unet tương tự sẽ khá vất vả cùng phức hợp. Người bắt đầu học tập sẽ gặp gỡ khó khăn vày trên mạng không nhiều những giải đáp mang lại bài toán này. Vậy nên bài xích này mình đang trả lời chi tiết biện pháp fine-tune vào pytorch để áp dụng vào bài toán thù Visual Saliency prediction

2. Visual Saliency prediction

2.1 What is Visual Saliency ?

*

lúc chú ý vào 1 tấm hình, mắt thông thường sẽ có Xu thế tập trung chú ý vào 1 vài công ty thiết yếu. Ảnh trên đấy là 1 minch hoạ, màu quà được sử dụng để bộc lộ cường độ thu hút. Saliency prediction là bài toán thù mô phỏng sự tập trung của đôi mắt người Khi quan liêu tiếp giáp 1 tấm hình. Cụ thể, bài toán thù yên cầu sản xuất 1 Model, mã sản phẩm này thừa nhận hình họa nguồn vào, trả về 1 mask tế bào phỏng cường độ say mê. Vậy nên, mã sản phẩm dìm vào 1 input đầu vào image và trả về 1 mask tất cả kích thước tương đương.

Để rõ rộng về bài tân oán này, chúng ta có thể hiểu bài: Visual Saliency Prediction with Contextual Encoder-Decoder Network.Dataset thông dụng nhất: SALICON DATASET

2.2 Unet

Note: Bạn rất có thể bỏ qua phần này nếu như vẫn biết về Unet

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

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

*

2.3 Resnet

Để giải quyết bài bác toán thù, bản thân sẽ xây dựng mã sản phẩm Unet cùng với backbone là Resnet50. Bạn buộc phải tò mò về Resnet giả dụ không biết về phong cách xây dựng này. Hãy quan liền kề hình minch hoạ tiếp sau đây. Resnet50 được chia thành những khối hận to . Unet được tạo với Encoder là Resnet50. Ta đang kéo ra output của từng kân hận, sản xuất những skip-connection kết nối từ bỏ Encoder sang trọng Decoder. Decoder được thiết kế vì những Convolution Transpose layer (đan xen trong số ấy là các lớp Convolution nhằm mục tiêu mục đích sút số chanel của feature maps -> sút số lượng weight cho model).

Theo cách nhìn cá nhân, pytorch rất đơn giản code, dễ nắm bắt hơn rất nhiều đối với Tensorflow 1.x hoặc ngang ngửa Keras. Tuy nhiên, Việc fine-tuning model vào pytorch lại nặng nề hơn rất nhiều đối với Keras. Trong Keras, ta không cần quá quan tâm tới phong cách xây dựng, luồng xử trí của mã sản phẩm, chỉ việc lôi ra những output tại một số layer khăng khăng có tác dụng skip-connection, ghxay nối và tạo ra Model new.

*

Trong pytorch thì ngược lại, bạn phải gọi được luồng xử trí cùng copy code những layer ý muốn giữ gìn vào model mới. Hình bên trên là code của resnet50 vào torchvision. quý khách hàng hoàn toàn có thể tìm hiểu thêm link: torchvision-resnet50. bởi vậy lúc sản xuất Unet nhỏng phong cách xây dựng vẫn mô tả trên, ta bắt buộc đảm bảo an toàn đoạn code từ Conv1 -> Layer4 không xẩy ra thay đổi. Hãy gọi phần tiếp theo để nắm rõ hơn.

Xem thêm: Game Aaa Là Gì ? Sức Ảnh Hưởng Của Game Aaa Đến Ngành Công Nghiệp Game

3. Code

Tất cả code của chính bản thân mình được đóng gói vào file notebook Salicon_main.ipynb. quý khách có thể cài đặt về và run code theo links github: github/trungthanhnguyen0502 . Trong nội dung bài viết mình sẽ chỉ giới thiệu phần nhiều đoạn code thiết yếu.

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ó vật dụng từ dimension khác cùng với Keras/TF/numpy. Đôi khi cùng với numpy xuất xắc keras, hình ảnh bao gồm dimension theo đồ vật tự (batchform size,h,w,chanel)(batchkích thước, h, w, chanel)(batchkích thước,h,w,chanel). Thứ từ bỏ trong Pytorch ngược trở lại là (batchkích thước,chanel,h,w)(batchkích thước, chanel, h, w)(batchsize,chanel,h,w). Mình sẽ xây dựng dựng 2 hàm toTensor và toNumpy nhằm chuyển đổi qua lại thân hai 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 2 function trả về module Convolution với 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 xã = < Tconv, nn.BatchNorm2d(n_output), nn.LeakyReLU(inplace=True), > return nn.Sequential(*block) def Conv(n_input, 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) bloông xã = < conv, nn.BatchNorm2d(n_output), nn.LeakyReLU(0.2, inplace=True), nn.Dropout(dropout) > return nn.Sequential(*block)

3.2.2 Unet model

Init function: ta đang copy các layer nên giữ từ resnet50 vào unet. Sau kia khởi chế tạo các Conv / Deconv layer cùng những layer cần thiết.

Forward function: đề xuất đảm bảo luồng cách xử lý của resnet50 được giữ nguyên tương tự code cội (trừ Fully-connected layer). Sau đó ta ghnghiền nối các layer lại theo phong cách xây dựng Unet đã diễn đạt vào phần 2.

Tạo model: bắt buộc load resnet50 cùng truyền vào Unet. Đừng quên Freeze những layer của resnet50 vào Unet.

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 make skip connection self.layer1 = resnet.layer1 self.layer2 = resnet.layer2 self.layer3 = resnet.layer3 self.layer4 = resnet.layer4 # convolution layer, use khổng lồ 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)model = 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 Datamix và Dataloader

Dataphối trả dìm 1 menu những image_path và mask_dir, trả về image với mask tương ứ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("/")<-1>.split(".")<0> 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<"image"> mask = sample<"mask"> # to 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_transsize = A.Compose(< A.Resize(width=256,height=256, p=1), A.RandomSizedCrop(<240,256>, 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)<:,:,0>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 xích toán dễ dàng với để cho dễ nắm bắt, mình sẽ train Theo phong cách dễ dàng nhất, không validate vào qúa trình train mà chỉ lưu giữ Mã Sản Phẩm sau một số ít epoch độc nhất định

train_params = optimizer = torch.optlặng.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_transkhung = A.Compose(< A.Resize(width=256,height=256, p=1), A.HorizontalFlip(p=0.5),>)Mã Sản Phẩm.eval()val_dataphối = MaskDataset(img_fns, mask_dir, val_transform)val_loader = DataLoader(val_datamix, 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 trái thu được:

*

Đây là bài xích tân oán đơn giản dễ dàng đề xuất bản thân chú trọng vào quy trình và phương thức fine tuning trong pytorch hơn là đi sâu vào giải quyết bài bác toán. Cảm ơn các bạn đang đọc

4. Reference

Dataset: salinhỏ.net

Code bài viết: https://github.com/trungthanhnguyen0502/-bigbiglands.com-Visual-Saliency-prediction

Resnet50 torchvision code: torchvision-resnet

Bài viết cùng chủ đề Visual saliency: Visual Saliency Prediction with Contextual Encoder-Decoder Network!

Theo dõi những nội dung bài viết chuyên sâu về AI/Deep learning tại: Vietnam AI Link Sharing Community

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 *