當前位置:
首頁 > 最新 > pytorch深度學習和自然語言處理入門

pytorch深度學習和自然語言處理入門

之前也提過,pytorch之於tensorflow,優雅不是一星半點。

pytorch學習是輕鬆愉快了。本期文章寫pytorch在nlp上的應用。(paul allen的allennlp也由tensorflow遷移到了pytorch平台,可見一斑)

導入模塊:

import torch

import torch.autograd as autograd

import torch.nn as nn

import torch.optim as optim

torch.manual_seed(1)

一、線性模塊,這裡需要注意是y = xw+b。不是我們數學上習慣的y=wx+b(矩陣是不滿足乘法交換率的)

定義一個全連接層,也就是線性仿射變換。W=(5,3),b=(3)

lin = nn.Linear(5,3)

這裡需要特別注意,輸入變數是n*5,輸出為n*3

data = autograd.Variable(torch.randn(2,5))

lin(data)

運算得到結果如下:

Variable containing:-0.2889 0.3574 0.6554-0.9682 0.0289 0.4426[torch.FloatTensor of size 2x3]

二、非線性激活函數

常用的Relu和tanh。sigmoid因為梯度消失的問題,反而不常用。從理論上講,非線性的激活函數可以無窮多,為什麼選這兩個?這是工程上的問題,因為它們的導數形式便於計算

我們用隨機正態分布,初始化2*2的矩陣。

data = autograd.Variable(torch.randn(2,2))

Variable containing:-0.6331 0.8795-0.6842 0.4533[torch.FloatTensor of size 2x2]

把變數經由relu計算(Rectified Linear Unit,修正線性單元),relu的公式很簡單=max(0,x),就是如果x>0,就取x,否則取0,就是把負的信號給屏蔽了。

F.relu(data)

Variable containing: 0.0000 0.8795 0.0000 0.4533[torch.FloatTensor of size 2x2]

下圖的藍線是relu

對比sigmoid類函數主要變化是:

1)單側抑制

2)相對寬闊的興奮邊界

3)稀疏激活性。

這與人的神經皮層的工作原理接近。

另外一個很重要的激活函數就是softmax。

data = autograd.Variable(torch.randn(2,2))

Variable containing:-0.3968 -0.6571-1.6428 0.9803[torch.FloatTensor of size 2x2]

F.softmax(data,dim=0),dim=0,按第0維softmax,就是概率化。這個函數在輸出層很有用,比如mnist要分成10類,那softmax就是這10類對應的概率。概率最大者就是對應的分類。(概率思維也在這裡體現了)

Variable containing: 0.7766 0.1628 0.2234 0.8372[torch.FloatTensor of size 2x2]

還有一個類似的函數F.log_softmax()也是工程上的考慮,因為最小二乘損失函數求導要會帶來計算量的問題,所以考慮交叉熵損失。與之配合的就是這個對數softmax

三、目標函數。也就是反身傳播要優化的目標。也稱為成本函數或損失函數。

四,詞袋模型(Bag-Of-Words=BOW),應該算最簡單的語言模型,不考慮詞的位置,就是數數。比如辭彙表如果就兩個詞,hello,world。那麼"hello hello hello hello" = [4,0],"hello world hello world"=[2,2],即所謂語言模型,就是對一個字元串,或文章內容,如何進行編碼,轉為計算機和pytorch可以處理的向量或矩陣類型。這裡的數字就是表達詞的出現次數

用這個最簡單的BOW,來對西班牙語和英語做分類。

先定義最簡單的訓練語料和測試語料。

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_2_idx = {}

for sent,_ in data + test_data:

print(sent)

for word in sent:

if word not in word_2_idx:

#這裡用的是這個word首次出現的位置,比如me就是第1個出現的,下標為0

word_2_idx[word] = len(word_2_idx)

有了辭彙表,就可以算辭彙表的長度,以及我們需要把句子分成兩類。

VOCAB_SIZE = len(word_2_idx)

NUM_LABELS = 2

神經網路模型:

class BoWClassifier(nn.Module): # 從nn.Module繼承bow分類器

def __init__(self, num_labels, vocab_size):

#父類初始化

super(BoWClassifier, self).__init__()

self.linear = nn.Linear(vocab_size, num_labels)

def forward(self, bow_vec):

#bow_vec是詞的bow向量

return F.log_softmax(self.linear(bow_vec))

把句子變成向量:

就是用句子里的詞,去辭彙表裡查下標,在向量對應的位置加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

#vec本來是個向量,變形成1*N的矩陣

return vec.view(1, -1)

make_bow_vector("Give it to me".split(),word_2_idx)

在用戶手動定義Variable時,參數requires_grad默認值是False。而在Module中的層在定義時,相關Variable的requires_grad參數默認是True。

在計算圖中,如果有一個輸入的requires_grad是True,那麼輸出的requires_grad也是True。只有在所有輸入的requires_grad都為False時,輸出的requires_grad才為False。

關於作者:魏佳斌,互聯網產品/技術總監,北京大學光華管理學院(MBA),特許金融分析師(CFA),資深產品經理/碼農。偏愛python,深度關注互聯網趨勢,人工智慧,AI金融量化。致力於使用最前沿的認知技術去理解這個複雜的世界。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI量化實驗室 的精彩文章:

實戰:基於django+nuxt前後端分離的web產品架構

TAG:AI量化實驗室 |