Berbagi teknologi

VGG16 mengimplementasikan implementasi klasifikasi gambar pytorch dan menjelaskan langkah-langkahnya secara detail

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

VGG16 mengimplementasikan klasifikasi gambar

Di sini kami menerapkan jaringan VGG-16 untuk mengklasifikasikan kumpulan data CIFAR

Pengenalan jaringan VGG16

Kata pengantar

《Jaringan Konvolusional Sangat Dalam untuk Pengenalan Gambar Skala Besar》

ICLR tahun 2015

VGGIni dari OxfordBahasa Indonesia: Vbiasa sajaGgeometriG Diusulkan oleh grup roup (Anda harus bisa melihat asal usul nama VGG). Jaringan ini merupakan pekerjaan terkait di ILSVRC 2014. Pekerjaan utamanya adalah membuktikan bahwa peningkatan kedalaman jaringan dapat mempengaruhi kinerja akhir jaringan sampai batas tertentu. VGG memiliki dua struktur yaitu VGG16 dan VGG19. Tidak ada perbedaan mendasar antara keduanya, namun kedalaman jaringannya berbeda.

Prinsip VGG

Peningkatan VGG16 dibandingkan dengan AlexNet adalahGunakan beberapa kernel konvolusi 3x3 berturut-turut untuk menggantikan kernel konvolusi yang lebih besar di AlexNet (11x11, 7x7, 5x5) . Untuk bidang reseptif tertentu (ukuran lokal dari gambar masukan relatif terhadap keluaran), menggunakan kernel konvolusi kecil yang bertumpuk lebih baik daripada menggunakan kernel konvolusi besar, karena beberapa lapisan nonlinier dapat meningkatkan kedalaman jaringan untuk memastikan mode pembelajaran yang lebih kompleks, dan biayanya relatif kecil (parameternya lebih sedikit).

Sederhananya, di VGG, tiga kernel konvolusi 3x3 digunakan untuk menggantikan kernel konvolusi 7x7, dan dua kernel konvolusi 3x3 digunakan untuk menggantikan kernel konvolusi 5*5 bidang reseptif, kedalaman jaringan ditingkatkan, dan efek jaringan saraf ditingkatkan sampai batas tertentu.

Misalnya, superposisi lapis demi lapis dari tiga inti konvolusi 3x3 dengan langkah 1 dapat dianggap sebagai bidang reseptif berukuran 7 (sebenarnya, ini berarti bahwa tiga konvolusi kontinu 3x3 setara dengan konvolusi 7x7), dan superposisinya total parameter adalah Jumlahnya adalah 3x(9xC^2). Jika kernel konvolusi 7x7 digunakan secara langsung, jumlah total parameter adalah 49xC^2, di mana C mengacu pada jumlah saluran input dan output.Jelas, 27xC2 kurang dari 49xC2, yaitu, parameternya dikurangi; dan kernel konvolusi 3x3 kondusif untuk menjaga properti gambar dengan lebih baik.

Berikut penjelasan mengapa dua kernel konvolusi 3x3 dapat digunakan sebagai ganti kernel konvolusi 5*5:

Konvolusi 5x5 dianggap sebagai jaringan kecil yang terhubung penuh yang meluncur di area 5x5. Pertama-tama kita dapat melakukan konvolusi dengan filter konvolusi 3x3, dan kemudian menggunakan lapisan yang terhubung penuh untuk menghubungkan keluaran konvolusi 3x3 dilihat sebagai lapisan konvolusional 3x3. Dengan cara ini, kita dapat melakukan kaskade (melapiskan) dua konvolusi 3x3, bukan satu konvolusi 5x5.

Detailnya ditunjukkan pada gambar di bawah ini:

Masukkan deskripsi gambar di sini

Struktur jaringan VGG

Masukkan deskripsi gambar di sini

Berikut ini adalah struktur jaringan VGG (ada VGG16 dan VGG19):

Masukkan deskripsi gambar di sini

Struktur jaringan GG

VGG16 berisi 16 lapisan tersembunyi (13 lapisan konvolusional dan 3 lapisan terhubung penuh), seperti yang ditunjukkan pada kolom D pada gambar di atas

VGG19 berisi 19 lapisan tersembunyi (16 lapisan konvolusional dan 3 lapisan terhubung penuh), seperti yang ditunjukkan pada kolom E pada gambar di atas

Struktur jaringan VGG sangat konsisten, menggunakan konvolusi 3x3 dan pooling maksimal 2x2 dari awal hingga akhir.

Keunggulan VGG

Struktur VGGNet sangat sederhana. Seluruh jaringan menggunakan ukuran kernel konvolusi yang sama (3x3) dan ukuran pooling maksimum (2x2).

Kombinasi beberapa lapisan konvolusional filter kecil (3x3) lebih baik daripada satu lapisan konvolusional filter besar (5x5 atau 7x7):

Terbukti bahwa kinerja dapat ditingkatkan dengan terus memperdalam struktur jaringan.

Kekurangan VGG

VGG mengkonsumsi lebih banyak sumber daya komputasi dan menggunakan lebih banyak parameter (ini bukan konvolusi 3x3), sehingga menghasilkan penggunaan memori lebih banyak (140M).

Pemrosesan kumpulan data

Pengenalan kumpulan data

Kumpulan data CIFAR (Canadian Institute For Advanced Research) adalah kumpulan data gambar kecil yang banyak digunakan di bidang visi komputer. Data ini terutama digunakan untuk melatih algoritma pembelajaran mesin dan visi komputer, terutama dalam tugas-tugas seperti pengenalan dan klasifikasi gambar. Dataset CIFAR terdiri dari dua bagian utama: CIFAR-10 dan CIFAR-100.

CIFAR-10 merupakan dataset berisi 60.000 gambar berwarna berukuran 32x32 yang terbagi dalam 10 kategori yang masing-masing kategori berisi 6.000 gambar. 10 kategori tersebut adalah: pesawat terbang, mobil, burung, kucing, rusa, anjing, katak, kuda, perahu, dan truk. Dalam kumpulan data, 50.000 gambar digunakan untuk pelatihan dan 10.000 gambar digunakan untuk pengujian. Kumpulan data CIFAR-10 telah menjadi salah satu kumpulan data yang sangat populer dalam penelitian dan pengajaran di bidang visi komputer karena ukurannya yang moderat dan informasi kelas yang kaya.

Karakteristik kumpulan data
  • ukuran sedang: Ukuran gambar kecil dari kumpulan data CIFAR (32x32) menjadikannya ideal untuk melatih dan menguji algoritme visi komputer baru dengan cepat.
  • Berbagai kategori: CIFAR-10 memberikan tugas klasifikasi gambar dasar, sementara CIFAR-100 lebih lanjut menantang kemampuan klasifikasi algoritma yang terperinci.
  • banyak digunakan: Karena karakteristik ini, kumpulan data CIFAR banyak digunakan dalam penelitian dan pengajaran di bidang visi komputer, pembelajaran mesin, pembelajaran mendalam, dan bidang lainnya.
adegan yang akan digunakan

Kumpulan data CIFAR biasanya digunakan untuk tugas-tugas seperti klasifikasi gambar, pengenalan objek, serta pelatihan dan pengujian jaringan saraf konvolusional (CNN). Karena ukurannya yang moderat dan informasi kategori yang kaya, ini ideal untuk pemula dan peneliti yang mengeksplorasi algoritma pengenalan gambar. Selain itu, banyak kompetisi visi komputer dan pembelajaran mesin juga menggunakan dataset CIFAR sebagai tolok ukur untuk mengevaluasi kinerja algoritma kontestan.

Untuk menyiapkan data setnya sudah saya download, jika tidak bisa langsung saja download di website resminya, atau saya akan memberikannya langsung kepada anda.

Jika Anda membutuhkan kumpulan data, silakan hubungi email: [email protected]

Kumpulan data saya awalnya dibuat melalui data yang diunduh di torchvision. Saya tidak benar-benar ingin melakukan itu sekarang. Saya ingin menerapkan definisi Kumpulan Data dan memuat DataLoader selangkah demi selangkah, memahami proses ini, dan memahami. proses pemrosesan kumpulan data, dapat membuat Anda lebih mendalami pembelajaran mendalam.

Gaya kumpulan datanya adalah sebagai berikut:

Masukkan deskripsi gambar di sini

Parsing semua label kumpulan data

Kategori label pada dataset menggunakan a.metaFile disimpan, jadi kita perlu menguraikannya .meta file untuk membaca semua data tag. Kode penguraiannya adalah sebagai berikut:

# 首先了解所有的标签,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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Hasil analisisnya adalah sebagai berikut:

['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
  • 1

Muat satu kumpulan data untuk pengujian data sederhana

Kumpulan data kita telah diunduh, jadi kita perlu membaca isi file tersebut. Karena file tersebut adalah file biner, kita perlu menggunakan mode membaca biner untuk membacanya.

Kode bacaannya adalah sebagai berikut:

# 载入单个批次的数据
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}')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

hasil:

数据形状: (10000, 32, 32, 3), 标签形状: (10000,)
  • 1

Muat semua data

Setelah pengujian di atas, kita tahu cara memuat data. Sekarang mari kita memuat semua data.

Memuat set pelatihan:

# 整合所有批次的数据
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Keluaran:

训练数据形状: (50000, 32, 32, 3), 训练标签形状: (50000,)
  • 1

Memuat set pengujian:

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}')

  • 1
  • 2
  • 3
  • 4
  • 5

Keluaran:

测试数据形状: (10000, 32, 32, 3), 测试标签形状: (10000,)
  • 1

Tentukan subkelas Kumpulan Data

Mendefinisikan subkelas dari kelas Dataset adalah untuk memfasilitasi pemuatan Dataloader selanjutnya untuk pelatihan batch.

Ada tiga metode yang harus diterapkan oleh subkelas Dataset.

  • __init__()konstruktor kelas
  • __len__()Mengembalikan panjang kumpulan data
  • __getitem__()Dapatkan sepotong data dari kumpulan data

Di sini implementasi saya adalah sebagai berikut:

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Muat kumpulan data sebagai Dataloader

  1. Tentukan transformasi untuk menyempurnakan data. Berikut adalah set pelatihan terlebih dahulu. Set pelatihan perlu diperlebar sebesar 4 piksel, dinormalisasi, dibalik secara horizontal, diproses skala abu-abu, dan terakhir dikembalikan ke piksel asli 32 * 32.
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),
     ])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. Karena melibatkan pemrosesan gambar, dan data yang kita baca dari file biner adalah data numpy, kita perlu mengubah array numpy menjadi data Gambar untuk memudahkan pemrosesan gambar. Prosesnya sebagai berikut:
# 把数据集变成 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. Dapatkan pemuat data terlatih
train_data = get_PIL_Images(X_train)
train_loader = DataLoader(CIFARDataset(train_data, Y_train, transform_train), batch_size=24, shuffle=True)
  • 1
  • 2
  1. Mendapatkan set pengujian pemuat data pengujian tidak memerlukan terlalu banyak pemrosesan. Kode diberikan langsung di sini.
# 测试集的预处理
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Definisikan jaringan

Kami menerapkan kerangka Pytorch berdasarkan jaringan VGG16 yang disebutkan di atas.

terutama dibagi:

  • lapisan konvolusi
  • Lapisan yang terhubung sepenuhnya
  • lapisan klasifikasi

Implementasinya adalah sebagai berikut:

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

pelatihan dan pengujian

Untuk pelatihan dan pengujian, Anda hanya perlu membuat instance model, lalu menentukan fungsi pengoptimalan, fungsi kerugian, dan tingkat kerugian, lalu melakukan pelatihan dan pengujian.

kode tampil seperti di bawah ini:

Definisi hiperparameter:

# 定义模型进行训练
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Fungsi tes:

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))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Zaman pelatihan:

# 定义训练步骤
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

Simpan model yang dilatih:

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

tes

  1. Tentukan modelnya
model_my_vgg = VGG16()
  • 1
  1. Tambahkan data model terlatih
model_my_vgg.load_state_dict(torch.load('./my-VGG16-best.pth',map_location='cpu'))
  • 1
  1. Memproses gambar verifikasi yang saya temukan sendiri
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Keluaran:

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>)
  • 1
  • 2
  • 3
  • 4
  • 5
  1. Hasil cetak
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)])
  • 1
  • 2
  • 3
airplane
cat
pred: cat
  • 1
  • 2
  • 3

Masukkan deskripsi gambar di sini

Verifikasi kuda

Masukkan deskripsi gambar di sini

anjing verifikasi

Masukkan deskripsi gambar di sini