昇思25天學習打卡營第8天|ResNet50遷移學習

一、遷移學習定義

遷移學習(Transfer Learning):在一個任務上訓練得到的模型包含的知識可以部分或全部地轉移到另一個任務上。允許模型將從一個任務中學到的知識應用到另一個相關的任務中。適用于數據稀缺的情況,可減少對大量標記數據的需求。

遷移學習是一種機器學習方法,具體是指將已經在某一領域(或任務)學習到的知識或模型,應用到另一個不同但相關的領域(或任務)中,以提高在該新任務上的學習效率和效果。這種知識或模型的遷移可以包括網絡參數、特征表示、數據間的關系等多種形式的知識。

遷移學習通常可以分為以下幾種類型:

  1. 基于模型的遷移學習:直接使用源任務的預訓練模型作為目標任務的起點,進行微調或重新訓練。
  2. 基于特征的遷移學習:從源任務中提取特征表示,然后在這些特征上訓練目標任務的模型。
  3. 基于關系的遷移學習:從源任務中學習數據間的關系,然后將這種關系應用到目標任務中。

二、遷移學習實現流程

遷移學習的實現流程通常包括以下幾個步驟:

  1. 選擇源任務:選擇一個具有豐富數據的相關預測建模問題作為源任務。
  2. 開發源模型:為源任務開發一個精巧的模型,并確保其性能優于普通模型。
  3. 重用模型:將源任務的模型作為目標任務的學習起點(固定特征進行訓練),這可能涉及全部或部分使用源模型。
  4. 調整模型:在目標數據集上對模型進行微調,以使其適應目標任務。

三、Resnet50遷移學習實踐:狗、狼分類

3.1下載數據集

狼狗數據集提取自ImageNet分類數據集

from download import downloaddataset_url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/intermediate/Canidae_data.zip"download(dataset_url, "./datasets-Canidae", kind="zip", replace=True)

輸出數據集目錄結構:
在這里插入圖片描述
使用mindspore.dataset.ImageFolderDataset接口來加載數據集,并進行相關圖像增強操作

import mindspore as ms
import mindspore.dataset as ds
import mindspore.dataset.vision as vision# 數據集目錄路徑
data_path_train = "./datasets-Canidae/data/Canidae/train/"
data_path_val = "./datasets-Canidae/data/Canidae/val/"# 創建訓練數據集def create_dataset_canidae(dataset_path, usage):"""數據加載"""data_set = ds.ImageFolderDataset(dataset_path,num_parallel_workers=workers,shuffle=True,)# 數據增強操作mean = [0.485 * 255, 0.456 * 255, 0.406 * 255]std = [0.229 * 255, 0.224 * 255, 0.225 * 255]scale = 32if usage == "train":# Define map operations for training datasettrans = [vision.RandomCropDecodeResize(size=image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)),vision.RandomHorizontalFlip(prob=0.5),vision.Normalize(mean=mean, std=std),vision.HWC2CHW()]else:# Define map operations for inference datasettrans = [vision.Decode(),vision.Resize(image_size + scale),vision.CenterCrop(image_size),vision.Normalize(mean=mean, std=std),vision.HWC2CHW()]# 數據映射操作data_set = data_set.map(operations=trans,input_columns='image',num_parallel_workers=workers)# 批量操作data_set = data_set.batch(batch_size)return data_setdataset_train = create_dataset_canidae(data_path_train, "train")
step_size_train = dataset_train.get_dataset_size()dataset_val = create_dataset_canidae(data_path_val, "val")
step_size_val = dataset_val.get_dataset_size()# 數據集可視化
data = next(dataset_train.create_dict_iterator())
images = data["image"]
labels = data["label"]print("Tensor of image", images.shape)
print("Labels:", labels)
import matplotlib.pyplot as plt
import numpy as np
# class_name對應label,按文件夾字符串從小到大的順序標記label
class_name = {0: "dogs", 1: "wolves"}plt.figure(figsize=(5, 5))
for i in range(4):# 獲取圖像及其對應的labeldata_image = images[i].asnumpy()data_label = labels[i]# 處理圖像供展示使用data_image = np.transpose(data_image, (1, 2, 0))mean = np.array([0.485, 0.456, 0.406])std = np.array([0.229, 0.224, 0.225])data_image = std * data_image + meandata_image = np.clip(data_image, 0, 1)# 顯示圖像plt.subplot(2, 2, i+1)plt.imshow(data_image)plt.title(class_name[int(labels[i].asnumpy())])plt.axis("off")plt.show()

在這里插入圖片描述

3.2 構建神經網絡模型

使用ResNet50模型進行訓練。搭建好模型框架后,通過將pretrained參數設置為True來下載ResNet50的預訓練模型并將權重參數加載到網絡中。
下載ResNet50的預訓練模型

1.構建模型

from typing import Type, Union, List, Optional
from mindspore import nn, train
from mindspore.common.initializer import Normalweight_init = Normal(mean=0, sigma=0.02)
gamma_init = Normal(mean=1, sigma=0.02)class ResidualBlockBase(nn.Cell):expansion: int = 1  # 最后一個卷積核數量與第一個卷積核數量相等def __init__(self, in_channel: int, out_channel: int,stride: int = 1, norm: Optional[nn.Cell] = None,down_sample: Optional[nn.Cell] = None) -> None:super(ResidualBlockBase, self).__init__()if not norm:self.norm = nn.BatchNorm2d(out_channel)else:self.norm = normself.conv1 = nn.Conv2d(in_channel, out_channel,kernel_size=3, stride=stride,weight_init=weight_init)self.conv2 = nn.Conv2d(in_channel, out_channel,kernel_size=3, weight_init=weight_init)self.relu = nn.ReLU()self.down_sample = down_sampledef construct(self, x):"""ResidualBlockBase construct."""identity = x  # shortcuts分支out = self.conv1(x)  # 主分支第一層:3*3卷積層out = self.norm(out)out = self.relu(out)out = self.conv2(out)  # 主分支第二層:3*3卷積層out = self.norm(out)if self.down_sample is not None:identity = self.down_sample(x)out += identity  # 輸出為主分支與shortcuts之和out = self.relu(out)return out

殘差模塊:

class ResidualBlock(nn.Cell):expansion = 4  # 最后一個卷積核的數量是第一個卷積核數量的4倍def __init__(self, in_channel: int, out_channel: int,stride: int = 1, down_sample: Optional[nn.Cell] = None) -> None:super(ResidualBlock, self).__init__()self.conv1 = nn.Conv2d(in_channel, out_channel,kernel_size=1, weight_init=weight_init)self.norm1 = nn.BatchNorm2d(out_channel)self.conv2 = nn.Conv2d(out_channel, out_channel,kernel_size=3, stride=stride,weight_init=weight_init)self.norm2 = nn.BatchNorm2d(out_channel)self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion,kernel_size=1, weight_init=weight_init)self.norm3 = nn.BatchNorm2d(out_channel * self.expansion)self.relu = nn.ReLU()self.down_sample = down_sampledef construct(self, x):identity = x  # shortscuts分支out = self.conv1(x)  # 主分支第一層:1*1卷積層out = self.norm1(out)out = self.relu(out)out = self.conv2(out)  # 主分支第二層:3*3卷積層out = self.norm2(out)out = self.relu(out)out = self.conv3(out)  # 主分支第三層:1*1卷積層out = self.norm3(out)if self.down_sample is not None:identity = self.down_sample(x)out += identity  # 輸出為主分支與shortcuts之和out = self.relu(out)return out

網絡層

def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],channel: int, block_nums: int, stride: int = 1):down_sample = None  # shortcuts分支if stride != 1 or last_out_channel != channel * block.expansion:down_sample = nn.SequentialCell([nn.Conv2d(last_out_channel, channel * block.expansion,kernel_size=1, stride=stride, weight_init=weight_init),nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)])layers = []layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))in_channel = channel * block.expansion# 堆疊殘差網絡for _ in range(1, block_nums):layers.append(block(in_channel, channel))return nn.SequentialCell(layers)

組合

from mindspore import load_checkpoint, load_param_into_netclass ResNet(nn.Cell):def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],layer_nums: List[int], num_classes: int, input_channel: int) -> None:super(ResNet, self).__init__()self.relu = nn.ReLU()# 第一個卷積層,輸入channel為3(彩色圖像),輸出channel為64self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)self.norm = nn.BatchNorm2d(64)# 最大池化層,縮小圖片的尺寸self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')# 各個殘差網絡結構塊定義,self.layer1 = make_layer(64, block, 64, layer_nums[0])self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)# 平均池化層self.avg_pool = nn.AvgPool2d()# flattern層self.flatten = nn.Flatten()# 全連接層self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)def construct(self, x):x = self.conv1(x)x = self.norm(x)x = self.relu(x)x = self.max_pool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)x = self.avg_pool(x)x = self.flatten(x)x = self.fc(x)return xdef _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],layers: List[int], num_classes: int, pretrained: bool, pretrianed_ckpt: str,input_channel: int):model = ResNet(block, layers, num_classes, input_channel)if pretrained:# 加載預訓練模型download(url=model_url, path=pretrianed_ckpt, replace=True)param_dict = load_checkpoint(pretrianed_ckpt)load_param_into_net(model, param_dict)return modeldef resnet50(num_classes: int = 1000, pretrained: bool = False):"ResNet50模型"resnet50_url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt"resnet50_ckpt = "./LoadPretrainedModel/resnet50_224_new.ckpt"return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,pretrained, resnet50_ckpt, 2048)

3.3 固定特征進行訓練

使用固定特征進行訓練的時候,需要凍結除最后一層之外的所有網絡層。通過設置requires_grad == False凍結參數,以便不在反向傳播中計算梯度。

import mindspore as ms
import matplotlib.pyplot as plt
import os
import timenet_work = resnet50(pretrained=True)# 全連接層輸入層的大小
in_channels = net_work.fc.in_channels
# 輸出通道數大小為狼狗分類數2
head = nn.Dense(in_channels, 2)
# 重置全連接層
net_work.fc = head# 平均池化層kernel size為7
avg_pool = nn.AvgPool2d(kernel_size=7)
# 重置平均池化層
net_work.avg_pool = avg_pool# 凍結除最后一層外的所有參數
for param in net_work.get_parameters():if param.name not in ["fc.weight", "fc.bias"]:param.requires_grad = False# 定義優化器和損失函數
opt = nn.Momentum(params=net_work.trainable_params(), learning_rate=lr, momentum=0.5)
loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')def forward_fn(inputs, targets):logits = net_work(inputs)loss = loss_fn(logits, targets)return lossgrad_fn = ms.value_and_grad(forward_fn, None, opt.parameters)def train_step(inputs, targets):loss, grads = grad_fn(inputs, targets)opt(grads)return loss# 實例化模型
model1 = train.Model(net_work, loss_fn, opt, metrics={"Accuracy": train.Accuracy()})

在這里插入圖片描述
訓練和評估

import mindspore as ms
import matplotlib.pyplot as plt
import os
import time
dataset_train = create_dataset_canidae(data_path_train, "train")
step_size_train = dataset_train.get_dataset_size()dataset_val = create_dataset_canidae(data_path_val, "val")
step_size_val = dataset_val.get_dataset_size()num_epochs = 5# 創建迭代器
data_loader_train = dataset_train.create_tuple_iterator(num_epochs=num_epochs)
data_loader_val = dataset_val.create_tuple_iterator(num_epochs=num_epochs)
best_ckpt_dir = "./BestCheckpoint"

可視化模型預測
使用固定特征得到的best.ckpt文件對對驗證集的狼和狗圖像數據進行預測。若預測字體為藍色即為預測正確,若預測字體為紅色則預測錯誤。

import mindspore as ms
import matplotlib.pyplot as plt
import os
import time
# 開始循環訓練
print("Start Training Loop ...")best_acc = 0for epoch in range(num_epochs):losses = []net_work.set_train()epoch_start = time.time()# 為每輪訓練讀入數據for i, (images, labels) in enumerate(data_loader_train):labels = labels.astype(ms.int32)loss = train_step(images, labels)losses.append(loss)# 每個epoch結束后,驗證準確率acc = model1.eval(dataset_val)['Accuracy']epoch_end = time.time()epoch_seconds = (epoch_end - epoch_start) * 1000step_seconds = epoch_seconds/step_size_trainprint("-" * 20)print("Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]" % (epoch+1, num_epochs, sum(losses)/len(losses), acc))print("epoch time: %5.3f ms, per step time: %5.3f ms" % (epoch_seconds, step_seconds))if acc > best_acc:best_acc = accif not os.path.exists(best_ckpt_dir):os.mkdir(best_ckpt_dir)ms.save_checkpoint(net_work, best_ckpt_path)print("=" * 80)
print(f"End of validation the best Accuracy is: {best_acc: 5.3f}, "f"save the best ckpt file in {best_ckpt_path}", flush=True)
import matplotlib.pyplot as plt
import mindspore as msdef visualize_model(best_ckpt_path, val_ds):net = resnet50()# 全連接層輸入層的大小in_channels = net.fc.in_channels# 輸出通道數大小為狼狗分類數2head = nn.Dense(in_channels, 2)# 重置全連接層net.fc = head# 平均池化層kernel size為7avg_pool = nn.AvgPool2d(kernel_size=7)# 重置平均池化層net.avg_pool = avg_pool# 加載模型參數param_dict = ms.load_checkpoint(best_ckpt_path)ms.load_param_into_net(net, param_dict)model = train.Model(net)# 加載驗證集的數據進行驗證data = next(val_ds.create_dict_iterator())images = data["image"].asnumpy()labels = data["label"].asnumpy()class_name = {0: "dogs", 1: "wolves"}# 預測圖像類別output = model.predict(ms.Tensor(data['image']))pred = np.argmax(output.asnumpy(), axis=1)# 顯示圖像及圖像的預測值plt.figure(figsize=(5, 5))for i in range(4):plt.subplot(2, 2, i + 1)# 若預測正確,顯示為藍色;若預測錯誤,顯示為紅色color = 'blue' if pred[i] == labels[i] else 'red'plt.title('predict:{}'.format(class_name[pred[i]]), color=color)picture_show = np.transpose(images[i], (1, 2, 0))mean = np.array([0.485, 0.456, 0.406])std = np.array([0.229, 0.224, 0.225])picture_show = std * picture_show + meanpicture_show = np.clip(picture_show, 0, 1)plt.imshow(picture_show)plt.axis('off')plt.show()visualize_model(best_ckpt_path, dataset_val)

在這里插入圖片描述


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40359.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40359.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40359.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

掌握Linux網絡:深入理解TC —— 你的流量控制利器

目錄 簡單概述: qdisc(隊列): 舉例: Bash 整形隊列算法: FIFO (First-In-First-Out) PFIFO (Priority FIFO) SFQ (Stochastic Fair Queuing) RED (Random Early Detection) HTB (Hierarchical Token Bucket) TBF…

谷粒商城筆記-04-項目微服務架構圖簡介

文章目錄 一,網絡二,網關1,網關選型2,認證鑒權3,動態路由4,限流5,負載均衡6,熔斷降級 三,微服務四,存儲層五,服務治理六,日志系統七&a…

前端面試題3-淺談http協議及常見的面試題

1、淺談http協議 HTTP(Hypertext Transfer Protocol)超文本傳輸協議,是互聯網上應用最為廣泛的一種網絡協議,所有的WWW文件都必須遵守這個標準。它是基于TCP/IP通信協議來傳遞數據(HTML文件、圖片文件、查詢結果等&am…

在Apache HTTP服務器上配置 TLS加密

安裝mod_ssl軟件包 [rootlocalhost conf.d]# dnf install mod_ssl -y此時查看監聽端口多了一個443端口 自己構造證書 [rootlocalhost conf.d]# cd /etc/pki/tls/certs/ [rootlocalhost certs]# openssl genrsa > jiami.key [rootlocalhost certs]# openssl req -utf8 -n…

OLED示波器的實現

OLED示波器是一種使用有機發光二極管(OLED)顯示屏來顯示波形的儀器。它可以實時顯示電壓、電流、頻率等信號的波形。 OLED顯示屏具有高對比度、高亮度、廣視角和快速響應時間等優點,使得OLED示波器在波形顯示方面具有更好的表現。與傳統的液…

鴻蒙開發設備管理:【@ohos.usb (USB管理)】

USB管理 本模塊主要提供管理USB設備的相關功能,包括查詢USB設備列表、批量數據傳輸、控制命令傳輸、權限控制等。 說明: 本模塊首批接口從API version 8開始支持。后續版本的新增接口,采用上角標單獨標記接口的起始版本。 導入模塊 import …

【JavaScript腳本宇宙】優化你的Web色彩:精選JavaScript顏色工具對比

萬能色彩助手:詳解最受歡迎的JavaScript顏色庫 前言 在現代Web開發中,顏色處理和轉換是一個不可忽視的環節。無論是網站設計、數據可視化還是用戶界面開發,都離不開對顏色的精確控制和轉換。為了滿足這一需求,眾多JavaScript庫應…

Toocaa Studio已開發的功能

2024年07月01日 Toocaa Studio 一個激光切割雕刻機的上位機, 未來會對標Xtool的xTool Creative Space和LightBurn,同時它也是一款圖形編輯器,矢量圖形編輯器。 工具類 鼠標畫矩形或正方形 鼠標畫橢圓或畫圓 鼠標畫直線或軌跡路徑 往畫布中…

你的機器人購物新體驗——安全、高效、無憂

如果你跟我一樣,對找到那些“恰到好處”的商品充滿渴望,那么,讓我來告訴你為什么BFT會成為你的下一個購物“心頭好”。 BFT的優勢 高效安全的支付體系:BFT交易系統保障了交易的安全性和透明性,讓你的每一筆消費都安全…

Build a Large Language Model (From Scratch)附錄B(gpt-4o翻譯版)

來源:https://github.com/rasbt/LLMs-from-scratch?tabreadme-ov-file https://www.manning.com/books/build-a-large-language-model-from-scratch

《More Effective C++》《雜項討論——34、如何在同一個程序中結合C++和C》

文章目錄 1、Terms34:如何在同一個程序中結合C和C1.1 名稱重整1.2 statics的初始化1.3 動態內存的分配1.4 數據結構的兼容性 2、總結3、參考 1、Terms34:如何在同一個程序中結合C和C 在大型項目中一般都用C進行開發,但是不可避免會用一些C語言進行底層的調用。在確…

【寵粉贈書】UML 2.5基礎、建模與設計實踐

為了回饋粉絲們的厚愛,今天小智給大家送上一套系統建模學習的必備書籍——《UML 2.5基礎、建模與設計實踐》。下面我會詳細給大家介紹這本書,文末留有領取方式。 圖書介紹 《UML 2.5基礎、建模與設計實踐》以實戰為主旨,結合draw.io免費軟件…

匿名內部類

下面代碼中,Person24 是一個抽象類,這意味著它不能被直接實例化,只能通過繼承它的子類來實現其抽象方法。代碼片段中展示了如何使用匿名內部類來實現一個抽象類的實例。 package chapter04;public class Java24_Object_匿名內部類 {public s…

verilog行為建模(三):塊語句

目錄 1.塊語句2.延遲賦值語句 微信公眾號獲取更多FPGA相關源碼: 1.塊語句 塊語句用來將多個語句組織在一起,使得他們在語法上如同一個語句。 塊語句分為兩類: 順序塊:語句置于關鍵字begin和end之間,塊中的語句以順…

鴻蒙‘ohpm‘ 不是內部或外部命令,也不是可運行的程序-解決方案

🔥 博客主頁: 小韓本韓! ?? 感謝大家點贊👍收藏?評論?? 在鴻蒙的DevEco Studio的終端下輸入 onpm -v 或者 你需要下載第三方ohpm包的時候提示‘ohpm‘ 不是內部或外部命令,也不是可運行的程序- 主要是因為我們…

學習測試1

計算機基礎 1、計算機范式:馮諾依曼機 2、存儲單元 bit、byte、KB、MB、GB3、網絡 ip、域名、ping 域名、 ipconfig測試工作的流程 ------------------------------------------------------------------------------------------- 一 編寫測試大綱 羅列測試…

C++STL函數對象的應用

STL函數對象 文章目錄 STL函數對象1.基本概念2.使用方法1. 簡單函數對象示例2. 函數對象作為算法參數3. Lambda表達式作為函數對象 2.一元謂詞和二元謂詞1.一元謂詞2.二元謂詞3.總結 3.算術仿函數1.使用示例2.Lambda表達式的替代 4.關系仿函數5.邏輯仿函數 C中的函數對象&#…

文化創新與社交媒體:探索Facebook的足跡

在過去的十多年里,Facebook從一個簡單的校園社交網絡發展成為全球最大的社交媒體平臺之一。它不僅改變了人們的溝通方式,更在許多方面推動了文化的創新和變革。本文將深入探索Facebook如何通過其平臺的演進和功能創新,成為文化創新的重要推動…

Ubuntu / Debian安裝FTP服務

本章教程,記錄在Ubuntu中安裝FTP服務的具體步驟。FTP默認端口:21 1、安裝 pure-ftpd sudo apt-get install pure-ftpd2、修改默認配置 # 與 centos 不同,這里需要在 /etc/pure-ftpd/conf 文件夾下執行下列命令,增加對應配置文件: # 創建 /etc/pure-ftpd/conf/PureDB 文件…

【數據結構】(6.2)堆的應用——Top-K問題(C語言)

系列文章目錄 文章目錄 系列文章目錄問題引入一、TopK 問題 是什么?二、TopK 問題解決思路2.1 TopK 思路2.2 隨機產生數字2.2 完整代碼2.3 驗證結果 問題引入 TopK 問題 (在一堆數據里面找到前 K 個最大 / 最小的數)。 一、TopK 問題 是什么? 生活中也…