Datawhale_PyTorch Task3

PyTorch实现Logistic regression

参考链接

import torch
import torch.nn as nn
import torchvision
import torch.nn.functional as F
import numpy as np
from torchvision.datasets import MNIST
import matplotlib.pyplot as plt
import torchvision.transforms as transforms
from torch.utils.data.sampler import SubsetRandomSampler
from torch.utils.data.dataloader import DataLoader

#Download training dataset
dataset = MNIST(root='data/', download=True)
test_dataset = MNIST(root='data/', train=False)
#Check the data
image, label = dataset[0]
plt.imshow(image, cmap='gray')
print('Label:', label)

#MNIST dataset (images and labels)
dataset = MNIST(root='data/', 
                train=True,
                transform=transforms.ToTensor())
img_tensor, label = dataset[0]
print(img_tensor.shape, label)

#Plot the image by passing in the 28x28 matrix
plt.imshow(img_tensor[0,10:15,10:15], cmap='gray');

#Training and Validation Datasets
def split_indices(n, val_pct):
    # Determine size of validation set
    n_val = int(val_pct*n)
    # Create random permutation of 0 to n-1
    idxs = np.random.permutation(n)
    # Pick first n_val indices for validation set
    return idxs[n_val:], idxs[:n_val]
train_indices, val_indices = split_indices(len(dataset), val_pct=0.2)
print(len(train_indices), len(val_indices))
print('Sample val indices: ', val_indices[:20])

batch_size=100

#Training sampler and data loader
train_sampler = SubsetRandomSampler(train_indices)
train_loader = DataLoader(dataset, 
                          batch_size, 
                          sampler=train_sampler)

#Validation sampler and data loader
val_sampler = SubsetRandomSampler(val_indices)
val_loader = DataLoader(dataset,
                        batch_size, 
                        sampler=val_sampler)

for batch in val_loader:
    inputs, targets = batch
    print(inputs.shape)
    print(targets.shape)
    break
    
input_size = 28*28
num_classes = 10
#Logistic regression model
model = nn.Linear(input_size, num_classes)
print(model.weight.shape)
model.weight
print(model.bias.shape)
model.bias
for batch in train_loader:
    images, labels = batch
    images = images.reshape(100, 784)
    print('input shape:', images.shape)
    outputs = model(images)
#outputs = images @ model.weight.t() + model.bias
    break
print('output shape:', outputs.shape)

class MnistModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(input_size, num_classes)
        
    def forward(self, xb):
        xb = xb.reshape(-1, 784)
        out = self.linear(xb)
        return out
    
model = MnistModel()

print(model.linear.weight.shape, model.linear.bias.shape)
list(model.parameters())

for images, labels in train_loader:
    print('input shape:', images.shape)
    outputs = model(images)
    break

print('outputs.shape : ', outputs.shape)
print('Sample outputs :\n', outputs[:2].data)
#Apply softmax for each output row
probs = F.softmax(outputs, dim=1)

#Look at sample probabilities
print("Sample probabilities:\n", probs[:2].data)

#Add up the probabilities of an output row
print("Sum: ", torch.sum(probs[0]).item())
max_probs, preds = torch.max(probs, dim=1)
print(preds)
def accuracy(l1, l2):
    return torch.sum(l1 == l2).item() / len(l1)
print(accuracy(preds, labels))
loss_fn = F.cross_entropy
#Loss for current batch of data
loss = loss_fn(outputs, labels)
print(loss)

learning_rate = 0.001
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
def loss_batch(model, loss_func, xb, yb, opt=None, metric=None):
    #Calculate loss
    preds = model(xb)
    loss = loss_func(preds, yb)
                     
    if opt is not None:
        #Compute gradients
        loss.backward()
        #Update parameters             
        opt.step()
        #Reset gradients
        opt.zero_grad()
    
    metric_result = None
    if metric is not None:
        #Compute the metric
        metric_result = metric(preds, yb)
    
    return loss.item(), len(xb), metric_result
   def evaluate(model, loss_fn, valid_dl, metric=None):
   with torch.no_grad():
        #Pass each batch through the model
        results = [loss_batch(model, loss_fn, xb, yb, metric=metric)
                   for xb,yb in valid_dl]
        #Separate losses, counts and metrics
        losses, nums, metrics = zip(*results)
        #Total size of the dataset
        total = np.sum(nums)
        #Avg. loss across batches 
        avg_loss = np.sum(np.multiply(losses, nums)) / total
        avg_metric = None
        if metric is not None:
            #Avg. of metric across batches
            avg_metric = np.sum(np.multiply(metrics, nums)) / total
    	return avg_loss, total, avg_metric
    def accuracy(outputs, labels):
    	_, preds = torch.max(outputs, dim=1)
    	return torch.sum(preds == labels).item() / len(preds)
val_loss, total, val_acc = evaluate(model, loss_fn, val_loader, metric=accuracy)
print('Loss: {:.4f}, Accuracy: {:.4f}'.format(val_loss, val_acc))
def fit(epochs, model, loss_fn, opt, train_dl, valid_dl, metric=None):
    for epoch in range(epochs):
        #Training
        for xb,yb in train_dl:
            loss,_,_ = loss_batch(model, loss_fn, xb, yb, opt)

        #Evaluation
        result = evaluate(model, loss_fn, valid_dl, metric)
        val_loss, total, val_metric = result
        
        #Print progress
        if metric is None:
            print('Epoch [{}/{}], Loss: {:.4f}'
                  .format(epoch+1, epochs, val_loss))
        else:
            print('Epoch [{}/{}], Loss: {:.4f}, {}: {:.4f}'
                  .format(epoch+1, epochs, val_loss, metric.__name__, val_metric))
# Redifine model and optimizer
model = MnistModel()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
fit(5, model, F.cross_entropy, optimizer, 
    train_loader, val_loader, accuracy)

输出

Epoch [1/5], Loss: 1.8719, accuracy: 0.6530
Epoch [2/5], Loss: 1.5743, accuracy: 0.7440
Epoch [3/5], Loss: 1.3650, accuracy: 0.7756
Epoch [4/5], Loss: 1.2146, accuracy: 0.7938
Epoch [5/5], Loss: 1.1031, accuracy: 0.8053
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值