14-bo‘lim
Rasmlarni tasniflash
Fashion-MNIST to'plami, torchvision datasets, zich tarmoq va CNN ni haqiqiy ma'lumotda solishtirish, sinflar bo'yicha tahlil.
Ushbu bo‘lim mundarijasi
Nazariya yetarli - endi haqiqiy to'plamda ishlaymiz. Fashion-MNIST kiyim rasmlaridan iborat: 70 000 ta kulrang 28x28 rasm, 10 ta sinf.
Ma'lumotni yuklash #
torchvision mashhur to'plamlarni o'zi yuklab beradi:
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
torch.manual_seed(42)
o_ds = datasets.FashionMNIST("./data", train=True, download=True, transform=transforms.ToTensor())
t_ds = datasets.FashionMNIST("./data", train=False, download=True, transform=transforms.ToTensor())
sinflar = ['Futbolka', 'Shim', 'Sviter', 'Libos', 'Palto',
'Sandal', "Ko'ylak", 'Krossovka', 'Sumka', 'Botinka']
print("o'quv:", len(o_ds), "| test:", len(t_ds), "| sinflar:", len(sinflar))
x, y = o_ds[0]
print("rasm:", tuple(x.shape), "min/max:", round(x.min().item(), 2), round(x.max().item(), 2))
print("sinf taqsimoti:", torch.bincount(o_ds.targets).tolist())
o'quv: 60000 | test: 10000 | sinflar: 10
rasm: (1, 28, 28) min/max: 0.0 1.0
sinf taqsimoti: [6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000]
Har sinfdan aynan 6000 tadan - to'plam mukammal muvozanatli. Bu qulay: aniqlikni baholashda hech qanday tuzatish kerak emas.
transforms.ToTensor() ikkita ishni bajaradi: rasmni tenzorga aylantiradi
va qiymatlarni 0-255 dan 0.0-1.0 ga keltiradi.
train=True va train=FalseFashion-MNIST allaqachon ikkiga bo'lingan: 60 000 o'quv va 10 000 test. Bu standart bo'linish - shuning uchun turli maqolalardagi natijalarni bir-biri bilan solishtirish mumkin.
O'z loyihangizda bunday tayyor bo'linish bo'lmasa, uni random_split
bilan o'zingiz qilasiz (7-bo'lim).
Ikki modelni o'qitamiz #
o_dl = DataLoader(o_ds, batch_size=64, shuffle=True)
t_dl = DataLoader(t_ds, batch_size=256)
class CNN(nn.Module):
def __init__(self):
super().__init__()
self.xususiyat = nn.Sequential(
nn.Conv2d(1, 16, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2))
self.tasnif = nn.Sequential(nn.Flatten(), nn.Linear(32 * 7 * 7, 10))
def forward(self, x):
return self.tasnif(self.xususiyat(x))
O'quv sikli 8-bo'limdagi bilan bir xil - faqat ma'lumot boshqacha.
--- Zich tarmoq (101,770 parametr) ---
Davr | O'quv yo'q. | Test yo'q. | Test aniqlik | Vaqt
1 | 0.5459 | 0.4845 | 83.33% | 6.1s
2 | 0.3987 | 0.4080 | 85.69% | 5.8s
3 | 0.3611 | 0.3952 | 85.87% | 5.8s
4 | 0.3318 | 0.3918 | 86.02% | 5.7s
5 | 0.3132 | 0.3538 | 87.33% | 5.7s
--- CNN (20,490 parametr) ---
Davr | O'quv yo'q. | Test yo'q. | Test aniqlik | Vaqt
1 | 0.5235 | 0.3838 | 86.64% | 12.2s
2 | 0.3447 | 0.3407 | 87.63% | 12.4s
3 | 0.3060 | 0.3133 | 88.73% | 12.5s
4 | 0.2825 | 0.3311 | 88.35% | 12.6s
5 | 0.2656 | 0.2976 | 89.34% | 12.4s
Natijani o'qiymiz #
| Model | Parametrlar | Test aniqligi | Bir davr vaqti |
|---|---|---|---|
| Zich tarmoq | 101 770 | 87.33% | ~5.8 s |
| CNN | 20 490 | 89.34% | ~12.4 s |
CNN 5 barobar kam parametr bilan 2 foiz ko'proq aniqlik berdi. Buning sababi 13-bo'limda aytilgan edi: konvolyutsiya piksellarning qo'shnichiligini saqlaydi.
Parametrlar kam bo'lsa ham, CNN ikki barobar ko'p vaqt oldi. Chunki konvolyutsiya har piksel uchun qayta-qayta hisoblanadi, zich qatlam esa bitta katta matritsa ko'paytmasi.
CPU da bu farq sezilarli. GPU da esa konvolyutsiya juda yaxshi parallellashadi va farq deyarli yo'qoladi - aynan shuning uchun rasm modellari GPU da o'qitiladi.
Diqqat qiling: 4-davrda CNN ning test yo'qotishi 0.3133 dan 0.3311 ga o'sdi, keyin yana tushdi. Bunday kichik tebranish normal - 11-bo'limdagi barqaror o'sish esa muammo belgisi edi.
Qaysi sinf qiyin #
Umumiy aniqlik 89.34% - lekin u har sinfda bir xil emas:
cnn.eval()
togri = torch.zeros(10); jami = torch.zeros(10)
chalkashlik = torch.zeros(10, 10, dtype=torch.long)
with torch.no_grad():
for xb, yb in t_dl:
p = cnn(xb).argmax(1)
for haq, bash in zip(yb, p):
jami[haq] += 1
chalkashlik[haq, bash] += 1
if haq == bash:
togri[haq] += 1
for i in range(10):
print(f"{sinflar[i]:10s} | {togri[i]/jami[i]:6.1%}")
Sinf | Aniqlik
-----------|--------
Futbolka | 80.9%
Shim | 97.7%
Sviter | 83.1%
Libos | 95.6%
Palto | 83.7%
Sandal | 97.0%
Ko'ylak | 65.7%
Krossovka | 94.8%
Sumka | 97.8%
Botinka | 97.1%
umumiy: 89.34%
Farq juda katta: Sumka 97.8%, Ko'ylak esa atigi 65.7%. Umumiy son buni butunlay yashirgan edi.
Nima bilan chalkashtiryapti #
juft = [(chalkashlik[i,j].item(), i, j) for i in range(10) for j in range(10) if i != j]
for n, i, j in sorted(juft, reverse=True)[:5]:
print(f" {sinflar[i]:10s} -> {sinflar[j]:10s} : {n} marta")
Ko'ylak -> Futbolka : 114 marta
Ko'ylak -> Palto : 92 marta
Futbolka -> Ko'ylak : 88 marta
Sviter -> Palto : 84 marta
Futbolka -> Libos : 65 marta
Xatolar tasodifiy emas. Hammasi ustki kiyimlar orasida: ko'ylak, futbolka, sviter, palto. 28x28 kulrang rasmda ularning shakli deyarli bir xil - mato va tugmalar ko'rinmaydi.
Poyabzal va sumka esa hech qachon ular bilan chalkashmadi.
89% degan son modelni yaxshi ko'rsatadi. Aslida esa u ko'ylaklarning uchdan birini noto'g'ri tasniflaydi.
Agar bu do'kon uchun yozilgan tizim bo'lsa, ko'ylak buyurtmalari muntazam noto'g'ri turkumga tushardi - va bu umumiy hisobotda ko'rinmasdi.
Har doim sinflar bo'yicha taqsimotni chiqaring. 18-bo'limda buni chuqurroq ko'ramiz.
Ushbu 89.34% - boshlang'ich natija. Uni oshirish uchun: ko'proq davr,
uchinchi konvolyutsion blok, BatchNorm2d, ma'lumotni normallash va
kengaytirish (15-bo'lim), yoki tayyor modeldan foydalanish (16-bo'lim).
Har birini alohida sinab, ta'sirini o'lchang.
- Fashion-MNIST ni yuklab, o'quv va test hajmini chop eting.
- Bitta rasmning shakli va qiymatlar oralig'ini tekshiring.
- Sinf taqsimotini
bincountbilan chiqaring. - Zich tarmoqni 5 davr o'qitib, test aniqligini yozing.
- CNN ni xuddi shu sharoitda o'qitib, natijalarni solishtiring.
- Ikkala modelning parametrlari sonini va davr vaqtini jadvalga yozing.
- Sinflar bo'yicha aniqlikni hisoblang va eng yomonini toping.
- Eng ko'p chalkashgan 5 ta juftlikni chiqaring.
- Xatolar nega aynan ustki kiyimlar orasida ko'pligini tushuntiring.
- CNN ga uchinchi konvolyutsion blok qo'shib, aniqlik o'zgarishini o'lchang.
Xulosa #
torchvision.datasetsmashhur to'plamlarni bitta qator bilan yuklaydi.transforms.ToTensor()rasmni tenzorga aylantiradi va0-1oralig'iga keltiradi.- Fashion-MNIST muvozanatli: har sinfdan 6000 tadan.
- CNN 20 490 parametr bilan 89.34%, zich tarmoq 101 770 parametr bilan 87.33% berdi.
- Ya'ni CNN 5 barobar kam parametrda aniqroq ishladi.
- CNN CPU da sekinroq, chunki konvolyutsiya ko'p hisob talab qiladi - GPU da bu farq yo'qoladi.
- Test yo'qotishining kichik tebranishi normal; barqaror o'sish esa ortiqcha moslashish belgisi.
- Umumiy aniqlik sinflar orasidagi katta farqni yashiradi.
- Bizning modelda Sumka 97.8%, Ko'ylak esa atigi 65.7% aniqlik berdi.
- Xatolar tasodifiy emas - ular o'zaro o'xshash sinflar orasida to'planadi.
Keyingi bo'limda ma'lumotni normallash va sun'iy kengaytirish bilan natijani yaxshilaymiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.