Jovian
⭐️
Sign In
In [2]:
# Imports
import torch
import torchvision
from torchvision.datasets import MNIST
# Download training dataset
dataset = MNIST(root='data/', download=True)

Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to data/MNIST/raw/train-images-idx3-ubyte.gz
100.1%
Extracting data/MNIST/raw/train-images-idx3-ubyte.gz Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to data/MNIST/raw/train-labels-idx1-ubyte.gz
113.5%
Extracting data/MNIST/raw/train-labels-idx1-ubyte.gz Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to data/MNIST/raw/t10k-images-idx3-ubyte.gz
100.4%
Extracting data/MNIST/raw/t10k-images-idx3-ubyte.gz Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to data/MNIST/raw/t10k-labels-idx1-ubyte.gz
180.4%
Extracting data/MNIST/raw/t10k-labels-idx1-ubyte.gz Processing... Done!
In [3]:
len(dataset)

Out[3]:
60000
In [12]:
test_dataset = MNIST(root='data/', train=False)
len(test_dataset)
import matplotlib.pyplot as plt
%matplotlib inline
image, label = dataset[10]
img=image.convert("1")
plt.imshow(img)
print('Label:', label)

('Label:', 3)
Notebook Image
In [13]:
import torchvision.transforms as transforms
# MNIST dataset (images and labels)
dataset = MNIST(root='data/', 
                train=True,
                transform=transforms.ToTensor())
img_tensor, label = dataset[0]
print(img_tensor.shape, label)
(torch.Size([1, 28, 28]), 5)
In [14]:
print(img_tensor[:,10:15,10:15])
print(torch.max(img_tensor), torch.min(img_tensor))

tensor([[[0.0039, 0.6039, 0.9922, 0.3529, 0.0000], [0.0000, 0.5451, 0.9922, 0.7451, 0.0078], [0.0000, 0.0431, 0.7451, 0.9922, 0.2745], [0.0000, 0.0000, 0.1373, 0.9451, 0.8824], [0.0000, 0.0000, 0.0000, 0.3176, 0.9412]]]) (tensor(1.), tensor(0.))
In [15]:
plt.imshow(img_tensor[0], cmap='gray');

Notebook Image
In [25]:
from torch.utils.data.sampler import SubsetRandomSampler
from torch.utils.data.dataloader import DataLoader
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import torchvision.transforms as transforms
import torch
import torchvision
from torchvision.datasets import MNIST



batch_size=100

input_size = 28*28
num_classes = 10

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


#随机分配函数
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])


# Training sampler and data loader
train_sampler = SubsetRandomSampler(train_indices)
print train_sampler
#数据加载
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)


 
class MnistModel(nn.Module):
     
    def __init__(self):        
        super(MnistModel, self).__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.weight.shape)
print("model.linear.bias.shape: ",model.linear.bias.shape)
for images, labels in train_loader:
    outputs = model(images)
    print('outputs.shape : ', outputs.shape)
    # Apply softmax for each output row
    #我的注释:outputs的第2个数表示需要分的类别数,这里是10个类别,
    #输出尺寸为('outputs.shape : ', torch.Size([100, 10]))
    #对应于caffe-protext文件最后的pool层。probs对应caffe里的prob前半部分
    '''
    layer {
	bottom: "pool5"
	top: "fc10"
	name: "fc10"
	type: "InnerProduct"
	inner_product_param {
    #表面最后输出10个类别数
		num_output: 10
		weight_filler {
      		  type: "xavier"
    		}
    		bias_filler {
      		  type: "constant"
      		  value: 0
    	        }
	}
}

layer {
	bottom: "fc10"
	bottom: "label"
	top: "prob"
	name: "prob"
    #计算loss的方法
	type: "SoftmaxWithLoss"
	include {
	  phase: TRAIN
	}
}
    '''
    probs = F.softmax(outputs, dim=1)
    print('probs.shape : ', probs.shape)
    # 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())
    break

print('outputs.shape : ', outputs.shape)
print('Sample outputs :\n', outputs[:2].data) 

#最后,我们只需选择每个输出行中概率最高的元素的索引,确定每张图像的预测标签即可。这可使用torch.max 完成,它会返回沿张量的一个特定维度的最大元素和该最大元素的索引。


max_probs, preds = torch.max(probs, dim=1)
print("preds: ", preds)
print("labels: ",labels)
def accuracy(l1, l2):
    print("equal: ", l1==l2)
    print(torch.sum(l1 == l2) )
    return torch.sum(l1 == l2).float() / len(l2)
def accuracyMatrix(outputs, labels):
    _, preds = torch.max(outputs, dim=1)
    return torch.sum(preds == labels).float() / len(preds)


print("accuracy: ", accuracy(preds, labels))
#用交叉熵评估损失
loss_fn = F.cross_entropy

# Loss for current batch of data
loss = loss_fn(outputs, labels)
print("loss: ", loss)




#定义批量损失
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

#交叉验证,计算loss
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


val_loss, total, val_acc = evaluate(model, loss_fn, val_loader, metric=accuracyMatrix)
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()
learning_rate=0.001
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

fit(5, model, F.cross_entropy, optimizer, train_loader, val_loader, accuracyMatrix)

 
(48000, 12000) ('Sample val indices: ', array([55773, 8140, 6926, 4349, 5941, 11426, 2120, 23654, 30744, 18790, 43251, 26235, 30933, 56968, 9014, 34834, 8624, 12723, 18203, 13118])) <torch.utils.data.sampler.SubsetRandomSampler object at 0x1050a3a10> ('model.linear.weight.shape: ', torch.Size([10, 784])) ('model.linear.bias.shape: ', torch.Size([10])) ('outputs.shape : ', torch.Size([100, 10])) ('probs.shape : ', torch.Size([100, 10])) ('Sample probabilities:\n', tensor([[0.0720, 0.0897, 0.1025, 0.1175, 0.1538, 0.0800, 0.1102, 0.0783, 0.0991, 0.0970], [0.0724, 0.0830, 0.1108, 0.0988, 0.1405, 0.0738, 0.1157, 0.1018, 0.1272, 0.0760]])) ('Sum: ', 1.0000001192092896) ('outputs.shape : ', torch.Size([100, 10])) ('Sample outputs :\n', tensor([[-0.4192, -0.1992, -0.0663, 0.0707, 0.3397, -0.3138, 0.0068, -0.3357, -0.0994, -0.1207], [-0.4235, -0.2871, 0.0014, -0.1127, 0.2390, -0.4048, 0.0452, -0.0830, 0.1398, -0.3757]])) ('preds: ', tensor([4, 4, 4, 8, 7, 8, 9, 9, 4, 8, 9, 4, 4, 9, 6, 4, 6, 4, 4, 4, 7, 7, 4, 4, 4, 4, 4, 9, 6, 4, 4, 8, 7, 4, 4, 6, 4, 4, 4, 4, 9, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 6, 4, 4, 4, 7, 4, 4, 7, 4, 4, 4, 2, 4, 3, 9, 1, 4, 4, 7, 4, 4, 8, 4, 9, 4, 4, 4, 4, 9, 3, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 6, 6, 9, 4, 6, 7, 9, 4, 4])) ('labels: ', tensor([9, 6, 9, 6, 1, 8, 5, 3, 0, 2, 1, 1, 1, 4, 1, 8, 4, 2, 7, 9, 8, 8, 3, 8, 5, 6, 8, 1, 6, 8, 5, 9, 5, 7, 5, 5, 7, 0, 2, 5, 8, 5, 4, 3, 6, 8, 3, 9, 2, 7, 9, 6, 8, 0, 2, 1, 1, 3, 6, 0, 8, 0, 4, 7, 5, 4, 2, 4, 9, 4, 7, 9, 2, 5, 1, 3, 4, 3, 9, 4, 3, 3, 7, 0, 4, 7, 4, 8, 6, 5, 9, 4, 4, 5, 5, 4, 5, 1, 7, 3])) ('equal: ', tensor([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=torch.uint8)) tensor(8) ('accuracy: ', tensor(0.0800)) ('loss: ', tensor(2.2969, grad_fn=<NllLossBackward>)) Loss: 2.3117, Accuracy: 0.0748 Epoch [1/5], Loss: 1.8835, accuracyMatrix: 0.6586 Epoch [2/5], Loss: 1.5820, accuracyMatrix: 0.7436 Epoch [3/5], Loss: 1.3703, accuracyMatrix: 0.7779 Epoch [4/5], Loss: 1.2182, accuracyMatrix: 0.7962 Epoch [5/5], Loss: 1.1056, accuracyMatrix: 0.8089
In [ ]:



In [ ]:
 
In [ ]: