摘要:遞歸神經網絡有一些不可思議的地方,有些時候,模型與你期望的相差甚遠,許多人認為是非常難訓練,那么究竟是什么呢就有這篇文章來帶給大家。遞歸神經網絡有一些不可思議的地方。但是我們正在不斷超越自己那么究竟是什么呢遞歸神經網絡序列。
遞歸神經網絡有一些不可思議的地方,有些時候,模型與你期望的相差甚遠,許多人認為是RNNS非常難訓練,那么RNNs究竟是什么呢?就有這篇文章來帶給大家。遞歸神經網絡(RNNs)有一些不可思議的地方。我仍然記得我訓練的第一個用于 圖片字幕的遞歸網絡。從花幾十分鐘訓練我的第一個嬰兒模型(相當隨意挑選的超參數)開始,到訓練出能夠針對圖像給出有意義描述的模型。有些時候,模型對于輸出結果質量的簡單程度的比例,會與你的期望相差甚遠,而這還僅僅是其中一點。有如此令人震驚結果,許多人認為是因為RNNs非常難訓練(事實上,通過多次試驗,我得出了相反的結論)。一年前:我一直在訓練RNNs,我多次見證了它們的強大的功能和魯棒性,而且它們的輸出結果同樣讓我感到有趣。這篇文章將會給你展現它不可思議的地方。
我們將訓練一個RNNs讓它一個字符一個字符地生成文本,然后我們思考“這怎么可能?”
順便說句,在講述這篇文章的同時,我同樣會將代碼上傳到 Github 上,這樣你就可以基于多層LSTMs來訓練字符級語言模型。你向它輸入大量的文本,它會學習并產生類似的文本。你也可以用它來重新運行我下面的代碼。但是我們正在不斷超越自己;那么RNNs究竟是什么呢?
遞歸神經網絡
序列。你可能會問:是什么讓遞歸神經網絡如此特殊?Vanilla神經網絡(卷積網絡也一樣)較大的局限之處就是它們API的局限性:它們將固定大小的向量作為輸入(比如一張圖片),然后輸出一個固定大小的向量(比如不同分類的概率)。還不止這些:這些模型按照固定的計算步驟來(比如模型中層的數量)實現這樣的輸入輸出。遞歸網絡更令人興奮的主要原因是,它允許我們對向量序列進行操作:輸入序列、輸出序列、或大部分的輸入輸出序列。通過幾個例子可以具體理解這點:
? ?
? ?
?
這個模型完全拼湊出了timestamp,id等等。同樣,注意到它以正確的嵌套順序適當的閉合了正確的標簽。如果你有興趣了解更多,這里有 100,000 characters of sampled wikipedia
代數幾何(Latex)
以上結果表明,該模型在學習復雜句法結構方面表現得相當不錯。這些結果令人印象深刻,我的實驗伙伴( Justin Johnson )和我打算在結構上再深入研究,我們使用這本關于代數棧/幾何的 書 。我們下載了Latex的源文件(16MB),然后訓練了一個多層的LSTM。令人驚訝的是,由Latex產生的樣本幾乎是已經匯總好了的。我們不得不介入并手動修復了一些問題,這樣你就得到了合理的數學推論,這是相當驚人的:
代數幾何樣本(假的), 真正的PDF文件在這 。
這是另一份樣本:
?
產生了更多假的代數幾何,嘗試處理圖像(右)
正如上面你所看到的那樣,有些時候這個模型試圖生成LaTeX圖像,但很明顯它并不明白圖像的具體意思。同樣我很喜歡模型選擇跳過證明過程的那部分(“Proof omitted”,左上角)。當然,Latex有相對困難的結構化句法格式,我自己都還沒有完全掌握。為舉例說明,下面是模型中的一個原始樣本(未被編輯):
egin{proof}
We may assume that $mathcal{I}$ is an abelian sheaf on $mathcal{C}$.
item Given a morphism $Delta : mathcal{F} o mathcal{I}$
is an injective and let $mathfrak q$ be an abelian sheaf on $X$.
Let $mathcal{F}$ be a fibered complex. Let $mathcal{F}$ be a category.
egin{enumerate}
item hyperref[setain-construction-phantom]{Lemma}
label{lemma-characterize-quasi-finite}
Let $mathcal{F}$ be an abelian quasi-coherent sheaf on $mathcal{C}$.
Let $mathcal{F}$ be a coherent $mathcal{O}_X$-module. Then
$mathcal{F}$ is an abelian catenary over $mathcal{C}$.
item The following are equivalent
egin{enumerate}
item $mathcal{F}$ is an $mathcal{O}_X$-module.
end{lemma}
這份樣本來自一個相對合適的模型,其中顯示出了一些常見錯誤。比如,模型打開了一個egin{proof}環境,但是卻以end{lemma}結束。這個問題我們必須手動修復,這可能是由于依賴關系太長而導致的:當這個模型做完了 proof過程,它就忘記了它是在做proof還是lemma了。同樣的,當模型打開了一個egin{enumerate}環境,然后卻忘記關閉它了。我們發現,當我們使用更大/更好的模型的時候,這種情況出現得就較少了,盡管如此,這些問題還是會出現。
Linux源代碼
我想看看這個模型處理結構化數據的極限,所以為了這一終極目標,我打算開始編寫一些代碼,特別的,我瀏覽了 Github上Linux repo 所有的原始資料和頭文件,把它們串在一起形成一個單一的巨大文件(474MB大小的C代碼)(我本來打算只訓練內核,但是它只有16MB)。然后,我花了幾天時間訓練出了大小剛好適合我GPU的3層LSTM網絡。這些模型有大約1000萬個參數,然而這對于RNN網絡來說還是微不足道的。結果非常有趣:
/*
?* Increment the size file of the new incorrect UI_FILTER group information
?* of the size generatively.
?*/
static int indicate_policy(void)
{
? int error;
? if (fd == MARN_EPT) {
? ? /*
? ? ?* The kernel blank will coeld it to userspace.
? ? ?*/
? ? if (ss->segment < mem_total)
? ? ? unblock_graph_and_set_blocked();
? ? else
? ? ? ret = 1;
? ? goto bail;
? }
? segaddr = in_SB(in.addr);
? selector = seg / 16;
? setup_works = true;
? for (i = 0; i < blocks; i++) {
? ? seq = buf[i++];
? ? bpf = bd->bd.next + i * search;
? ? if (fd) {
? ? ? current = blocked;
? ? }
? }
? rw->name = "Getjbbregs";
? bprm_self_clearl(&iv->version);
? regs->new = blocks[(BPF_STATS << info->historidac)] | PFMR_CLOBATHINC_SECONDS << 12;
? return segtable;
}
這代碼整體上看起來非常棒。我認為它不會馬上就能編譯通過,但是當你滾動查看這些代碼的時候給你的感覺是這是一個非常強大的C代碼庫。注意到,RNN到處隨機生成代碼片段和注釋。它很少會犯語法錯誤。比如,它適當的使用了字符類型、指針概念等。同樣它正確打開和關閉了代碼塊{[,并且學習將代碼縮進。一處常見的錯誤就是它不能跟蹤變量名:它常常會使用未定義的變量(比如上面出現的rw),或者聲明它從來不用的變量(比如上面的int error),或者返回一個不存在的變量。讓我們來看看更多的案例。下面是另外一個代碼片段,顯示了RNN學習操作數組的情況:
/*
?* If this error is set, we will need anything right after that BSD.
?*/
static void action_new_function(struct s_stat_info *wb)
{
? unsigned long flags;
? int lel_idx_bit = e->edd, *sys & ~((unsigned long) *FIRST_COMPAT);
? buf[0] = 0xFFFFFFFF & (bit << 4);
? min(inc, slist->bytes);
? printk(KERN_WARNING "Memory allocated x/x, "
? ? "original MLL instead "),
? ? min(min(multi_run - s->len, max) * num_data_in),
? ? frame_pos, sz + first_seg);
? div_u64_w(val, inb_p);
? spin_unlock(&disk->queue_lock);
? mutex_unlock(&s->sock->mutex);
? mutex_unlock(&func->mutex);
? return disassemble(info->pending_bh);
}
static void num_serial_settings(struct tty_struct *tty)
{
? if (tty == tty)
? ? disable_single_st_p(dev);
? pci_disable_spool(port);
? return 0;
}
static void do_command(struct seq_file *m, void *v)
{
? int column = 32 << (cmd[2] & 0x80);
? if (state)
? ? cmd = (int)(int_state ^ (in_8(&ch->ch_flags) & Cmd) ? 2 : 1);
? else
? ? seq = 1;
? for (i = 0; i < 16; i++) {
? ? if (k & (1 << 1))
? ? ? pipe = (in_use & UMXTHREAD_UNCCA) +
? ? ? ? ((count & 0x00000000fffffff8) & 0x000000f) << 8;
? ? if (count == 0)
? ? ? sub(pid, ppc_md.kexec_handle, 0x20000000);
? ? pipe_set_bytes(i, 0);
? }
? /* Free our user pages pointer to place camera if all dash */
? subsystem_info = &of_changes[PAGE_SIZE];
? rek_controls(offset, idx, &soffset);
? /* Now we want to deliberately put it to device */
? control_check_polarity(&context, val, 0);
? for (i = 0; i < COUNTER; i++)
? ? seq_puts(s, "policy ");
}
注意到,在第二個函數中,模型進行了這樣的比較tty == tty,這是永遠成立的。但是,至少這次變量tty只在這個函數中起作用!最后一個函數,注意到代碼沒有返回任何值,但是這是正確的因為函數的返回值聲明成了void。但是,前兩個函數同樣聲明成了void返回類型,卻返回了數值。這又是一個由于長期迭代導致的常見錯誤。
有些時候模型會決定現在是時候產生一個新的文件了。這通常是有趣的部分:首先模型一個一個字符記住GNU許可證,然后include幾個頭文件,聲明一些宏,然后就開始生成代碼部分:
/*
?* ?Copyright (c) 2006-2010, Intel Mobile Communications. ?All rights reserved.
?*
?* ? This program is free software; you can Redistribute it and/or modify it
?* under the terms of the GNU General Public License version 2 as published by
?* the Free Software Foundation.
?*
?* ? ? ? ?This program is distributed in the hope that it will be useful,
?* but WITHOUT ANY WARRANTY; without even the implied warranty of
?* ? MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ?See the
?*
?* ?GNU General Public License for more details.
?*
?* ? You should have received a copy of the GNU General Public License
?* ? ?along with this program; if not, write to the Free Software Foundation,
?* ?Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
?*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define REG_PG ? ?vesa_slot_addr_pack
#define PFM_NOCOMP ?AFSR(0, load)
#define STACK_DDR(type) ? ? (func)
#define SWAP_ALLOCATE(nr) ? ? (e)
#define emulate_sigs() ?arch_get_unaligned_child()
#define access_rw(TST) ?asm volatile("movd %%esp, %0, %3" : : "r" (0)); ?
? if (__type & DO_READ)
static void stat_PC_SEC __read_mostly offsetof(struct seq_argsqueue,
? ? ? ? ? pC>[1]);
static void
os_prefix(unsigned long sys)
{
#ifdef CONFIG_PREEMPT
? PUT_PARAM_RAID(2, sel) = get_state_state();
? set_pid_sum((unsigned long)state, current_state_str(),
? ? ? ? ? ?(unsigned long)-1->lr_full; low;
}
這里有太多有趣的地方可以講述了,關于這部分我可能可以寫一篇完整的博客來講述。但是在這里我就省略這部分了,如果你有興趣查看,請點擊 1MB of sampled Linux code
了解到底發生了什么
我們可以看出,最終訓練出的結果是令人印象深刻的,但是這一切都是如何工作的?讓我們通過運行兩個快速的實驗來簡要探索下。
訓練中樣本的演變
首先,探索模型訓練過程中樣本文本是如何演變的是件有趣的事,比如,我用列夫·托爾斯泰的《戰爭與和平》訓練了一個LSTM網絡,然后每100次迭代訓練就生成樣本。100次迭代后模型生成了隨機、混亂的樣本:
tyntd-iafhatawiaoihrdemot ?lytdws ?e ,tfti, astai f ogoh eoase rrranbyne "nhthnee e?
plia tklrgd t o idoe ns,smtt ? h ne etie h,hregtrs nigtike,aoaenns lng
但是,注意到模型最少知道了要在每個“單詞”間加上空格。有些時候會加上兩個空格。同樣模型不知道逗號后面通常跟著空格。300次迭代后我們可以看到模型開始有了引號和句號的概念:
"Tmont thithey" fomesscerliund
Keushey. Thom here
sheulke, anmerenith ol sivh I lalterthend Bleipile shuwy fil on aseterlome
coaniogennc Phe lism thond hon at. MeiDimorotion in ther thize."
這次單詞之間同樣由空格隔開,而且模型開始知道在句子末尾加上句號。500次迭代:
we counter. He stutn co des. His stanted out one ofler that concossions and was?
to gearang reay Jotrets and with fre colt otf paitt thin wall. Which das stimn?
現在模型會拼寫最短、最常見單詞,比如“we”,“He”,“His”,“Which”,“and”等。700次迭代的時候,我們得到了更像英語的文本:
Aftair fall unsuch that the hall for Prince Velzonski"s that me of
her hearly, and behs to so arwage fiving were to it beloge, pavu say falling misfort?
how, and Gogition is so overelical and ofter.
在經過1200次迭代后,我們發現模型開始使用引號和問號/感嘆號了,與此同時也學會了更長的單詞:
"Kite vouch!" he repeated by her
door. "But I would be done and quarts, feeling, then, son is people...."
經過2000次迭代,模型能夠正確拼寫的單詞,引號,名字等:
"Why do what that day," replied Natasha, and wishing to himself the fact the
princess, Princess Mary was easier, fed in had oftened him.
Pierre aking his soul came to the packs and drove up his father-in-law women.
大體上我們可以這么認為,首先模型發現了單詞-空格這樣普遍的結構,然后迅速學會拼寫單詞;從學習拼寫簡單單詞開始到最后學習拼寫長單詞。在單詞中顯現出主題內容(一般依賴于長期性)在很多次迭代后才出現。
RNN預測結果和神經元激活可視化
可視化有趣的另一個方面是可以按字符來觀察預測分布。在下面的可視化圖中,我們向Wikipedia RNN模型中輸入了校驗好的數據集(藍色/綠色的行)中的字符,然后在每個字符下面,我們列出了(紅色部分)模型預測會出現的前5個字符,顏色深淺根據它們概率大小決定(深紅:預測準確,白色:不準確)。比如,注意到有一連串字符是模型非常有信心能夠預測準確的(對http://www.序列模型置信度非常高)。
輸入字符序列(藍色/綠色)的顏色取決于RNN隱藏層中隨機選擇的神經元的激活情況。定義綠色=非常興奮,藍色=不是那么興奮(對于那些熟悉LSTMs細節的人來說,這些就是隱藏向量中[-1,1]范圍內的值,也就是經過門限操作和tanh函數的LSTM單元狀態)。直觀的,下圖顯示了在RNN“大腦”讀取輸入序列時一些神經元的激活情況。不同的神經元可能有不同的模式;下面我們將會看到我找到的4個不同的神經元,我認為這幾個是有趣的,并且是可解釋的(許多其他的并不容易解釋):
此圖中高亮的神經元似乎對URL極度興奮,URL以外的地方就不那么興奮。LSTM似乎會用這種神經元來記住它是否在URL之中。
在這張圖中,當RNN在[[]]標記之中時,高亮的神經元表現極度興奮,所以在這種標記之外就沒那么興奮,在神經元碰到字符“[”的時候不會表現得興奮,它一定要等到出現第二個“[”才會激活。計算模型是否碰到了一個還是兩個“[”的任務似乎可以用一個不同的神經元完成。
在這里,我們可以看出在[[]]環境中,神經元有著線性的變化。換句話說,它的激活函數給了RNN中[[]]范圍的一種基于時間的坐標系統。RNN可以通過這些信息或多或少的依賴于字符在[[]]中出現的早/晚來生成不同的字符(有可能是這樣)。
這是另外一個神經元,它有著更個性化的行為:它整體上比較平淡無常,但是碰到“www”中第一個“w”的時候突然就開始變得興奮。RNN可能可以使用這種神經元來計算“www”序列的長度,這樣它就知道是否應該再添加一個“w”還是開始添加URL。
當然,由于RNN隱藏狀態的龐大性,高維度性和分布式特性,很多這樣的結論都稍微要加上特別說明才能理解。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/4331.html
摘要:由一層函數調用進入下一層函數調用的遞推。此時,中的一個稱為孤兒的類就會收留這個對象。禁止訪問服務器拒絕請求服務器找不到請求的頁面服務器內部錯誤壞的網關一般是網關服務器請求后端服務時,后端服務沒有按照協議正確返回結果。 持續更新。。。。 php 1. 簡述 php 中的 autoload Autoload 的加載機制,當通過 new 來實例化一個類時,PHP 會通過定義的 autol...
摘要:自從年深秋,他開始在上撰寫并公開分享他感興趣的機器學習論文。本文選取了上篇閱讀注釋的機器學習論文筆記。希望知名專家注釋的深度學習論文能使一些很復雜的概念更易于理解。主要講述的是奧德賽因為激怒了海神波賽多而招致災禍。 Hugo Larochelle博士是一名謝布克大學機器學習的教授,社交媒體研究科學家、知名的神經網絡研究人員以及深度學習狂熱愛好者。自從2015年深秋,他開始在arXiv上撰寫并...
閱讀 1818·2021-10-09 09:44
閱讀 3387·2021-09-28 09:35
閱讀 1374·2021-09-01 10:31
閱讀 1661·2019-08-30 15:55
閱讀 2705·2019-08-30 15:54
閱讀 930·2019-08-29 17:07
閱讀 1376·2019-08-29 15:04
閱讀 2004·2019-08-26 13:56