<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【深度學習】PyTorch訓練一個CNN分類器

          共 6541字,需瀏覽 14分鐘

           ·

          2022-04-11 18:55

          前言

          原文翻譯自:Deep Learning with PyTorch: A 60 Minute Blitz

          翻譯:林不清(https://www.zhihu.com/people/lu-guo-92-42-88)

          目錄

          訓練一個分類器

          你已經學會如何去定義一個神經網絡,計算損失值和更新網絡的權重。

          你現(xiàn)在可能在思考:數(shù)據哪里來呢?

          關于數(shù)據

          通常,當你處理圖像,文本,音頻和視頻數(shù)據時,你可以使用標準的Python包來加載數(shù)據到一個numpy數(shù)組中.然后把這個數(shù)組轉換成torch.*Tensor

          • 對于圖像,有諸如Pillow,OpenCV包等非常實用
          • 對于音頻,有諸如scipy和librosa包
          • 對于文本,可以用原始Python和Cython來加載,或者使用NLTK和SpaCy 對于視覺,我們創(chuàng)建了一個torchvision包,包含常見數(shù)據集的數(shù)據加載,比如Imagenet,CIFAR10,MNIST等,和圖像轉換器,也就是torchvision.datasetstorch.utils.data.DataLoader

          這提供了巨大的便利,也避免了代碼的重復。

          在這個教程中,我們使用CIFAR10數(shù)據集,它有如下10個類別:’airplane’,’automobile’,’bird’,’cat’,’deer’,’dog’,’frog’,’horse’,’ship’,’truck’。這個數(shù)據集中的圖像大小為3*32*32,即,3通道,32*32像素。

          訓練一個圖像分類器

          我們將按照下列順序進行:

          • 使用torchvision加載和歸一化CIFAR10訓練集和測試集.
          • 定義一個卷積神經網絡
          • 定義損失函數(shù)
          • 在訓練集上訓練網絡
          • 在測試集上測試網絡

          1. 加載和歸一化CIFAR10

          使用torchvision加載CIFAR10是非常容易的。

          %matplotlib?inline
          import?torch
          import?torchvision
          import?torchvision.transforms?as?transforms

          torchvision的輸出是[0,1]的PILImage圖像,我們把它轉換為歸一化范圍為[-1, 1]的張量。

          注意

          如果在Windows上運行時出現(xiàn)BrokenPipeError,嘗試將torch.utils.data.DataLoader()的num_worker設置為0。

          transform?=?transforms.Compose(
          ????[transforms.ToTensor(),
          ?????transforms.Normalize((0.5,?0.5,?0.5),?(0.5,?0.5,?0.5))])

          trainset?=?torchvision.datasets.CIFAR10(root='./data',?train=True,
          ????????????????????????????????????????download=True,?transform=transform)
          trainloader?=?torch.utils.data.DataLoader(trainset,?batch_size=4,
          ??????????????????????????????????????????shuffle=True,?num_workers=2)

          testset?=?torchvision.datasets.CIFAR10(root='./data',?train=False,
          ???????????????????????????????????????download=True,?transform=transform)
          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')
          #這個過程有點慢,會下載大約340mb圖片數(shù)據。

          我們展示一些有趣的訓練圖像。

          import?matplotlib.pyplot?as?plt
          import?numpy?as?np

          #?functions?to?show?an?image


          def?imshow(img):
          ????img?=?img?/?2?+?0.5?????#?unnormalize
          ????npimg?=?img.numpy()
          ????plt.imshow(np.transpose(npimg,?(1,?2,?0)))
          ????plt.show()


          #?get?some?random?training?images
          dataiter?=?iter(trainloader)
          images,?labels?=?dataiter.next()

          #?show?images
          imshow(torchvision.utils.make_grid(images))
          #?print?labels
          print('?'.join('%5s'?%?classes[labels[j]]?for?j?in?range(4)))

          2. 定義一個卷積神經網絡

          從之前的神經網絡一節(jié)復制神經網絡代碼,并修改為接受3通道圖像取代之前的接受單通道圖像。

          import?torch.nn?as?nn
          import?torch.nn.functional?as?F


          class?Net(nn.Module):
          ????def?__init__(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):
          ????????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. 定義損失函數(shù)和優(yōu)化器

          我們使用交叉熵作為損失函數(shù),使用帶動量的隨機梯度下降。

          import?torch.optim?as?optim

          criterion?=?nn.CrossEntropyLoss()
          optimizer?=?optim.SGD(net.parameters(),?lr=0.001,?momentum=0.9)

          4. 訓練網絡

          這是開始有趣的時刻,我們只需在數(shù)據迭代器上循環(huán),把數(shù)據輸入給網絡,并優(yōu)化。

          for?epoch?in?range(2):??#?loop?over?the?dataset?multiple?times

          ????running_loss?=?0.0
          ????for?i,?data?in?enumerate(trainloader,?0):
          ????????#?get?the?inputs;?data?is?a?list?of?[inputs,?labels]
          ????????inputs,?labels?=?data

          ????????#?zero?the?parameter?gradients
          ????????optimizer.zero_grad()

          ????????#?forward?+?backward?+?optimize
          ????????outputs?=?net(inputs)
          ????????loss?=?criterion(outputs,?labels)
          ????????loss.backward()
          ????????optimizer.step()

          ????????#?print?statistics
          ????????running_loss?+=?loss.item()
          ????????if?i?%?2000?==?1999:????#?print?every?2000?mini-batches
          ????????????print('[%d,?%5d]?loss:?%.3f'?%
          ??????????????????(epoch?+?1,?i?+?1,?running_loss?/?2000))
          ????????????running_loss?=?0.0

          print('Finished?Training')

          保存一下我們的訓練模型

          PATH?=?'./cifar_net.pth'
          torch.save(net.state_dict(),?PATH)

          點擊這里查看關于保存模型的詳細介紹

          5. 在測試集上測試網絡

          我們在整個訓練集上訓練了兩次網絡,但是我們還需要檢查網絡是否從數(shù)據集中學習到東西。

          我們通過預測神經網絡輸出的類別標簽并根據實際情況進行檢測,如果預測正確,我們把該樣本添加到正確預測列表。

          第一步,顯示測試集中的圖片一遍熟悉圖片內容。

          dataiter?=?iter(testloader)
          images,?labels?=?dataiter.next()

          #?print?images
          imshow(torchvision.utils.make_grid(images))
          print('GroundTruth:?',?'?'.join('%5s'?%?classes[labels[j]]?for?j?in?range(4)))

          接下來,讓我們重新加載我們保存的模型(注意:保存和重新加載模型在這里不是必要的,我們只是為了說明如何這樣做):

          net?=?Net()
          net.load_state_dict(torch.load(PATH))

          現(xiàn)在我們來看看神經網絡認為以上圖片是什么?

          outputs?=?net(images)

          輸出是10個標簽的概率。一個類別的概率越大,神經網絡越認為他是這個類別。所以讓我們得到最高概率的標簽。

          _,?predicted?=?torch.max(outputs,?1)

          print('Predicted:?',?'?'.join('%5s'?%?classes[predicted[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))

          結果看起來好于偶然,偶然的正確率為10%,似乎網絡學習到了一些東西。

          那在什么類上預測較好,什么類預測結果不好呢?

          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上運行神經網絡呢?

          在GPU上訓練

          你是如何把一個Tensor轉換GPU上,你就如何把一個神經網絡移動到GPU上訓練。這個操作會遞歸遍歷有所模塊,并將其參數(shù)和緩沖區(qū)轉換為CUDA張量。

          device?=?torch.device("cuda:0"?if?torch.cuda.is_available()?else?"cpu")
          #?Assume?that?we?are?on?a?CUDA?machine,?then?this?should?print?a?CUDA?device:
          #假設我們有一臺CUDA的機器,這個操作將顯示CUDA設備。
          print(device)

          接下來假設我們有一臺CUDA的機器,然后這些方法將遞歸遍歷所有模塊并將其參數(shù)和緩沖區(qū)轉換為CUDA張量:

          net.to(device)

          請記住,你也必須在每一步中把你的輸入和目標值轉換到GPU上:

          inputs,?labels?=?inputs.to(device),?labels.to(device)

          為什么我們沒注意到GPU的速度提升很多?那是因為網絡非常的小。

          實踐:

          嘗試增加你的網絡的寬度(第一個nn.Conv2d的第2個參數(shù), 第二個nn.Conv2d的第一個參數(shù),他們需要是相同的數(shù)字),看看你得到了什么樣的加速。

          實現(xiàn)的目標:

          • 深入了解了PyTorch的張量庫和神經網絡
          • 訓練了一個小網絡來分類圖片

          在多GPU上訓練

          如果你希望使用所有GPU來更大的加快速度,請查看選讀:[數(shù)據并行]:(https://pytorch.org/tutorials/beginner/blitz/data_parallel_tutorial.html)

          接下來做什么?

          • 訓練神經網絡玩電子游戲
          • 在ImageNet上訓練最好的ResNet
          • 使用對抗生成網絡來訓練一個人臉生成器
          • 使用LSTM網絡訓練一個字符級的語言模型
          • 更多示例
          • 更多教程
          • 在論壇上討論PyTorch
          • 在Slack上與其他用戶聊天


          往期精彩回顧




          瀏覽 45
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99热国产在线 | 在线观看视频免费黄 | 国产肏屄高视频大香蕉 | 欧美视频色 | 青草青青成人在线 |