Fine tuning là gì

1. Introduction

1.1 Fine-tuning là gì ?

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

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

Hiểu dễ dàng, fine-tuning là các bạn đem 1 pre-trained mã sản phẩm, tận dụng một phần hoặc toàn cục những layer, thêm/sửa/xoá 1 vài 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 các layer này đang không xẩy ra biến đổi giá trị vào quá trình train. Lý bởi vì vày các layer này đã có tác dụng trích xuất lên tiếng nút trìu tượng thấp , tài năng này được học từ quy trình training trước đó. Ta freeze lại nhằm tận dụng tối đa được tài năng này cùng giúp vấn đề train ra mắt nhanh hao hơn (Model chỉ đề xuất update weight sinh hoạt những layer cao). Có tương đối nhiều những Object detect Mã Sản Phẩm được desgin dựa trên những Classifier Mã Sản Phẩm. VD Retimãng cầu mã sản phẩm (Object detect) được thành lập cùng với backbone là Resnet.

*

1.2 Tại sao pytorch nuốm vì chưng Keras ?

Chủ đề nội dung bài viết từ bây giờ, bản thân sẽ chỉ dẫn fine-tuning Resnet50 - 1 pre-trained mã sản phẩm được hỗ trợ sẵn trong torchvision của pytorch. Tại sao là pytorch nhưng mà chưa hẳn Keras ? Lý vì chưng vị câu hỏi fine-tuning model vào keras khôn cùng đơn giản. Dưới đó là 1 đoạn code minh hoạ mang lại Việc kiến tạo 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 hàng rất có thể thấy, fine-tuning Model vào Keras đích thực rất dễ dàng và đơn giản, dễ làm, dễ dàng nắm bắt. Việc add thêm các nhánh rất dễ bởi vì cú pháp đơn giản dễ dàng. Trong pytorch thì ngược lại, xuất bản 1 Mã Sản Phẩm Unet tương tự như sẽ rất vất vả và tinh vi. Người bắt đầu học tập đã gặp trở ngại bởi trên mạng rất hiếm các hướng dẫn cho câu hỏi này. Vậy đề xuất bài bác này bản thân đang gợi ý cụ thể bí quyết fine-tune trong pytorch nhằm vận dụng vào bài tân oán Visual Saliency prediction

2. Visual Saliency prediction

2.1 What is Visual Saliency ?

*

khi quan sát vào 1 tấm hình, đôi mắt thường sẽ có xu hướng tập trung chú ý vào 1 vài ba công ty bao gồm. Ảnh bên trên đây là 1 minh hoạ, color quà được sử dụng nhằm biểu thị mức độ đắm đuối. Saliency prediction là bài toán thù mô rộp sự tập trung của mắt fan Lúc quan gần cạnh 1 tấm hình. Cụ thể, bài toán đòi hỏi xây dừng 1 mã sản phẩm, Mã Sản Phẩm này dìm ảnh đầu vào, trả về 1 mask tế bào bỏng mức độ gợi cảm. vì thế, mã sản phẩm dìm vào 1 input image và trả về 1 mask gồm form size tương đương.

Để rõ rộng về bài toán này, chúng ta cũng có thể hiểu bài: Visual Saliency Prediction with Contextual Encoder-Decoder Network.Dataset phổ biến nhất: SALICON DATASET

2.2 Unet

Note: quý khách hàng rất có thể làm lơ phần này trường hợp sẽ biết về Unet

Đây là 1 trong bài bác toán Image-to-Image. Để giải quyết bài bác toán thù này, bản thân sẽ xây dựng dựng 1 model theo kiến trúc Unet. Unet là một kiến trúc được áp dụng nhiều trong bài tân oán 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ương tự cùng với phong cách xây dựng Encoder-Decoder đối xứng, được thêm những skip connection tự Encode quý phái Decode khớp ứng. Về cơ bản, các layer càng cao càng trích xuất đọc tin ở tầm mức trìu tượng cao, điều ấy đồng nghĩa với vấn đề những công bố nút trìu tượng thấp nhỏng mặt đường nét, Color, độ sắc nét... sẽ ảnh hưởng mất đuối đi vào quá trình lan truyền. Người ta thêm các skip-connection vào nhằm giải quyết và xử lý vụ việc này.

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

*

2.3 Resnet

Để xử lý bài toán, mình sẽ xây dựng dựng mã sản phẩm Unet cùng với backbone là Resnet50. Quý Khách buộc phải tò mò về Resnet nếu như chưa chắc chắn về kiến trúc này. Hãy quan lại sát hình minh hoạ sau đây. Resnet50 được phân thành các kăn năn Khủng . Unet được tạo với Encoder là Resnet50. Ta sẽ kéo ra output của từng kăn năn, chế tạo ra các skip-connection kết nối từ bỏ Encoder quý phái Decoder. Decoder được xây dựng do những Convolution Transpose layer (đan xen trong số đó là những lớp Convolution nhằm mục đích mục tiêu giảm số chanel của feature bản đồ -> giảm số lượng weight mang đến model).

Theo ý kiến cá thể, pytorch rất giản đơn code, dễ dàng nắm bắt hơn tương đối 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ề rộng không ít so với Keras. Trong Keras, ta ko bắt buộc thừa quan tâm cho tới phong cách xây dựng, luồng cách xử trí của model, chỉ cần mang ra những output trên 1 số layer nhất quyết làm skip-connection, ghép nối cùng tạo thành Mã Sản Phẩm bắt đầu.

*

Trong pytorch thì trở lại, bạn phải gọi được luồng cách xử trí với copy code phần nhiều layer mong giữ gìn vào mã sản phẩm bắt đầu. Hình trên là code của resnet50 trong torchvision. Bạn có thể tham khảo link: torchvision-resnet50. do đó Lúc desgin Unet nhỏng bản vẽ xây dựng đang mô tả bên trên, ta phải đảm bảo an toàn đoạn code trường đoản cú Conv1 -> Layer4 không bị đổi khác. Hãy đọc phần tiếp theo sau nhằm nắm rõ hơn.

Xem thêm: 3 Cách Sửa Lỗi Fake Serial Number Của Idm Trên Máy Tính Đơn Giản

3. Code

Tất cả code của chính mình được đóng gói trong file notebook Salicon_main.ipynb. Quý khách hàng có thể cài về và run code theo link github: github/trungthanhnguyen0502 . Trong nội dung bài viết mình đã chỉ chỉ dẫn số đông đoạn code chủ 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, tài liệu tất cả thứ tự dimension không giống với Keras/TF/numpy. Thông thường cùng với numpy hay keras, ảnh có dimension theo vật dụng từ (batchform size,h,w,chanel)(batchsize, h, w, chanel)(batchform size,h,w,chanel). Thứ đọng từ bỏ vào Pytorch ngược trở lại là (batchform size,chanel,h,w)(batchkích cỡ, chanel, h, w)(batchform size,chanel,h,w). Mình sẽ xây dựng dựng 2 hàm toTensor với toNumpy để thay đổi tương hỗ 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 and 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 đầu vào, n_output, k_size=4, stride=2, padding=1): Tconv = nn.ConvTranspose2d( n_đầu vào, n_output, kernel_size=k_kích thước, 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 thước, stride=stride, padding=padding, bias=False) bloông chồng = < 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 vẫn copy các layer phải duy trì tự resnet50 vào unet. Sau đó khởi sinh sản các Conv / Deconv layer với các layer cần thiết.

Forward function: yêu cầu bảo đảm an toàn luồng xử trí của resnet50 được không thay đổi tương tự code cội (trừ Fully-connected layer). Sau kia ta ghnghiền nối những layer lại theo phong cách thiết kế Unet đã biểu thị vào phần 2.

Tạo model: phải load resnet50 cùng truyền vào Unet. Đừng quên Freeze các layer của resnet50 trong 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 khổng lồ 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 Datamix & Dataloader

Dataset trả nhấn 1 danh mục các image_path cùng mask_dir, trả về image và mask tương xứ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 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_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_dataphối, 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 bác toán thù đơn giản dễ dàng cùng làm cho dễ nắm bắt, mình vẫn train theo cách dễ dàng và đơn giản nhất, ko validate trong qúa trình train nhưng chỉ lưu lại mã sản phẩm sau một số ít epoch tốt nhất định

train_params = optimizer = torch.optyên ổn.Adam(train_params, lr=0.001, betas=(0.9, 0.99))epochs = 5mã sản phẩm.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_transform = 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_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 trái thu được:

*

Đây là bài bác toán dễ dàng và đơn giản bắt buộc bản thân chú trọng vào quá trình cùng phương thức fine tuning vào pytorch hơn là đi sâu vào xử lý bài xích toán thù. Cảm ơn chúng ta sẽ đọc

4. Reference

Dataset: salicon.net

Code bài xích viết: https://github.com/trungthanhnguyen0502/-theartinpixels.com-Visual-Saliency-prediction

Resnet50 torchvision code: torchvision-resnet

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

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