久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    PyTorch專欄(十七): 使用PyTorch進行深度學習

     taotao_2016 2019-10-16

    【磐創AI 導讀】:本篇文章講解了PyTorch專欄的第五章中在深度學習和NLP中使用Pytorch部分的第一小節使用PyTorch進行深度學習查看關于本專欄的介紹:PyTorch專欄開篇查看本章歷史文章,請點擊下方藍色字體進入相應鏈接閱讀。

    專欄目錄:
    第五章:PyTorch之文本篇
    • 使用Sequence2Sequence網絡和注意力進行翻譯

    使用PyTorch進行深度學

    1.深度學習構建模塊:仿射變換, 非線性函數以及目標函數

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

    1.1 仿射變換

    深度學習的核心組件之一是仿射變換,仿射變換是一個關于矩陣A和向量x,b的函數,如下所示

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

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

    # 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
    • 輸出結果:

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

    1.2 非線性函數

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

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

    注意:盡管你可能在AI課程的介紹中學習了一些神經網絡,在這些神經網絡中

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

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

    1.3 Softmax和概率

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

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

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

    # 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
    • 輸出結果:

    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 目標函數

    目標函數正是神經網絡通過訓練來最小化的函數(因此,它常常被稱作損失函數或者成本函數)。

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

    在你的訓練實例中最小化損失函數的目的是使你的網絡擁有很好的泛化能力,可以在開發數據集,測試數據集以及實際生產中擁有很小的損失。

    損失函數的一個例子是負對數似然損失函數,這個函數經常在多級分類中出現。在監督多級分類中,這意味著訓練網絡最小化正確輸出的負對數概率(等效的于最大化正確輸出的對數概率)。

    2.優化和訓練

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

    設θ為我們的參數,為損失函數,η一個正的學習率。然后,

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

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

    3.使用PyTorch創建網絡組件

    在我們繼續關注 NLP 之前,讓我們先使用PyTorch構建一個只用仿射變換和非線性函數組成的網絡示例。我們也將了解如何計算損失函數,使用PyTorch內置的負對數似然函數,以及通過反向傳播更新參數。

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

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

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

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

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

    [4,0]

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

    [2,2]

    通常表示成

    [Count(hello),Count(world)]

    用x來表示這個BOW向量。網絡的輸出是:

    也就是說,我們數據傳入一個仿射變換然后做對數歸一化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)

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

    # 要運行模型,請傳入BoW矢量
    # 這里我們不需要訓練,所以代碼包含在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)
    • 輸出結果:

    {'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]])

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

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

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

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

    # 在我們訓練之前運行測試數據,只是為了看到之前-之后
    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”對應的矩陣列
    print(next(model.parameters())[:, word_to_ix['creo']])

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

    # 通常,您希望多次傳遞訓練數據.
    # 100比實際數據集大得多,但真實數據集有兩個以上的實例。
    # 通常,在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向量,并且我們必須將目標作為整數包裝在Tensor中。
            # 例如,如果目標是SPANISH,那么我們包裝整數0.
            # 然后,loss函數知道對數概率的第0個元素是對應于SPANISH的對數概率
            bow_vec = make_bow_vector(instance, word_to_ix)
            target = make_target(label, label_to_ix)

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

            # 步驟4:通過調用optimizer.step()來計算損失,梯度和更新參數
            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)

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

    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>)

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

    現在你了解了如何創建一個PyTorch組件,將數據傳入并進行梯度更新。現在我們已經可以開始進行深度學習上的自然語言處理了。

    想要PyTorch視頻學習資料嗎?請戳:

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

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

      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 一本之道高清乱码少妇 | 国产精品福利中文字幕| 国产成人午夜福利院| 色综合久久久久综合99| 男人狂桶女人出白浆免费视频 | 久久超碰色中文字幕超清| 野花免费社区在线| 综合色一色综合久久网| 久久无码人妻丰满熟妇区毛片| 亚洲人成网网址在线看| 久久男人AV资源网站| 精品日韩人妻中文字幕| 日本XXXX色视频在线观看免费| 男女动态无遮挡动态图| 色橹橹欧美在线观看视频高清 | 日本一道一区二区视频| 久久婷婷综合色丁香五月| 亚洲国产中文字幕精品| 欧美性XXXX极品HD欧美风情| 高清自拍亚洲精品二区| 69久久夜色精品国产69| 久久这里精品国产99丫E6| 男人扒开女人腿桶到爽免费| 一道本AV免费不卡播放| 一区二区三区精品不卡| 饥渴的少妇2中文字幕| 国产精品久久福利新婚之夜| 欧美野外伦姧在线观看| 狠狠色丁香婷婷综合尤物| 成人午夜大片免费看爽爽爽| 亚洲欧洲中文日韩久久AV乱码| 男同精品视频免费观看网站| 双乳奶水饱满少妇呻吟免费看| 国色天香天天影院综合网| 国产破外女出血视频| 亚洲av无码乱码在线观看野外 | 国产在线午夜不卡精品影院| 免费观看的AV毛片的网站| 亚洲最大成人网色| 草裙社区精品视频播放| 国产精品久久露脸蜜臀|