Tensorflow2.4從頭訓(xùn)練Word?Embedding實(shí)現(xiàn)文本分類
前言
本文主要使用 cpu 版本的 tensorflow 2.4 版本完成文本的 word embedding 訓(xùn)練,并且以此為基礎(chǔ)完成影評(píng)文本分類任務(wù)。
具體介紹
1. 三種文本向量化方法
通常在深度學(xué)習(xí)模型中我們的輸入都是以向量形式存在的,所以我們處理數(shù)據(jù)過程的重要一項(xiàng)任務(wù)就是將文本中的 token (一個(gè) token 可以是英文單詞、一個(gè)漢字、一個(gè)中文詞語等,需要自己規(guī)定)轉(zhuǎn)換成對(duì)應(yīng)的向量,本文會(huì)給出三種常見文本向量化的策略。
(1)One-Hot Encodings 。其實(shí)很好理解,假如我們的數(shù)據(jù)是“我是人”,因?yàn)橛?3 個(gè)不同的漢字,我會(huì)給每個(gè)漢字一個(gè)對(duì)應(yīng)的索引,然后我會(huì)創(chuàng)建一個(gè)長(zhǎng)度為 3 的向量,假如我給每個(gè)漢字賦予的索引為“我->0”“是->1”“人->2”,那么每個(gè)字對(duì)應(yīng)的 One-Hot Encodings 為 [1,0,0]、[0,1,0]、[0,0,1] 。那么“我是人”的這個(gè)句子的向量表示就可以將這三個(gè)向量拼接起來即可。這種方法的優(yōu)點(diǎn)明顯,方便理解和實(shí)現(xiàn),但是缺點(diǎn)也很明顯,效率非常低。One-Hot Encodings 所產(chǎn)生的的向量都是稀疏的。假如詞匯表中有 1000 個(gè)單詞,要對(duì)每個(gè)單詞進(jìn)行向量化編碼,其中幾乎 99% 的位置都為零。
(2)encode each word with a unique num 。我們可以使用唯一的數(shù)字對(duì)每個(gè)單詞進(jìn)行編碼。還是上面的例子,我們給每個(gè)字分配一個(gè)對(duì)應(yīng)的整數(shù),假如分配結(jié)果為 “我->1”“是->2”“人->3”,我就能將句子“我是人”這句話就可以編碼為一個(gè)稠密向量,如 [1,2,3]。此時(shí)的向量是一個(gè)稠密向量(所有位置都有有意義的整數(shù)填充)。但是這種方法有個(gè)缺點(diǎn),編碼的數(shù)字是可以人為任意設(shè)置,它不能捕獲漢字之間的任何語義關(guān)系,也無法從數(shù)字上看出對(duì)應(yīng)的近義詞之間的關(guān)系。
(3)Word Embeddings 。詞嵌入是一種將單詞編碼為有效稠密向量的方法,其中相似的單詞具有相似相近的向量編碼。詞嵌入是浮點(diǎn)類型的稠密向量,向量的長(zhǎng)度需要人為指定。我們不必像上面兩種方法手動(dòng)去設(shè)置編碼中的向量值,而是將他們都作為可訓(xùn)練的參數(shù),通過給模型喂大量的數(shù)據(jù),不斷的訓(xùn)練來捕獲單詞之間的細(xì)粒度語義關(guān)系,常見的詞向量維度可以設(shè)置從 8 維到 1024 維范圍中的任意整數(shù)。理論上維度越高詞嵌入的語義越豐富但是訓(xùn)練成本越高。如我們上面的例子,我們?cè)O(shè)置詞嵌入維度為 4 ,最后通過訓(xùn)練得到的詞嵌入可能是 “我->[-3.2, 1.5, -4,6, 3.4]”“是-> [0.2, 0.6, -0.6, 1.5]”“人->[3.4, 5.3, -7.2, 1.5]”。
2. 獲取數(shù)據(jù)
(1)本次我們要用到的是數(shù)據(jù)是 Large Movie Review Dataset ,我們需要使用 tensorflow 的內(nèi)置函數(shù)從網(wǎng)絡(luò)上下載到本地磁盤,為了簡(jiǎn)化數(shù)據(jù),我們將訓(xùn)練數(shù)據(jù)目錄中的 unsup 子目錄都刪除,最后取出 20000 個(gè)訓(xùn)練樣本作為訓(xùn)練集,取出 5000 個(gè)訓(xùn)練樣本作為驗(yàn)證集。
import io import os import re import shutil import string import tensorflow as tf from tensorflow.keras import Sequential from tensorflow.keras.layers import Dense, Embedding, GlobalAveragePooling1D from tensorflow.keras.layers import TextVectorization batch_size = 512 seed = 1 url = "https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz" dataset = tf.keras.utils.get_file("aclImdb_v1.tar.gz", url, untar=True, cache_dir='.', cache_subdir='') dataset_dir = os.path.join(os.path.dirname(dataset), 'aclImdb') train_dir = os.path.join(dataset_dir, 'train') remove_dir = os.path.join(train_dir, 'unsup') shutil.rmtree(remove_dir) train_datas = tf.keras.utils.text_dataset_from_directory( 'aclImdb/train', batch_size=batch_size, validation_split=0.2, subset='training', seed=seed) val_datas = tf.keras.utils.text_dataset_from_directory( 'aclImdb/train', batch_size=batch_size, validation_split=0.2, subset='validation', seed=seed)
(2)這里展示出 2 條樣本,每個(gè)樣本都有一個(gè)標(biāo)簽和一個(gè)文本描述,標(biāo)簽 1 表示評(píng)論是 positive , 標(biāo)簽 0 表示評(píng)論是: negative 。
1 b'The first time I saw this film, I was in shock for days afterwards. Its painstaking and absorbing treatment of the subject holds the attention, helped by good acting and some really intriguing music. The ending, quite simply, had me gasping. First rate!' 0 b"This is quite possibly the worst movie of all time. It stars Shaquille O'Neil and is about a rapping genie. Apparently someone out there thought that this was a good idea and got suckered into dishing out cash to produce this wonderful masterpiece. The movie gets 1 out of 10."
3. 處理數(shù)據(jù)
(1)為了保證在加載數(shù)據(jù)的時(shí)候不會(huì)出現(xiàn) I/O 不會(huì)阻塞,我們?cè)趶拇疟P加載完數(shù)據(jù)之后,使用 cache 會(huì)將數(shù)據(jù)保存在內(nèi)存中,確保在訓(xùn)練模型過程中數(shù)據(jù)的獲取不會(huì)成為訓(xùn)練速度的瓶頸。如果說要保存的數(shù)據(jù)量太大,可以使用 cache 創(chuàng)建磁盤緩存提高數(shù)據(jù)的讀取效率。另外我們還使用 prefetch 在訓(xùn)練過程中可以并行執(zhí)行數(shù)據(jù)的預(yù)獲取。
AUTOTUNE = tf.data.AUTOTUNE train_datas = train_datas.cache().prefetch(buffer_size=AUTOTUNE) val_datas = val_datas.cache().prefetch(buffer_size=AUTOTUNE)
(2)將訓(xùn)練數(shù)據(jù)中的標(biāo)簽去掉,只保留文本描述,然后使用 TextVectorization 對(duì)數(shù)據(jù)進(jìn)行預(yù)處理,先轉(zhuǎn)換層小寫英文,然后再將無用的字符剔除,并且我們規(guī)定了每個(gè)文本的最大長(zhǎng)度為 100 個(gè)單詞,超過的文本部分會(huì)被丟棄。最后將訓(xùn)練數(shù)據(jù)中的詞都放入一個(gè)最大為 10000 的詞匯表中,其中有一個(gè)特殊的表示 OOV 的 [UNK] ,也就說來自訓(xùn)練數(shù)據(jù)中的詞只有 9999 個(gè),使用 vectorize_layer 為每個(gè)單詞進(jìn)行 int 向量化,其實(shí)就是在文章開頭提到的第二種向量化策略。
def handle(input_data): lowercase = tf.strings.lower(input_data) stripped_html = tf.strings.regex_replace(lowercase, '<br />', ' ') return tf.strings.regex_replace(stripped_html, '[%s]' % re.escape(string.punctuation), '') vocab_size = 10000 sequence_length = 100 vectorize_layer = TextVectorization(standardize=handle, max_tokens=vocab_size, output_mode='int', output_sequence_length=sequence_length) text_datas = train_datas.map(lambda x, y: x) vectorize_layer.adapt(text_datas)
4. 搭建、訓(xùn)練模型
我們此次搭建的模型是一個(gè)“Continuous bag of words" 風(fēng)格的模型。
(1)第一層是已經(jīng)上面初始化好的 vectorize_layer ,它可以將文本經(jīng)過預(yù)處理,然后將分割出來的單詞都賦予對(duì)應(yīng)的整數(shù)。
(2)第二層是一個(gè)嵌入層,我們定義了詞嵌入維度為 32,也就是為每一個(gè)詞對(duì)應(yīng)的整數(shù)都轉(zhuǎn)換為一個(gè) 32 維的向量來進(jìn)行表示,這些向量的值是可以在模型訓(xùn)練時(shí)進(jìn)行學(xué)習(xí)的權(quán)重參數(shù)。通過此層輸出的維度為:(batch_size, sequence_length, embedding_dim)。
(3)第三層是一個(gè) GlobalAveragePooling1D 操作,因?yàn)槊總€(gè)樣本的維度為 (sequence_length, embedding_dim) ,該操作可以按照對(duì) sequence_length 維度求平均值來為每個(gè)樣本返回一個(gè)固定長(zhǎng)度的輸出向量,最后輸出的維度為:(batch_size, embedding_dim)。
(4)第四層是一個(gè)輸出 32 維向量的全連接層操作,并且使用 relu 激活函數(shù)進(jìn)行非線性變化。
(5)最后一層是一個(gè)輸出 1 維向量的全連接層操作,表示該樣本的屬于 positive 的概率。
(6)優(yōu)化器選擇 Adam ,損失函數(shù)為 BinaryCrossentropy ,評(píng)估指標(biāo)為 accuracy
embedding_dim=32 model = Sequential([ vectorize_layer, Embedding(vocab_size, embedding_dim, name="embedding"), GlobalAveragePooling1D(), Dense(32, activation='relu'), Dense(1) ]) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy']) model.fit(train_datas, validation_data=val_datas, epochs=20, callbacks=[tensorboard_callback])
訓(xùn)練過程打?。?/p>
Epoch 1/20
40/40 [==============================] - 3s 52ms/step - loss: 0.6898 - accuracy: 0.4985 - val_loss: 0.6835 - val_accuracy: 0.5060
Epoch 2/20
40/40 [==============================] - 2s 50ms/step - loss: 0.6654 - accuracy: 0.4992 - val_loss: 0.6435 - val_accuracy: 0.5228
...
Epoch 19/20
40/40 [==============================] - 2s 49ms/step - loss: 0.1409 - accuracy: 0.9482 - val_loss: 0.4532 - val_accuracy: 0.8210
Epoch 20/20
40/40 [==============================] - 2s 48ms/step - loss: 0.1327 - accuracy: 0.9528 - val_loss: 0.4681 - val_accuracy: 0.8216
5. 導(dǎo)出訓(xùn)練好的詞嵌入向量
這里我們?nèi)〕鲆呀?jīng)訓(xùn)練好的詞嵌入,然后打印出前三個(gè)單詞以及詞向量,因?yàn)樗饕?0 的詞是空字符,所以直接跳過了,只顯示了兩個(gè)單詞的內(nèi)容。我們可以將所有訓(xùn)練好的詞嵌入向量都寫入本地磁盤的文件,供以后使用。
weights = model.get_layer('embedding').get_weights()[0] vocab = vectorize_layer.get_vocabulary() for i, word in enumerate(vocab[:3]): if i == 0: continue vecoter = weights[i] print(word,"||", ','.join([str(x) for x in vecoter]))
單詞和對(duì)應(yīng)詞嵌入向量:
[UNK] || 0.020502748,-0.038312573,-0.036612183,-0.050346173,-0.07899615,-0.03143682,-0.06429587,0.07334388,-0.01887771,-0.08744612,-0.021639654,0.04726765,0.042426057,0.2240213,0.022607388,-0.08052631,0.023943739,0.05245169,-0.017815227,0.053340062,-0.033523336,0.057832733,-0.007486237,-0.16336738,0.022891225,0.12611994,-0.11084395,-0.0076115266,-0.03733231,-0.010371257,-0.045643456,-0.05392711
the || -0.029460065,-0.0021714368,-0.010394105,-0.03353872,-0.097529344,-0.05249973,-0.03901586,0.009200298,-0.085409686,-0.09302798,-0.07607663,0.046305165,-0.010357974,0.28357282,0.009442638,-0.036655612,0.063269086,0.06721396,0.063007854,0.03185595,-0.014642656,0.089468665,-0.014918188,-0.15671577,0.043026615,0.17086154,-0.0461816,0.021180542,-0.045269016,-0.101499856,-0.03948177,0.028299723
以上就是Tensorflow2.4從頭訓(xùn)練Word Embedding實(shí)現(xiàn)文本分類的詳細(xì)內(nèi)容,更多關(guān)于Tensorflow Word Embedding的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Tensorflow2.10使用BERT從文本中抽取答案實(shí)現(xiàn)詳解
- tensorflow2.10使用BERT實(shí)現(xiàn)Semantic Similarity過程解析
- 使用Tensorflow?hub完成目標(biāo)檢測(cè)過程詳解
- 使用TensorFlow創(chuàng)建生成式對(duì)抗網(wǎng)絡(luò)GAN案例
- javascript命名約定(變量?函數(shù)?類?組件)
- Tensorflow 2.4 搭建單層和多層 Bi-LSTM 模型
- 深度學(xué)習(xí)Tensorflow2.8?使用?BERT?進(jìn)行文本分類
- TensorFlow自定義模型保存加載和分布式訓(xùn)練
相關(guān)文章
用python統(tǒng)計(jì)代碼行的示例(包括空行和注釋)
今天小編就為大家分享一篇用python統(tǒng)計(jì)代碼行的示例(包括空行和注釋),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-07-07Django用戶登錄與注冊(cè)系統(tǒng)的實(shí)現(xiàn)示例
這篇文章主要介紹了Django用戶登錄與注冊(cè)系統(tǒng)的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06pytorch 求網(wǎng)絡(luò)模型參數(shù)實(shí)例
今天小編就為大家分享一篇pytorch 求網(wǎng)絡(luò)模型參數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-12-12python修改linux中文件(文件夾)的權(quán)限屬性操作
這篇文章主要介紹了python修改linux中文件(文件夾)的權(quán)限屬性操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03Python使用ClickHouse的實(shí)踐與踩坑記錄
這篇文章主要介紹了Python使用ClickHouse的實(shí)踐與踩坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05