【NLP】NLP实战篇之tensorflow2.0快速入门
修改上版代碼格式問題。Tensorflow2.0跟Keras緊密結合,相比于1.0版本,2.0可以更快上手,并且能更方便找到需要的api。本文中以IMDB文本分類為例,簡單介紹了從數據下載、預處理、建模、訓練到模型保存等等在2.0中的操作,可以讓你從無到有快速入門。
實戰系列篇章中主要會分享,解決實際問題時的過程、遇到的問題或者使用的工具等等。如問題分解、bug排查、模型部署等等。相關代碼實現開源在:https://github.com/wellinxu/nlp_store?
數據下載與處理
數據下載
重構詞的索引
簡單預處理
模型構建
sequential方式
subclass方式
模型訓練與評估
模型的保存與加載
checkpoint方式
hdf5方式
saved_model
參考
數據下載與處理
數據下載
import?tensorflow?as?tf #?下載IMDB數據 vocab_size?=?10000????#?保留詞的個數 imdb?=?tf.keras.datasets.imdb (train_data,?train_labels),?(test_data,?test_labels)?=?imdb.load_data(num_words=vocab_size) print("train?len:",?len(train_data))????#?[25000] print("test?len:",?len(test_data))????#?[25000]IMDB數據集已經打包在tensorflow中,可以方便的下載,vocab_size是保留了訓練數據中最常見的詞,刪除了一些低頻詞。
重構詞的索引
#?一個將單詞映射到整數索引的詞典 word_index?=?imdb.get_word_index()???#?索引從1開始word_index?=?{k:(v+3)?for?k,v?in?word_index.items()} word_index["<PAD>"]?=?0 word_index["<START>"]?=?1 word_index["<UNK>"]?=?2??#?unknown word_index["<UNUSED>"]?=?3原來的索引是從1開始創建的,新建的索引將所有詞的index都加了3,然后添加了4個新的詞。
簡單預處理
#?統一文本序列長度 train_data?=?tf.keras.preprocessing.sequence.pad_sequences(train_data,?value=word_index["<PAD>"],?padding="post",?truncating="post",?maxlen=256) test_data?=?tf.keras.preprocessing.sequence.pad_sequences(test_data,?value=word_index["<PAD>"],?padding="post",?truncating="post",?maxlen=256)因為文本有長有短,這個處理是將所有文本都處理成統一的長度,太長的截斷,太短的補全。參數中,value是補全時用的值,padding是表示太短時在前面補還是后面補,truncating表示太長時在前面截斷還是后面截斷,maxlen表示統一的長度。
模型構建
使用的模型結構如下圖所示,輸入接入embedding層,然后是一層全局平均池化層,再接兩層全連接即輸出:
sequential方式
????#?model?=?tf.keras.Sequential()#?model.add(tf.keras.layers.Embedding(vocab_size,?16))????#?[batch_size,?seq_len,?16]#?model.add(tf.keras.layers.GlobalAveragePooling1D())????#?[batch_size,?16]#?model.add(tf.keras.layers.Dense(16,?activation='relu'))????#?[batch_size,?16]#?model.add(tf.keras.layers.Dense(1,?activation='sigmoid'))????#?[batch_size,?1]#?上下這兩種方式是完全等價的model?=?tf.keras.Sequential([tf.keras.layers.Embedding(vocab_size,?16),????#?[batch_size,?seq_len,?16]tf.keras.layers.GlobalAveragePooling1D(),????#?[batch_size,?16]tf.keras.layers.Dense(16,?activation='relu'),????#?[batch_size,?16]tf.keras.layers.Dense(1,?activation='sigmoid')????#?[batch_size,?1]])model.summary()??#?打印網絡結構概覽代碼中注釋的部分跟下面部分是完全等價的,tf2.0中,可以在tf.keras.layers里方便地找到各種已經實現好的層。sequential方式顧名思義就是將模型當作一個序列,一層一層地疊加在一起就可以構建出簡單的模型。其優點是簡單易用,缺點是缺少靈活性。上面網絡結構圖的打印結果是:
subclass方式
????class?MyModel(tf.keras.models.Model):def?__init__(self):super(MyModel,?self).__init__()self.embedding?=?tf.keras.layers.Embedding(vocab_size,?16)self.g_avg_pool?=?tf.keras.layers.GlobalAveragePooling1D()self.d1?=?tf.keras.layers.Dense(16,?activation="relu")self.d2?=?tf.keras.layers.Dense(1,?activation="sigmoid")def?call(self,?inputs,?training=None,?mask=None):#?inputs:?[batch_size,?seq_len]x?=?self.embedding(inputs)????#?[batch_size,?seq_len,?16]x?=?self.g_avg_pool(x)????#?[batch_size,?16]x?=?self.d1(x)????#?[batch_size,?16]x?=?self.d2(x)????#?[batch_size,?1]]return?xmodel?=?MyModel()通過繼承tf.keras.models.Model類來實現自己的模型類,可以在__init__方法中初始化各個層,在call方法實現從輸入到輸出的流程計算。此方法可以實現相對復雜的網絡結構,后續文章會講到的自定義層跟這種形式也非常類似。
模型訓練與評估
#?配置模型訓練參數 #?model.compile(optimizer='adam',?loss='binary_crossentropy',?metrics=['accuracy']) model.compile(optimizer=tf.keras.optimizers.Adam(),?loss=tf.keras.losses.BinaryCrossentropy(),?metrics=[tf.keras.metrics.BinaryAccuracy()]) #?訓練模型 history?=?model.fit(train_data,?train_labels,?epochs=40,?batch_size=512) #?評估測試集 model.evaluate(test_data,??test_labels,?verbose=2)首先要對模型進行編譯,也就是給模型制定優化器、loss、指標計算方式等等,這三個都可以方便地在tf.keras.optimizers/tf.keras.losses/tf.keras.metrics里找到已實現好的類。
模型訓練只要簡單地調用fit方法就可以實現,可以制定迭代輪次,batch大小,驗證集,回調函數等等。返回值history里面包含了訓練過程中的loss跟指標的值。fit方法封裝得很好,但也因此失去了靈活性,模型訓練也可以用更細致的方式,具體的后續文章再介紹。
上面運行的結果是:
模型的保存與加載
checkpoint方式
????#?保存權重model.save_weights("checkpoint/my_checkpoint")#?加載權重new_model?=?create_model_by_subclass()#?預測之前需要先編譯new_model.compile(optimizer='adam',?loss='binary_crossentropy',?metrics=['accuracy'])new_model.load_weights("checkpoint/my_checkpoint")#?評估測試集new_model.evaluate(test_data,??test_labels,?verbose=2)checkpoint方式只保留了模型的權重,并沒有保留模型結構。優點是保存的模型較小,缺點是不知道模型結構的時候就不好用。因為只保存了權重,所以在加載過程中,需要先構建模型(并編譯),然后才能使用。
hdf5方式
????"""只能用于Functional?model?or?a?Sequential?model,目前不能用于subclassed?model,2020-06"""#?保存模型model.save("h5/my_model.h5")#?加載模型#?重新創建完全相同的模型,包括其權重和優化程序new_model?=?tf.keras.models.load_model('h5/my_model.h5')#?顯示網絡結構new_model.summary()#?評估測試集new_model.evaluate(test_data,?test_labels,?verbose=2)hdf5方式既保留了模型權重也保留了模型結構,但目前只能保存用sequential方式構建的模型,subclass方式構建的模型則不能保存為hdf5模型。因為其保留了模型結構,所以模型加載后就可以直接使用,也方便移植到其他環境中使用。
saved_model
????#?保存模型tf.saved_model.save(model,?"saved_model/1")#?加載模型new_model?=?tf.saved_model.load("saved_model/1")#?預測結果result?=?new_model(test_data)saved_model方式跟hdf5一樣將整個模型都保留下來了,這種格式可以保存各種方法構建的模型。saved_model格式常用于預測或部署時,跟前兩種情況不同,這種格式加載后的模型,已經不具備Model(sequential或subclass方式構建的模型)的一些特性,比如沒有了fit,evaluate方法,但可以用來直接進行預測。這種格式常用在tensorflow serving中。
參考
https://tensorflow.google.cn/tutorials/quickstart/beginner?hl=zh_cn
https://tensorflow.google.cn/tutorials/quickstart/advanced?hl=zh_cn
https://tensorflow.google.cn/tutorials/keras/text_classification?hl=zh_cn
https://tensorflow.google.cn/tutorials/keras/save_and_load?hl=zh_cn
總結
以上是生活随笔為你收集整理的【NLP】NLP实战篇之tensorflow2.0快速入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【机器学习基础】数学推导+纯Python
- 下一篇: 【Python基础】必知必会的8个Pyt