愛鋒貝

 找回密碼
 立即注冊

只需一步,快速開始

扫一扫,极速登录

查看: 1010|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

使用PaddleNLP進行惡意網(wǎng)頁識別(二)

[復(fù)制鏈接]

1465

主題

1527

帖子

6083

積分

Rank: 8Rank: 8

跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2023-4-8 04:25:05 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

一鍵注冊,加入手機圈

您需要 登錄 才可以下載或查看,沒有帳號?立即注冊   

x
本文是《使用PaddleNLP進行惡意網(wǎng)頁識別》系列第二篇,該系列持續(xù)更新中……
系列目錄


  • 使用PaddleNLP進行惡意網(wǎng)頁識別(一)

    • 使用PaddleNLP的文本分類模型,做正常網(wǎng)頁與被黑網(wǎng)頁的簡單二分類,根據(jù)HTML網(wǎng)頁內(nèi)容處理結(jié)果判斷網(wǎng)頁是否正常。



  • 使用PaddleNLP進行惡意網(wǎng)頁識別(二)

    • 使用PaddleNLP的預(yù)訓(xùn)練模型Fine-tune,大幅提高根據(jù)HTML網(wǎng)頁內(nèi)容處理結(jié)果判斷網(wǎng)頁準(zhǔn)確率。

  • 本文能順利完成,要特別感謝社區(qū)@沒入門的研究生大佬的指導(dǎo)
  • 使用PaddleNLP進行惡意網(wǎng)頁識別(三)

    • 使用PaddleNLP的文本分類模型,做正常網(wǎng)頁與惡意網(wǎng)頁的簡單二分類,提取HTML標(biāo)簽信息判斷網(wǎng)頁是否正常。



  • 使用PaddleNLP進行惡意網(wǎng)頁識別(四)

    • 嘗試使用人工判斷條件,設(shè)計提取HTML標(biāo)簽信息識別惡意網(wǎng)頁的流程。
    • 使用PaddleNLP的預(yù)訓(xùn)練模型Fine-tune,嘗試提高提取HTML標(biāo)簽信息判斷網(wǎng)頁是否正常的效果。
    • 將動態(tài)圖訓(xùn)練的網(wǎng)頁分類模型導(dǎo)出并使用Python部署。

  • 使用PaddleNLP進行惡意網(wǎng)頁識別(五)

    • 該項目直接對標(biāo)系列第二篇,對比BERT中文預(yù)訓(xùn)練模型和Ernie預(yù)訓(xùn)練模型在HTML網(wǎng)頁內(nèi)容分類流程和效果上的差異。
    • 項目進一步完善和優(yōu)化了HTML網(wǎng)頁內(nèi)容提取和數(shù)據(jù)清洗流程。
    • 驗證集上模型準(zhǔn)確率可以輕松達到91.5%以上,最高達到95%,在BERT預(yù)訓(xùn)練模型上進行finetune,得到了目前在該HTML網(wǎng)頁內(nèi)容分類任務(wù)上的最好表現(xiàn)。



  • 使用PaddleNLP進行惡意網(wǎng)頁識別(六)

    • 該項目直接對標(biāo)系列第四篇,對比BERT中文預(yù)訓(xùn)練模型和Ernie預(yù)訓(xùn)練模型在HTML網(wǎng)頁標(biāo)簽分類效果上的差異。
    • 項目進一步完善和優(yōu)化了HTML的tag內(nèi)容提取和數(shù)據(jù)清洗流程。
    • 驗證集上模型準(zhǔn)確率可以輕松達到96.5%以上,測試集上準(zhǔn)確率接近97%,在BERT預(yù)訓(xùn)練模型上進行finetune,得到了目前在該HTML網(wǎng)頁標(biāo)簽序列分類任務(wù)上的最好表現(xiàn)。

  • 使用PaddleNLP進行惡意網(wǎng)頁識別(七)

    • 介紹了使用自動化測試工具selenium進行網(wǎng)頁快照抓取的方法。
    • 介紹了使用zxing開源庫進行網(wǎng)頁快照二維碼定位和解析的方法。
    • 介紹使用系列第六篇訓(xùn)練的模型,對二維碼中包含的url網(wǎng)頁鏈接進行識別分類的思路。

關(guān)于Fine-tune

近年來隨著深度學(xué)習(xí)的發(fā)展,模型參數(shù)數(shù)量飛速增長,為了訓(xùn)練這些參數(shù),需要更大的數(shù)據(jù)集來避免過擬合。然而,對于大部分NLP任務(wù)來說,構(gòu)建大規(guī)模的標(biāo)注數(shù)據(jù)集成本過高,非常困難,特別是對于句法和語義相關(guān)的任務(wù)。相比之下,大規(guī)模的未標(biāo)注語料庫的構(gòu)建則相對容易。最近的研究表明,基于大規(guī)模未標(biāo)注語料庫的預(yù)訓(xùn)練模型(Pretrained Models, PTM) 能夠習(xí)得通用的語言表示,將預(yù)訓(xùn)練模型Fine-tune到下游任務(wù),能夠獲得出色的表現(xiàn)。另外,預(yù)訓(xùn)練模型能夠避免從零開始訓(xùn)練模型。





預(yù)訓(xùn)練模型一覽,圖片來源:https://github.com/thunlp/PLMpapers

在PaddleNLP文檔中,介紹了下面這個示例:
使用預(yù)訓(xùn)練模型Fine-tune完成情感分析分類任務(wù)

該示例展示了以ERNIE(Enhanced Representation through Knowledge Integration)為代表的預(yù)訓(xùn)練模型如何Finetune完成中文情感分析任務(wù)。首先來看看這個示例的效果。
使用從源碼安裝的方法,安裝最新的PaddleNLP develop分支
!pip install --upgrade git+https://gitee.com/PaddlePaddle/PaddleNLP.git
!git clone https://gitee.com/paddlepaddle/PaddleNLP.git
import paddle
import paddlenlp
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/utils.py:26: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  def convert_to_list(value, n, name, dtype=np.int):預(yù)訓(xùn)練模型簡介

PaddleNLP針對中文文本分類問題,開源了一系列模型,供用戶可配置地使用:

  • BERT(Bidirectional Encoder Representations from Transformers)中文模型,簡寫bert-base-chinese, 其由12層Transformer網(wǎng)絡(luò)組成。
  • ERNIE(Enhanced Representation through Knowledge Integration),支持ERNIE 1.0中文模型(簡寫ernie-1.0)和ERNIE Tiny中文模型(簡寫ernie-tiny)。 其中ernie由12層Transformer網(wǎng)絡(luò)組成,ernie-tiny由3層Transformer網(wǎng)絡(luò)組成。
  • RoBERTa(A Robustly Optimized BERT Pretraining Approach),支持24層Transformer網(wǎng)絡(luò)的roberta-wwm-ext-large和12層Transformer網(wǎng)絡(luò)的roberta-wwm-ext。
| 模型 | dev acc | test acc | | --- | --- | --- | | bert-base-chinese | 0.93833 | 0.94750 | | bert-wwm-chinese | 0.94583 | 0.94917 | | bert-wwm-ext-chinese | 0.94667 | 0.95500 | | ernie-1.0 | 0.94667 | 0.95333 | | ernie-tiny | 0.93917 | 0.94833 | | roberta-wwm-ext | 0.94750 | 0.95250 | | roberta-wwm-ext-large | 0.95250 | 0.95333 | | rbt3 | 0.92583 | 0.93250 | | rbtl3 | 0.9341 | 0.93583 |
詳細說明可以參考:PaddleNLP文檔:使用預(yù)訓(xùn)練模型Fine-tune完成中文文本分類任務(wù),這里就不做贅述,主要看看訓(xùn)練效果:
!cd PaddleNLP/examples/text_classification/pretrained_models/ && python -m paddle.distributed.launch train.py --device gpu --save_dir ./checkpoints
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/utils.py:26: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  def convert_to_list(value, n, name, dtype=np.int):
-----------  Configuration Arguments -----------
gpus: None
heter_worker_num: None
heter_workers:
http_port: None
ips: 127.0.0.1
log_dir: log
nproc_per_node: None
server_num: None
servers:
training_script: train.py
training_script_args: ['--device', 'gpu', '--save_dir', './checkpoints']
worker_num: None
workers:
------------------------------------------------
WARNING 2021-04-28 10:53:28,780 launch.py:316] Not found distinct arguments and compiled with cuda. Default use collective mode
launch train in GPU mode
INFO 2021-04-28 10:53:28,782 launch_utils.py:471] Local start 1 processes. First process distributed environment info (Only For Debug):
    +=======================================================================================+
    |                        Distributed Envs                      Value                    |
    +---------------------------------------------------------------------------------------+
    |                       PADDLE_TRAINER_ID                        0                      |
    |                 PADDLE_CURRENT_ENDPOINT                 127.0.0.1:48117               |
    |                     PADDLE_TRAINERS_NUM                        1                      |
    |                PADDLE_TRAINER_ENDPOINTS                 127.0.0.1:48117               |
    |                     FLAGS_selected_gpus                        0                      |
    +=======================================================================================+

INFO 2021-04-28 10:53:28,782 launch_utils.py:475] details abouts PADDLE_TRAINER_ENDPOINTS can be found in log/endpoints.log, and detail running logs maybe found in log/workerlog.0
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/utils.py:26: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  def convert_to_list(value, n, name, dtype=np.int):
[2021-04-28 10:53:30,163] [    INFO] - Already cached /home/aistudio/.paddlenlp/models/ernie-tiny/ernie_tiny.pdparams
W0428 10:53:30.165206  8918 device_context.cc:362] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1
W0428 10:53:30.170289  8918 device_context.cc:372] device: 0, cuDNN Version: 7.6.
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py:1303: UserWarning: Skip loading for classifier.weight. classifier.weight is not found in the provided dict.
  warnings.warn(("Skip loading for {}. ".format(key) + str(err)))
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py:1303: UserWarning: Skip loading for classifier.bias. classifier.bias is not found in the provided dict.
  warnings.warn(("Skip loading for {}. ".format(key) + str(err)))
[2021-04-28 10:53:37,440] [    INFO] - Found /home/aistudio/.paddlenlp/models/ernie-tiny/vocab.txt
[2021-04-28 10:53:37,441] [    INFO] - Found /home/aistudio/.paddlenlp/models/ernie-tiny/spm_cased_simp_sampled.model
[2021-04-28 10:53:37,441] [    INFO] - Found /home/aistudio/.paddlenlp/models/ernie-tiny/dict.wordseg.pickle
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/parallel.py:423: UserWarning: The program will return to single-card operation. Please check 1, whether you use spawn or fleetrun to start the program. 2, Whether it is a multi-card program. 3, Is the current environment multi-card.
  warnings.warn("The program will return to single-card operation. "
global step 10, epoch: 1, batch: 10, loss: 0.52361, accu: 0.65000, speed: 9.22 step/s
global step 20, epoch: 1, batch: 20, loss: 0.50937, accu: 0.75625, speed: 11.10 step/s
global step 30, epoch: 1, batch: 30, loss: 0.20778, accu: 0.79271, speed: 11.12 step/s
global step 40, epoch: 1, batch: 40, loss: 0.17973, accu: 0.81719, speed: 11.10 step/s
global step 50, epoch: 1, batch: 50, loss: 0.13715, accu: 0.83500, speed: 11.10 step/s
global step 60, epoch: 1, batch: 60, loss: 0.31635, accu: 0.84792, speed: 10.91 step/s
global step 70, epoch: 1, batch: 70, loss: 0.48289, accu: 0.85759, speed: 11.09 step/s
global step 80, epoch: 1, batch: 80, loss: 0.33256, accu: 0.85977, speed: 11.09 step/s
global step 90, epoch: 1, batch: 90, loss: 0.23529, accu: 0.86528, speed: 10.92 step/s
global step 100, epoch: 1, batch: 100, loss: 0.10831, accu: 0.86781, speed: 11.07 step/s
eval loss: 0.24311, accu: 0.91000
global step 110, epoch: 1, batch: 110, loss: 0.24633, accu: 0.88750, speed: 1.30 step/s
global step 120, epoch: 1, batch: 120, loss: 0.21631, accu: 0.88594, speed: 11.09 step/s
global step 130, epoch: 1, batch: 130, loss: 0.24054, accu: 0.88542, speed: 11.08 step/s
global step 140, epoch: 1, batch: 140, loss: 0.14191, accu: 0.88828, speed: 11.06 step/s
global step 150, epoch: 1, batch: 150, loss: 0.17121, accu: 0.89687, speed: 11.11 step/s
global step 160, epoch: 1, batch: 160, loss: 0.26325, accu: 0.90104, speed: 11.13 step/s
global step 170, epoch: 1, batch: 170, loss: 0.11606, accu: 0.89955, speed: 11.10 step/s
global step 180, epoch: 1, batch: 180, loss: 0.06721, accu: 0.90391, speed: 11.08 step/s
global step 190, epoch: 1, batch: 190, loss: 0.24036, accu: 0.90417, speed: 11.10 step/s
global step 200, epoch: 1, batch: 200, loss: 0.58651, accu: 0.90312, speed: 11.13 step/s
eval loss: 0.21573, accu: 0.92583
global step 210, epoch: 1, batch: 210, loss: 0.29864, accu: 0.91563, speed: 1.29 step/s
global step 220, epoch: 1, batch: 220, loss: 0.33272, accu: 0.92188, speed: 11.08 step/s
global step 230, epoch: 1, batch: 230, loss: 0.30313, accu: 0.91771, speed: 11.10 step/s
global step 240, epoch: 1, batch: 240, loss: 0.26417, accu: 0.92109, speed: 11.09 step/s
global step 250, epoch: 1, batch: 250, loss: 0.32720, accu: 0.91938, speed: 11.08 step/s
global step 260, epoch: 1, batch: 260, loss: 0.29275, accu: 0.92188, speed: 11.11 step/s
global step 270, epoch: 1, batch: 270, loss: 0.22924, accu: 0.92277, speed: 11.13 step/s
global step 280, epoch: 1, batch: 280, loss: 0.07589, accu: 0.92461, speed: 11.09 step/s
global step 290, epoch: 1, batch: 290, loss: 0.19718, accu: 0.92708, speed: 11.11 step/s
global step 300, epoch: 1, batch: 300, loss: 0.09135, accu: 0.92875, speed: 11.06 step/s
eval loss: 0.19773, accu: 0.93583
^C
Traceback (most recent call last):
  File "/opt/conda/envs/python35-paddle120-env/lib/python3.7/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/opt/conda/envs/python35-paddle120-env/lib/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/distributed/launch.py", line 16, in <module>
    launch.launch()
  File "/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/distributed/fleet/launch.py", line 328, in launch
    launch_collective(args)
  File "/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/distributed/fleet/launch.py", line 244, in launch_collective
    time.sleep(3)
KeyboardInterrupt可以明顯看出,僅用了1個epoch后,情感分析的分類準(zhǔn)確率就來到90%以上,效果顯著。因此,可以想想,F(xiàn)inetune將是解決使用PaddleNLP進行惡意網(wǎng)頁識別(一)這個項目中,從0開始訓(xùn)練,效果不佳問題的一個答案。
使用PaddleNLP語義預(yù)訓(xùn)練模型ERNIE優(yōu)化惡意網(wǎng)頁識別效果

關(guān)于自定義數(shù)據(jù)集

不得不說,上面介紹的PaddleNLP Finetune示例封裝程度有點高,是直接使用了DatasetBuilder 的子類實現(xiàn)數(shù)據(jù)集的貢獻到數(shù)據(jù)集加載、模型訓(xùn)練的打通。但是在自定義數(shù)據(jù)集中,其實我們只需要關(guān)注訓(xùn)練數(shù)據(jù)是怎么整理的,格式如何即可。對應(yīng)到PaddleNLP的源碼中,就是text_classification/pretrained_models/train.py里的實現(xiàn),相關(guān)語句摘錄如下。
from paddlenlp.datasets import load_dataset
train_ds, dev_ds, test_ds = load_dataset(
    "chnsenticorp", splits=["train", "dev", "test"])
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/utils.py:26: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  def convert_to_list(value, n, name, dtype=np.int):
train_ds.label_list
['0', '1']
train_ds.data[:5]
[{'text': '選擇珠江花園的原因就是方便,有電動扶梯直接到達海邊,周圍餐館、食廊、商場、超市、攤位一應(yīng)俱全。酒店裝修一般,但還算整潔。 泳池在大堂的屋頂,因此很小,不過女兒倒是喜歡。 包的早餐是西式的,還算豐富。 服務(wù)嗎,一般',
  'label': 1},
{'text': '15.4寸筆記本的鍵盤確實爽,基本跟臺式機差不多了,蠻喜歡數(shù)字小鍵盤,輸數(shù)字特方便,樣子也很美觀,做工也相當(dāng)不錯',
  'label': 1},
{'text': '房間太小。其他的都一般。。。。。。。。。', 'label': 0},
{'text': '1.接電源沒有幾分鐘,電源適配器熱的不行. 2.攝像頭用不起來. 3.機蓋的鋼琴漆,手不能摸,一摸一個印. 4.硬盤分區(qū)不好辦.',
  'label': 0},
{'text': '今天才知道這書還有第6卷,真有點郁悶:為什么同一套書有兩種版本呢?當(dāng)當(dāng)網(wǎng)是不是該跟出版社商量商量,單獨出個第6卷,讓我們的孩子不會有所遺憾。',
  'label': 1}]因此,我們現(xiàn)在需要做的,就是將自定義數(shù)據(jù)集整理成上面的形式,其實就是PaddleNLP的MapDataset。由于PaddleNLP的文檔尚在完善中,讀者可能一下找不到相關(guān)入口,這時,可以從源代碼的注釋里找,比如利用AI Studio或者IDE上的這個功能:
??load_dataset自定義數(shù)據(jù)集的內(nèi)容則來自于上一個項目生成的webtrain.txt,webdev.txt,webtest.txt,本文已經(jīng)內(nèi)置。
PaddleNLP文檔:如何自定義數(shù)據(jù)集
通過使用PaddleNLP提供的 load_dataset() , MapDataset 和 IterDataset 。任何人都可以方便的定義屬于自己的數(shù)據(jù)集。
從本地文件創(chuàng)建數(shù)據(jù)集?
從本地文件創(chuàng)建數(shù)據(jù)集時,我們 推薦 根據(jù)本地數(shù)據(jù)集的格式給出讀取function并傳入 load_dataset() 中創(chuàng)建數(shù)據(jù)集。
以 waybill_ie 快遞單信息抽取任務(wù)中的數(shù)據(jù)為例:
```python from paddlenlp.datasets import load_dataset
def read(data_path):     with open(data_path, 'r', encoding='utf-8') as f:         # 跳過列名         next(f)         for line in f:             words, labels = line.strip('\n').split('\t')             words = words.split('\002')             labels = labels.split('\002')             yield {'tokens': words, 'labels': labels}
data_path為read()方法的參數(shù)
map_ds = load_dataset(read, data_path='train.txt',lazy=False) iter_ds = load_dataset(read, data_path='train.txt',lazy=True) ```
我們推薦將數(shù)據(jù)讀取代碼寫成生成器(generator)的形式,這樣可以更好的構(gòu)建 MapDataset 和 IterDataset 兩種數(shù)據(jù)集。同時我們也推薦將單條數(shù)據(jù)寫成字典的格式,這樣可以更方便的監(jiān)測數(shù)據(jù)流向。
事實上,MapDataset 在絕大多數(shù)時候都可以滿足要求。一般只有在數(shù)據(jù)集過于龐大無法一次性加載進內(nèi)存的時候我們才考慮使用 IterDataset 。任何人都可以方便的定義屬于自己的數(shù)據(jù)集。
注解
需要注意的是,只有從 DatasetBuilder 初始化的數(shù)據(jù)集具有將數(shù)據(jù)中的label自動轉(zhuǎn)為id的功能(詳細條件參見 如何貢獻數(shù)據(jù)集)。
像上例中的自定義數(shù)據(jù)集需要在自定義的convert to feature方法中添加label轉(zhuǎn)id的功能。
自定義數(shù)據(jù)讀取function中的參數(shù)可以直接以關(guān)鍵字參數(shù)的的方式傳入 load_dataset() 中。而且對于自定義數(shù)據(jù)集,lazy 參數(shù)是 必須 傳入的。
from paddlenlp.datasets import load_dataset

def read(data_path):
    with open(data_path, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip('\n').split('\t')
            # 注意,原數(shù)據(jù)集中可能文本里還有\(zhòng)t殘留,因此要使用下面的方法提取文本與標(biāo)簽,否則會報錯
            words = ''.join(line[:-1])
            labels = line[-1]
            yield {'text': words, 'label': labels}

# data_path為read()方法的參數(shù)
train_ds = load_dataset(read, data_path='webtrain.txt',lazy=False)
dev_ds = load_dataset(read, data_path='webdev.txt',lazy=False)
test_ds = load_dataset(read, data_path='webtest.txt',lazy=False)
train_ds.data[:10]
[{'text': '年以內(nèi),2萬公里以內(nèi)SUV1年以內(nèi)易車二手車體驗更好,速度更快立即前往APP看電腦版看微信版提意見購車熱線:4000-189-167(,9:00,–,21:00,)易車二手車,m.taoche.com',
  'label': '0'},
{'text': 'ipaime.com/thread-694853-1-1.htmlcoryphaei.com/forum.php?mod=viewthread&tid=3074054回復(fù)返回版塊參與回復(fù)?,棲霞商業(yè)網(wǎng)',
  'label': '0'},
{'text': '大直街店集體課表人和國際健身俱樂部首頁集體課表聯(lián)系我們掃描二維碼用手機訪問本站由業(yè)界領(lǐng)先的搜狐快站免費提供技術(shù)支持人和國際健身俱樂部人和健身大直街店集體課表15小時前閱讀Powered,by,搜狐快站',
  'label': '0'},
{'text': '個人帳戶工作或?qū)W校帳戶單位或?qū)W校未分配帳戶?使用,Microsoft,帳戶登錄厭煩了這個帳戶名稱?重命名您的個人,Microsoft,帳戶。?,2017,Microsoft使用條款隱私與,Cookie',
  'label': '0'},
{'text': 'ONGAB4yONGAB4y精絕美女-在線直播在線播放-高清無水印九獅賭城-美女荷官All,rights,reserved.Copyright,?2016,&2017',
  'label': '0'},
{'text': '蕭蕭聯(lián)稿...友情鏈接與我在線留言本站|友情連接|后臺管理2008--2012|http://www.syslh.com,|管理:塵涵圣域詩聯(lián)網(wǎng)站魯ICP備06019539號Open,LoginBar',
  'label': '1'},
{'text': '專利加急,專利查詢免責(zé)聲明:本站部分資料來自互聯(lián)網(wǎng),轉(zhuǎn)載時會注明出處;如果侵犯了你的權(quán)益,請通知我們,我們會及時刪除侵權(quán)內(nèi)容,謝謝合作!Powered,bywqCms5.7withWangqiInc.',
  'label': '0'},
{'text': '銀河賭場澳門賭場玩法在線賭博真錢賭博網(wǎng)站賭博現(xiàn)金網(wǎng)線上賭博平臺葡京娛樂場新葡京娛樂場金沙娛樂場bet365娛樂場真人娛樂場博彩網(wǎng)澳門博彩網(wǎng)站博彩公司博彩公司評級博彩現(xiàn)金網(wǎng)博彩網(wǎng)導(dǎo)航博彩技巧博彩公司排名',
  'label': '1'},
{'text': '云集品電子商務(wù)有限公司,版權(quán)所有.粵ICP備14072989號-2聯(lián)系方式0755-33198568elapsed_time:0.1559,memory_usage:6.96MB關(guān)注微信,贏取更多優(yōu)惠',
  'label': '0'},
{'text': '云集品電子商務(wù)有限公司,版權(quán)所有.粵ICP備14072989號-2聯(lián)系方式0755-33198568elapsed_time:0.1958,memory_usage:6.96MB關(guān)注微信,贏取更多優(yōu)惠',
  'label': '0'}]
# label_list手動添加進去就行
train_ds.label_list = ['0', '1']
dev_ds.label_list = ['0', '1']
test_ds.label_list = ['0', '1']
# 查看效果,確認(rèn)自定義數(shù)據(jù)集完成
print(train_ds.label_list)

for data in train_ds.data[:5]:
    print(data)
['0', '1']
{'text': '年以內(nèi),2萬公里以內(nèi)SUV1年以內(nèi)易車二手車體驗更好,速度更快立即前往APP看電腦版看微信版提意見購車熱線:4000-189-167(,9:00,–,21:00,)易車二手車,m.taoche.com', 'label': '0'}
{'text': 'ipaime.com/thread-694853-1-1.htmlcoryphaei.com/forum.php?mod=viewthread&tid=3074054回復(fù)返回版塊參與回復(fù)?,棲霞商業(yè)網(wǎng)', 'label': '0'}
{'text': '大直街店集體課表人和國際健身俱樂部首頁集體課表聯(lián)系我們掃描二維碼用手機訪問本站由業(yè)界領(lǐng)先的搜狐快站免費提供技術(shù)支持人和國際健身俱樂部人和健身大直街店集體課表15小時前閱讀Powered,by,搜狐快站', 'label': '0'}
{'text': '個人帳戶工作或?qū)W校帳戶單位或?qū)W校未分配帳戶?使用,Microsoft,帳戶登錄厭煩了這個帳戶名稱?重命名您的個人,Microsoft,帳戶。?,2017,Microsoft使用條款隱私與,Cookie', 'label': '0'}
{'text': 'ONGAB4yONGAB4y精絕美女-在線直播在線播放-高清無水印九獅賭城-美女荷官All,rights,reserved.Copyright,?2016,&2017', 'label': '0'}參考項目:『NLP經(jīng)典項目集』02:使用預(yù)訓(xùn)練模型ERNIE優(yōu)化情感分析 ,該項目也提供了數(shù)據(jù)處理腳本utils.py,本文已經(jīng)內(nèi)置。
PaddleNLP一鍵加載預(yù)訓(xùn)練模型

PaddleNLP對于各種預(yù)訓(xùn)練模型已經(jīng)內(nèi)置了對于下游任務(wù)-文本分類的Fine-tune網(wǎng)絡(luò)。以下教程ERNIE為例,介紹如何將預(yù)訓(xùn)練模型Fine-tune完成文本分類任務(wù)。

  • paddlenlp.transformers.ErnieModel()一行代碼即可加載預(yù)訓(xùn)練模型ERNIE。
  • paddlenlp.transformers.ErnieForSequenceClassification()一行代碼即可加載預(yù)訓(xùn)練模型ERNIE用于文本分類任務(wù)的Fine-tune網(wǎng)絡(luò)。

    • 其在ERNIE模型后拼接上一個全連接網(wǎng)絡(luò)(Full Connected)進行分類。



  • paddlenlp.transformers.ErnieForSequenceClassification.from_pretrained() 只需指定想要使用的模型名稱和文本分類的類別數(shù)即可完成網(wǎng)絡(luò)定義。
# 設(shè)置想要使用模型的名稱

MODEL_NAME = "ernie-1.0"

ernie_model = paddlenlp.transformers.ErnieModel.from_pretrained(MODEL_NAME)

model = paddlenlp.transformers.ErnieForSequenceClassification.from_pretrained(MODEL_NAME, num_classes=len(train_ds.label_list))
[2021-04-28 13:16:39,380] [    INFO] - Already cached /home/aistudio/.paddlenlp/models/ernie-1.0/ernie_v1_chn_base.pdparams
[2021-04-28 13:16:45,760] [    INFO] - Already cached /home/aistudio/.paddlenlp/models/ernie-1.0/ernie_v1_chn_base.pdparams
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py:1303: UserWarning: Skip loading for classifier.weight. classifier.weight is not found in the provided dict.
  warnings.warn(("Skip loading for {}. ".format(key) + str(err)))
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py:1303: UserWarning: Skip loading for classifier.bias. classifier.bias is not found in the provided dict.
  warnings.warn(("Skip loading for {}. ".format(key) + str(err)))調(diào)用ppnlp.transformers.ErnieTokenizer進行數(shù)據(jù)處理

預(yù)訓(xùn)練模型ERNIE對中文數(shù)據(jù)的處理是以字為單位。PaddleNLP對于各種預(yù)訓(xùn)練模型已經(jīng)內(nèi)置了相應(yīng)的tokenizer。指定想要使用的模型名字即可加載對應(yīng)的tokenizer。
tokenizer作用為將原始輸入文本轉(zhuǎn)化成模型model可以接受的輸入數(shù)據(jù)形式。









ERNIE模型框架示意圖

tokenizer = paddlenlp.transformers.ErnieTokenizer.from_pretrained(MODEL_NAME)
[2021-04-28 13:16:47,310] [    INFO] - Found /home/aistudio/.paddlenlp/models/ernie-1.0/vocab.txt數(shù)據(jù)讀入

使用paddle.io.DataLoader接口多線程異步加載數(shù)據(jù)。
from functools import partial
from paddlenlp.data import Stack, Tuple, Pad
from utils import  convert_example, create_dataloader

# 模型運行批處理大小
batch_size = 16
max_seq_length = 128

trans_func = partial(
    convert_example,
    tokenizer=tokenizer,
    max_seq_length=max_seq_length)
batchify_fn = lambda samples, fn=Tuple(
    Pad(axis=0, pad_val=tokenizer.pad_token_id),  # input
    Pad(axis=0, pad_val=tokenizer.pad_token_type_id),  # segment
    Stack(dtype="int64")  # label
): [data for data in fn(samples)]

train_data_loader = create_dataloader(
    train_ds,
    mode='train',
    batch_size=batch_size,
    batchify_fn=batchify_fn,
    trans_fn=trans_func)
dev_data_loader = create_dataloader(
    dev_ds,
    mode='dev',
    batch_size=batch_size,
    batchify_fn=batchify_fn,
    trans_fn=trans_func)
test_data_loader = create_dataloader(
    test_ds,
    mode='test',
    batch_size=batch_size,
    batchify_fn=batchify_fn,
    trans_fn=trans_func)
from paddlenlp.transformers import LinearDecayWithWarmup

# 訓(xùn)練過程中的最大學(xué)習(xí)率
learning_rate = 5e-5
# 訓(xùn)練輪次
epochs = 10
# 學(xué)習(xí)率預(yù)熱比例
warmup_proportion = 0.1
# 權(quán)重衰減系數(shù),類似模型正則項策略,避免模型過擬合
weight_decay = 0.01

num_training_steps = len(train_data_loader) * epochs
lr_scheduler = LinearDecayWithWarmup(learning_rate, num_training_steps, warmup_proportion)
optimizer = paddle.optimizer.AdamW(
    learning_rate=lr_scheduler,
    parameters=model.parameters(),
    weight_decay=weight_decay,
    apply_decay_param_fun=lambda x: x in [
        p.name for n, p in model.named_parameters()
        if not any(nd in n for nd in ["bias", "norm"])
    ])

criterion = paddle.nn.loss.CrossEntropyLoss()
metric = paddle.metric.Accuracy()
# checkpoint文件夾用于保存訓(xùn)練模型
!mkdir /home/aistudio/checkpoint模型訓(xùn)練與評估

模型訓(xùn)練的過程通常有以下步驟:

  • 從dataloader中取出一個batch data
  • 將batch data喂給model,做前向計算
  • 將前向計算結(jié)果傳給損失函數(shù),計算loss。將前向計算結(jié)果傳給評價方法,計算評價指標(biāo)。
  • loss反向回傳,更新梯度。重復(fù)以上步驟。
每訓(xùn)練一個epoch時,程序?qū)u估一次,評估當(dāng)前模型訓(xùn)練的效果。
import paddle.nn.functional as F
from utils import evaluate
from visualdl import LogWriter

global_step = 0
for epoch in range(1, epochs + 1):
    with LogWriter(logdir="./visualdl") as writer:
        for step, batch in enumerate(train_data_loader, start=1):
            input_ids, segment_ids, labels = batch
            logits = model(input_ids, segment_ids)
            loss = criterion(logits, labels)
            probs = F.softmax(logits, axis=1)
            correct = metric.compute(probs, labels)
            metric.update(correct)
            acc = metric.accumulate()
            global_step += 1
            if global_step % 10 == 0 :
                print("global step %d, epoch: %d, batch: %d, loss: %.5f, acc: %.5f" % (global_step, epoch, step, loss, acc))
                # 向記錄器添加一個tag為`loss`的數(shù)據(jù)
            writer.add_scalar(tag="loss", step=global_step, value=loss)
            # 向記錄器添加一個tag為`acc`的數(shù)據(jù)
            writer.add_scalar(tag="acc", step=global_step, value=acc)
            loss.backward()
            optimizer.step()
            lr_scheduler.step()
            optimizer.clear_grad()
        evaluate(model, criterion, metric, dev_data_loader)

model.save_pretrained('/home/aistudio/checkpoint')
tokenizer.save_pretrained('/home/aistudio/checkpoint')
global step 10, epoch: 1, batch: 10, loss: 0.20771, acc: 0.96875
eval loss: 0.30647, accu: 0.87963
global step 20, epoch: 2, batch: 1, loss: 0.06249, acc: 1.00000
global step 30, epoch: 2, batch: 11, loss: 0.11620, acc: 0.97727
eval loss: 0.36536, accu: 0.87037
global step 40, epoch: 3, batch: 2, loss: 0.02215, acc: 1.00000
global step 50, epoch: 3, batch: 12, loss: 0.00893, acc: 0.98958
eval loss: 0.56552, accu: 0.86111
global step 60, epoch: 4, batch: 3, loss: 0.00972, acc: 0.95833
global step 70, epoch: 4, batch: 13, loss: 0.01328, acc: 0.98077
eval loss: 0.81667, accu: 0.77778
global step 80, epoch: 5, batch: 4, loss: 0.22332, acc: 0.95312
global step 90, epoch: 5, batch: 14, loss: 0.27860, acc: 0.96429
eval loss: 0.40668, accu: 0.85185
global step 100, epoch: 6, batch: 5, loss: 0.03298, acc: 1.00000
global step 110, epoch: 6, batch: 15, loss: 0.00961, acc: 0.99167
eval loss: 0.27407, accu: 0.87963
global step 120, epoch: 7, batch: 6, loss: 0.01436, acc: 1.00000
global step 130, epoch: 7, batch: 16, loss: 0.00705, acc: 1.00000
eval loss: 0.31425, accu: 0.88889
global step 140, epoch: 8, batch: 7, loss: 0.00653, acc: 1.00000
global step 150, epoch: 8, batch: 17, loss: 0.00868, acc: 1.00000
eval loss: 0.30953, accu: 0.87963
global step 160, epoch: 9, batch: 8, loss: 0.00582, acc: 1.00000
global step 170, epoch: 9, batch: 18, loss: 0.00582, acc: 1.00000
eval loss: 0.31251, accu: 0.87963
global step 180, epoch: 10, batch: 9, loss: 0.00378, acc: 1.00000
global step 190, epoch: 10, batch: 19, loss: 0.00494, acc: 1.00000
eval loss: 0.31438, accu: 0.87963








VisualDL訓(xùn)練過程

模型預(yù)測

訓(xùn)練保存好的訓(xùn)練,即可用于預(yù)測。如以下示例代碼自定義預(yù)測數(shù)據(jù),調(diào)用predict()函數(shù)即可一鍵預(yù)測。
from utils import predict

data = [
{'text': ',3,4號不發(fā)貨,介意者慎拍,謝謝!有品燃脂營微信“掃一掃”立即關(guān)注微信號:picoocbxj主頁最新商品有品私教有品魔秤我的訂單店鋪主頁會員中心關(guān)注我們店鋪信息有贊提供技術(shù)支持取消清除歷史搜索購物車'},

{'text': 'et是什么意思weekend是什么意思warn是什么意思team是什么意思Copyright,?,2006,-,2016,XUEXILA.COM,All,Rights,Reserved學(xué)習(xí)啦,版權(quán)所有'},

{'text': '太陽娛樂城現(xiàn)金開戶皇家堡娛樂城彩票網(wǎng)上投注怎么領(lǐng)獎彩票網(wǎng)上投注那個好網(wǎng)上賭場排行送173元,一肖中特免費資料博悅娛樂是不是正規(guī)的天苑娛樂城xvsr姦全犯罪成海うるみkzcs16.com藝考不是博彩首頁'},

{'text': 'SS訂閱抵制不良游戲,拒絕盜版游戲,注意自我保護,謹(jǐn)防受騙上當(dāng),適度游戲益腦,沉迷游戲傷身,合理安排時間,享受健康生活Copyright,?,201788130安卓下載滬ICP備16000974號-9'},

{'text': '百度架構(gòu)師手把手帶你實現(xiàn)零基礎(chǔ)小白到AI工程師的華麗蛻變'},
]
label_map = {0: '正常頁面', 1: '被黑頁面'}

results = predict(
    model, data, tokenizer, label_map, batch_size=batch_size)
for idx, text in enumerate(data):
    print('Data: {} \t Lable: {}'.format(text, results[idx]))
Data: {'text': ',3,4號不發(fā)貨,介意者慎拍,謝謝!有品燃脂營微信“掃一掃”立即關(guān)注微信號:picoocbxj主頁最新商品有品私教有品魔秤我的訂單店鋪主頁會員中心關(guān)注我們店鋪信息有贊提供技術(shù)支持取消清除歷史搜索購物車'}   Lable: 正常頁面
Data: {'text': 'et是什么意思weekend是什么意思warn是什么意思team是什么意思Copyright,?,2006,-,2016,XUEXILA.COM,All,Rights,Reserved學(xué)習(xí)啦,版權(quán)所有'}   Lable: 正常頁面
Data: {'text': '太陽娛樂城現(xiàn)金開戶皇家堡娛樂城彩票網(wǎng)上投注怎么領(lǐng)獎彩票網(wǎng)上投注那個好網(wǎng)上賭場排行送173元,一肖中特免費資料博悅娛樂是不是正規(guī)的天苑娛樂城xvsr姦全犯罪成海うるみkzcs16.com藝考不是博彩首頁'}   Lable: 被黑頁面
Data: {'text': 'SS訂閱抵制不良游戲,拒絕盜版游戲,注意自我保護,謹(jǐn)防受騙上當(dāng),適度游戲益腦,沉迷游戲傷身,合理安排時間,享受健康生活Copyright,?,201788130安卓下載滬ICP備16000974號-9'}   Lable: 正常頁面
Data: {'text': '百度架構(gòu)師手把手帶你實現(xiàn)零基礎(chǔ)小白到AI工程師的華麗蛻變'}   Lable: 正常頁面為試驗?zāi)P偷姆夯芰Γ@里還把情感分析的文本也傳入模型中(腦洞大開= =),輸出結(jié)果正常。
from utils import predict

data = [
    {"text":'這個賓館比較陳舊了,特價的房間也很一般。總體來說一般'},
    {"text":'懷著十分激動的心情放映,可是看著看著發(fā)現(xiàn),在放映完畢后,出現(xiàn)一集米老鼠的動畫片'},
    {"text":'作為老的四星酒店,房間依然很整潔,相當(dāng)不錯。機場接機服務(wù)很好,可以在車上辦理入住手續(xù),節(jié)省時間。'},
]
label_map = {0: '正常頁面', 1: '被黑頁面'}

results = predict(
    model, data, tokenizer, label_map, batch_size=batch_size)
for idx, text in enumerate(data):
    print('Data: {} \t Lable: {}'.format(text, results[idx]))
Data: {'text': '這個賓館比較陳舊了,特價的房間也很一般??傮w來說一般'}     Lable: 正常頁面
Data: {'text': '懷著十分激動的心情放映,可是看著看著發(fā)現(xiàn),在放映完畢后,出現(xiàn)一集米老鼠的動畫片'}    Lable: 正常頁面
Data: {'text': '作為老的四星酒店,房間依然很整潔,相當(dāng)不錯。機場接機服務(wù)很好,可以在車上辦理入住手續(xù),節(jié)省時間。'}   Lable: 正常頁面也可以通過自定義數(shù)據(jù)集的方式,從測試集直接加載數(shù)據(jù)
from paddlenlp.datasets import load_dataset

def read(data_path):
    with open(data_path, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip('\n').split('\t')
            # 注意,原數(shù)據(jù)集中可能文本里還有\(zhòng)t殘留,因此要使用下面的方法提取文本與標(biāo)簽,否則會報錯
            words = ''.join(line[:-1])
            yield {'text': words}

# data_path為read()方法的參數(shù)
test_ds = load_dataset(read, data_path='webtest.txt',lazy=False)
test_ds.label_list = ['0', '1']
test_ds[-5:]
[{'text': '區(qū)永壽縣三原縣禮泉縣長武縣陜西相關(guān)分類:安康綜合醫(yī)院黃頁寶雞綜合醫(yī)院黃頁漢中綜合醫(yī)院黃頁商洛綜合醫(yī)院黃頁銅川綜合醫(yī)院黃頁渭南綜合醫(yī)院黃頁西安綜合醫(yī)院黃頁延安綜合醫(yī)院黃頁榆林綜合醫(yī)院黃頁分享到更多...'},
{'text': '云集品電子商務(wù)有限公司,版權(quán)所有.粵ICP備14072989號-2聯(lián)系方式0755-33198568elapsed_time:0.1522,memory_usage:6.96MB關(guān)注微信,贏取更多優(yōu)惠'},
{'text': '陽城娛樂開戶網(wǎng)址實戰(zhàn)百家樂真錢娛樂百家樂莊和閑哪個多澳門賭場攻略彩摘博彩資訊網(wǎng)上真錢賭博新華區(qū)體育路小學(xué)足球博彩網(wǎng)址大全太陽城開戶澳門皇冠賭場足球盈虧指數(shù)優(yōu)博博彩太陽城游戲開戶皇冠在線充值平臺大家比分'},
{'text': '站長統(tǒng)計'},
{'text': '公司名:常熟市鑫豐貨運有限公司會員組:免費會員,\xa0[我要升級]狀態(tài):離線姓名:魏如文(先生)職位:總經(jīng)理電話:0512-52849533手機:15962489066QQ:地址:常熟市通港路88一99號'}]
from utils import predict

label_map = {0: '正常頁面', 1: '被黑頁面'}

results = predict(
    model, test_ds[-5:], tokenizer, label_map, batch_size=batch_size)
for idx, text in enumerate(test_ds[-5:]):
    print('Data: {} \t Lable: {}'.format(text, results[idx]))
Data: {'text': '區(qū)永壽縣三原縣禮泉縣長武縣陜西相關(guān)分類:安康綜合醫(yī)院黃頁寶雞綜合醫(yī)院黃頁漢中綜合醫(yī)院黃頁商洛綜合醫(yī)院黃頁銅川綜合醫(yī)院黃頁渭南綜合醫(yī)院黃頁西安綜合醫(yī)院黃頁延安綜合醫(yī)院黃頁榆林綜合醫(yī)院黃頁分享到更多...'}   Lable: 正常頁面
Data: {'text': '云集品電子商務(wù)有限公司,版權(quán)所有.粵ICP備14072989號-2聯(lián)系方式0755-33198568elapsed_time:0.1522,memory_usage:6.96MB關(guān)注微信,贏取更多優(yōu)惠'}   Lable: 正常頁面
Data: {'text': '陽城娛樂開戶網(wǎng)址實戰(zhàn)百家樂真錢娛樂百家樂莊和閑哪個多澳門賭場攻略彩摘博彩資訊網(wǎng)上真錢賭博新華區(qū)體育路小學(xué)足球博彩網(wǎng)址大全太陽城開戶澳門皇冠賭場足球盈虧指數(shù)優(yōu)博博彩太陽城游戲開戶皇冠在線充值平臺大家比分'}   Lable: 被黑頁面
Data: {'text': '站長統(tǒng)計'}   Lable: 正常頁面
Data: {'text': '公司名:常熟市鑫豐貨運有限公司會員組:免費會員,\xa0[我要升級]狀態(tài):離線姓名:魏如文(先生)職位:總經(jīng)理電話:0512-52849533手機:15962489066QQ:地址:常熟市通港路88一99號'}    Lable: 正常頁面小結(jié)


  • Finetune后模型預(yù)測效果得到了大幅提升,且收斂非???。當(dāng)然,由于第一個項目在數(shù)據(jù)預(yù)處理的時候還是采用比較粗暴的方式,因此數(shù)據(jù)集里可能有一些瑕疵,影響了指標(biāo)進一步提升,在后續(xù)的項目中,會進一步研究數(shù)據(jù)清洗問題。
  • NLP的調(diào)參有點玄學(xué),F(xiàn)inetune后模型如何“煉丹”,需要讀者進一步探索。
  • 再次感謝社區(qū)@沒入門的研究生大佬的指導(dǎo),NLP果然上手難度比較大,建議初學(xué)者使用的時候,遇到問題也要多交流,避免卡很久。
參考資料:PaddleNLP更多教程


  • 使用seq2vec模塊進行句子情感分類
  • 使用BiGRU-CRF模型完成快遞單信息抽取
  • 使用預(yù)訓(xùn)練模型ERNIE優(yōu)化快遞單信息抽取
  • 使用Seq2Seq模型完成自動對聯(lián)
  • 使用預(yù)訓(xùn)練模型ERNIE-GEN實現(xiàn)智能寫詩
  • 使用TCN網(wǎng)絡(luò)完成新冠疫情病例數(shù)預(yù)測
  • 使用預(yù)訓(xùn)練模型完成閱讀理解
  • 自定義數(shù)據(jù)集實現(xiàn)文本多分類任務(wù)

-----------------------------
精選高品質(zhì)二手iPhone,上愛鋒貝APP
您需要登錄后才可以回帖 登錄 | 立即注冊   

本版積分規(guī)則

QQ|Archiver|手機版|小黑屋|愛鋒貝 ( 粵ICP備16041312號-5 )

GMT+8, 2025-2-12 16:41

Powered by Discuz! X3.4

© 2001-2013 Discuz Team. 技術(shù)支持 by 巔峰設(shè)計.

快速回復(fù) 返回頂部 返回列表