2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
अत्र वयं CIFAR-दत्तांशसमूहस्य वर्गीकरणार्थं VGG-16 संजालं कार्यान्वयामः
प्रस्तावना
《बृहत्-परिमाणस्य चित्र-परिचयस्य कृते अत्यन्तं गहनं परिवर्तनकारी-जालम्》
आईसीएलआर २०१५
विजीजीइदं आक्सफोर्डतः अस्तिविisualजीeometry इतिजी roup इत्यस्य समूहेन प्रस्तावितं (भवन्तः VGG इति नामस्य उत्पत्तिं द्रष्टुं शक्नुवन्ति)। इदं संजालं ILSVRC 2014 इत्यस्मिन् सम्बद्धं कार्यम् अस्ति मुख्यं कार्यं सिद्धं कर्तुं यत् संजालस्य गभीरतां वर्धयित्वा संजालस्य अन्तिमप्रदर्शनं किञ्चित्पर्यन्तं प्रभावितं कर्तुं शक्नोति। VGG इत्यस्य द्वौ संरचना अस्ति, VGG16 तथा VGG19 इति द्वयोः मध्ये कोऽपि अत्यावश्यकः अन्तरः नास्ति, परन्तु जालस्य गभीरता भिन्ना अस्ति ।
विजीजी सिद्धान्त
AlexNet इत्यस्य तुलने VGG16 इत्यस्य एकः सुधारः अस्ति यत्AlexNet (11x11, 7x7, 5x5) इत्यस्मिन् बृहत्तरं कन्वोल्यूशन कर्नेल् प्रतिस्थापयितुं अनेकानाम् क्रमशः 3x3 कन्वोल्यूशन कर्नल्स् इत्यस्य उपयोगं कुर्वन्तु । . दत्तग्राहकक्षेत्रस्य कृते (निर्गमस्य सापेक्षतया निवेशप्रतिबिम्बस्य स्थानीयाकारः), बृहत्-विवर्तन-कर्णिकानां उपयोगात् स्टैक्ड्-लघु-कन्वोल्यूशन-कर्नेल्-इत्यस्य उपयोगः उत्तमः भवति, यतः अधिक-जटिल-शिक्षण-विधिं सुनिश्चित्य बहुविध-अरैखिक-स्तराः जाल-गहनतां वर्धयितुं शक्नुवन्ति, तथा च व्ययः तुल्यकालिकरूपेण अल्पः (कमानि मापदण्डाः) भवति ।
सरलतया वक्तुं शक्यते यत् VGG इत्यस्मिन् 7x7 कन्वोल्यूशन कर्नेल् इत्यस्य स्थाने त्रीणि 3x3 कन्वोल्यूशन कर्नेल्स् उपयुज्यन्ते, तथा च 5*5 कन्वोल्यूशन कर्नेल् इत्यस्य स्थाने द्वौ 3x3 कन्वोल्यूशन कर्नेल्स् उपयुज्यन्ते अस्य मुख्यं उद्देश्यं Under the condition इति समानं सुनिश्चितं कर्तुं भवति ग्राहकक्षेत्रस्य जालस्य गभीरता सुधरति, तंत्रिकाजालस्य प्रभावः च किञ्चित्पर्यन्तं सुधरति ।
यथा, 1 इत्यस्य स्ट्राइड्-युक्तानां त्रयाणां 3x3-विवर्तन-कणिकानां स्तर-स्तर-अधिस्थापनं 7 आकारस्य ग्राहकक्षेत्रं गणयितुं शक्यते (वास्तवतः, तस्य अर्थः अस्ति यत् त्रीणि 3x3 निरन्तर-कण्ठनानि 7x7-विवर्तनस्य समकक्षाः सन्ति), तथा च तस्य total parameters are राशि 3x(9xC^2) अस्ति यदि 7x7 convolution kernel इत्यस्य प्रत्यक्षं उपयोगः भवति तर्हि parameters इत्यस्य कुलसंख्या 49xC^2 भवति, यत्र C input and output channels इत्यस्य संख्यां निर्दिशति ।स्पष्टतया, २७xC२ ४९xC इत्यस्मात् न्यूनम्२, अर्थात् पैरामीटर्स् न्यूनीकृताः भवन्ति तथा च 3x3 कन्वोल्यूशन कर्नेल् इमेज् गुणानाम् उत्तमं निर्वाहार्थं अनुकूलं भवति ।
अत्र व्याख्या अस्ति यत् 5*5 कन्वोल्यूशन कर्नेल् इत्यस्य स्थाने 3x3 कन्वोल्यूशन कर्नलद्वयं किमर्थं उपयोक्तुं शक्यते:
5x5 convolution इति 5x5 क्षेत्रे स्लाइड् कृत्वा लघु पूर्णतया सम्बद्धं जालम् इति गण्यते, ततः वयं 3x3 convolution output इत्यस्य संयोजनाय पूर्णतया सम्बद्धस्य लेयरस्य उपयोगं कर्तुं शक्नुमः 3x3 कन्वोल्यूशनल लेयर इति दृश्यते। एवं प्रकारेण वयं एकस्य 5x5 कन्वोल्यूशनस्य स्थाने द्वौ 3x3 कन्वोल्यूशन्स् cascade (superpose) कर्तुं शक्नुमः ।
विवरणं अधोलिखिते चित्रे दर्शितम् अस्ति ।
VGG संजालसंरचना
VGG जालस्य संरचना निम्नलिखितम् अस्ति (VGG16 तथा VGG19 इत्येतौ द्वौ अपि वर्तन्ते) ।
जीजी जालसंरचना
VGG16 इत्यस्मिन् १६ गुप्तस्तराः (१३ कन्वोल्यूशनल् लेयर्स् तथा ३ पूर्णतया सम्बद्धाः लेयर्स्) सन्ति, यथा उपरि चित्रे D स्तम्भे दर्शितम् अस्ति
VGG19 इत्यत्र १९ गुप्तस्तराः (१६ कन्वोल्यूशनल् लेयर्स् तथा ३ पूर्णतया सम्बद्धाः लेयर्स्) सन्ति, यथा उपरिष्टात् चित्रे स्तम्भे E दर्शितम् अस्ति
VGG संजालस्य संरचना अतीव सुसंगता अस्ति, आरम्भात् अन्ते यावत् 3x3 convolution तथा 2x2 max pooling इत्येतयोः उपयोगः भवति ।
वीजीजी इत्यस्य लाभाः
VGGNet इत्यस्य संरचना अतीव सरलं भवति सम्पूर्णं संजालं समानं कन्वोल्यूशन कर्नेल् आकारं (3x3) अधिकतमं पूलिंग् आकारं (2x2) च उपयुज्यते ।
अनेकानाम् लघु-छिद्रकस्य (3x3) कन्वोल्यूशनल-स्तरस्य संयोजनं एकस्य बृहत्-छिद्रकस्य (5x5 अथवा 7x7) कन्वोल्यूशनल्-स्तरस्य अपेक्षया उत्तमम् अस्ति:
जालसंरचनायाः निरन्तरं गभीरं कृत्वा कार्यप्रदर्शने सुधारः कर्तुं शक्यते इति सत्यापितं भवति ।
वीजीजी इत्यस्य दोषाः
VGG अधिकगणनासंसाधनानाम् उपभोगं करोति तथा च अधिकमापदण्डानां उपयोगं करोति (एतत् 3x3 convolution इत्यस्य घटः नास्ति), यस्य परिणामेण अधिकस्मृतिप्रयोगः (140M) भवति ।
CIFAR (Canadian Institute For Advanced Research) इति आँकडासंग्रहः सङ्गणकदृष्टेः क्षेत्रे व्यापकरूपेण प्रयुक्तः लघुः चित्रदत्तांशसमूहः अस्ति, यस्य उपयोगः मुख्यतया यन्त्रशिक्षणस्य, सङ्गणकदृष्टि-अल्गोरिदमस्य च प्रशिक्षणार्थं भवति, विशेषतः चित्रपरिचयः, वर्गीकरणं च इत्यादिषु कार्येषु CIFAR-दत्तांशसमूहे मुख्यतया द्वौ भागौ स्तः : CIFAR-10 तथा CIFAR-100 इति ।
CIFAR-10 इति ६०,००० ३२x३२ वर्णचित्रं समाविष्टं दत्तांशसमूहं, यत् १० वर्गेषु विभक्तम् अस्ति, प्रत्येकं वर्गे ६,००० चित्राणि सन्ति । १० वर्गाः सन्ति : विमानं, काराः, पक्षिणः, बिडालाः, मृगाः, श्वाः, मण्डूकाः, अश्वाः, नौकाः, ट्रकाः च । दत्तांशसमूहे प्रशिक्षणार्थं ५०,००० चित्राणि, परीक्षणार्थं १०,००० चित्राणि च उपयुज्यन्ते । CIFAR-10 दत्तांशसमूहः मध्यमप्रमाणस्य समृद्धवर्गसूचनायाश्च कारणेन सङ्गणकदृष्टेः क्षेत्रे अनुसन्धानशिक्षणयोः अत्यन्तं लोकप्रियदत्तांशसमूहेषु अन्यतमः अभवत्
CIFAR-दत्तांशसमूहस्य उपयोगः सामान्यतया चित्रवर्गीकरणं, वस्तुपरिचयः, तथा च कन्वोल्यूशनल् न्यूरल नेटवर्क् (CNN) इत्यस्य प्रशिक्षणं परीक्षणं च इत्यादीनां कार्याणां कृते भवति मध्यम आकारस्य, समृद्धवर्गसूचनायाः च कारणात्, चित्रपरिचय-अल्गोरिदम्-अन्वेषणं कुर्वतां आरम्भकानां शोधकर्तृणां च कृते आदर्शम् अस्ति । तदतिरिक्तं, अनेके सङ्गणकदृष्टिः, यन्त्रशिक्षणस्पर्धाः अपि प्रतियोगिनां एल्गोरिदम्-प्रदर्शनस्य मूल्याङ्कनार्थं CIFAR-दत्तांशसमूहस्य उपयोगं मापदण्डरूपेण कुर्वन्ति
दत्तांशसमूहं सज्जीकर्तुं मया पूर्वमेव तत् अवतरणं कृतम् यदि कार्यं न करोति तर्हि केवलं आधिकारिकजालस्थलात् अवतरणं कुर्वन्तु, अथवा अहं भवद्भ्यः प्रत्यक्षतया दास्यामि।
यदि भवन्तः आँकडासमूहस्य आवश्यकतां अनुभवन्ति तर्हि कृपया ईमेल: [email protected] इत्यत्र सम्पर्कं कुर्वन्तु
मम दत्तांशसमूहः मूलतः torchvision इत्यस्मिन् डाउनलोड् कृतस्य दत्तांशस्य माध्यमेन उत्पन्नः आसीत् अहं वास्तवतः तत् कर्तुम् इच्छामि Dataset इत्यस्य परिभाषां तथा च DataLoader इत्यस्य लोडिंग् पदे पदे कार्यान्वितुं, एतां प्रक्रियां अवगन्तुं इच्छामि, अवगन्तुं च इच्छामि the process of data set processing , भवन्तं गहनशिक्षणस्य विषये अधिकं गभीरं कर्तुं शक्नोति।
दत्तांशसमूहशैली निम्नलिखितरूपेण अस्ति ।
दत्तांशसमूहस्य लेबलवर्गः a.meta
सञ्चिका संगृहीता अस्ति, अतः अस्माभिः विश्लेषणं कर्तव्यम् .meta
सर्वाणि टैग्-दत्तांशं पठितुं सञ्चिका । पार्सिंग् कोडः निम्नलिखितरूपेण अस्ति ।
# 首先了解所有的标签,TODO 可以详细了解一下这个解包的过程
import pickle
def unpickle(file):
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='bytes')
return dict
meta_data = unpickle('./dataset_method_1/cifar-10-batches-py/batches.meta')
label_names = meta_data[b'label_names']
# 将字节标签转换为字符串
label_names = [label.decode('utf-8') for label in label_names]
print(label_names)
विश्लेषणस्य परिणामाः यथा सन्ति ।
['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
अस्माकं दत्तांशसमूहः डाउनलोड् कृतः अस्ति, अतः अस्माभिः सञ्चिकायाः सामग्रीः पठितव्या यतः सञ्चिका द्विचक्रीयसञ्चिका अस्ति, अतः अस्माभिः तस्याः पठनार्थं द्विचक्रीयपठनविधिः उपयोक्तव्या ।
पठनसङ्केतः निम्नलिखितरूपेण अस्ति ।
# 载入单个批次的数据
import numpy as np
def load_data_batch(file):
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='bytes')
X = dict[b'data']
Y = dict[b'labels']
X = X.reshape(10000, 3, 32, 32).transpose(0, 2, 3, 1) # reshape and transpose to (10000, 32, 32, 3)
Y = np.array(Y)
return X, Y
# 加载第一个数据批次
data_batch_1 = './dataset_method_1/cifar-10-batches-py/data_batch_1'
X1, Y1 = load_data_batch(data_batch_1)
print(f'数据形状: {X1.shape}, 标签形状: {Y1.shape}')
परिणाम:
数据形状: (10000, 32, 32, 3), 标签形状: (10000,)
उपरिष्टाद् परीक्षणस्य अनन्तरं वयं दत्तांशं कथं लोड् कर्तव्यम् इति जानीमः अधुना सर्वाणि दत्तांशं लोड् कुर्मः ।
प्रशिक्षणसमूहं लोड् करणम् : १.
# 整合所有批次的数据
def load_all_data_batches(batch_files):
X_list, Y_list = [], []
for file in batch_files:
X, Y = load_data_batch(file)
X_list.append(X)
Y_list.append(Y)
X_all = np.concatenate(X_list)
Y_all = np.concatenate(Y_list)
return X_all, Y_all
batch_files = [
'./dataset_method_1/cifar-10-batches-py/data_batch_1',
'./dataset_method_1/cifar-10-batches-py/data_batch_2',
'./dataset_method_1/cifar-10-batches-py/data_batch_3',
'./dataset_method_1/cifar-10-batches-py/data_batch_4',
'./dataset_method_1/cifar-10-batches-py/data_batch_5'
]
X_train, Y_train = load_all_data_batches(batch_files)
print(f'训练数据形状: {X_train.shape}, 训练标签形状: {Y_train.shape}')
Y_train = Y_train.astype(np.int64)
उत्पादनम् : १.
训练数据形状: (50000, 32, 32, 3), 训练标签形状: (50000,)
परीक्षणसमूहं लोड् करणम् : १.
test_batch = './dataset_method_1/cifar-10-batches-py/test_batch'
X_test, Y_test = load_data_batch(test_batch)
Y_test = Y_test.astype(np.int64)
print(f'测试数据形状: {X_test.shape}, 测试标签形状: {Y_test.shape}')
उत्पादनम् : १.
测试数据形状: (10000, 32, 32, 3), 测试标签形状: (10000,)
Dataset वर्गस्य उपवर्गस्य परिभाषा बैच प्रशिक्षणार्थं Dataloader इत्यस्य अनन्तरं लोडिंग् इत्यस्य सुविधां कर्तुं भवति ।
तत्र त्रीणि पद्धतयः सन्ति येषां कार्यान्वयनं Dataset इत्यस्य उपवर्गाः अवश्यं कुर्वन्ति ।
__init__()
class constructor इति__len__()
दत्तांशसमूहस्य दीर्घतां प्रत्यागच्छति__getitem__()
दत्तांशसमूहात् दत्तांशस्य एकं भागं प्राप्नुवन्तुअत्र मम कार्यान्वयनम् अस्ति ।
from torch.utils.data import DataLoader, Dataset
# 定义 Pytorch 的数据集
class CIFARDataset(Dataset):
def __init__(self, images, labels, transform=None):
self.images = images
self.labels = labels
self.transform = transform
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
image = self.images[idx]
label = self.labels[idx]
if self.transform:
image = self.transform(image)
return image, label
transform_train = transforms.Compose(
[transforms.Pad(4),
transforms.ToTensor(),
transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
transforms.RandomHorizontalFlip(),
transforms.RandomGrayscale(),
transforms.RandomCrop(32, padding=4),
])
# 把数据集变成 Image 的数组,不然好像不能进行数据的增强
# 改变训练数据
from PIL import Image
def get_PIL_Images(origin_data):
datas = []
for i in range(len(origin_data)):
data = Image.fromarray(origin_data[i])
datas.append(data)
return datas
train_data = get_PIL_Images(X_train)
train_loader = DataLoader(CIFARDataset(train_data, Y_train, transform_train), batch_size=24, shuffle=True)
# 测试集的预处理
transform_test = transforms.Compose(
[
transforms.ToTensor(),
transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))]
)
test_loader = DataLoader(CIFARDataset(X_test, Y_test, transform_test), batch_size=24, shuffle=False)
वयं उपरि उल्लिखितस्य VGG16 संजालस्य आधारेण Pytorch framework कार्यान्वयामः ।
मुख्यतः विभक्ताः : १.
कार्यान्वयनम् अस्ति यथा - १.
class VGG16(nn.Module):
def __init__(self):
super(VGG16, self).__init__()
# 卷积层,这里进行卷积
self.convolusion = nn.Sequential(
nn.Conv2d(3, 96, kernel_size=3, padding=1), # 设置为padding=1 卷积完后,数据大小不会变
nn.BatchNorm2d(96),
nn.ReLU(inplace=True),
nn.Conv2d(96, 96, kernel_size=3, padding=1),
nn.BatchNorm2d(96),
nn.ReLU(inplace=True),
nn.Conv2d(96, 96, kernel_size=3, padding=1),
nn.BatchNorm2d(96),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(96, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(128, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(256, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.AvgPool2d(kernel_size=1, stride=1)
)
# 全连接层
self.dense = nn.Sequential(
nn.Linear(512, 4096), # 32*32 的图像大小经过 5 次最大化池化后就只有 1*1 了,所以就是 512 个通道的数据输入全连接层
nn.ReLU(inplace=True),
nn.Dropout(0.4),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.4),
)
# 输出层
self.classifier = nn.Linear(4096, 10)
def forward(self, x):
out = self.convolusion(x)
out = out.view(out.size(0), -1)
out = self.dense(out)
out = self.classifier(out)
return out
प्रशिक्षणस्य परीक्षणस्य च कृते, भवद्भिः केवलं मॉडलस्य उदाहरणं करणीयम्, ततः अनुकूलनकार्यं, हानिकार्यं, हानिदरं च परिभाषितुं, ततः प्रशिक्षणं परीक्षणं च कर्तुं आवश्यकम् ।
कोडः अधोलिखितरूपेण दर्शयतु:
अतिपैरामीटर परिभाषा : १.
# 定义模型进行训练
model = VGG16()
# model.load_state_dict(torch.load('./my-VGG16.pth'))
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=5e-3)
loss_func = nn.CrossEntropyLoss()
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.4, last_epoch=-1)
परीक्षणकार्यम् : १.
def test():
model.eval()
correct = 0 # 预测正确的图片数
total = 0 # 总共的图片数
with torch.no_grad():
for data in test_loader:
images, labels = data
images = images.to(device)
outputs = model(images).to(device)
outputs = outputs.cpu()
outputarr = outputs.numpy()
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
accuracy = 100 * correct / total
accuracy_rate.append(accuracy)
print(f'准确率为:{accuracy}%'.format(accuracy))
प्रशिक्षणयुगानि : १.
# 定义训练步骤
total_times = 40
total = 0
accuracy_rate = []
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
for epoch in range(total_times):
model.train()
model.to(device)
running_loss = 0.0
total_correct = 0
total_trainset = 0
print("epoch: ",epoch)
for i, (data,labels) in enumerate(train_loader):
data = data.to(device)
outputs = model(data).to(device)
labels = labels.to(device)
loss = loss_func(outputs,labels).to(device)
optimizer.zero_grad()
loss.backward()
optimizer.step()
running_loss += loss.item()
_,pred = outputs.max(1)
correct = (pred == labels).sum().item()
total_correct += correct
total_trainset += data.shape[0]
if i % 100 == 0 and i > 0:
print(f"正在进行第{i}次训练, running_loss={running_loss}".format(i, running_loss))
running_loss = 0.0
test()
scheduler.step()
प्रशिक्षितं प्रतिरूपं रक्षन्तु : १.
torch.save(model.state_dict(), './my-VGG16.pth')
accuracy_rate = np.array(accuracy_rate)
times = np.linspace(1, total_times, total_times)
plt.xlabel('times')
plt.ylabel('accuracy rate')
plt.plot(times, accuracy_rate)
plt.show()
print(accuracy_rate)
model_my_vgg = VGG16()
model_my_vgg.load_state_dict(torch.load('./my-VGG16-best.pth',map_location='cpu'))
from torchvision import transforms
from PIL import Image
# 定义图像预处理步骤
preprocess = transforms.Compose([
transforms.Resize((32, 32)),
transforms.ToTensor(),
# transforms.Normalize(mean=[0.485,0.456,0.406], std=[0.229,0.224,0.225]),
])
def load_image(image_path):
image = Image.open(image_path)
image = preprocess(image)
image = image.unsqueeze(0) # 添加批次维度
return image
image_data = load_image('./plane2.jpg')
print(image_data.shape)
output = model_my_vgg(image_data)
verify_data = X1[9]
verify_label = Y1[9]
output_verify = model_my_vgg(transform_test(verify_data).unsqueeze(0))
print(output)
print(output_verify)
उत्पादनम् : १.
torch.Size([1, 3, 32, 32])
tensor([[ 1.5990, -0.5269, 0.7254, 0.3432, -0.5036, -0.3267, -0.5302, -0.9417,
0.4186, -0.1213]], grad_fn=<AddmmBackward0>)
tensor([[-0.6541, -2.0759, 0.6308, 1.9791, 0.8525, 1.2313, 0.1856, 0.3243,
-1.3374, -1.0211]], grad_fn=<AddmmBackward0>)
print(label_names[torch.argmax(output,dim=1,keepdim=False)])
print(label_names[verify_label])
print("pred:",label_names[torch.argmax(output_verify,dim=1,keepdim=False)])
airplane
cat
pred: cat
अश्वस्य सत्यापनम्
सत्यापन कुत्ता