DeepPavlov:一個訓練對話系統和聊天機器人的開源庫

思源發表於2018-02-27

專案地址:https://github.com/deepmipt/DeepPavlov

這是一個開源的對話 AI 庫,建立在 TensorFlow 和 Keras 上,其用途是:

  • NLP 和對話系統研究;

  • 複雜對話系統的實現和評估。

我們的目標是為研究者提供:

  • 用於實現和測試他們自己的對話模型並隨後將模型共享的框架;

  • 一系列預定義的 NLP 模型/對話系統元件(機器學習/深度學習/規則系統)和流程模板;

  • 對話模型的基準測試環境和對相關資料的系統性評估。

併為 AI 應用開發者提供:

  • 建立對話軟體的框架;

  • 將應用與對應基礎建設(通訊、技術支援軟體等)相整合的工具。

專案特徵

格位填充元件(Slot filling component):基於命名實體識別(NER)神經網路和模糊 Levenshtein 搜尋,以從文字中提取歸一化的格位值(slot values)。NER 網路元件根據論文《Application of a Hybrid Bi-LSTM-CRF model to the task of Russian Named Entity Recognition》重新生成了架構,由《Neural Architectures for Named Entity Recognition》中的 LSTM+CRF 架構所啟發。

專用分類元件:基於論文《Convolutional Neural Networks for Sentence Classification》中的 shallow-and-wide CNN 架構。該模型允許語句的多標籤分類。

自動拼寫和校正元件:基於論文《An Improved Error Model for Noisy Channel Spelling Correction》,並使用基於統計學的誤差模型、一個靜態詞典和一個 ARPA 語言模型以校正拼寫錯誤。

目標導向的對話機器人:基於論文《Hybrid Code Networks: practical and efficient end-to-end dialog control with supervised and reinforcement learning》中的 Hybrid Code Networks 架構。它允許在目標導向任務的對話中預測回應。該模型是相當可定製的:嵌入、格位填充器和專用分類器可以根據需要使用或者不用。

為俄語預訓練的嵌入:在聯合俄語 Wikipedia 和 Lenta.ru 語料庫詞向量上進行預訓練得到的詞嵌入。

簡單示例

用 Telegram 部署目標導向的對話機器人和格位填充(slot-filling)的影片 demo:


  • 用 Telegram 介面執行目標導向的對話機器人:

python deep.py interactbot skills/go_bot/config.json -t <TELEGRAM_TOKEN>
  • 用控制檯介面執行目標導向的對話機器人:

python deep.py interact skills/go_bot/config.json
  • 用 Telegram 介面執行格位填充模型:

python deep.py interactbot models/ner/config.json -t <TELEGRAM_TOKEN>
  • 用控制檯介面執行格位填充模型:

python deep.py interact models/ner/config.json

概念簡述

原則

這個庫遵循以下原則設計:

  • 將端到端學習架構作為長期目標;

  • 目前採用混合的機器學習/深度學習/規則系統的架構;

  • 模組化的對話系統架構;

  • 基於元件的軟體工程,最大化複用性;

  • 易於擴充套件和基準測試;

  • 為單個 NLP 任務提供多個元件,透過資料驅動選擇合適的元件。

目標架構

我們的庫的目標架構:

DeepPavlov:一個訓練對話系統和聊天機器人的開源庫

DeepPavlov 建立在機器學習庫(TensorFlow、Keras)之上。可以用其它外部的庫建立基礎元件。

關鍵概念

  • Agent(智慧體):對話智慧體用自然語言(文字)和使用者進行交流。

  • Skill(技能):用於滿足使用者需求的互動單元。通常可以透過展示資訊或完成任務(例如,透過 FAQ 回答問題等);然而,根據經驗,某些任務的成功會被定義成連續的進展(例如,閒聊)。

  • Components(元件):基礎功能模組:

  • Rule-based Components(基於規則的元件)—無法訓練;

  • Machine Learning Components(機器學習元件)—僅能獨立訓練;

  • Deep Learning Components(深度學習元件)—可以獨立地訓練,也能以端對端的方式結合到工作鏈中。

  • Switcher(轉換器):智慧體排序和選擇向使用者展示的最終應答的機制。

  • Components Chainer(元件連結器):從各種元件(Rule-based/ml/dl)構建智慧體/元件管道的工具,允許以整體的形式訓練和推理管道。

技術概覽

專案模組

DeepPavlov:一個訓練對話系統和聊天機器人的開源庫

配置

NLP 的流程配置為 JSON 檔案,它包含四個元素:

{
 "dataset_reader": {
 },
 "dataset": {
 },
 "vocabs": {
 },
 "model": {
 }
}

配置檔案中每一個類都有一個 name 引數,它是註冊的程式碼名。透過重複它的__init__() 方法引數,我們可以定義其它任何引數。__init__() 引數的預設值在類的例項初始化中被配置值覆蓋。

資料集讀取器

DatasetReader 類能讀取資料並返回特定的格式。一個具體的 DatasetReader 類應該從基本的 deeppavlov.data.dataset_reader.DatasetReader 類繼承,並註冊為程式碼名:

@register('dstc2_datasetreader')
class DSTC2DatasetReader(DatasetReader):

資料集

Dataset 類構成我們所需的資料集(「訓練」、「驗證」和「測試」)和批次資料。一個具體的 Dataset 類應該註冊並可以從 deeppavlov.data.dataset_reader.Dataset 類繼承。

deeppavlov.data.dataset_reader.Dataset 類不是抽象類,它同樣可以像 Dataset 類那樣使用。

詞彙

Vocab 是一個可訓練的類,它能構建和序列化詞彙。Vocab 能索引任何資料,它能索引 X(特徵)和 y(回答)型別的資料。一個具體的 Vocab 類應該註冊並可以從 deeppavlov.data.vocab.DefaultVocabulary 類繼承。

deeppavlov.data.vocab.DefaultVocabulary 並不是一個抽象的類,它同樣可以像 Vocab 類那樣使用。

模型

Model 是制定訓練、推斷過程和生成特徵的主要類。如果模型需要其它模型生成特徵,那麼就需要將其傳遞到建構函式和配置檔案中。所有的模型可根據需要巢狀,例如 deeppavlov.skills.go_bot.go_bot.GoalOrientedBot 主要由 11 個獨立的 Model 類構建,其中有三個為神經網路:

{
 "model": {
   "name": "go_bot",
   "network": {
     "name": "go_bot_rnn"
   },
   "slot_filler": {
     "name": "dstc_slotfilling",
     "ner_network": {
        "name": "ner_tagging_network",
     }
   },
   "intent_classifier": {
     "name": "intent_model",
     "embedder": {
       "name": "fasttext"
     },
     "tokenizer": {
       "name": "nltk_tokenizer"
     }
   },
   "embedder": {
     "name": "fasttext"
   },
   "bow_encoder": {
     "name": "bow"
   },
   "tokenizer": {
     "name": "spacy_tokenizer"
   },
   "tracker": {
     "name": "featurized_tracker"
   }
 }
}

所有模型都應該註冊並從 deeppavlov.core.models.inferable.Inferable 或 Inferable 和 deeppavlov.core.models.trainable.Trainable 介面繼承。從 Trainable 繼承的模型可以繼續訓練,從 Inferable 介面繼承的模型只能執行推斷。通常,Inferable 模型是基於規則的模型或從第三方庫匯入的預訓練模型。

訓練

所有從 deeppavlov.core.models.trainable.Trainable 介面繼承的模型都可訓練,訓練過程在 train() 方法中有詳細描述。

@register("my_model")
class MyModel(Inferable, Trainable):

  def train(*args, **kwargs):
      """
      Implement training here.
      """

所有在實驗中可以改變的訓練引數(如 Epoch 數、批次大小、容忍度、學習率個最佳化器等)都應該傳遞到模型的建構函式__init__(),且__init__() 中的預設引數值將會被 JSON 配置值覆蓋。要改變這些值,我們不需重寫程式碼,只需要修改配置檔案就行。

訓練過程由 train_now 屬性控制。如果 train_now 為真,表示模型正在執行訓練。在使用 Vocab 時,這個引數十分有用,因為可以在單個模型中訓練一些詞彙,而另一些詞彙只會在流程中的其它模型上執行推斷。JASON 配置檔案中的訓練引數以設定成:

{
 "model": {
   "name": "my_model",
   "train_now": true,
   "optimizer": "Adam",
   "learning_rate": 0.2,
   "num_epochs": 1000
 }
}

推斷

所有從 deeppavlov.core.models.inferable.Inferable 介面繼承的模型都能執行推斷。infer() 方法應返回模型可執行的操作,例如分詞器應該返回符號、命名實體識別器應該返回識別的實體等。此外,infer() 中應該定義特定格式的返回資料。

推斷由 deeppavlov.core.commands.train.infer_model_from_config()函式觸發,並不需要單獨的 JSON 進行推斷,且 train_now 引數在推斷中也會被忽略。

相關文章