开心六月综合激情婷婷|欧美精品成人动漫二区|国产中文字幕综合色|亚洲人在线成视频

    1. 
      
        <b id="zqfy3"><legend id="zqfy3"><fieldset id="zqfy3"></fieldset></legend></b>
          <ul id="zqfy3"></ul>
          <blockquote id="zqfy3"><strong id="zqfy3"><dfn id="zqfy3"></dfn></strong></blockquote>
          <blockquote id="zqfy3"><legend id="zqfy3"></legend></blockquote>
          打開APP
          userphoto
          未登錄

          開通VIP,暢享免費電子書等14項超值服

          開通VIP
          PyTorch專欄(十七): 使用PyTorch進行深度學(xué)習(xí)

          【磐創(chuàng)AI 導(dǎo)讀】:本篇文章講解了PyTorch專欄的第五章中在深度學(xué)習(xí)和NLP中使用Pytorch部分的第一小節(jié)使用PyTorch進行深度學(xué)習(xí)。查看關(guān)于本專欄的介紹:PyTorch專欄開篇。查看本章歷史文章,請點擊下方藍色字體進入相應(yīng)鏈接閱讀。

          專欄目錄:
          第五章:PyTorch之文本篇
          • 使用Sequence2Sequence網(wǎng)絡(luò)和注意力進行翻譯

          使用PyTorch進行深度學(xué)習(xí)

          1.深度學(xué)習(xí)構(gòu)建模塊:仿射變換, 非線性函數(shù)以及目標函數(shù)

          深度學(xué)習(xí)表現(xiàn)為使用更巧妙的方法將線性函數(shù)和非線性函數(shù)進行組合。非線性函數(shù)的引入使得訓(xùn)練出來的模型更加強大。在本節(jié)中,我們將學(xué)習(xí)這些核心組件,建立目標函數(shù),并理解模型是如何構(gòu)建的。

          1.1 仿射變換

          深度學(xué)習(xí)的核心組件之一是仿射變換,仿射變換是一個關(guān)于矩陣A和向量x,b的函數(shù),如下所示

          對于矩陣A和向量x,b。這里要學(xué)習(xí)的參數(shù)是A和b。通常,b被稱為偏差項。

          PyTorch以及大多數(shù)的深度學(xué)習(xí)框架所做的事情都與傳統(tǒng)的線性代數(shù)有些不同。它的映射輸入是行而不是列。也就是說,下面代碼輸出的第i行
          是輸入的第i行進行A變換,并加上偏移項的結(jié)果。看下面的例子:

          # Author: Robert Guthrie

          import torch
          import torch.nn as nn
          import torch.nn.functional as F
          import torch.optim as optim

          torch.manual_seed(1)
          lin = nn.Linear(5, 3) # maps from R^5 to R^3, parameters A, b
          # data is 2x5. A maps from 5 to 3... can we map 'data' under A?
          data = torch.randn(2, 5)
          print(lin(data)) # yes
          • 輸出結(jié)果:

          tensor([[ 0.1755, -0.3268, -0.5069],
                  [-0.6602, 0.2260, 0.1089]], grad_fn=<AddmmBackward>)

          1.2 非線性函數(shù)

          首先,注意以下這個例子,它將解釋為什么我們需要非線性函數(shù)。假設(shè)我們有兩個仿射變換。

          那么又是什么呢?
          是一個矩陣,
          是一個向量,可以看出,兩個仿射變換的組合還是一個仿射變換。
          由此可以看出,使用以上方法將多個仿射變換組合成的長鏈式的神經(jīng)網(wǎng)絡(luò),相對于單個仿射變換并沒有性能上的提升。
          但是如果我們在兩個仿射變換之間引入非線性,那么結(jié)果就大不一樣了,我們可以構(gòu)建出一個高性能的模型。
          最常用的核心的非線性函數(shù)有:
          ,
          。
          你可能會想:“為什么是這些函數(shù)?明明有其他更多的非線性函數(shù)。”這些函數(shù)常用的原因是它們擁有可以容易計算的梯度,而計算梯度是學(xué)習(xí)的本質(zhì)。例如:

          注意:盡管你可能在AI課程的介紹中學(xué)習(xí)了一些神經(jīng)網(wǎng)絡(luò),在這些神經(jīng)網(wǎng)絡(luò)中

          σ(x)是默認非線性的,但是通常在實際使用的過程中都會避開它們。這是因為當參數(shù)的絕對值增長時,梯度會很快消失。小梯度意味著很難學(xué)習(xí)。因此大部分人默認選擇tanh或者ReLU。
          # 在pytorch中,大多數(shù)非線性都在torch.函數(shù)中(我們將它導(dǎo)入為F)
          # 請注意,非線性通常沒有像仿射圖那樣的參數(shù)。
          # 也就是說,他們沒有在訓(xùn)練期間更新的權(quán)重。
          data = torch.randn(2, 2)
          print(data)
          print(F.relu(data))
          • 輸出結(jié)果:

          tensor([[-0.5404, -2.2102],
                  [ 2.1130, -0.0040]])
          tensor([[0.0000, 0.0000],
                  [2.1130, 0.0000]])

          1.3 Softmax和概率

          Softmax(x)也是一個非線性函數(shù),但它的特殊之處在于,它通常是神經(jīng)網(wǎng)絡(luò)的最后一個操作。這是因為它接受實數(shù)向量,并且返回一個概率分布。它的定義如下。設(shè)x為實數(shù)向量(正、負,無論什么,沒有約束)。然后Softmax(x)的第i個分量是:

          很明顯,輸出的是一個概率分布:每一個元素都非負且和為1。

          你也可以認為這只是一個對輸入的元素進行的求冪運算符,使所有的內(nèi)容都非負,然后除以規(guī)范化常量。

          # Softmax也在torch.nn.functional中
          data = torch.randn(5)
          print(data)
          print(F.softmax(data, dim=0))
          print(F.softmax(data, dim=0).sum()) # 總和為1,因為它是一個分布!
          print(F.log_softmax(data, dim=0)) # theres also log_softmax
          • 輸出結(jié)果:

          tensor([ 1.3800, -1.3505, 0.3455, 0.5046, 1.8213])
          tensor([0.2948, 0.0192, 0.1048, 0.1228, 0.4584])
          tensor(1.)
          tensor([-1.2214, -3.9519, -2.2560, -2.0969, -0.7801])

          1.4 目標函數(shù)

          目標函數(shù)正是神經(jīng)網(wǎng)絡(luò)通過訓(xùn)練來最小化的函數(shù)(因此,它常常被稱作損失函數(shù)或者成本函數(shù))。

          這需要首先選擇一個訓(xùn)練數(shù)據(jù)實例,通過神經(jīng)網(wǎng)絡(luò)運行它并計算輸出的損失。然后通過損失函數(shù)的導(dǎo)數(shù)來更新模型的參數(shù)。因此直觀來講,如果它的結(jié)果是錯誤的,而模型完全信任他,那么損失將會很高。反之,當模型信任計算結(jié)果而結(jié)果正確時,損失會很低。

          在你的訓(xùn)練實例中最小化損失函數(shù)的目的是使你的網(wǎng)絡(luò)擁有很好的泛化能力,可以在開發(fā)數(shù)據(jù)集,測試數(shù)據(jù)集以及實際生產(chǎn)中擁有很小的損失。

          損失函數(shù)的一個例子是負對數(shù)似然損失函數(shù),這個函數(shù)經(jīng)常在多級分類中出現(xiàn)。在監(jiān)督多級分類中,這意味著訓(xùn)練網(wǎng)絡(luò)最小化正確輸出的負對數(shù)概率(等效的于最大化正確輸出的對數(shù)概率)。

          2.優(yōu)化和訓(xùn)練

          那么,我們該怎么計算函數(shù)實例的損失函數(shù)呢?我們應(yīng)該做什么呢?我們在之前了解到 TensorFlow 中的 Tensor 知道如何計算梯度以及計算梯度相關(guān)的東西。由于我們的損失正是一個 Tensor ,因此我們可以使用所有與梯度有關(guān)的參數(shù)來計算梯度。然后我們可以進行標準梯度更新。

          設(shè)θ為我們的參數(shù),

          為損失函數(shù),η一個正的學(xué)習(xí)率。然后,

          目前,有大量的算法和積極的研究試圖做一些除了這種普通的梯度更新以外的事情。許多人嘗試去基于訓(xùn)練時發(fā)生的事情來改變學(xué)習(xí)率。但是,你不需要擔(dān)心這些特殊的算法到底在干什么,除非你真的很感興趣。

          Torch提供了大量的算法在torch.optim包中,且全部都是透明的。在語法上使用復(fù)雜的算法和使用最簡單的梯度更新一樣簡單。但是嘗試不同的更新算法和在更新算法中使用不同的參數(shù)(例如不同的初始學(xué)習(xí)率)對于優(yōu)化你的網(wǎng)絡(luò)的性能很重要。通常,僅僅將普通的SGD替換成一個例如Adam或者RMSProp優(yōu)化器都可以顯著的提升性能。

          3.使用PyTorch創(chuàng)建網(wǎng)絡(luò)組件

          在我們繼續(xù)關(guān)注 NLP 之前,讓我們先使用PyTorch構(gòu)建一個只用仿射變換和非線性函數(shù)組成的網(wǎng)絡(luò)示例。我們也將了解如何計算損失函數(shù),使用PyTorch內(nèi)置的負對數(shù)似然函數(shù),以及通過反向傳播更新參數(shù)。

          所有的網(wǎng)絡(luò)組件應(yīng)該繼承nn.Module并覆蓋forward()方法。繼承nn.Module提供給了一些方法給你的組件。例如,它可以跟蹤可訓(xùn)練的參數(shù),你可以通過.to(device)方法在 CPU 和 GPU 之間交換它們。

          .to(device)方法中的 device 可以是CPU設(shè)備torch.device('cpu')或者 CUDA 設(shè)備torch.device('cuda:0')

          讓我們寫一個神經(jīng)網(wǎng)絡(luò)的示例,它接受一些稀疏的BOW(詞袋模式)表示,然后輸出分布在兩個標簽上的概率:“English”和“Spanish”。這個模型只是一個邏輯回歸。

          3.1 示例: 基于邏輯回歸與詞袋模式的文本分類器

          我們的模型將會把BOW表示映射成標簽上的對數(shù)概率。我們?yōu)樵~匯中的每個詞指定一個索引。例如,我們所有的詞匯是兩個單詞“hello”和'world',用0和1表示。句子“hello hello hello hello”的表示是

          [4,0]

          對于“hello world world hello”, 則表示成

          [2,2]

          通常表示成

          [Count(hello),Count(world)]

          用x來表示這個BOW向量。網(wǎng)絡(luò)的輸出是:

          也就是說,我們數(shù)據(jù)傳入一個仿射變換然后做對數(shù)歸一化logsoftmax。

          data = [('me gusta comer en la cafeteria'.split(), 'SPANISH'),
                  ('Give it to me'.split(), 'ENGLISH'),
                  ('No creo que sea una buena idea'.split(), 'SPANISH'),
                  ('No it is not a good idea to get lost at sea'.split(), 'ENGLISH')]

          test_data = [('Yo creo que si'.split(), 'SPANISH'),
                       ('it is lost on me'.split(), 'ENGLISH')]

          # word_to_ix maps each word in the vocab to a unique integer, which will be its
          # index into the Bag of words vector
          word_to_ix = {}
          for sent, _ in data + test_data:
              for word in sent:
                  if word not in word_to_ix:
                      word_to_ix[word] = len(word_to_ix)
          print(word_to_ix)

          VOCAB_SIZE = len(word_to_ix)
          NUM_LABELS = 2

          class BoWClassifier(nn.Module):  # inheriting from nn.Module!

              def __init__(self, num_labels, vocab_size):
                  # calls the init function of nn.Module. Dont get confused by syntax,
                  # just always do it in an nn.Module
                  super(BoWClassifier, self).__init__()

                  # Define the parameters that you will need. In this case, we need A and b,
                  # the parameters of the affine mapping.
                  # Torch defines nn.Linear(), which provides the affine map.
                  # Make sure you understand why the input dimension is vocab_size
                  # and the output is num_labels!
                  self.linear = nn.Linear(vocab_size, num_labels)

                  # NOTE! The non-linearity log softmax does not have parameters! So we don't need
                  # to worry about that here

              def forward(self, bow_vec):
                  # Pass the input through the linear layer,
                  # then pass that through log_softmax.
                  # Many non-linearities and other functions are in torch.nn.functional
                  return F.log_softmax(self.linear(bow_vec), dim=1)

          def make_bow_vector(sentence, word_to_ix):
              vec = torch.zeros(len(word_to_ix))
              for word in sentence:
                  vec[word_to_ix[word]] += 1
              return vec.view(1, -1)

          def make_target(label, label_to_ix):
              return torch.LongTensor([label_to_ix[label]])

          model = BoWClassifier(NUM_LABELS, VOCAB_SIZE)

          # 模型知道它的參數(shù)。下面的第一個輸出是A,第二個輸出是b。
          # 無論何時將組件分配給模塊的__init__函數(shù)中的類變量,都是使用self.linear = nn.Linear(...)行完成的。
          # 然后通過PyTorch,你的模塊(在本例中為BoWClassifier)將存儲nn.Linear參數(shù)的知識
          for param in model.parameters():
              print(param)

          # 要運行模型,請傳入BoW矢量
          # 這里我們不需要訓(xùn)練,所以代碼包含在torch.no_grad()中
          with torch.no_grad():
              sample = data[0]
              bow_vector = make_bow_vector(sample[0], word_to_ix)
              log_probs = model(bow_vector)
              print(log_probs)
          • 輸出結(jié)果:

          {'me': 0, 'gusta': 1, 'comer': 2, 'en': 3, 'la': 4, 'cafeteria': 5, 'Give': 6, 'it': 7, 'to': 8, 'No': 9, 'creo': 10, 'que': 11, 'sea': 12, 'una': 13, 'buena': 14, 'idea': 15, 'is': 16, 'not': 17, 'a': 18, 'good': 19, 'get': 20, 'lost': 21, 'at': 22, 'Yo': 23, 'si': 24, 'on': 25}
          Parameter containing:
          tensor([[ 0.1194, 0.0609, -0.1268, 0.1274, 0.1191, 0.1739, -0.1099, -0.0323,
                   -0.0038, 0.0286, -0.1488, -0.1392, 0.1067, -0.0460, 0.0958, 0.0112,
                    0.0644, 0.0431, 0.0713, 0.0972, -0.1816, 0.0987, -0.1379, -0.1480,
                    0.0119, -0.0334],
                  [ 0.1152, -0.1136, -0.1743, 0.1427, -0.0291, 0.1103, 0.0630, -0.1471,
                    0.0394, 0.0471, -0.1313, -0.0931, 0.0669, 0.0351, -0.0834, -0.0594,
                    0.1796, -0.0363, 0.1106, 0.0849, -0.1268, -0.1668, 0.1882, 0.0102,
                    0.1344, 0.0406]], requires_grad=True)
          Parameter containing:
          tensor([0.0631, 0.1465], requires_grad=True)
          tensor([[-0.5378, -0.8771]])

          上面的哪一個值對應(yīng)的是 ENGLISH 的對數(shù)概率,哪一個是SPANISH的對數(shù)概率?我們還沒有定義,但是如果我必須要定義我們想要訓(xùn)練的東西。

          label_to_ix = {'SPANISH': 0, 'ENGLISH': 1}

          讓我們來訓(xùn)練吧! 我們將實例傳入來獲取對數(shù)概率,計算損失函數(shù),計算損失函數(shù)的梯度,然后使用一個梯度步長來更新參數(shù)。在PyTorch的nn包里提供了損失函數(shù)。nn.NLLLoss()是我們想要的負對數(shù)似然損失函數(shù)。torch.optim中也定義了優(yōu)化方法。這里,我們只使用SGD。

          注意,因為NLLLoss的輸入是一個對數(shù)概率的向量以及目標標簽。它不會為我們計算對數(shù)概率。這也是為什么我們最后一層網(wǎng)絡(luò)是log_softmax的原因。損失函數(shù)nn.CrossEntropyLoss()除了對結(jié)果額外計算了logsoftmax之外,和NLLLoss()沒什么區(qū)別。

          # 在我們訓(xùn)練之前運行測試數(shù)據(jù),只是為了看到之前-之后
          with torch.no_grad():
              for instance, label in test_data:
                  bow_vec = make_bow_vector(instance, word_to_ix)
                  log_probs = model(bow_vec)
                  print(log_probs)

          # 打印與“creo”對應(yīng)的矩陣列
          print(next(model.parameters())[:, word_to_ix['creo']])

          loss_function = nn.NLLLoss()
          optimizer = optim.SGD(model.parameters(), lr=0.1)

          # 通常,您希望多次傳遞訓(xùn)練數(shù)據(jù).
          # 100比實際數(shù)據(jù)集大得多,但真實數(shù)據(jù)集有兩個以上的實例。
          # 通常,在5到30個epochs之間是合理的。
          for epoch in range(100):
              for instance, label in data:
                  # 步驟1:請記住,PyTorch會累積梯度。
                  # We need to clear them out before each instance
                  model.zero_grad()

                  # 步驟2:制作我們的BOW向量,并且我們必須將目標作為整數(shù)包裝在Tensor中。
                  # 例如,如果目標是SPANISH,那么我們包裝整數(shù)0.
                  # 然后,loss函數(shù)知道對數(shù)概率的第0個元素是對應(yīng)于SPANISH的對數(shù)概率
                  bow_vec = make_bow_vector(instance, word_to_ix)
                  target = make_target(label, label_to_ix)

                  # 步驟3:運行我們的前向傳遞.
                  log_probs = model(bow_vec)

                  # 步驟4:通過調(diào)用optimizer.step()來計算損失,梯度和更新參數(shù)
                  loss = loss_function(log_probs, target)
                  loss.backward()
                  optimizer.step()

          with torch.no_grad():
              for instance, label in test_data:
                  bow_vec = make_bow_vector(instance, word_to_ix)
                  log_probs = model(bow_vec)
                  print(log_probs)

          # 對應(yīng)西班牙語的指數(shù)上升,英語下降!
          print(next(model.parameters())[:, word_to_ix['creo']])
          • 輸出結(jié)果:

          tensor([[-0.9297, -0.5020]])
          tensor([[-0.6388, -0.7506]])
          tensor([-0.1488, -0.1313], grad_fn=<SelectBackward>)
          tensor([[-0.2093, -1.6669]])
          tensor([[-2.5330, -0.0828]])
          tensor([ 0.2803, -0.5605], grad_fn=<SelectBackward>)

          我們得到了正確的結(jié)果!你可以看到Spanish的對數(shù)概率比第一個例子中的高的多,English的對數(shù)概率在第二個測試數(shù)據(jù)中更高,結(jié)果也應(yīng)該是這樣。

          現(xiàn)在你了解了如何創(chuàng)建一個PyTorch組件,將數(shù)據(jù)傳入并進行梯度更新。現(xiàn)在我們已經(jīng)可以開始進行深度學(xué)習(xí)上的自然語言處理了。

          想要PyTorch視頻學(xué)習(xí)資料嗎?請戳:

          PyTorch 中文版官方視頻教程-60分鐘快速入門:

          https://www.bilibili.com/video/av66421076/

          本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
          打開APP,閱讀全文并永久保存 查看更多類似文章
          猜你喜歡
          類似文章
          深度學(xué)習(xí)之PyTorch實戰(zhàn)(1)
          還不會使用PyTorch框架進行深度學(xué)習(xí)的小伙伴,看過來
          PyTorch學(xué)習(xí)系列教程:何為Tensor?
          PyTorch 深度學(xué)習(xí)入門
          卷積神經(jīng)網(wǎng)絡(luò)超詳細的代碼實現(xiàn)篇
          Pytorch中交叉熵Loss趣解
          更多類似文章 >>
          生活服務(wù)
          分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
          綁定賬號成功
          后續(xù)可登錄賬號暢享VIP特權(quán)!
          如果VIP功能使用有故障,
          可點擊這里聯(lián)系客服!

          聯(lián)系客服