• PyTorch简明教程 | 2-CNN定义和训练


    ##训练分类器
    
    import torch
    import torchvision
    import torchvision.transforms as transforms
    import torch.nn as nn
    import torch.nn.functional as F
    
    
    #1- 加载和预处理数据
    transfrom = transforms.Compose(
        [transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    
    trainset = torchvision.datasets.CIFAR10(root='/path/to/data', train=True,
        download=True, transform=transform)
    testset  = torchvision.datasets.CIFAR10(root='/path/to/data', train=False,
        download=True, transform=transform)
    
    trainloader = torch.utils.data.Dataloader(trainset, batch_size=4, shffule=True, num_workers=2)
    testloader  = torch.utils.data.DataLoader(testset,  batch_size=4, shuffle=False, num_workers=2)
    
    classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    
    #2- 定义卷积网络
    class Net(nn.Module):
        def __init__(self):
            """ 在构造函数里,定义模块,把它们保存到self里。 """
            super(Net, self).__init__()
            self.conv1 = nn.Conv2d(3, 6, 5)
            self.pool = nn.MaxPool2d(2, 2)
            self.conv2 = nn.Conv2d(6, 16, 5)
            self.fc1 = nn.Linear(16 * 5 * 5, 120)
            self.fc2 = nn.Linear(120, 84)
            self.fc3 = nn.Linear(84, 10)
    
        def forward(self, x):
            """ 在forward函数里,我们需要根据网络结构来实现前向计算。 通常我们会上定义的模块来计算。 """
            x = self.pool(F.relu(self.conv1(x)))
            x = self.pool(F.relu(self.conv2(x)))
            x = x.view(-1, 16 * 5 * 5)
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x
    
    net = Net()
    
    #3- 定义损失函数
    import torch.optim as optim
    
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
    
    #4- 用训练数据训练模型
    for epoch in range(10):
        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            # 得到输入
            inputs, labels = data
    
            # 梯度清零 
            optimizer.zero_grad()
    
            # forward + backward + optimize
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
    
            #定义统计信息
            running_loss += loss.item()
            if i % 2000 == 1999:
                print('[%d, %5d] loss: %.3f' %
                    (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0
    
    print("Finished Training")
    
    #5- 用测试数据测试模型
    # imshow(torchvision.utils.make_grid(images))
    # print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
    
    correct = 0
    total = 0
    with torch.no_grad():
        for data in testloader:
            images, labels = data
            outputs = net(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
    print('Accuracy of the network on the 10000 test images: %d %%' % (
        100 * correct / total))
    
    #每个类别的准确率
    class_correct = list(0. for i in range(10))
    class_total = list(0. for i in range(10))
    with torch.no_grad():
        for data in testloader:
            images, labels = data
            outputs = net(images)
            _, predicted = torch.max(outputs, 1)
            c = (predicted == labels).squeeze()
            for i in range(4):
                label = labels[i]
                class_correct[label] += c[i].item()
                class_total[label] += 1
    
    
    for i in range(10):
        print('Accuracy of %5s : %2d %%' % (
            classes[i], 100 * class_correct[i] / class_total[i]))
    
    
    #GPU训练
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    
    #在NN定义和每个epoch数据加载中后面增加.to(device)
    
    
    ################################
    #和TF对比
    
    #Tensorflow和PyTorch最大的区别之一就是Tensorflow使用静态计算图和PyTorch使用动态计算图。
    #在Tensorflow里,我们首先构建计算图,然后多次执行它。
    
    
    import tensorflow as tf
    import numpy as np
    
    # 首先构建计算图。
    
    # N是batch大小;D_in是输入大小。
    # H是隐单元个数;D_out是输出大小。
    N, D_in, H, D_out = 64, 1000, 100, 10
    
    # 输入和输出是placeholder,在用session执行graph的时候
    # 我们会feed进去一个batch的训练数据。
    x = tf.placeholder(tf.float32, shape=(None, D_in))
    y = tf.placeholder(tf.float32, shape=(None, D_out))
    
    
    # 创建变量,并且随机初始化。 
    # 在Tensorflow里,变量的生命周期是整个session,因此适合用它来保存模型的参数。
    w1 = tf.Variable(tf.random_normal((D_in, H)))
    w2 = tf.Variable(tf.random_normal((H, D_out)))
    
    # Forward pass:计算模型的预测值y_pred 
    # 注意和PyTorch不同,这里不会执行任何计算,
    # 而只是定义了计算,后面用session.run的时候才会真正的执行计算。
    h = tf.matmul(x, w1)
    h_relu = tf.maximum(h, tf.zeros(1))
    y_pred = tf.matmul(h_relu, w2)
    
    # 计算loss 
    loss = tf.reduce_sum((y - y_pred) ** 2.0)
    
    # 计算梯度。 
    grad_w1, grad_w2 = tf.gradients(loss, [w1, w2])
    
    # 使用梯度下降来更新参数。assign同样也只是定义更新参数的操作,不会真正的执行。
    # 在Tensorflow里,更新操作是计算图的一部分;
    # 而在PyTorch里,因为是动态的”实时“的计算,
    # 所以参数的更新只是普通的Tensor计算,不属于计算图的一部分。
    learning_rate = 1e-6
    new_w1 = w1.assign(w1 - learning_rate * grad_w1)
    new_w2 = w2.assign(w2 - learning_rate * grad_w2)
    
    # 计算图构建好了之后,我们需要创建一个session来执行计算图。
    with tf.Session() as sess:
        # 首先需要用session初始化变量 
        sess.run(tf.global_variables_initializer())
        
        # 这是fake的训练数据
        x_value = np.random.randn(N, D_in)
        y_value = np.random.randn(N, D_out)
        for _ in range(500):
            # 用session多次的执行计算图。每次feed进去不同的数据。
            # 这里是模拟的,实际应该每次feed一个batch的数据。
            # run的第一个参数是需要执行的计算图的节点,它依赖的节点也会自动执行,
            # 因此我们不需要手动执行forward的计算。
            # run返回这些节点执行后的值,并且返回的是numpy array
            loss_value, _, _ = sess.run([loss, new_w1, new_w2],
                    feed_dict={x: x_value, y: y_value})
            print(loss_value)
  • 相关阅读:
    BZOJ_3159_决战
    11.19 ~ 11.25训练计划+总结
    BZOJ_1304_[CQOI2009]叶子的染色_树形DP
    BZOJ_1999_[Noip2007]Core树网的核_单调队列+树形DP
    BZOJ_4033_[HAOI2015]树上染色_树形DP
    BZOJ_5338_ [TJOI2018]xor_可持久化trie
    BZOJ_2957_楼房重建_线段树
    BZOJ_3124_[Sdoi2013]直径_树形DP
    BZOJ_4987_Tree_树形DP
    「JOISC 2019 Day2」两个天线(线段树)
  • 原文地址:https://www.cnblogs.com/geo-will/p/13546598.html
Copyright © 2020-2023  润新知