TRANSFER LEARNING LÀ GÌ

  -  
1. Introduction

1.1 Fine-tuning là gì ?

Chắc hẳn hồ hết ai thao tác với các model vào deep learning hồ hết sẽ nghe/thân quen cùng với có mang Transfer learningFine tuning. Khái niệm tổng quát: Transfer learning là tận dụng tối đa tri thức học được từ 1 vấn đề nhằm áp dụng vào 1 vấn đề gồm liên quan khác. Một ví dụ đối chọi giản: cố gắng bởi vì train 1 Model bắt đầu hoàn toàn cho bài xích toán phân nhiều loại chó/mèo, người ta rất có thể tận dụng 1 Mã Sản Phẩm đã có được train trên ImageNet dataphối cùng với hằng triệu hình họa. 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, quy trình train này diễn ra nhanh khô rộng, hiệu quả thường giỏi hơn. Có không hề ít thứ hạng Transfer learning, những chúng ta có thể tham khảo vào bài xích này: Tổng phù hợp Transfer learning. Trong bài xích này, mình đã viết về 1 dạng transfer learning phổ biến: Fine-tuning.

Bạn đang xem: Transfer learning là gì

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

*

1.2 Tại sao pytorch nắm vị Keras ?

Chủ đề nội dung bài viết bây giờ, bản thân đã giải đáp fine-tuning Resnet50 - 1 pre-trained mã sản phẩm được hỗ trợ sẵn vào torchvision của pytorch. Tại sao là pytorch nhưng mà không hẳn Keras ? Lý bởi vị vấn đề fine-tuning Mã Sản Phẩm vào keras khôn cùng dễ dàng. Dưới đấy là 1 đoạn code minc hoạ mang lại bài toán xây đắp 1 Unet dựa vào Resnet trong 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 rất có thể thấy, fine-tuning Mã Sản Phẩm trong Keras thực sự rất đơn giản và dễ dàng, dễ có tác dụng, dễ nắm bắt. Việc add thêm các nhánh rất giản đơn vày cú pháp đơn giản dễ dàng. Trong pytorch thì ngược trở lại, xây dựng 1 model Unet tương tự sẽ tương đối vất vả cùng phức tạp. Người bắt đầu học vẫn chạm chán khó khăn bởi vì bên trên mạng không nhiều những trả lời đến việc này. Vậy bắt buộc bài xích này bản thân đang trả lời cụ thể phương pháp 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 triệu tập nhìn vào 1 vài cửa hàng thiết yếu. Ảnh trên đây là 1 minc hoạ, màu sắc quà được áp dụng để biểu lộ mức độ thú vị. Saliency prediction là bài tân oán tế bào bỏng sự tập trung của mắt bạn lúc quan lại gần cạnh 1 tấm hình. Cụ thể, bài xích toán đòi hỏi kiến tạo 1 model, mã sản phẩm này nhận hình ảnh nguồn vào, trả về 1 mask tế bào rộp cường độ thú vị. bởi vậy, Mã Sản Phẩm nhấn vào 1 input image với trả về 1 mask bao gồm form size tương đương.

Để rõ hơn về bài xích tân oán này, bạn cũng có thể hiểu bài: Visual Saliency Prediction with Contextual Encoder-Decoder Network.Dataphối thông dụng nhất: SALICON DATASET

2.2 Unet

Note: quý khách hàng rất có thể làm lơ phần này giả dụ đã biết về Unet

Đây là 1 trong những bài tân oán Image-to-Image. Để giải quyết bài tân oán này, mình sẽ xây dựng dựng 1 Mã Sản Phẩm theo bản vẽ xây dựng Unet. Unet là 1 phong cách xây dựng được áp dụng nhiều vào bài toán Image-to-image như: semantic segmentation, tự động color, super resolution ... Kiến trúc của Unet có điểm tương tự với bản vẽ xây dựng Encoder-Decoder đối xứng, đạt thêm các skip connection từ bỏ Encode sang Decode tương xứng. Về cơ bạn dạng, những layer càng tốt càng trích xuất thông báo tại mức trìu tượng cao, điều ấy đồng nghĩa tương quan cùng với việc các ban bố nút trìu tượng thấp như con đường đường nét, Màu sắc, độ phân giải... sẽ ảnh hưởng mất đuối đi vào quy trình Viral. 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ởi các Convolution. trái lại, ở đoạn decode, feature-map được upscale vì những Upsampling layer, vào bài bác này mình áp dụng các Convolution Transpose.

*

2.3 Resnet

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

Theo cách nhìn cá nhân, pytorch rất đơn giản code, dễ hiểu hơn không ít so với Tensorflow 1.x hoặc ngang ngửa Keras. Tuy nhiên, Việc fine-tuning model vào pytorch lại khó khăn rộng không hề ít so với Keras. Trong Keras, ta ko phải thừa quan tâm tới kiến trúc, luồng cách xử trí của Model, chỉ cần kéo ra những output tại một số layer khăng khăng làm skip-connection, ghxay nối với tạo ra mã sản phẩm mới.

*

Trong pytorch thì ngược lại, bạn cần đọc được luồng xử trí với copy code gần như layer ao ước lưu giữ trong mã sản phẩm new. Hình bên trên là code của resnet50 vào torchvision. quý khách có thể xem thêm link: torchvision-resnet50. Như vậy lúc gây ra Unet như bản vẽ xây dựng sẽ diễn tả trên, ta nên đảm bảo an toàn đoạn code từ Conv1 -> Layer4 không biến thành biến đổi. Hãy gọi phần tiếp theo nhằm nắm rõ rộng.

Xem thêm: 10 Khách Sạn 3 Sao Tốt Nhất Tại Mũi Né, Khách Sạn 3 Sao Phường Mũi Né

3. Code

Tất cả code của chính mình được đóng gói vào tệp tin notebook Salicon_main.ipynb. Bạn có thể sở hữu về với run code theo liên kết github: github/trungthanhnguyen0502 . Trong nội dung bài viết bản thân đang chỉ chỉ dẫn hồ hết đoạn code chính.

Import các 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ả trang bị từ dimension không giống với Keras/TF/numpy. thường thì cùng với numpy tuyệt keras, hình ảnh gồm dimension theo sản phẩm công nghệ tự (batchkích cỡ,h,w,chanel)(batchkích cỡ, h, w, chanel)(batchform size,h,w,chanel). Thứ từ bỏ trong Pytorch ngược chở lại là (batchform size,chanel,h,w)(batchsize, chanel, h, w)(batchform size,chanel,h,w). Mình sẽ xây dựng 2 hàm toTensor cùng toNumpy nhằm thay đổi 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 & Deconv

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

def Deconv(n_input đầu vào, n_output, k_size=4, stride=2, padding=1): Tconv = nn.ConvTranspose2d( n_input, n_output, kernel_size=k_kích cỡ, stride=stride, padding=padding, bias=False) blochồng = < 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_size, stride=stride, padding=padding, bias=False) block = < 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 đề nghị giữ lại tự resnet50 vào unet. Sau kia khởi tạo thành những Conv / Deconv layer cùng những layer cần thiết.

Forward function: nên đảm bảo an toàn luồng xử trí của resnet50 được giữ nguyên tương tự code nơi bắt đầu (trừ Fully-connected layer). Sau kia ta ghép nối các layer lại theo phong cách xây dựng Unet sẽ biểu đạt vào phần 2.

Tạo model: đề xuất load resnet50 và truyền vào Unet. Đừng quên Freeze những layer của resnet50 vào Unet.

Xem thêm: Vé Tàu Sài Gòn Nha Trang Giá Rẻ Trực Tuyến, Vé Tàu Sài Gòn Nha Trang

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 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)model.to(device)## Freeze resnet50"s layers in Unetfor i, child in enumerate(Model.children()): if i 7: for param in child.parameters(): param.requires_grad = False

3.3 Dataphối and Dataloader

Dataset trả thừa nhận 1 các mục các 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 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(< 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_datamix, 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 tân oán dễ dàng và đơn giản và làm cho dễ nắm bắt, mình đã train Theo phong cách đơn giản và dễ dàng độc nhất, không validate trong qúa trình train cơ mà chỉ lưu mã sản phẩm sau một số ít epoch tốt nhất định

train_params = optimizer = torch.optyê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_transsize = A.Compose(< A.Resize(width=256,height=256, p=1), A.HorizontalFlip(p=0.5),>)model.eval()val_dataset = 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 quả thu được:

*

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

4. Reference

Dataset: salibé.net

Code bài viết: https://github.com/trungthanhnguyen0502/-tanhailonghotel.com.vn-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 sâu sát về AI/Deep learning tại: Vietphái nam AI Link Sharing Community