欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    允中 發(fā)自 凹非寺

    量子位 報道 | 公眾號

    編者按:

    語言模型的身影遍布在NLP研究中的各個角落,想要了解NLP領(lǐng)域,就不能不知道語言模型。

    想要讓模型能落地奔跑,就需借助深度學(xué)習(xí)框架之力,、自然是主流,但在都成獨(dú)家專利之后,不儲備“B計劃”,多少讓人有些擔(dān)驚受怕

    這里有一份飛槳()語言模型應(yīng)用實例,從基礎(chǔ)概念到代碼實現(xiàn),娓娓道來,一一說明。現(xiàn)在,量子位分享轉(zhuǎn)載如下,宜學(xué)習(xí),宜收藏。

    剛?cè)腴T深度學(xué)習(xí)與自然語言處理(NLP)時,在學(xué)習(xí)了 特別棒的入門書 ,斯坦福 等等后,也無限次起念頭,寫個系列吧,但都不了了之了。

    近來,NLP 領(lǐng)域因為超大預(yù)訓(xùn)練模型,很多研究需要耗費(fèi)大量計算資源(比如百度新發(fā)布持續(xù)學(xué)習(xí)語義理解框架 ERNIE 2.0,該模型在共計 16 個中英文任務(wù)上超越了 BERT 和 XLNet,取得了 SOTA 效果),這樣的項目基本上就是在燒錢,小家小戶玩不起,于是就傻傻地等著大佬們發(fā)出論文,放出代碼,刷新榜單。不過這也意味著一個總結(jié)的好機(jī)會,加上額外的推動,便重新起了念頭。

    這個系列會介紹我認(rèn)為現(xiàn)代 NLP 最重要的幾個主題,同時包括它們的實現(xiàn)與講解。

    這里會使用的百度的開源深度學(xué)習(xí)平臺飛槳(),關(guān)于這點(diǎn),有如下幾個原因。

    首先,不久前和一個科技媒體朋友聊天,因為當(dāng)時封鎖華為事件的原因,聊到了美國企業(yè)是否可能對我們封鎖深度學(xué)習(xí)框架,比如說主流的 和 ,我當(dāng)時答是說不定可能呢,畢竟谷歌連 都能去申請專利。只要之后改一下許可,不讓使用這些框架的更新,估計我們也沒辦法,于是就想著可以了解一下國內(nèi)百度的框架飛槳。

    去飛槳的 看了一下,內(nèi)容很豐富,感覺飛槳對 NLP 這塊支持非常好,值得關(guān)注。

    項目地址:

    語言模型

    現(xiàn)代 NLP 領(lǐng)域的一個核心便是語言模型 ( Model),可以說它無處不在,一方面它給 NLP 發(fā)展帶來巨大推動,是多個領(lǐng)域的關(guān)鍵部分,但另一方面,成也蕭何敗也蕭何,語言模型其實也限制了 NLP 發(fā)展,比如說在創(chuàng)新性生成式任務(wù)上,還有如何用語言模型獲得雙向信息。

    那到底什么是語言模型?

    什么是語言模型

    就是語言的模型(認(rèn)真臉),開個玩笑,語言模型通俗點(diǎn)講其實就是判斷一句話是不是人話,正式點(diǎn)講就是計算一句話的概率,這個概率值表示這個本文有多大概率是一段正常的文本。

    對于一句話,比如說用臉滾出來的一句話:“哦他發(fā)看和了犯點(diǎn)就看見發(fā)”,很明顯就不像人話,所以語言模型判斷它是人話的概率就小。而一句很常用的話:“好的,謝謝”,語言模型就會給它比較高的概率評分。

    用數(shù)學(xué)的方式來表示,語言模型需要獲得這樣的概率:

    其中 X 表示句子,x1,x2… 代表句子中的詞。怎么計算這樣一個概率呢,一個比較粗暴的方法就是有個非常非常大的語料庫,里面有各種各樣的句子,然后我們一個個數(shù),來計算不同句子的概率,但稍微想想就知道這個方法不太可能,因為句子組合無窮無盡。

    為更好計算,利用條件概率公式和鏈?zhǔn)椒▌t,按照從左到右的句序,可以將公式轉(zhuǎn)換成:

    題變成了如何求解:

    怎么根據(jù)前面所有的詞預(yù)測下一個詞,當(dāng)然這個問題對于現(xiàn)在還有點(diǎn)復(fù)雜,之后可以用 RNN 模型來計算,但現(xiàn)在讓我們先假設(shè)對于一個詞離它近的詞重要性更大,于是基于馬爾可夫性假設(shè),一個詞只依賴它前面 n-1 個詞,這種情況下的語言模型就被稱為 N-gram 語言模型。

    比如說基于前面2個詞來預(yù)測下一個詞就是 3-gram (tri-gram) 語言模型:

    細(xì)心些的話,會發(fā)現(xiàn),當(dāng) n-gram 中的 n 增大,就會越接近原始語言模型概率方程。

    當(dāng)然n并不是越大越好,因為一旦n過大,計算序列就會變長,在計算時 n-gram 時詞表就會太大,也就會引發(fā)所謂的 The Curse of (維度災(zāi)難) 。因此一般大家都將n的大小取在3,4,5附近。

    早期實現(xiàn):數(shù)一數(shù)就知道了

    最早了解類似語言模型計算概率,是在研究生階段當(dāng)時號稱全校最難的信息論課上,老師強(qiáng)烈安利香農(nóng)的經(jīng)典論文 A of ,論文中有一小節(jié)中,他就給利用類似計算上述語言模型概率的方法,生成了一些文本。

    其中一個就是用 2-gram (bi-gram) 的頻率表來生成的,這已經(jīng)相當(dāng)于一個 bi-gram 語言模型了。

    同樣,要構(gòu)建這樣一個 n-gram 語言模型,最主要工作就是,基于大量文本來統(tǒng)計 n-gram 頻率。

    當(dāng)時有個課程作業(yè),就是先準(zhǔn)備一些英文文本,然后一個一個數(shù) n-gram,之后除以總數(shù)算出語言模型中需要的概率估計值,這種方法叫 Count-based Model。

    傳統(tǒng) NLP 中搭建語言模型便是這樣,當(dāng)然還有更多技巧,比如平滑算法,具體可以參考 教授的書和課。

    但這種方法會有一個很大的問題,那就是前面提到的維度災(zāi)難,而這里要實現(xiàn)的神經(jīng)網(wǎng)絡(luò)語言模型( Model),便是用神經(jīng)網(wǎng)絡(luò)構(gòu)建語言模型,通過學(xué)習(xí)分布式詞表示(即詞向量)的方式解決了這個問題。

    語言模型能干什么

    不過在談神經(jīng)網(wǎng)絡(luò)語言模型前,我們先來看看語言模型的用途。

    那它有什么用呢,如之前提到,語言模型可以說是現(xiàn)代 NLP 核心之一,無處不在。比如說詞向量,最早算是語言模型的副產(chǎn)品;同時經(jīng)典的序列到序列() 模型,其中解碼器還可以被稱為, Model(條件語言模型);而現(xiàn)在大火的預(yù)訓(xùn)練模型,主要任務(wù)也都是語言模型。

    在實際 NLP 應(yīng)用中,我認(rèn)為能總結(jié)成以下三條:

    第一,給句子打分,排序。先在大量文本上訓(xùn)練,之后就能用獲得的語言模型來評估某句話的好壞。這在對一些生成結(jié)果進(jìn)行重排序時非常有用,能很大程度地提高指標(biāo),機(jī)器翻譯中有一個技巧便是結(jié)合語言模型 Loss 來重排序生成的候選結(jié)果。

    第二,用于文本生成。首先其訓(xùn)練方式是根據(jù)前面詞,生成之后詞。于是只要不斷重復(fù)此過程(自回歸)就能生成長文本了。比較有名的例子就包括最近的 GPT2,其標(biāo)題就叫 “ and Their .” 它生成的句子效果真的非常棒,可以自己體驗一番

    第三,作為預(yù)訓(xùn)練模型的預(yù)訓(xùn)練任務(wù)。最近很火的預(yù)訓(xùn)練模型,幾乎都和語言模型脫不開關(guān)系。

    比如說 ELMo 就是先訓(xùn)練雙向 LSTM 語言模型,之后雙向不同層向量拼接獲得最后的 ELMo詞向量,還有 BERT 里最主要的方法就是 Model (遮掩語言模型)。

    而最近的 XLNet 中最主要訓(xùn)練任務(wù)也叫做 Model (排列語言模型),可見語言模型在其中的重要性重要性。

    神經(jīng)網(wǎng)絡(luò)語言模型架構(gòu)

    接下來簡單介紹一下這里要實現(xiàn)的網(wǎng)絡(luò)結(jié)構(gòu),借鑒自 的經(jīng)典論文 A Model 中的模型。

    這里我們訓(xùn)練 Tri-gram 語言模型,即用前面兩個詞預(yù)測當(dāng)前詞。

    于是輸入就是兩個單詞,然后查表取出對應(yīng)詞向量,之后將兩個詞向量拼接起來,過一個線性層,加入 tanh 激活函數(shù),最后再過線性層輸出分?jǐn)?shù),通過 將分?jǐn)?shù)轉(zhuǎn)換成對各個詞預(yù)測的概率,一般取最大概率位置為預(yù)測詞。

    用公式表達(dá)整個過程就是:

    整個結(jié)構(gòu)非常簡單,接下來就來看看如何用 飛槳來實現(xiàn)這個結(jié)構(gòu)吧,同時介紹以下 飛槳的基本思想,和一般訓(xùn)練流程。

    項目地址:

    代碼基本實現(xiàn)

    這里拿一個小例子來解說,假設(shè)我們在一個叫做 的世界,這個世界的人們只會說三句話,每句話三個詞,我們需要建立一個 Tri-gram 語言模型,來通過一句話前兩個詞預(yù)測下一個詞。

    關(guān)于整個流程,主要分成準(zhǔn)備,數(shù)據(jù)預(yù)處理,模型構(gòu)建,訓(xùn)練,保存,預(yù)測幾個階段,這也是一般一個 NLP 任務(wù)的基礎(chǔ)流程。

    準(zhǔn)備

    首先,先導(dǎo)入需要的庫。

    import numpy as np 
    import paddle 
    import paddle.fluid as fluid
    

    之后準(zhǔn)備訓(xùn)練數(shù)據(jù)與詞表,統(tǒng)計所有不同詞,建立詞表,然后按照順序建立一個單詞到 id 的映射表和配套的 id 到單詞映射表。因為模型無法直接讀這些詞,所以需要單詞與 id 之間的轉(zhuǎn)換。

    # 假設(shè)在這個叫做Paddle的世界里,人們只會說這三句話 
    sentences = ["我 喜歡 Paddle", "Paddle 等于 飛槳", "我 會 Paddle"] 
    vocab = set(' '.join(sentences).split(' ')) # 統(tǒng)計詞表 
    word2idx = {w: i for i, w in enumerate(word_list)} # 建立單詞到id映射表 
    idx2word = word_list # id到單詞的映射表 
    n_vocab = len(word2idx) # 詞表大小
    

    準(zhǔn)備好數(shù)據(jù)后,設(shè)置模型參數(shù)和訓(xùn)練相關(guān)參數(shù),因為任務(wù)很簡單,所以參數(shù)都設(shè)很小。

    # 參數(shù)設(shè)置 
    # 語言模型參數(shù) 
    n_step = 2 # 輸入前面多少個詞,tri-gram 所以取 3-1=2 個 
    n_hidden = 2 # 隱層的單元個數(shù) 
    # 訓(xùn)練參數(shù) 
    n_epochs = 5000 # 訓(xùn)練 epoch 數(shù) 
    word_dim = 2 # 詞向量大小 
    lr = 0.001 # 學(xué)習(xí)率 
    use_cuda = False #用不用GPU
    

    數(shù)據(jù)預(yù)處理

    根據(jù) 數(shù)據(jù)輸入要求,需要準(zhǔn)備數(shù)據(jù)讀取器 (),之后通過它來讀取數(shù)據(jù),對輸入數(shù)據(jù)進(jìn)行一些前處理,最后作為 batch 輸出。

    def sent_reader(): 
     def reader(): 
     batch = [] 
     for sent in sentences: 
     words = sent.split(' ') 
     input_ids = [word2idx[word] for word in words[:-1]] # 將輸入轉(zhuǎn)為id 
     target_id = word2idx[words[-1]] # 目標(biāo)轉(zhuǎn)為id 
     input = np.eye(n_vocab)[input_ids] # 將輸入id轉(zhuǎn)換成one_hot表示 
     target = np.array([target_id]) 
     batch.append((input, target)) 
     yield batch 
     return reader
    

    構(gòu)建模型

    這里從飛槳中較底層 API 來進(jìn)行構(gòu)建,理解更透徹。先創(chuàng)建所需參數(shù)矩陣,之后按照前面的公式來一步步運(yùn)算。

    def nnlm(one_hots): 
     # 創(chuàng)建所需參數(shù) 
     # 詞向量表 
     L = fluid.layers.create_parameter(shape=[n_vocab, word_dim], dtype='float32') 
     # 運(yùn)算所需參數(shù) 
     W1 = fluid.layers.create_parameter(shape=[n_step*word_dim, n_hidden], dtype='float32') 
     b1 = fluid.layers.create_parameter(shape=[n_hidden], dtype='float32', is_bias=True) 
     W2 = fluid.layers.create_parameter(shape=[n_hidden, n_vocab], dtype='float32') 
     b2 = fluid.layers.create_parameter(shape=[n_vocab], dtype='float32', is_bias=True) 
     # 取出詞向量 
     word_emb = fluid.layers.matmul(one_hots, L) 
     # 兩個詞向量拼接 
     input = fluid.layers.reshape(x=word_emb, shape=[-1, n_step*word_dim], inplace=True) 
     # 前向運(yùn)算 
     input2hid = fluid.layers.tanh(fluid.layers.matmul(input, W1) + b1) # 輸入到隱層 
     hid2out = fluid.layers.softmax(fluid.layers.matmul(input2hid, W2) + b2) # 隱層到輸出 
     return hid2out
    

    先根據(jù)輸入的獨(dú)熱(one-hot)向量,取出對應(yīng)的詞向量,因為每個例子輸入前兩個詞,因此每個例子可獲得兩個詞向量,之后按照步驟,將它們拼接起來,然后與 W1 和 b1 進(jìn)行運(yùn)算,過 tanh 非線性,最后再拿結(jié)果與 W2 和 b2 進(jìn)行運(yùn)算, 輸出結(jié)果。

    接下來構(gòu)建損失函數(shù),我們用常用的交叉熵(cross-)損失函數(shù),直接調(diào) API。

    def ce_loss(softmax, target): 
     cost = fluid.layers.cross_entropy(input=softmax, label=target) # 計算每個batch的損失 
     avg_cost = fluid.layers.mean(cost) # 平均 
     return avg_cost
    

    開始訓(xùn)練

    終于進(jìn)入了訓(xùn)練環(huán)節(jié),不過為了更好理解,先稍稍介紹一點(diǎn) 飛槳的設(shè)計思想。

    飛槳同時為用戶提供動態(tài)圖和靜態(tài)圖兩種計算圖。動態(tài)圖組網(wǎng)更加靈活、調(diào)試網(wǎng)絡(luò)便捷,實現(xiàn)AI 想法更快速;靜態(tài)圖部署方便、運(yùn)行速度快,應(yīng)用落地更高效。

    如果想了解飛槳動態(tài)圖更多內(nèi)容,可以參考項目地址:

    實際應(yīng)用中,靜態(tài)圖更為常見,下面我們以靜態(tài)圖為例介紹一個完整的實現(xiàn):

    首先,需要先定義 ,整個 中包括了各種網(wǎng)絡(luò)定義,操作等等,定義完之后,再創(chuàng)建一個 來運(yùn)行 ,用過類似框架的同學(xué)應(yīng)該并不陌生。

    因此先來看看這兩行代碼,fluid 中最重要的兩個 ,將它們?nèi)〕鰜怼?/p>

    startup_program = fluid.default_startup_program() # 默認(rèn)啟動程序 
    main_program = fluid.default_main_program() # 默認(rèn)主程序
    

    ram 主要定義了輸入輸出,創(chuàng)建模型參數(shù),還有可學(xué)習(xí)參數(shù)的初始化;而 則是定義了神經(jīng)網(wǎng)絡(luò)模型,前向反向,還有優(yōu)化算法的更新。

    之后將之前定義好的一些模塊放入訓(xùn)練代碼中。

    train_reader = sent_reader() # 獲取數(shù)據(jù) reader 
    # 定義輸入和目標(biāo)數(shù)據(jù) 
    input = fluid.layers.data(name='input', shape=[-1, n_step, n_vocab], dtype='float32') 
    target = fluid.layers.data(name='target', shape=[-1, 1], dtype='int64') 
    # 輸入到模型,獲得 loss 
    softmax = nnlm(input) 
    loss = ce_loss(softmax, target)
    之后還需要定義優(yōu)化器(Optimizer),還有數(shù)據(jù) Feeder 用于喂入數(shù)據(jù)。
    # 配置優(yōu)化器 
    optimizer = fluid.optimizer.Adam(learning_rate=0.001) # 萬金油的 Adam 
    optimizer.minimize(loss) 
    # 用于之后預(yù)測 
    prediction = fluid.layers.argmax(softmax, axis=-1) 
    # 定義 Executor 
    place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() # 指定運(yùn)行位置 
    exe = fluid.Executor(place) 
    #定義數(shù)據(jù) Feeder 
    feeder = fluid.DataFeeder(feed_list=[input, target], place=place) # 每次喂入input和target
    至此就完成了第一步的定義環(huán)節(jié),然后就可以用定義的 Executor 來執(zhí)行程序了。
    # 參數(shù)初始化 
    exe.run(startup_program) 
    # 訓(xùn)練 
    for epoch in range(n_epochs): 
     for data in train_reader(): 
     metrics = exe.run( 
     main_program, # 主程序 
     feed=feeder.feed(data), # 數(shù)據(jù)喂入 
     fetch_list=[loss]) # 要取出的數(shù)據(jù) 
     if epoch % 500 == 0: 
     print("Epoch {}, Cost {:.5f}".format(epoch, step, float(metrics[0][0])))
    

    簡單解釋一下代碼,訓(xùn)練時需要exe.run來執(zhí)行每一步的訓(xùn)練,對于run需要傳入主程序,還有輸入 ,和需要拿出來(fetch)的輸出。

    之后運(yùn)行就能看到訓(xùn)練 log 了。

    能明顯看到 loss 在不斷下降,等訓(xùn)練完成,我們就獲得一個訓(xùn)練好的模型。

    保存模型

    在預(yù)測前可以嘗試先保存一個模型,可以便于之后使用,比如 load 出來做預(yù)測。

    fluid.io.save_inference_model('./model', ['input'], [prediction], exe)
    

    很簡單,只需要傳入保存的路徑’./model’,預(yù)測需要 feed 的數(shù)據(jù)’input’,之后需要 fetch 出的預(yù)測結(jié)果 ,最后加上執(zhí)行器 exe,就 OK 了。

    非常快。

    預(yù)測階段

    預(yù)測階段其實和訓(xùn)練階段類似,但因為主程序都保存下來了,所以只用先建立執(zhí)行器 ,同時建立一個用于預(yù)測的作用域。

    infer_exe = fluid.Executor(place) # 預(yù)測 Executor 
    inference_scope = fluid.core.Scope() # 預(yù)測作用域
    

    然后在預(yù)測作用域中 load 出模型,進(jìn)行預(yù)測運(yùn)算,大部分操作都和訓(xùn)練很類似了。唯一不同就是 load 模型這塊,其實就是把之前保存下來的參數(shù)給 load 出來了,然后用于預(yù)測。

    with fluid.scope_guard(inference_scope): 
     [inference_program, feed_target_names, 
     fetch_targets] = fluid.io.load_inference_model('./model', infer_exe) # 載入預(yù)訓(xùn)練模型 
     infer_reader = sent_reader() # 定義預(yù)測數(shù)據(jù) reader 
     infer_data = next(infer_reader()) # 讀出數(shù)據(jù) 
     infer_feat = np.array([data[0] for data in infer_data]).astype("float32") 
     assert feed_target_names[0] == 'input' 
     results = infer_exe.run(inference_program, 
     feed={feed_target_names[0]: infer_feat}, 
     fetch_list=fetch_targets) # 進(jìn)行預(yù)測
    

    結(jié)果如何?

    for sent, idx in zip(sentences, results[0]):
     print("{} -> {}".format(' '.join(sent.split()[:2]), idx2word[idx]))
    我 喜歡 -> Paddle
    Paddle 等于 -> 飛槳
    我 會 -> Paddle
    

    模型完美地學(xué)習(xí)到了 世界中僅有的幾個 規(guī)則,當(dāng)然因為該任務(wù)非常簡單,所以模型一下就能學(xué)會。

    更多嘗試

    在了解完以上這個小例子之后,就能在它基礎(chǔ)上做很多修改了,感興趣的同學(xué)不妨拿下面的幾個思路作為練習(xí)。

    比如說用一個大數(shù)據(jù)集,加上更大模型神經(jīng)網(wǎng)絡(luò)設(shè)計方法與實例分析神經(jīng)網(wǎng)絡(luò)設(shè)計方法與實例分析,來進(jìn)行訓(xùn)練,可以嘗試復(fù)現(xiàn) 論文中的模型規(guī)模,大致結(jié)構(gòu)差不多,只是修改一下參數(shù)大小。

    還比如說,在這里搭建網(wǎng)絡(luò)結(jié)構(gòu)時,用的是較底層API,直接創(chuàng)建矩陣權(quán)重,相乘相加,而 飛槳中有很多好用的API,能否調(diào)用這些API來重新構(gòu)建這個模型呢,比如說詞向量部分,可以用fluid..直接傳入詞 id 來實現(xiàn),還有全連接層,可以直接用 fluid..fc 來實現(xiàn),激活函數(shù)可以直接通過里面參數(shù)設(shè)置,非常方便。

    其實還可以在這里嘗試些小技巧,比如共享詞向量表為 前全連接層的權(quán)重 W2,以及加入 論文中提到的類似殘差連接直接將 連到輸出的部分。

    這次在這里介紹神經(jīng)網(wǎng)絡(luò)語言模型,并通過 飛槳來實現(xiàn)了一個簡單的小例子,主要想做的是:

    第一,語言模型任務(wù)在 NLP 領(lǐng)域很重要,想首先介紹一下;

    第二, 這篇神經(jīng)網(wǎng)絡(luò)語言模型的論文非常經(jīng)典,比如說提出了用神經(jīng)網(wǎng)絡(luò)實現(xiàn)語言模型,同時還最早提出詞表示來解決“維數(shù)災(zāi)難”問題,通過復(fù)現(xiàn),也好引出之后詞向量,還有 等話題;

    第三,通過用 飛槳來實現(xiàn)這樣一個簡單例子,可以拋開各種模型與數(shù)據(jù)復(fù)雜度,更直觀了解一個飛槳程序是如何構(gòu)建的,也為之后講解飛槳更復(fù)雜程序打下基礎(chǔ)。

網(wǎng)站首頁   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權(quán)所有