天天看點

利用PaddleHub 2.x 完成文本分類訓練的坑

       基于項目選擇了PaddlePaddle 作為文本分類的基礎,經過一周多的使用終于有所進展,把文本分類的相關工作做了一個簡單模型。

       首先說說PaddlePaddle , 現在做深度學習,更多使用者使用的是TensorFlow / PyTorch ,但其實還有很多類似的架構,PaddlePaddle就是其中之一。有人會說TensorFlow / PyTorch 已經這麼優秀了,為何還用 PaddlePaddle 呢 ?我這裡也想結合一周多的使用說說 。當初使用 Paddle Paddle架構我看中的是他在自然語言中文領域有很多現成的模型,舉個例子如情感分類,如閱讀了解,還有自動問答等,而且在使用上也是非常簡單。我就是奔着這個去的,至于其他像記憶體占用小啊,API易用這些用過就知道其實是一個場景相對的工作。如果我們使用自然語言相關,我是建議使用,但在計算機視覺或者其他的都差不多。PaddlePaddle 在設計初期就兼顧了動态圖和靜态圖,是以還是不錯的。 

        PaddlePaddle 有不少預訓練的模型,基于預訓練組建了一個PaddleHub ,  可以讓你快速調用并完成模型的管理,你還可以基于自有的模型做遷移學習,更好地服務應用場景。這裡做文本分類,我就直接用了PaddleHub 自有的 ERNIE 進行遷移學習。就這樣我就開始了一段神奇之旅。

一.ERNIE

在中文領域,這是一個非常非常棒的自然語言模型,和BERT 比,采用了先知Mask機制,和随機Mask 的BERT比,能更有效對中文常用詞進行判斷。更多可以參考  https://github.com/PaddlePaddle/ERNIE

二. 具體使用遇到的一些問題,PaddlePaddle 在網上搜尋的例子都是有問題的,因為基于原來的例子基本是按照1.x 版本(https://aistudio.baidu.com/aistudio/projectdetail/186443)改的,隻能自己碰

1.  環境問題,我現在的Cuda  環境是11.1 , 但是無論最新的2.1 還是2.0.2 其實都沒有支援的,開始我自己也慌了第一步就放棄麼?但我認真看了下,其實2.0.2 是支援11.0 也是可以在11.1的CUDA上跑,是以安裝環境就變成了

pip install paddlepaddle-gpu==2.0.2.post110 -f https://paddlepaddle.org.cn/whl/stable.html
           

是以對應的PaddleHub 就是2.1.0 (這裡還是得修正下,PaddleHub 用2.1,原來是2.0.2)

注:如果你是CPU就不需要考慮這個,但我覺得沒有GPU訓練也是太扯了如果做這個

2. ERNIE 版本選擇,其實我本來想要ERNIE,但最後選擇ERNIE-TINY是因為他更小巧,更适應我的場景, 如果你想應用其他也是可以的,他支援多種語義模型

利用PaddleHub 2.x 完成文本分類訓練的坑
import paddlehub as hub
model = hub.Module(name='ernie_tiny', version='2.0.1', task='seq-cls', num_classes=5)
           

 3. 因為我是做遷移學習的文本分類是以這裡就需要去繼承原有的TextClassificationDataset,我一直覺得是一個簡單活,結果花了我一堆時間,因為這裡對資料格式有要求,第一列必須是Label , 而且token是一個Bert+Custom ,  并且一定要做好測試集和訓練集,這裡我真的花了5天去找,但最後還是追看TextClassificationDataset 找到答案,主要是文檔太少

from typing import Dict, List, Optional, Union, Tuple
from paddlehub.datasets.base_nlp_dataset import TextClassificationDataset
import paddlenlp.data.tokenizer as tk
from paddlenlp.data import JiebaTokenizer
from paddlenlp.transformers import BertTokenizer
from paddlehub.text.tokenizer import CustomTokenizer

DATA_HOME = "./datasets/data/"

class TagDatasets(TextClassificationDataset):
    def __init__(self ,  tokenizer: Union[BertTokenizer, CustomTokenizer],max_seq_len: int = 128, mode: str = 'train'):
        if mode == 'train':
            data_file = 'data_train_list.tsv' 
        elif mode == 'test':
            data_file = 'data_test_list.tsv'
        else:
            data_file = 'data_all_list.tsv'
        super().__init__(
            base_path=DATA_HOME,
            max_seq_len=max_seq_len,
            tokenizer= tokenizer,
            data_file=data_file,
            label_list = ['0', '1', '2', '3', '4'], #改動2
            is_file_with_header=True)

train_dataset = TagDatasets(tokenizer=model.get_tokenizer(), max_seq_len=128, mode='train')
test_dataset = TagDatasets(tokenizer=model.get_tokenizer(), max_seq_len=128, mode='test')
           

       4. 訓練這裡細節也挺多的,特别最基本的一個traindata 這裡要說,我發現是要補充上learning_rate ,否則有些東西奇奇怪怪   

import paddle
optimizer = paddle.optimizer.Adam(learning_rate=5e-5, parameters=model.parameters())

trainer = hub.Trainer(model, optimizer,use_gpu=True, checkpoint_dir='./model/2021052501/ernie_text_cls')

trainer.train(train_dataset, epochs=10, batch_size=32, eval_dataset=train_dataset,save_interval=5)
trainer.evaluate(test_dataset, batch_size=32)
           

    這是我訓練的一些結果,還是不錯,這個過程我花了5個工作日,真是痛哭流涕

利用PaddleHub 2.x 完成文本分類訓練的坑

三.  一些工作還是要繼續的

1.  部署,其實PaddleHub建議用PaddleServing 來部署的,但由于現在模型還在調整,資料在增加,是以臨時方案還是直接用PaddleHub去解釋模型,這裡記憶體在伺服器占用大,要改進 

2.  調優,還有很多方法,還在學習中,希望日後可以填上 

3.  onnx , 還是想轉換為onnx ,但文檔很少,還是得花時間

4. 壓縮,模型壓縮就是技術活了,怎麼樣能做到一個精度高,容量小的模型,又是我要考慮的了

四. 小結

學習是一步步的,經過1周多,終于有成果, PaddlePaddle是好東西,但文檔,例子欠缺,我希望利用自己項目的經驗分享給大家。

繼續閱讀