2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
ResNet मुख्यतया गहनपरिवर्तनजालस्य "अवक्षेपण" समस्यायाः समाधानं करोति यदा गभीरता गभीरा भवति । सामान्यतया कन्वोल्यूशनल् न्यूरल नेटवर्क् इत्यत्र जालस्य गभीरतां वर्धयित्वा प्रथमा समस्या ढालस्य अन्तर्धानं विस्फोटः च भवति । BN स्तरः प्रत्येकस्य स्तरस्य उत्पादनं सामान्यं कर्तुं शक्नोति, येन स्तरः स्तरं विपरीतरूपेण पारितस्य अनन्तरं अपि ढालः आकारे स्थिरः भवितुम् अर्हति, अपि च अतिलघुः अतिबृहत् वा न भविष्यति परन्तु लेखकेन ज्ञातं यत् बीएन योजयित्वा गभीरतां वर्धयित्वा अद्यापि अभिसरणं सुलभं नास्ति सः द्वितीयसमस्यायाः उल्लेखं कृतवान् - सटीकताक्षयस्य समस्या यदा स्तरः किञ्चित्पर्यन्तं पर्याप्तं विशालः भवति तदा सटीकता संतृप्ता भविष्यति, ततः द्रुतगत्या न्यूनतां गच्छन्ति।
सटीकतायां न्यूनतायाः समस्या जालसंरचनायाः एव समस्या नास्ति, अपितु विद्यमानप्रशिक्षणपद्धतीनां कारणेन भवति ये आदर्शाः न सन्ति वर्तमान समये व्यापकरूपेण प्रयुक्ताः अनुकूलकाः, भवेत् ते SGD, RMSProp, अथवा Adam, यदा जालगहनता बृहत्तरं भवति तदा सैद्धान्तिकरूपेण इष्टतमं अभिसरणफलं प्राप्तुं न शक्नुवन्ति
यावत् यावत् उपयुक्ता जालसंरचना अस्ति तावत् गभीरतरं जालम् अवश्यमेव अतल्लीनजालस्य अपेक्षया उत्तमं कार्यं करिष्यति । प्रमाणप्रक्रिया अपि अतीव सरलम् अस्ति : मानातु यत् A जालस्य पृष्ठतः कतिपयानि स्तराः योजिताः भवन्ति यत् नूतनं जालम् B निर्माति यदि योजिताः स्तराः केवलं A इत्यस्य निर्गमस्य उपरि तादात्म्यमानचित्रणं कुर्वन्ति अर्थात् A इत्यस्य निर्गमः योजितः भवति through the new network A. स्तरः B इत्यस्य निर्गमः भवति ततः परं परिवर्तनं न भवति, अतः जालस्य A जालस्य B च त्रुटिदराः समानाः सन्ति, येन सिद्धं भवति यत् गभीरीकरणानन्तरं जालं गभीरीकरणात् पूर्वं जालस्य अपेक्षया दुष्टतरं न भविष्यति।
चित्रवर्गीकरणं सर्वाधिकं मूलभूतं सङ्गणकदृष्टि-अनुप्रयोगं भवति तथा च पर्यवेक्षितशिक्षणस्य वर्गे अन्तर्भवति यथा, प्रतिबिम्बं (बिडालः, श्वः, विमानं, कारः इत्यादयः) दत्त्वा, प्रतिबिम्बं कस्मिन् वर्गे अन्तर्भवति इति निर्धारयन्तु अस्मिन् अध्याये CIFAR-10 आँकडासमूहस्य वर्गीकरणार्थं ResNet50 संजालस्य उपयोगस्य परिचयः भविष्यति ।
ResNet50 संजालं २०१५ तमे वर्षे Microsoft Labs इत्यस्य He Kaiming इत्यनेन प्रस्तावितं आसीत् तथा च ILSVRC2015 इमेज वर्गीकरणप्रतियोगितायां प्रथमस्थानं प्राप्तवान् । ResNet जालस्य प्रस्तावात् पूर्वं परिवर्तनशीलस्तरस्य श्रृङ्खलां स्तम्भयित्वा स्तरानाम् एकत्रीकरणेन पारम्परिकाः कन्वोल्यूशनल् न्यूरल नेटवर्क् प्राप्ताः आसन् तथापि यदा जालं निश्चितगभीरतापर्यन्तं स्तम्भितं भवति तदा अवनतिसमस्याः भविष्यन्ति अधोलिखितं चित्रं CIFAR-10 आँकडा-समूहे 56-स्तरीय-जालस्य 20-स्तरीय-जालस्य च उपयोगेन प्रशिक्षण-दोषस्य परीक्षण-दोषस्य च आलेखः अस्ति ५६-स्तरीयजालं २०-स्तरीयजालस्य अपेक्षया बृहत्तरं भवति यथा यथा जालं गभीरं भवति तथा तथा त्रुटिः अपेक्षितरूपेण न न्यूनीभवति ।
ResNet संजालः अवनतिसमस्यायाः निवारणाय अवशिष्टजालसंरचना (Residual Network) प्रस्तावयति ResNet संजालस्य उपयोगेन गहनतरं संजालसंरचनं (1000 स्तरात् अधिकं) निर्मातुं शक्यते । CIFAR-10 आँकडा समुच्चये पत्रे प्रयुक्तस्य ResNet संजालस्य प्रशिक्षणदोषः परीक्षणदोषलेखः च अधोलिखिते चित्रे दर्शितः अस्ति चित्रे बिन्दुयुक्ता रेखा प्रशिक्षणदोषं प्रतिनिधियति, ठोसरेखा च परीक्षणदोषं प्रतिनिधियति चित्रे विद्यमानदत्तांशतः द्रष्टुं शक्यते यत् ResNet संजालस्तरः यथा गभीरः भवति तथा तस्य प्रशिक्षणदोषः परीक्षणदोषः च लघुः भवति ।
CIFAR-10 आँकडा-समूहे कुलम् ६०,००० ३२*३२ रङ्ग-प्रतिमाः सन्ति, ये १० वर्गेषु विभक्ताः सन्ति, प्रत्येकस्मिन् वर्गे ६,००० चित्राणि सन्ति, तथा च आँकडा-समूहे कुलम् ५०,००० प्रशिक्षण-प्रतिमानि १०,००० मूल्याङ्कन-प्रतिमानि च सन्ति प्रथमं, निम्नलिखित उदाहरणं डाउनलोड् कर्तुं विसंपीडयितुं च डाउनलोड् अन्तरफलकस्य उपयोगं करोति सम्प्रति, केवलं CIFAR-10 सञ्चिकानां द्विचक्रीयसंस्करणं (CIFAR-10 द्विचक्रीयसंस्करणं) समर्थितम् अस्ति ।
%%capture captured_output
# 实验环境已经预装了mindspore==2.2.14,如需更换mindspore版本,可更改下面mindspore的版本号
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14
%%capture captured_output
# 实验环境已经预装了mindspore==2.2.14,如需更换mindspore版本,可更改下面mindspore的版本号
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14
# 查看当前 mindspore 版本
!pip show mindspore
# 查看当前 mindspore 版本
!pip show mindspore
from download import download
url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz"
download(url, "./datasets-cifar10-bin", kind="tar.gz", replace=True)
from download import download
url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz"
download(url, "./datasets-cifar10-bin", kind="tar.gz", replace=True)
'./दत्तांशसमूहः-cifar10-bin'.
डाउनलोड् कृतस्य दत्तांशसमूहस्य निर्देशिकासंरचना निम्नलिखितरूपेण अस्ति ।
datasets-cifar10-bin/cifar-10-batches-bin
├── batches.meta.text
├── data_batch_1.bin
├── data_batch_2.bin
├── data_batch_3.bin
├── data_batch_4.bin
├── data_batch_5.bin
├── readme.html
└── test_batch.bin
ततः, dataset लोड् कर्तुं mindspore.dataset.Cifar10Dataset अन्तरफलकस्य उपयोगं कुर्वन्तु तथा च सम्बद्धानि चित्रवर्धनक्रियाः कर्तुं शक्नुवन्ति ।
import mindspore as ms
import mindspore.dataset as ds
import mindspore.dataset.vision as vision
import mindspore.dataset.transforms as transforms
from mindspore import dtype as mstype
data_dir = "./datasets-cifar10-bin/cifar-10-batches-bin" # 数据集根目录
batch_size = 256 # 批量大小
image_size = 32 # 训练图像空间大小
workers = 4 # 并行线程个数
num_classes = 10 # 分类数量
def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):
data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir,
usage=usage,
num_parallel_workers=workers,
shuffle=True)
trans = []
if usage == "train":
trans += [
vision.RandomCrop((32, 32), (4, 4, 4, 4)),
vision.RandomHorizontalFlip(prob=0.5)
]
trans += [
vision.Resize(resize),
vision.Rescale(1.0 / 255.0, 0.0),
vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),
vision.HWC2CHW()
]
target_trans = transforms.TypeCast(mstype.int32)
# 数据映射操作
data_set = data_set.map(operations=trans,
input_columns='image',
num_parallel_workers=workers)
data_set = data_set.map(operations=target_trans,
input_columns='label',
num_parallel_workers=workers)
# 批量操作
data_set = data_set.batch(batch_size)
return data_set
# 获取处理后的训练与测试数据集
dataset_train = create_dataset_cifar10(dataset_dir=data_dir,
usage="train",
resize=image_size,
batch_size=batch_size,
workers=workers)
step_size_train = dataset_train.get_dataset_size()
dataset_val = create_dataset_cifar10(dataset_dir=data_dir,
usage="test",
resize=image_size,
batch_size=batch_size,
workers=workers)
step_size_val = dataset_val.get_dataset_size()
import mindspore as ms
import mindspore.dataset as ds
import mindspore.dataset.vision as vision
import mindspore.dataset.transforms as transforms
from mindspore import dtype as mstype
data_dir = "./datasets-cifar10-bin/cifar-10-batches-bin" # 数据集根目录
batch_size = 256 # 批量大小
image_size = 32 # 训练图像空间大小
workers = 4 # 并行线程个数
num_classes = 10 # 分类数量
def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):
data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir,
usage=usage,
num_parallel_workers=workers,
shuffle=True)
trans = []
if usage == "train":
trans += [
vision.RandomCrop((32, 32), (4, 4, 4, 4)),
vision.RandomHorizontalFlip(prob=0.5)
]
trans += [
vision.Resize(resize),
vision.Rescale(1.0 / 255.0, 0.0),
vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),
vision.HWC2CHW()
]
target_trans = transforms.TypeCast(mstype.int32)
# 数据映射操作
data_set = data_set.map(operations=trans,
input_columns='image',
num_parallel_workers=workers)
data_set = data_set.map(operations=target_trans,
input_columns='label',
num_parallel_workers=workers)
# 批量操作
data_set = data_set.batch(batch_size)
return data_set
# 获取处理后的训练与测试数据集
dataset_train = create_dataset_cifar10(dataset_dir=data_dir,
usage="train",
resize=image_size,
batch_size=batch_size,
workers=workers)
step_size_train = dataset_train.get_dataset_size()
dataset_val = create_dataset_cifar10(dataset_dir=data_dir,
usage="test",
resize=image_size,
batch_size=batch_size,
workers=workers)
step_size_val = dataset_val.get_dataset_size()
CIFAR-10 प्रशिक्षणदत्तांशसमूहस्य कल्पनां कुर्वन्तु।
import matplotlib.pyplot as plt
import numpy as np
data_iter = next(dataset_train.create_dict_iterator())
images = data_iter["image"].asnumpy()
labels = data_iter["label"].asnumpy()
print(f"Image shape: {images.shape}, Label shape: {labels.shape}")
# 训练数据集中,前六张图片所对应的标签
print(f"Labels: {labels[:6]}")
classes = []
with open(data_dir + "/batches.meta.txt", "r") as f:
for line in f:
line = line.rstrip()
if line:
classes.append(line)
# 训练数据集的前六张图片
plt.figure()
for i in range(6):
plt.subplot(2, 3, i + 1)
image_trans = np.transpose(images[i], (1, 2, 0))
mean = np.array([0.4914, 0.4822, 0.4465])
std = np.array([0.2023, 0.1994, 0.2010])
image_trans = std * image_trans + mean
image_trans = np.clip(image_trans, 0, 1)
plt.title(f"{classes[labels[i]]}")
plt.imshow(image_trans)
plt.axis("off")
plt.show()
import matplotlib.pyplot as plt
import numpy as np
data_iter = next(dataset_train.create_dict_iterator())
images = data_iter["image"].asnumpy()
labels = data_iter["label"].asnumpy()
print(f"Image shape: {images.shape}, Label shape: {labels.shape}")
# 训练数据集中,前六张图片所对应的标签
print(f"Labels: {labels[:6]}")
classes = []
with open(data_dir + "/batches.meta.txt", "r") as f:
for line in f:
line = line.rstrip()
if line:
classes.append(line)
# 训练数据集的前六张图片
plt.figure()
for i in range(6):
plt.subplot(2, 3, i + 1)
image_trans = np.transpose(images[i], (1, 2, 0))
mean = np.array([0.4914, 0.4822, 0.4465])
std = np.array([0.2023, 0.1994, 0.2010])
image_trans = std * image_trans + mean
image_trans = np.clip(image_trans, 0, 1)
plt.title(f"{classes[labels[i]]}")
plt.imshow(image_trans)
plt.axis("off")
plt.show()
चित्राकारः (२५६, ३, ३२, ३२), लेबल आकारः (२५६,)
लेबलाः [३ २ ७ ६ ० ४] ।
अवशिष्टजालसंरचना (Residual Network) ResNet संजालस्य मुख्यं आकर्षणं भवति ResNet इत्यस्य अवशिष्टजालसंरचनायाः उपयोगः प्रभावीरूपेण क्षयसमस्यां न्यूनीकर्तुं, गहनतरजालसंरचनायाः डिजाइनं प्राप्तुं, संजालस्य प्रशिक्षणसटीकतायां सुधारं कर्तुं च शक्नोति अस्मिन् खण्डे प्रथमं अवशिष्टजालसंरचनायाः निर्माणं कथं करणीयम् इति वर्णितं भवति, ततः अवशिष्टजालस्य स्तम्भनं कृत्वा ResNet50 संजालस्य निर्माणं भवति ।
अवशिष्टजालसंरचनायाः निर्माणं कुर्वन्तु
残差网络结构图如下图所示,残差网络由两个分支构成:一个主分支,一个shortcuts(图中弧线表示)。主分支通过堆叠一系列的卷积操作得到,shotcuts从输入直接到输出,主分支输出的特征矩阵 𝐹(𝑥)
加上shortcuts输出的特征矩阵 𝑥 得到 𝐹(𝑥)+𝑥,通过Relu激活函数后即为残差网络最后的输出。
अवशिष्टजालसंरचनानां मुख्यप्रकारद्वयं भवति एकः Building Block, यः उथले ResNet जालस्य कृते उपयुक्तः अस्ति, यथा ResNet18 तथा ResNet34; .
भवनखण्डसंरचना आरेखं अधोलिखिते चित्रे दर्शितम् अस्ति मुख्यशाखायाः द्विस्तरीयं परिभ्रमणजालसंरचना अस्ति ।
मुख्यशाखायाः प्रथमस्तरजालं इनपुट् चैनल् 64 इति उदाहरणरूपेण गृह्णाति प्रथमं 3×3 इति पारयति
कन्वोल्यूशन लेयर, ततः Batch Normalization लेयर इत्यस्य माध्यमेन, अन्ते च Relu activation function layer इत्यस्य माध्यमेन, आउटपुट् चैनल् 64 भवति;
मुख्यशाखायाः द्वितीयस्तरजालस्य निवेशचैनलः 64. प्रथमं 3×3 पारयति
ततः कन्वोल्यूशनल् लेयरः Batch Normalization लेयरद्वारा गच्छति, तथा च आउटपुट् चैनल् 64 भवति ।
अन्ते मुख्यशाखाद्वारा फीचर-मात्रिक-निर्गमः, शॉर्टकट्-द्वारा विशेषता-मात्रिक-निर्गमः च योजितः भवति, तथा च Building Block इत्यस्य अन्तिम-निर्गमः Relu-सक्रियीकरण-कार्यस्य माध्यमेन प्राप्यते
मुख्यशाखायाः शॉर्टकट्-द्वारा च फीचर-मैट्रिक्स-निर्गमं योजयति सति, भवद्भिः सुनिश्चितं कर्तव्यं यत् मुख्यशाखायाः शॉर्टकट्-द्वारा च फीचर-मात्रिक्स्-निर्गमस्य आकारः समानः अस्ति यदि मुख्यशाखायाः शॉर्टकट्-द्वारा च फीचर-मात्रिक-आकार-निर्गमः भिन्नः भवति, उदाहरणार्थं, आउटपुट्-चैनलः इनपुट्-चैनलस्य द्विगुणः भवति, तर्हि शॉर्टकट्-मध्ये आउटपुट्-चैनलस्य समानसङ्ख्यायाः उपयोगः आवश्यकः भवति तथा च कृते 1×1 कन्वोल्यूशन-कर्नेल्-आकारस्य उपयोगः आवश्यकः भवति convolution operation यदि आउटपुट् यदि इमेज् इनपुट् इमेज् इत्यस्मात् द्विगुणं लघु भवति तर्हि शॉर्टकट्स् इत्यस्मिन् convolution operation इत्यस्मिन् स्ट्राइड् 2 इति सेट् कर्तव्यः, मुख्यशाखायाः प्रथमस्तरस्य convolution operation इत्यस्मिन् स्ट्राइड् अपि भवितुमर्हति 2 इति सेट् कृतम् ।
निम्नलिखित कोडः Building Block संरचनां कार्यान्वितुं ResidualBlockBase वर्गं परिभाषयति ।
from typing import Type, Union, List, Optional
import mindspore.nn as nn
from mindspore.common.initializer import Normal
# 初始化卷积层与BatchNorm的参数
weight_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 = norm
self.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_sample
def 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
Bottleneck संरचना आरेखं अधोलिखिते चित्रे दर्शितं यदा निवेशः समानः भवति तदा Bottleneck संरचनायाः मापदण्डाः Building Block संरचनायाः अपेक्षया न्यूनाः भवन्ति तथा च ResNet50 द्वारा प्रयुक्ता अवशिष्टसंरचना Bottleneck अस्ति अस्याः संरचनायाः मुख्यशाखायाः त्रयः स्तराः संवर्तनसंरचनायाः सन्ति, येषु प्रत्येकं १×१ भवति
घुमावदार परत, 3×3
घुमावदारस्तराः तथा १×१
कन्वोल्यूशनल लेयर, यत्र 1×1
परिभ्रमणस्तराः क्रमशः आयामिकता न्यूनीकरणस्य आयामत्वस्य च भूमिकां निर्वहन्ति ।
मुख्यशाखायाः प्रथमस्तरजालं इनपुट् चैनल् 256 इति उदाहरणरूपेण गृह्णाति प्रथमः पाससङ्ख्या 64 अस्ति तथा च आकारः 1×1 अस्ति
convolution kernel dimensionality reduction करोति, ततः Batch Normalization स्तरं गच्छति, अन्ते च Relu activation function layer मार्गेण गच्छति, तस्य output channel 64 भवति
मुख्यशाखायाः द्वितीयस्तरीयजालपास्-सङ्ख्या ६४, आकारः ३×३ च अस्ति
convolution kernel विशेषताः निष्कासयति, ततः Batch Normalization स्तरं गच्छति, अन्ते च Relu activation function layer मार्गेण गच्छति, तस्य output channel 64 भवति
मुख्यशाखायाः तृतीयस्तरस्य पाससङ्ख्या २५६, आकारः च १×१ अस्ति
convolution kernel इत्यस्य परिमाणं भवति, ततः Batch Normalization स्तरस्य माध्यमेन गच्छति, तस्य output channel 256 भवति ।
अन्ते मुख्यशाखाद्वारा फीचर-मात्रिक-निर्गमः, शॉर्टकट्-द्वारा विशेषता-मात्रिक-निर्गमः च योजितः भवति, तथा च Bottleneck-इत्यस्य अन्तिम-निर्गमः Relu-सक्रियीकरण-कार्यस्य माध्यमेन प्राप्यते
मुख्यशाखायाः शॉर्टकट्-द्वारा च फीचर-मैट्रिक्स-निर्गमं योजयन्ते सति, भवद्भिः सुनिश्चितं कर्तव्यं यत् मुख्यशाखायाः शॉर्टकट्-द्वारा च आउटपुट्-विशेषता-मात्रिकाणां आकारः समानः अस्ति यदि मुख्यशाखायाः शॉर्टकट्-द्वारा च फीचर-मात्रिक-आकार-निर्गमः भिन्नः भवति, उदाहरणार्थं, यदि आउटपुट्-चैनलः इनपुट्-चैनलस्य द्विगुणः भवति, तर्हि शॉर्टकट्-सङ्ख्या आउटपुट्-चैनलस्य समाना भवितुम् अर्हति, आकारः च १×१ भवति
कन्वोल्यूशन कर्नेल् कन्वोल्यूशन ऑपरेशनं करोति, यदि आउटपुट् इमेज् इनपुट् इमेज् इत्यस्मात् द्विगुणं लघु भवति तर्हि शॉर्टकट् इत्यत्र कन्वोल्यूशन ऑपरेशन इत्यस्मिन् स्ट्राइड् 2 इति सेट् कर्तुं आवश्यकं भवति, मुख्यशाखायाः द्वितीयस्तरस्य कन्वोल्यूशन ऑपरेशने स्ट्राइड् इत्यस्य अपि आवश्यकता भवति 2 इति सेट् कर्तव्यम् ।
निम्नलिखितसङ्केतः Bottleneck संरचनां कार्यान्वितुं ResidualBlock वर्गं परिभाषयति ।
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_sample
def 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
ResNet संजालस्तरस्य संरचना अधोलिखिते चित्रे दर्शिता अस्ति यत् इनपुट् रङ्गप्रतिबिम्बं उदाहरणरूपेण गृहीत्वा प्रथमं 64 इत्यस्य परिमाणेन, 7×7 इत्यस्य कन्वोल्यूशन कर्नेल् आकारेण, 2 इत्यस्य स्ट्राइड् इत्यनेन च कन्वोल्यूशन लेयर conv1 पारयन्तु . 4 अवशिष्टजालखण्डान् (conv2_x, conv3_x, conv4_x तथा conv5_x) स्तम्भयन्तु, अस्मिन् समये आउटपुट् इमेज आकारः 7×7 भवति तथा च आउटपुट् चैनल् 2048 भवति अन्ततः, वर्गीकरणसंभावना औसतपूलिंग् स्तरस्य माध्यमेन प्राप्ता भवति, यत् पूर्णतया सम्बद्धं स्तरम् अस्ति तथा softmax.
प्रत्येकस्य अवशिष्टजालखण्डस्य कृते, ResNet50 संजाले conv2_x इत्येतत् उदाहरणरूपेण गृहीत्वा, प्रत्येकस्य Bottleneck इत्यस्य इनपुट् चैनल् 64 भवति तथा च आउटपुट् चैनल् 256 भवति ।
निम्नलिखित उदाहरणं अवशिष्टखण्डस्य निर्माणं कार्यान्वितुं make_layer परिभाषयति, तस्य मापदण्डाः च निम्नलिखितरूपेण सन्ति ।
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)
ResNet50 संजाले कुलम् 5 कन्वोल्यूशनल् संरचनाः सन्ति, एकः औसतः पूलिंग् लेयरः तथा च एकः पूर्णतया सम्बद्धः लेयरः अस्ति CIFAR-10 डाटा सेट् उदाहरणरूपेण गृह्यताम् :
conv1: इनपुट् इमेज् आकारः 32×32, इनपुट् चैनल् च 3 अस्ति । प्रथमं, इदं 64 इत्यस्य कन्वोल्यूशन कर्नेल् आकारस्य, 2 इत्यस्य स्ट्राइड् इत्यस्य च कन्वोल्यूशन लेयर इत्यस्य माध्यमेन गच्छति; अस्य स्तरस्य आउटपुट् फीचर मैप् आकारः १६×१६, आउटपुट् चैनल् च ६४ अस्ति ।
conv2_x: इनपुट् फीचर मैप् आकारः 16×16, इनपुट् चैनल् च 64 अस्ति । प्रथमं, इदं 3×3 इत्यस्य कन्वोल्यूशन-कर्नेल्-आकारस्य, 2 इत्यस्य स्ट्राइड्-इत्यस्य च अधिकतमं डाउनसैम्पलिंग्-सञ्चालनं करोति, ततः [1×1, 64, 64; , २५६] । अस्य स्तरस्य आउटपुट् फीचर मैप् आकारः ८×८, आउटपुट् चैनल् च २५६ अस्ति ।
conv3_x: इनपुट् फीचर मैप् आकारः 8×8 अस्ति तथा च इनपुट् चैनल् 256 अस्ति । अयं स्तरः [१×१, १२८, १×१, ५१२; अस्य स्तरस्य आउटपुट् फीचर मैप् आकारः ४×४, आउटपुट् चैनल् च ५१२ अस्ति ।
conv4_x: इनपुट् फीचर मैप् आकारः 4×4 अस्ति तथा च इनपुट् चैनल् 512 अस्ति । अयं स्तरः [१×१, २५६; अस्य स्तरस्य आउटपुट् फीचर मैप् आकारः २×२ अस्ति, आउटपुट् चैनल् च १०२४ अस्ति ।
conv5_x: इनपुट् फीचर मैप् आकारः 2×2 अस्ति, इनपुट् चैनल् च 1024 अस्ति । एषा स्तरः [१×१, ५१२; अस्य स्तरस्य आउटपुट् फीचर मैप् आकारः १×१ अस्ति, आउटपुट् चैनल् च २०४८ अस्ति ।
average pool & fc: इनपुट् चैनल् २०४८ अस्ति, तथा च आउटपुट् चैनल् वर्गीकरणस्य श्रेणीनां संख्या अस्ति ।
निम्नलिखित उदाहरणसङ्केतः ResNet50 मॉडलस्य निर्माणं कार्यान्वितं करोति ResNet50 मॉडलस्य निर्माणं resnet50 इति फंक्शन् इत्यस्य आह्वानं कृत्वा कर्तुं शक्यते ।
from mindspore import load_checkpoint, load_param_into_net
class 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为64
self.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 x
def _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],
layers: List[int], num_classes: int, pretrained: bool, pretrained_ckpt: str,
input_channel: int):
model = ResNet(block, layers, num_classes, input_channel)
if pretrained:
# 加载预训练模型
download(url=model_url, path=pretrained_ckpt, replace=True)
param_dict = load_checkpoint(pretrained_ckpt)
load_param_into_net(model, param_dict)
return model
def 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)
अस्मिन् खण्डे सूक्ष्म-समायोजनाय ResNet50 पूर्व-प्रशिक्षितस्य प्रतिरूपस्य उपयोगः भवति । ResNet50 मॉडलस्य निर्माणार्थं resnet50 इति आह्वयन्तु तथा च पूर्वप्रशिक्षितं पैरामीटर् True इति सेट् कुर्वन्तु ResNet50 पूर्वप्रशिक्षितं मॉडलं स्वयमेव डाउनलोड् भविष्यति तथा च पूर्वप्रशिक्षितमाडलस्य पैरामीटर्स् नेटवर्क् मध्ये लोड् भविष्यन्ति। ततः अनुकूलकं हानिकार्यं च परिभाषयन्तु, प्रशिक्षणहानिमूल्यं मूल्याङ्कनसटीकतायुगं च युगद्वारा मुद्रयन्तु, तथा च वर्तमानमार्गे सर्वोच्चमूल्यांकनसटीकतायुक्तं ckptसञ्चिकां (resnet50-best.ckpt) ./BestCheckPoint इत्यत्र रक्षन्तु
यतः पूर्वप्रशिक्षितस्य मॉडलस्य पूर्णतया सम्बद्धस्य लेयरस्य (fc) आउटपुट् आकारः (अनुरूपः पैरामीटर् num_classes) 1000 अस्ति, पूर्वप्रशिक्षितभारानाम् सफलतया लोड् कर्तुं वयं मॉडलस्य पूर्णतया सम्बद्धं आउटपुट् आकारं पूर्वनिर्धारितरूपेण सेट् कुर्मः १००० । CIFAR10 दत्तांशसमूहे 10 श्रेणयः सन्ति यदा प्रशिक्षणार्थं एतस्य दत्तांशसमूहस्य उपयोगः भवति तदा पूर्वप्रशिक्षितभारैः भारितस्य मॉडलस्य पूर्णतया सम्बद्धस्य स्तरस्य आउटपुट् आकारं 10 इति पुनः सेट् कर्तुं आवश्यकम् अस्ति
अत्र वयं 5 युगानां प्रशिक्षणप्रक्रियाम् दर्शयामः यदि भवान् आदर्शप्रशिक्षणप्रभावं प्राप्तुम् इच्छति तर्हि 80 युगानां प्रशिक्षणं अनुशंसितम्।
# 定义ResNet50网络
network = resnet50(pretrained=True)
# 全连接层输入层的大小
in_channel = network.fc.in_channels
fc = nn.Dense(in_channels=in_channel, out_channels=10)
# 重置全连接层
network.fc = fc
# 设置学习率
num_epochs = 5
lr = nn.cosine_decay_lr(min_lr=0.00001, max_lr=0.001, total_step=step_size_train * num_epochs,
step_per_epoch=step_size_train, decay_epoch=num_epochs)
# 定义优化器和损失函数
opt = nn.Momentum(params=network.trainable_params(), learning_rate=lr, momentum=0.9)
loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
def forward_fn(inputs, targets):
logits = network(inputs)
loss = loss_fn(logits, targets)
return loss
grad_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
import os
# 创建迭代器
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_acc = 0
best_ckpt_dir = "./BestCheckpoint"
best_ckpt_path = "./BestCheckpoint/resnet50-best.ckpt"
if not os.path.exists(best_ckpt_dir):
os.mkdir(best_ckpt_dir)
import mindspore.ops as ops
def train(data_loader, epoch):
"""模型训练"""
losses = []
network.set_train(True)
for i, (images, labels) in enumerate(data_loader):
loss = train_step(images, labels)
if i % 100 == 0 or i == step_size_train - 1:
print('Epoch: [%3d/%3d], Steps: [%3d/%3d], Train Loss: [%5.3f]' %
(epoch + 1, num_epochs, i + 1, step_size_train, loss))
losses.append(loss)
return sum(losses) / len(losses)
def evaluate(data_loader):
"""模型验证"""
network.set_train(False)
correct_num = 0.0 # 预测正确个数
total_num = 0.0 # 预测总数
for images, labels in data_loader:
logits = network(images)
pred = logits.argmax(axis=1) # 预测结果
correct = ops.equal(pred, labels).reshape((-1, ))
correct_num += correct.sum().asnumpy()
total_num += correct.shape[0]
acc = correct_num / total_num # 准确率
return acc
# 开始循环训练
print("Start Training Loop ...")
for epoch in range(num_epochs):
curr_loss = train(data_loader_train, epoch)
curr_acc = evaluate(data_loader_val)
print("-" * 50)
print("Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]" % (
epoch+1, num_epochs, curr_loss, curr_acc
))
print("-" * 50)
# 保存当前预测准确率最高的模型
if curr_acc > best_acc:
best_acc = curr_acc
ms.save_checkpoint(network, 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)
Start Training Loop ...
Epoch: [ 1/ 5], Steps: [ 1/196], Train Loss: [2.389]
Epoch: [ 1/ 5], Steps: [101/196], Train Loss: [1.467]
Epoch: [ 1/ 5], Steps: [196/196], Train Loss: [1.093]
--------------------------------------------------
Epoch: [ 1/ 5], Average Train Loss: [1.641], Accuracy: [0.595]
--------------------------------------------------
Epoch: [ 2/ 5], Steps: [ 1/196], Train Loss: [1.253]
Epoch: [ 2/ 5], Steps: [101/196], Train Loss: [0.974]
Epoch: [ 2/ 5], Steps: [196/196], Train Loss: [0.832]
--------------------------------------------------
Epoch: [ 2/ 5], Average Train Loss: [1.019], Accuracy: [0.685]
--------------------------------------------------
Epoch: [ 3/ 5], Steps: [ 1/196], Train Loss: [0.917]
Epoch: [ 3/ 5], Steps: [101/196], Train Loss: [0.879]
Epoch: [ 3/ 5], Steps: [196/196], Train Loss: [0.743]
--------------------------------------------------
Epoch: [ 3/ 5], Average Train Loss: [0.852], Accuracy: [0.721]
--------------------------------------------------
Epoch: [ 4/ 5], Steps: [ 1/196], Train Loss: [0.911]
Epoch: [ 4/ 5], Steps: [101/196], Train Loss: [0.703]
Epoch: [ 4/ 5], Steps: [196/196], Train Loss: [0.768]
--------------------------------------------------
Epoch: [ 4/ 5], Average Train Loss: [0.777], Accuracy: [0.737]
--------------------------------------------------
Epoch: [ 5/ 5], Steps: [ 1/196], Train Loss: [0.793]
Epoch: [ 5/ 5], Steps: [101/196], Train Loss: [0.809]
Epoch: [ 5/ 5], Steps: [196/196], Train Loss: [0.734]
--------------------------------------------------
Epoch: [ 5/ 5], Average Train Loss: [0.745], Accuracy: [0.742]
--------------------------------------------------
================================================================================
End of validation the best Accuracy is: 0.742, save the best ckpt file in ./BestCheckpoint/resnet50-best.ckpt
visualize_model कार्यं परिभाषयन्तु, CIFAR-10 परीक्षणदत्तांशसमूहस्य पूर्वानुमानार्थं सर्वोच्चसत्यापनसटीकतायुक्तस्य उपरि उल्लिखितस्य मॉडलस्य उपयोगं कुर्वन्तु, भविष्यवाणीपरिणामान् च दृश्यन्ते यदि पूर्वानुमानस्य फ़ॉन्ट् वर्णः नीलः अस्ति तर्हि भविष्यवाणी सम्यक् अस्ति इति अर्थः, यदि भविष्यवाणी फ़ॉन्ट् वर्णः रक्तः अस्ति तर्हि भविष्यवाणी गलत् अस्ति इति अर्थः ।
उपर्युक्तपरिणामेभ्यः द्रष्टुं शक्यते यत् ५ युगानां अन्तर्गतं सत्यापनदत्तांशसमूहे प्रतिरूपस्य भविष्यवाणीसटीकता प्रायः ७०% भवति, अर्थात् सामान्यपरिस्थितौ ६ चित्रेषु २ चित्राणि भविष्यवाणीं कर्तुं असफलाः भविष्यन्ति यदि भवान् आदर्शप्रशिक्षणप्रभावं प्राप्तुम् इच्छति तर्हि ८० युगपर्यन्तं प्रशिक्षणं कर्तुं अनुशंसितम् ।
import matplotlib.pyplot as plt
def visualize_model(best_ckpt_path, dataset_val):
num_class = 10 # 对狼和狗图像进行二分类
net = resnet50(num_class)
# 加载模型参数
param_dict = ms.load_checkpoint(best_ckpt_path)
ms.load_param_into_net(net, param_dict)
# 加载验证集的数据进行验证
data = next(dataset_val.create_dict_iterator())
images = data["image"]
labels = data["label"]
# 预测图像类别
output = net(data['image'])
pred = np.argmax(output.asnumpy(), axis=1)
# 图像分类
classes = []
with open(data_dir + "/batches.meta.txt", "r") as f:
for line in f:
line = line.rstrip()
if line:
classes.append(line)
# 显示图像及图像的预测值
plt.figure()
for i in range(6):
plt.subplot(2, 3, i + 1)
# 若预测正确,显示为蓝色;若预测错误,显示为红色
color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'
plt.title('predict:{}'.format(classes[pred[i]]), color=color)
picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))
mean = np.array([0.4914, 0.4822, 0.4465])
std = np.array([0.2023, 0.1994, 0.2010])
picture_show = std * picture_show + mean
picture_show = np.clip(picture_show, 0, 1)
plt.imshow(picture_show)
plt.axis('off')
plt.show()
# 使用测试数据集进行验证
visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val)
import matplotlib.pyplot as plt
def visualize_model(best_ckpt_path, dataset_val):
num_class = 10 # 对狼和狗图像进行二分类
net = resnet50(num_class)
# 加载模型参数
param_dict = ms.load_checkpoint(best_ckpt_path)
ms.load_param_into_net(net, param_dict)
# 加载验证集的数据进行验证
data = next(dataset_val.create_dict_iterator())
images = data["image"]
labels = data["label"]
# 预测图像类别
output = net(data['image'])
pred = np.argmax(output.asnumpy(), axis=1)
# 图像分类
classes = []
with open(data_dir + "/batches.meta.txt", "r") as f:
for line in f:
line = line.rstrip()
if line:
classes.append(line)
# 显示图像及图像的预测值
plt.figure()
for i in range(6):
plt.subplot(2, 3, i + 1)
# 若预测正确,显示为蓝色;若预测错误,显示为红色
color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'
plt.title('predict:{}'.format(classes[pred[i]]), color=color)
picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))
mean = np.array([0.4914, 0.4822, 0.4465])
std = np.array([0.2023, 0.1994, 0.2010])
picture_show = std * picture_show + mean
picture_show = np.clip(picture_show, 0, 1)
plt.imshow(picture_show)
plt.axis('off')
plt.show()
# 使用测试数据集进行验证
visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val)