动手学深度学习——CNN应用demo

CNN应用demo

CNN实现简单的手写数字识别

import torch
import torch.nn.functional as F
from torchvision import datasets,transforms
from tqdm import tqdm
torch.zeros(8)
def relu(x):
    return torch.clamp(x,min=0)

def linear(x,weight,bias):
    out = torch.matmul(x,weight) + bias.view(1,-1)
    return out

def model(x,params):
    x = F.conv2d(x,params[0],params[1],2,0)
    x = relu(x)
    x = F.conv2d(x,params[2],params[3],2,0)
    x = relu(x)
    x = x.view(-1,200)
    x = linear(x,params[4],params[5])
    return x

init_std = 0.1
params = [
    torch.randn(4,1,5,5) * init_std,
    torch.zeros(4),
    torch.randn(8,4,3,3) * init_std,
    torch.zeros(8),
    torch.randn(200,10) * init_std,
    torch.zeros(10)
]
for p in params:
    p.requires_grad = True

TRAIN_BATCH_SIZE = 100
TEST_BATCH_SIZE = 100
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST(
        '/data',train=True,download=True,
        transform = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.1307,),(0.3080,))
        ])
    ),
    batch_size = TRAIN_BATCH_SIZE,shuffle=True
)
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST(
        '/data',train=False,
        transform = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.1307,),(0.3080,))
        ])
    ),
    batch_size = TEST_BATCH_SIZE,shuffle=False
)

LR = 0.1
EPOCH = 100
LOG_INTERVAL = 100

for epoch in range(EPOCH):
    for idx,(data,label) in enumerate(train_loader):
        output = model(data,params)
        loss = F.cross_entropy(output,label)
        for p in params:
            if p.grad is not None:
                p.grad.zero_()
        loss.backward()
        
        for p in params:
            p.data = p.data - LR*p.grad.data
        
        if idx % LOG_INTERVAL == 0:
            print('Epoch %03d [%03d/%03d]\tLoss:%.4f' % (epoch,idx,len(train_loader),loss.item()))
            
        correct_num = 0
        total_num = 0
        with torch.no_grad():
            for data,label in test_loader:
                output = model(data,params)
                pred = output.max(1)[1]
                correct_num += (pred==label).sum().item()
                total_num += len(data)
        acc = correct_num/total_num
        print('...Testing @ Epoch %03d\tAcc: %.4f' % (epoch,acc))
Epoch 000 [000/600]	Loss:2.3304
...Testing @ Epoch 000	Acc: 0.1093
...Testing @ Epoch 000	Acc: 0.1265
...Testing @ Epoch 000	Acc: 0.1392
...Testing @ Epoch 000	Acc: 0.1547
...Testing @ Epoch 000	Acc: 0.1753
...Testing @ Epoch 000	Acc: 0.1978
...Testing @ Epoch 000	Acc: 0.2243
...Testing @ Epoch 000	Acc: 0.2482
...Testing @ Epoch 000	Acc: 0.2802
...Testing @ Epoch 000	Acc: 0.3076
...Testing @ Epoch 000	Acc: 0.3206
...Testing @ Epoch 000	Acc: 0.3458
...Testing @ Epoch 000	Acc: 0.3649
...Testing @ Epoch 000	Acc: 0.4057
...Testing @ Epoch 000	Acc: 0.4618
...Testing @ Epoch 000	Acc: 0.4657
...Testing @ Epoch 000	Acc: 0.4729
...Testing @ Epoch 000	Acc: 0.5428
...Testing @ Epoch 000	Acc: 0.5659
...Testing @ Epoch 000	Acc: 0.5371
...Testing @ Epoch 000	Acc: 0.5344
...Testing @ Epoch 000	Acc: 0.5585
...Testing @ Epoch 000	Acc: 0.4423
...Testing @ Epoch 000	Acc: 0.6185
...
...Testing @ Epoch 000	Acc: 0.8701
...Testing @ Epoch 000	Acc: 0.8501
...Testing @ Epoch 000	Acc: 0.8750
...Testing @ Epoch 000	Acc: 0.8729

可以用GPU训练优化后的代码

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import DataLoader
import torchvision.datasets as datasets
import torchvision.transforms as transforms
from tqdm import tqdm
class CNN(nn.Module):
    def __init__(self,in_channels=1,num_classes=10):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=1,out_channels=8,kernel_size=(3,3),stride=(1,1),padding=(1,1))
        self.pool = nn.MaxPool2d(kernel_size=(2,2),stride=(2,2))
        self.conv2 = nn.Conv2d(in_channels=8,out_channels=16,kernel_size=(3,3),stride=(1,1),padding=(1,1))
        self.fc1 = nn.Linear(16*7*7,num_classes)
    def forward(self,x):
        x = F.relu(self.conv1(x))
        x = self.pool(x)
        x = F.relu(self.conv2(x))
        x = self.pool(x)
        x = x.reshape(x.shape[0],-1)
        x = self.fc1(x)
        return x

# Set device
device = torch.device("cuda"if torch.cuda.is_available() else "cpu")
print(device)
# Hyperparameters
in_channels = 1
num_classes = 10
learning_rate = 0.001
batch_size = 64
num_epochs = 5

# Load Data
train_dataset = datasets.MNIST(root="dataset/",train=True,transform=transforms.ToTensor(),download=True)
train_loader = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)

test_dataset = datasets.MNIST(root="dataset/",train=False,transform=transforms.ToTensor(),download=True)
test_loader = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)

# Initialize network
model = CNN().to(device)

# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(),lr=learning_rate)

# Train Network

for epoch in range(num_epochs):
    # for data,targets in tqdm(train_loadr,leave=False) # 进度显示在一行
    for data,targets in tqdm(train_loader):
        # Get data to cuda if possible
        data = data.to(device=device)
        targets = targets.to(device=device)

        # forward
        scores = model(data)
        loss = criterion(scores,targets)

        # backward
        optimizer.zero_grad()
        loss.backward()

        # gardient descent or adam step
        optimizer.step()
posted @ 2024-05-06 10:30  Sun-Wind  阅读(19)  评论(0编辑  收藏  举报