在自然語(yǔ)言處理(NLP)任務(wù)中,怎么處理數(shù)據(jù)——即怎么把文字輸入到模型中進(jìn)行處理? 原創(chuàng)
“ 文本序列化是自然語(yǔ)言處理任務(wù)的前置條件,而文本序列化需要經(jīng)過(guò)分詞,構(gòu)建詞匯表和序列化的幾個(gè)步驟”
在神經(jīng)網(wǎng)絡(luò)或者說(shuō)在機(jī)器學(xué)習(xí)領(lǐng)域中,數(shù)據(jù)主要以向量的形式存在,表現(xiàn)形式為多維矩陣;但怎么把現(xiàn)實(shí)世界中的數(shù)據(jù)輸入到神經(jīng)網(wǎng)絡(luò)中是機(jī)器學(xué)習(xí)的一個(gè)前提。
而現(xiàn)實(shí)世界中的數(shù)據(jù)格式雖然多種多樣,但事實(shí)上無(wú)非以下幾種主要模態(tài):
- 文字
- 圖片
- 視頻
但我們也知道,計(jì)算機(jī)只認(rèn)識(shí)數(shù)字,而不認(rèn)識(shí)文字和圖片;因此,就需要把這些數(shù)據(jù)轉(zhuǎn)換為計(jì)算機(jī)能夠識(shí)別的格式;而在神經(jīng)網(wǎng)絡(luò)模型中就是怎么把這些數(shù)據(jù)轉(zhuǎn)換為向量的格式。
簡(jiǎn)單來(lái)說(shuō),就是把現(xiàn)實(shí)世界中的數(shù)據(jù)轉(zhuǎn)化為用多維矩陣進(jìn)行表示的過(guò)程。圖片是由多個(gè)像素點(diǎn)組成,因此天生的就可以用矩陣表示;但文字卻不同,處理起來(lái)要復(fù)雜得多。至于視頻,就是動(dòng)起來(lái)的多張圖片。
文本處理
在自然語(yǔ)言處理任務(wù)中,要想把文本數(shù)據(jù)輸入到神經(jīng)網(wǎng)絡(luò)中,需要經(jīng)過(guò)大概以下幾個(gè)步驟:
- 分詞
- 構(gòu)建詞匯表
- 文本序列化
但為什么自然語(yǔ)言處理需要經(jīng)過(guò)以下幾個(gè)步驟? 下面來(lái)介紹一下每個(gè)步驟的作用:
分詞
在自然語(yǔ)言體系中,語(yǔ)義是以詞或句子的形態(tài)體現(xiàn)的;因此,我們就需要去理解詞或句子的意思;但眾所周知的是,以我們漢語(yǔ)為例常用的詞和字就幾千個(gè);而我們生活中絕大部分的語(yǔ)義都是由重復(fù)的字和詞組成的。
因此,從效率的角度來(lái)講,我們不可能把每個(gè)句子的語(yǔ)義都記下來(lái);我們需要的是找到其中常用的字和詞,然后通過(guò)類似排列組合的方式組合成一個(gè)個(gè)句子。
所以,自然語(yǔ)言處理的第一步就是分詞;也就是說(shuō)通過(guò)某種方式把句子中相同的字或詞挑出來(lái),組成一個(gè)字詞列表。而常用的分詞技術(shù)根據(jù)不同的語(yǔ)言又有不同的實(shí)現(xiàn)方式;比如說(shuō)在英語(yǔ)體系中,很多時(shí)候每個(gè)單詞就表示單獨(dú)的意思;因此最簡(jiǎn)單的分詞方式就是把每個(gè)不同的單詞都找出來(lái)。
但在漢語(yǔ)言中,由于存在多音字,成語(yǔ)等具有復(fù)雜語(yǔ)言的形態(tài);因此,漢語(yǔ)分詞就不能使用找不同字的形式。
因此,分詞的難點(diǎn)是怎么對(duì)文本數(shù)據(jù)進(jìn)行拆分,但又不會(huì)影響到詞語(yǔ)本身對(duì)意思。
詞匯表
理解了什么是分詞,以及為什么要分詞,那么再理解詞匯表就很簡(jiǎn)單了;對(duì)句子進(jìn)行分詞之后,就獲取到了一個(gè)字和詞的列表;因此就可以根據(jù)這個(gè)列表來(lái)構(gòu)建詞匯表,變成讓計(jì)算機(jī)可以處理的數(shù)字格式。
學(xué)過(guò)計(jì)算機(jī)原理的應(yīng)該都知道,計(jì)算機(jī)無(wú)法直接處理文字,因此文字在計(jì)算機(jī)中是通過(guò)編碼的方式來(lái)實(shí)現(xiàn)的;比如說(shuō)大名鼎鼎的ASCII碼表,就是用八位二進(jìn)制表示的。
而ASCII碼表本質(zhì)上就是一個(gè)字典結(jié)構(gòu),即使用K-V的形式來(lái)表示字符;需要計(jì)算機(jī)處理時(shí)就使用二進(jìn)制表示,需要現(xiàn)實(shí)給人看時(shí)就使用字符表示;而詞匯表就是類似ASCII碼表的形式,把字或詞作為K,把數(shù)字作為V。
這樣一個(gè)數(shù)字就可以代表一個(gè)字或詞;這樣就可以讓計(jì)算機(jī)處理。
在詞匯表中有兩個(gè)比較特殊的詞匯,那就是UNK和PAD;我們知道常用的漢字只有幾千個(gè),但實(shí)際上的漢字有上萬(wàn)個(gè);因此,我們根據(jù)文本數(shù)據(jù)的內(nèi)容,可能并不能獲取到所有的漢字;因此遇到“沒(méi)見(jiàn)過(guò)”的漢字該怎么辦呢,這時(shí)就使用UNK來(lái)表示。
而在矩陣計(jì)算中,需要的是相同的矩陣形式;比如說(shuō)需要5*5的固定矩陣;但在自然語(yǔ)言中,每個(gè)句子的長(zhǎng)度都不一樣;短的可能就一兩個(gè)字,長(zhǎng)的可能有幾十個(gè)字;這時(shí)變換的矩陣維度就不在相同。
dict = { "UNK_TAG": 0, "PAD_TAG": 1}
因此,就可以使用PAD對(duì)文字比較少的句子進(jìn)行補(bǔ)充;而對(duì)文字比較長(zhǎng)的句子進(jìn)行截取。
文本序列化
在經(jīng)過(guò)分詞和構(gòu)建詞匯表之后,就可以對(duì)文本進(jìn)行序列化;在自然語(yǔ)言處理任務(wù)中,文本需要轉(zhuǎn)換為編碼的數(shù)字進(jìn)行表示;也就是把文字變成數(shù)字表示。
dict_1 = { "UNK_TAG": 0, "PAD_TAG": 1}
dict_2 = { 0: "UNK_TAG", 1: "PAD_TAG"}
所以就有了一個(gè)從文字變成數(shù)字和從數(shù)字變成文字的過(guò)程;本質(zhì)上其實(shí)就是在詞匯表中,根據(jù)文本獲取其編碼的數(shù)字,以及根據(jù)編碼的數(shù)字獲取文字。
文本序列化最重要的一步,就是把數(shù)字表示的句子轉(zhuǎn)換成向量表示,也就是多維矩陣;而這就需要通過(guò)one-hot或者word embedding的方式來(lái)進(jìn)行序列化。
但是在使用word embedding之前,需要把句子的數(shù)字列表轉(zhuǎn)換為tensor格式。
# 將句子列表轉(zhuǎn)換為tensor
sentences_tensor = torch.tensor(sentences, dtype=torch.long)
# 定義 Embedding 層
embedding = nn.Embedding(vocab_size, embedding_dim)
# 通過(guò) Embedding 層
embedded_sentences = embedding(sentences_tensor)
本文轉(zhuǎn)載自公眾號(hào)AI探索時(shí)代 作者:DFires
