深度学习 10 — Pytorch 实现车牌识别

🍨 本文为[🔗365天深度学习训练营]中的学习记录博客

🍖 原作者:[K同学啊]

一、导入数据

import torch.nn as nn
import torch, torchvision
import torchvision.models as models
import torch.nn.functional as F
from torchvision import datasets
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device

1.获取类别名

import os, PIL, random, pathlib
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei'];
plt.rcParams['axes.unicode_minus'] = False;

data_dir = "./data"
data_dir = pathlib.Path(data_dir)

data_paths = list(data_dir.glob('*'))
classeNames = [str(path).split("/")[1].split("_")[1].split(".")[0] for path in data_paths]
print(classeNames)

data_paths = list(data_dir.glob('*'))
data_paths_str = [str(path) for path in data_paths]

data_paths_str

 2.数据可视化

 3.标签数字化

import numpy as np
char_enum = ["京","沪","津","渝","冀","晋","蒙","辽","吉","黑","苏","浙","皖","闽","赣","鲁",\
              "豫","鄂","湘","粤","桂","琼","川","贵","云","藏","陕","甘","青","宁","新","军","使"]
number = [str(i) for i in range(0,10)]
alphabet = [chr(i) for i in range(65,91)]

char_set = char_enum + number + alphabet
char_set_len = len(char_set)
label_name_len = len(classeNames[0])


def text2vec(text):
    vector = np.zeros([label_name_len,char_set_len])

    for i, c in enumerate(text):
        idx = char_set.index(c)
        vector[i][idx] = 1.0
    return vector

all_labels = [text2vec(i) for i in classeNames]

4.加载数据文件

import os
import pandas as pd
from PIL import Image

import torch.utils.data as data 
from torch.utils.data import Dataset
from torchvision.io import read_image

class MyDataset(data.Dataset):
    def __init__(self, all_labels, data_paths_str, transform):
        self.img_labels = all_labels
        self.img_dir = data_paths_str
        self.transform = transform

    def __len__(self):
        return len(self.img_labels)
    
    def __getitem__(self, index):
        image = Image.open(self.img_dir[index]).convert('RGB')
        label = self.img_labels[index]
        
        if self.transform:
            image = self.transform(image)
        return image, label
    
total_datadir = "./data"

train_transforms = transforms.Compose([
    transforms.Resize([224,224]),
    transforms.ToTensor(),
    transforms.Normalize(
        mean = [0.485, 0.456,0.406],
        std = [0.229, 0.224, 0.225])
])

total_data = MyDataset(all_labels, data_paths_str, train_transforms)
total_data

5.数据划分

train_size = int(0.8 * len(total_data))
test_size = len(total_data) - train_size

train_dataset, test_dataset = torch.utils.data.random_split(total_data, [train_size,test_size])

train_size, test_size

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16,shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16,shuffle=True)

print("The number of images in a training set is: ", len(train_loader)*16)
print("The number of images in a test set is: ", len(test_loader)*16)
print("The number of batches per epoch is: ", len(train_loader))

for X, y in test_loader:
    print("Shape of X [N, C, H, W]: ", X.shape);
    print("Shape of y: ", y.shape, y.dtype);
    break;

二、自建模型

class Network_bn(nn.Module):
    def __init__(self):
        super(Network_bn, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=5, stride=1, padding=0)
        self.bn1 = nn.BatchNorm2d(12)
        self.conv2 = nn.Conv2d(in_channels=12, out_channels=12, kernel_size=5, stride=1, padding=0)
        self.bn2 = nn.BatchNorm2d(12)
        self.pool = nn.MaxPool2d(2,2)
        self.conv4 = nn.Conv2d(in_channels=12, out_channels=24, kernel_size=5, stride=1, padding=0)
        self.bn4 = nn.BatchNorm2d(24)
        self.conv5 = nn.Conv2d(in_channels=24, out_channels=24, kernel_size=5, stride=1, padding=0)
        self.bn5 = nn.BatchNorm2d(24)
        self.fc1 = nn.Linear(24*50*50, label_name_len*char_set_len)
        self.reshape = Reshape([label_name_len,char_set_len])

    def forward(self, x):
        x = F.relu(self.bn1(self.conv1(x)))
        x = F.relu(self.bn2(self.conv2(x)))
        x = self.pool(x)
        x = F.relu(self.bn4(self.conv4(x)))
        x = F.relu(self.bn5(self.conv5(x)))
        x = self.pool(x)
        x = x.view(-1, 24*50*50)
        x = self.fc1(x)

        x = self.reshape(x)

        return x

class Reshape(nn.Module):
    def __init__(self, shape):
        super(Reshape, self).__init__()
        self.shape = shape

    def forward(self, x):
        return x.view(x.size(0),*self.shape)

device = "cuda" if torch.cuda.is_available() else "cpu"

print("Using {} device".format(device))
model = Network_bn().to(device)
model

import torchsummary

torchsummary.summary(model, (3,224,224))

三、模型训练

1. 优化器和损失函数

optimizer = torch.optim.Adam(model.parameters(),lr=1e-4,weight_decay=0.0001)

loss_model = nn.CrossEntropyLoss()
from torch.autograd import Variable
def test(model, test_loader, loss_model):
    size = len(test_loader.dataset) 
    num_batches = len(test_loader)
   
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in test_loader:
            X, y = X.to(device), y.to(device)
            pred = model(X)
            

            test_loss += loss_model(pred, y).item()
                  
            pred = pred.argmax(2)
            _, predicted = torch.max(y, 2)
            correct += (pred == predicted).type(torch.float).sum().item()/(y.size(0)*y.size(1))

    test_loss /= num_batches
    correct /= num_batches
 
    print(f'Avg loss: {test_loss:>8f}, accuracy:{correct:>8f}\n')
    return correct, test_loss
 
 
def train(model,train_loader, loss_model, optimizer):
    size = len(train_loader.dataset)
    num_batches = len(train_loader)
    model = model.to(device)
    model.train()
 
    for i, (images, labels) in enumerate(train_loader, 0):   # 0 是标起始位置的值
        images = Variable(images.to(device))
        labels = Variable(labels.to(device))
 
        optimizer.zero_grad()
        outputs = model(images)

        loss = loss_model(outputs, labels)
        loss.backward()
        optimizer.step()
 
        if i % 100 == 0:
            print('[%5d] loss: %.3f' % (i, loss))

2.模型训练

test_acc_list  = []
test_loss_list = []
epochs = 30

for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(model,train_loader,loss_model,optimizer)
    test_acc,test_loss = test(model, test_loader, loss_model)
    test_acc_list.append(test_acc)
    test_loss_list.append(test_loss)
print("Done!")
Epoch 1
-------------------------------
[    0] loss: 0.211
[  100] loss: 0.163
[  200] loss: 0.141
[  300] loss: 0.125
[  400] loss: 0.090
[  500] loss: 0.090
[  600] loss: 0.097
Avg loss: 0.072495, accuracy:0.312023

Epoch 2
-------------------------------
[    0] loss: 0.061
[  100] loss: 0.055
[  200] loss: 0.049
[  300] loss: 0.057
[  400] loss: 0.066
[  500] loss: 0.052
[  600] loss: 0.054
Avg loss: 0.054252, accuracy:0.391830

Epoch 3
-------------------------------
[    0] loss: 0.032
[  100] loss: 0.022
[  200] loss: 0.027
[  300] loss: 0.046
[  400] loss: 0.020
[  500] loss: 0.033
[  600] loss: 0.025
Avg loss: 0.046970, accuracy:0.445750

Epoch 4
-------------------------------
[    0] loss: 0.027
[  100] loss: 0.018
[  200] loss: 0.039
[  300] loss: 0.041
[  400] loss: 0.026
[  500] loss: 0.022
[  600] loss: 0.027
Avg loss: 0.045500, accuracy:0.476375

Epoch 5
-------------------------------
[    0] loss: 0.015
[  100] loss: 0.016
[  200] loss: 0.019
[  300] loss: 0.024
[  400] loss: 0.024
[  500] loss: 0.033
[  600] loss: 0.020
Avg loss: 0.041513, accuracy:0.496481

Epoch 6
-------------------------------
[    0] loss: 0.030
[  100] loss: 0.016
[  200] loss: 0.021
[  300] loss: 0.011
[  400] loss: 0.023
[  500] loss: 0.036
[  600] loss: 0.013
Avg loss: 0.039971, accuracy:0.512403

Epoch 7
-------------------------------
[    0] loss: 0.032
[  100] loss: 0.021
[  200] loss: 0.014
[  300] loss: 0.024
[  400] loss: 0.024
[  500] loss: 0.010
[  600] loss: 0.020
Avg loss: 0.037215, accuracy:0.525355

Epoch 8
-------------------------------
[    0] loss: 0.018
[  100] loss: 0.010
[  200] loss: 0.021
[  300] loss: 0.014
[  400] loss: 0.015
[  500] loss: 0.019
[  600] loss: 0.033
Avg loss: 0.036857, accuracy:0.527061

Epoch 9
-------------------------------
[    0] loss: 0.029
[  100] loss: 0.008
[  200] loss: 0.032
[  300] loss: 0.023
[  400] loss: 0.015
[  500] loss: 0.021
[  600] loss: 0.018
Avg loss: 0.036141, accuracy:0.538019

Epoch 10
-------------------------------
[    0] loss: 0.020
[  100] loss: 0.024
[  200] loss: 0.010
[  300] loss: 0.013
[  400] loss: 0.023
[  500] loss: 0.021
[  600] loss: 0.012
Avg loss: 0.035489, accuracy:0.550773

Epoch 11
-------------------------------
[    0] loss: 0.013
[  100] loss: 0.011
[  200] loss: 0.021
[  300] loss: 0.011
[  400] loss: 0.014
[  500] loss: 0.012
[  600] loss: 0.013
Avg loss: 0.034673, accuracy:0.552903

Epoch 12
-------------------------------
[    0] loss: 0.018
[  100] loss: 0.013
[  200] loss: 0.013
[  300] loss: 0.010
[  400] loss: 0.008
[  500] loss: 0.027
[  600] loss: 0.013
Avg loss: 0.032326, accuracy:0.570826

Epoch 13
-------------------------------
[    0] loss: 0.026
[  100] loss: 0.020
[  200] loss: 0.019
[  300] loss: 0.015
[  400] loss: 0.015
[  500] loss: 0.020
[  600] loss: 0.016
Avg loss: 0.033008, accuracy:0.565577

Epoch 14
-------------------------------
[    0] loss: 0.016
[  100] loss: 0.021
[  200] loss: 0.024
[  300] loss: 0.019
[  400] loss: 0.018
[  500] loss: 0.018
[  600] loss: 0.016
Avg loss: 0.032402, accuracy:0.578947

Epoch 15
-------------------------------
[    0] loss: 0.017
[  100] loss: 0.021
[  200] loss: 0.021
[  300] loss: 0.016
[  400] loss: 0.010
[  500] loss: 0.015
[  600] loss: 0.019
Avg loss: 0.031984, accuracy:0.579306

Epoch 16
-------------------------------
[    0] loss: 0.024
[  100] loss: 0.017
[  200] loss: 0.018
[  300] loss: 0.016
[  400] loss: 0.017
[  500] loss: 0.023
[  600] loss: 0.009
Avg loss: 0.031577, accuracy:0.587361

Epoch 17
-------------------------------
[    0] loss: 0.010
[  100] loss: 0.012
[  200] loss: 0.015
[  300] loss: 0.013
[  400] loss: 0.016
[  500] loss: 0.021
[  600] loss: 0.011
Avg loss: 0.030837, accuracy:0.593679

Epoch 18
-------------------------------
[    0] loss: 0.015
[  100] loss: 0.016
[  200] loss: 0.016
[  300] loss: 0.008
[  400] loss: 0.013
[  500] loss: 0.026
[  600] loss: 0.013
Avg loss: 0.029765, accuracy:0.600233

Epoch 19
-------------------------------
[    0] loss: 0.013
[  100] loss: 0.015
[  200] loss: 0.011
[  300] loss: 0.025
[  400] loss: 0.027
[  500] loss: 0.009
[  600] loss: 0.018
Avg loss: 0.029967, accuracy:0.599154

Epoch 20
-------------------------------
[    0] loss: 0.020
[  100] loss: 0.013
[  200] loss: 0.018
[  300] loss: 0.010
[  400] loss: 0.013
[  500] loss: 0.012
[  600] loss: 0.009
Avg loss: 0.030177, accuracy:0.596397

Epoch 21
-------------------------------
[    0] loss: 0.021
[  100] loss: 0.006
[  200] loss: 0.005
[  300] loss: 0.006
[  400] loss: 0.025
[  500] loss: 0.013
[  600] loss: 0.011
Avg loss: 0.028662, accuracy:0.611160

Epoch 22
-------------------------------
[    0] loss: 0.017
[  100] loss: 0.017
[  200] loss: 0.018
[  300] loss: 0.019
[  400] loss: 0.009
[  500] loss: 0.011
[  600] loss: 0.013
Avg loss: 0.028990, accuracy:0.611821

Epoch 23
-------------------------------
[    0] loss: 0.015
[  100] loss: 0.014
[  200] loss: 0.010
[  300] loss: 0.019
[  400] loss: 0.019
[  500] loss: 0.015
[  600] loss: 0.014
Avg loss: 0.028398, accuracy:0.612441

Epoch 24
-------------------------------
[    0] loss: 0.019
[  100] loss: 0.013
[  200] loss: 0.013
[  300] loss: 0.010
[  400] loss: 0.026
[  500] loss: 0.014
[  600] loss: 0.013
Avg loss: 0.027605, accuracy:0.615943

Epoch 25
-------------------------------
[    0] loss: 0.009
[  100] loss: 0.016
[  200] loss: 0.007
[  300] loss: 0.022
[  400] loss: 0.020
[  500] loss: 0.016
[  600] loss: 0.027
Avg loss: 0.028171, accuracy:0.614616

Epoch 26
-------------------------------
[    0] loss: 0.019
[  100] loss: 0.004
[  200] loss: 0.017
[  300] loss: 0.020
[  400] loss: 0.007
[  500] loss: 0.007
[  600] loss: 0.015
Avg loss: 0.028214, accuracy:0.620283

Epoch 27
-------------------------------
[    0] loss: 0.017
[  100] loss: 0.008
[  200] loss: 0.014
[  300] loss: 0.016
[  400] loss: 0.014
[  500] loss: 0.018
[  600] loss: 0.012
Avg loss: 0.027267, accuracy:0.623009

Epoch 28
-------------------------------
[    0] loss: 0.018
[  100] loss: 0.013
[  200] loss: 0.014
[  300] loss: 0.019
[  400] loss: 0.014
[  500] loss: 0.021
[  600] loss: 0.010
Avg loss: 0.026904, accuracy:0.625602

Epoch 29
-------------------------------
[    0] loss: 0.009
[  100] loss: 0.021
[  200] loss: 0.012
[  300] loss: 0.015
[  400] loss: 0.014
[  500] loss: 0.013
[  600] loss: 0.012
Avg loss: 0.027337, accuracy:0.627155

Epoch 30
-------------------------------
[    0] loss: 0.016
[  100] loss: 0.008
[  200] loss: 0.017
[  300] loss: 0.006
[  400] loss: 0.016
[  500] loss: 0.011
[  600] loss: 0.017
Avg loss: 0.027576, accuracy:0.623085

Done!

四、结果分析

import numpy as np
import matplotlib.pyplot as plt

x = [i for i in range(1,31)]

plt.plot(x, test_loss_list, label="Loss", alpha=0.8)

plt.xlabel("Epoch")
plt.ylabel("Loss")

plt.legend()    
plt.show()

 五、个人总结

在本次实战中,通过对标签的数字化处理,我们深入了解了 One-hot 编码的概念和应用。这是一种将分类数据转换成二进制向量表示的方法。与此同时,我们还探讨了多维分类任务中的一些独特挑战,尤其是在计算准确率(accuracy)时的不同处理方式。以下是对相关概念的详细总结和补充:

One-hot 编码(One-hot Encoding)

One-hot 编码是一种常用的技术,将分类数据转换为二进制向量表示。这种方法特别适用于处理离散的类别型数据。具体来说,每个类别被转换为一个长度为 N 的向量,其中 N 是所有可能类别的数量。在这个向量中,只有一个元素是 1,表示当前类别的位置,其余元素都是 0。

例如,假设我们有以下三个类别:['猫', '狗', '兔'],使用 One-hot 编码将它们转换为向量表示:

  1. '猫' -> [1, 0, 0]
  2. '狗' -> [0, 1, 0]
  3. '兔' -> [0, 0, 1]

这种编码方式有助于机器学习算法处理分类数据,因为它消除了类别之间的内在顺序或大小关系,使得所有类别在模型训练过程中被平等对待。

多维分类任务(Multi-dimensional Classification Tasks)

在多维分类任务中,每个输入样本可能对应多个分类标签。例如,某些自然语言处理和计算机视觉任务中,一个样本可能需要同时进行多个独立的分类。处理多维分类任务时,我们通常需要对每个分类任务分别计算预测结果,并结合所有任务的结果来评估模型性能。

计算准确率(Accuracy)

在多维分类任务中,计算准确率的方式有所不同。以下是处理多维分类任务时的一些关键步骤:

  1. 预测和真实标签的处理

    • 对于每个样本的每个分类任务,分别计算预测结果和真实标签。
    • 使用 argmax 等方法获取每个分类任务的预测类别。
  2. 准确率计算

    • 逐个任务计算每个样本的正确预测数量。
    • 累积所有分类任务的正确预测数量。
    • 将累积的正确预测数量除以总的分类任务数量,得到整体准确率。

通过本次实战,掌握了 One-hot 编码的基本概念和实现方法,并且深入理解了多维分类任务中准确率计算的特殊处理方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值