Pythonで作る対話システムの感想
背景
- 何か言語処理システムを作ってみようと思ったため
感想
- 自分のような理論だけじゃ嫌で作らないとわかりずらい・イメージしにくいという方にはかなりおすすめの本.(というか,対話システムの作成方法がまとめれられている日本語の新しい本がこれしかない?)
- 対話システムとは何なのかというところから,それらの種類について知ることができた.
- また,各種のシステムをこの本で作成することができ,どのようにして作成するのかのイメージができてよかった.
- 個人的には,方言への変化やスマートスピーカーへの応用などもあって面白かった.
- タスク指向の部分は,現状自分が考えていたほど自動化が進んでいるわけではなく,人によるタスク選定が重要なのかなと感じた.このタスクの選定までも自動化できたらかなり便利になるだろうなと思う.
次にやること
VagrantとDockerを用いたC++勉強のための環境構築方法
背景
環境構築
- train_cppフォルダを作成し,cdでこの中に移動
mkdir train_cpp cd train_cpp
- マウント用にshareフォルダに作成し,その中にtrain_srcフォルダも作成
mkdir share cd share mkdir train_src
- train_cppにVagrantfileを作成し以下のように記述
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.synced_folder "./share", "/home/vagrant/share" config.vm.define "train_cpp" do |machine| machine.vm.network "private_network", ip: "192.168.1.1" end end
- vmを作成
vagrant up # vm作成 vagrant ssh # vmに接続・アクセス
- 作成した仮想マシンにDockerを公式ページを見てインストールする.
- 作成した仮想マシンにDocker Composeを公式ページを見てインストールする.
- shareフォルダ内にDockerfileを作成し,以下の内容を記述する
FROM ubuntu:18.04 ENV DEBISN_FRONTEND=noninteractive RUN apt-get update && \ apt-get install -y build-essential
- shareフォルダ内にdocker-compose.ymlを作成し,以下の内容を記述する
version: '3.7' services: train_cpp: build: context: . dockerfile: Dockerfile image: train_cpp container_name: train_cpp volumes: - type: bind source: "./train_src" target: "/train_src"
- 以下のコマンドを実行しイメージとコンテナを作成
sudo su docker-compose build docker-compose up
- 作成したコンテナにアクセスする方法
sudo su docker-compose run train_cpp bash
感想
- やっぱり環境構築は時間がかかった.単純に仮想マシンに直で用意すればすぐだったはず......
- ただ,dockerの勉強にはなったのでそこは良かった.
次にやるとよいことは?
- C++の勉強
参考ページ
Vagrntで複数VMのネットワーク設定をしつつホストとの共有フォルダの設定方法
概要
背景
前提
- windows10
- Vagrant, Virtualbox インストール済み
- box は bento/centos-7.8 を利用
Vagrantfile の設定
- 以下のような内容をVagrantfileに記述する
- Vagrantfileと同じディレクトリにファイル共有フォルダ(ここではshare)を作成する
# -*- mode: ruby -*- # vi: set ft=ruby : Vargrant.configure("2") do |config| config.vm.box = "bento/centos-7.8" # 以下の一行でホストとvmとの共有フォルダの設定 config.vm.synced_folder "./share", "/home/vagrant/share" # これより以下はVMの例.具体的には2台のVMをIP指定をする設定. config.vm.define "任意の文字列" do |machine| # ホストオンリーアダプター machine.vm.network "private_network", ip: "任意のIPアドレス", auto_config:false # 内部ネットワーク machine.vm.network "private_network", ip: "任意のIPアドレス", virtualbox__intnet: "任意の内部ネットワーク名" end config.vm.define "任意の文字列" do |machine| # ホストオンリーアダプター machine.vm.network "private_network", ip: "任意のIPアドレス", auto_config:false # 内部ネットワーク machine.vm.network "private_network", ip: "任意のIPアドレス", virtualbox__intnet: "任意の内部ネットワーク名" end end
vagrant-vbguest のインストール
vargrant plugin install vagrant-vbguest
CentOS7のカーネルアップデート
確認作業
参考先
- Vagrant – 共有設定・カーネル更新
- 本記事よりも,参考先ではより細かく丁寧にフォルダの共有方法がまとめられています.
VagrantでCentOS7のホスト・ゲスト間とVM間ネットワークの設定
概要
背景
- mac m1でPythonで作る対話システムを学んでいるとopenNMTが使えない場面が出たため,Windowsで行なうことにした.
- 環境を作るところからだが,ただこれまでと同じように作っても面白くないと思い,ちゃんとやった事のないvagrantとdockerで環境を構築しようと考えた.
- そこで一時的に対話システムを止めてDockerの本を読んで勉強し始めた.
- が,思ったよりもvagrantでdockerの本用の環境を作成するのに時間がかかったのでまとめる.
Vagrantでの設定
- 以下のようなVagrantfileを作成
- 任意の文字列と任意のIPアドレスは重複しないように設定する
- 任意の内部ネットワーク名は同じ文字列を設定にする
#-*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "bento/centos-7.8" config.vm.define "任意の文字列" do |machine| # ホストオンリーアダプター machine.vm.network "private_network", ip: "任意のIPアドレス", auto_config:false # 内部ネットワーク machine.vm.network "private_network", ip: "任意のIPアドレス", virtualbox__intnet: "任意の内部ネットワーク名" end config.vm.define "任意の文字列" do |machine| # ホストオンリーアダプター machine.vm.network "private_network", ip: "任意のIPアドレス", auto_config:false # 内部ネットワーク machine.vm.network "private_network", ip: "任意のIPアドレス", virtualbox__intnet: "任意の内部ネットワーク名" end end
CentOS7での設定
# 上記のVagrantfileのように記述すればeth1がホストオンリーアダプター # eth2が内部ネットワーク nmcli device connection eth1 nmcli device connection eth2 # ログインしているVMのVagrant fileで設定したホストオンリーアダプターのIPアドレスを任意のIPアドレスと置換する nmcli con mod eth1 ipv4.addresses "任意のIPアドレス/24" # ログインしているVMのVagrant fileで設定した内部ネットワークのIPアドレスを任意のIPアドレスと置換する nmcli con mod eth1 ipv4.addresses "任意のIPアドレス/24" nmcli con mod eth1 ipv4.method "manual" nmcli con mod eth2 ipv4.method "manual" nmcli device disconnection eth1 nmcli device disconnection eth2 nmcli device connection eth1 nmcli device connection eth2
Pythonで作る対話システムの3-3までやってみた
背景
- 言語処理を使ったシステムを何か作ってみたくなったため
- いきなり自力では作れないので,何か写経してシステム作成イメージが欲しかった
やったこと
- 3.3章までの写経.個人的に使いやすくするために使用するデータの置き場所を一つのフォルダにまとめ,使えるように元のコードを編集した.コードはこちらです.
概要
- 非タスク型指向である用例ベース方式について書かれている
- 新たに利用するのは,Pytorch,GoogleColab,ElasticSearch.
- Pytorch:BERTの利用
- GoogleColab:GPUを用いたモデルの構築
- ElasticSearch:対話文の検索
- 用例ベースとは?
- 入力文と応答文のセット(用例)を元にする方式
- ルールベースの課題点を解決するために生まれた方式
- ルールベースは自由に条件を設定し制御しやすいが,条件を拡張する際のコストが高い
- 入力文に対する用例からの応答文決定には,類似度や対話破綻スコアなどが用いられている
- 入力文との類似度比較対象は?
- 用例の入力文・応答文・両方を用いる場合があり,どれが一番良いと言うものはない
- 求める結果によってどれを選ぶのか考え,工夫することが必要
- 用例の入力文・応答文・両方を用いる場合があり,どれが一番良いと言うものはない
- 類似度は?
- ElasticSearchの検索結果のスコア:大きい方が良い
- 文同士の単語頻度ベクトルコサイン類似度:0から1の値をとり,1に近いほど類似していることを意味する
- レーベンシュタイン距離(編集距離):得られる値である編集回数が少ないほど類似していることを意味する
- Word Mover's Distance (WMD):比較する文を構成する単語の類似度をもとに計算する方法
- 対話破綻スコアは?
- 返答文が破綻していない程度を表しており,1であればよく,0に近い程破綻していることを意味する
- 入力文との類似度比較対象は?
感想
- 発話ではなく,応答文との類似性に重きを置く方法を知り驚いた.
- 発話と応答それぞれとの類似度を掛け合わせる方法もあり,どちらかの類似度が低ければスコアが低くなるので,なるほどと感じた
- 複数のラベルがついているデータについての前処理として正例の頻度の割合で編集する点が勉強になった.
- Pytorchを使うのが初めてであったため,Kerasくらい使えるようになっておきたい.
- モデル構築時にGPUを使う事による処理待ち時間が予想よりもはやく驚いた.
次にやること
- 3.4を進める
- WMDの理解
- Pytorchの勉強
Pythonで作る対話システムを3-1から3-2までやってみた
背景
- 言語処理を使ったシステムを何か作ってみたくなったため
- いきなり自力では作れないので,何か写経してシステム作成イメージが欲しかった
- タスク指向型の部分は写経して確認したので,非タスク指向の方も進める
やったこと
- 3-1から3-2までの確認・写経
- 今回もプログラム内に利用するには登録が必要なAPIがあったが,個人的に登録が面倒なので登録なしでターミナル上に似たような結果が得られるようにした.
概要
- 非タスク指向型対話システムとは?
- 対話することが目的のシステム
- このシステムは必要?
- 必要:雑談によって,タスクが向上したとの研究報告がある
- 対話に必要な情報が得られる
- ルールベース方式
- 入力された文に対する返答をまとめたファイルを事前に作成
- マークアップ言語のArtifical Intelligence Markup Language (AIML) を用いてルールをまとめる
- ルールに基づいて返答を返す
- 入力された文に対する返答をまとめたファイルを事前に作成
変更した内容
import aiml import MeCab from telegram_bot import TelegramBot class AimlSystem: def __init__(self): # AIMLを読み込むためのインスタンスを用意 self.kernel = aiml.Kernel() # 形態素解析器を用意 self.tagger = MeCab.Tagger('-Owakati') def initial_message(self): # aiml.xmlを読み込む self.kernel.learn("data/aiml.xml") return {'utt':'はじめまして,雑談を始めましょう', 'end':False} def reply(self, dic_input): utt = dic_input['utt'] utt = self.tagger.parse(utt) # 対応するセッションのkernelを取り出し,respondでマッチするルールを探す response = self.kernel.respond(utt) # print(utt, response) return {'utt': response, 'end':False} if __name__ == '__main__': system = AimlSystem() dic_input = system.initial_message() #print('dic_input', dic_input) print("bot>"+dic_input['utt']) while True: raw_input = str(input("me>")) dic_input['utt'] = raw_input dic_input = system.reply(dic_input) print("bot>"+dic_input['utt'])
感想
- ルール通りに動いているだけとわかっていても対話してくると,機械的ではない対話をしているような感覚があって面白かった.
- チャットAPIを使わない方法も公開してくださっている事に今更気づいた...次回からこちらで勉強していく.
次にやること
- 非タスク試行型対話システムである3.2章以降を進める
Pythonで作る対話システムの2章までやってみた
背景
- 言語処理を使ったシステムを何か作ってみたくなったため
- いきなり自力では作れないので,何か写経してシステム作成イメージが欲しかった
やったこと
- 2章までの写経
- プログラム内に利用するには登録が必要なAPIがあったが,個人的に登録が面倒なので登録なしでターミナル上に似たような結果が得られるようにした.
概要
- 対話とは,情報交換の結果生じる変化の過程を意味する
- 対話システムの意義
- 音声入力であれば,声のみで使用可能になり便利になる
- 直感的に使用可能になり,操作方法の学習が不必要になる
- コミュニケーションを通して,幸せを提供する
- 対話システムの課題
- 言外の意味理解
- マルチモーダル情報の扱い
- マルチモーダル情報とは,テキストや身振りなどの複数のモダリティをまとめたもの
- モダリティとは,テキストのような対話に使用される情報種類の単位
- シンボルグラウンディング(記号接地)問題
- シンボルグラウンディングとは,指示語が何を示しているのかを外科医の情報と対応づけること
- フレーム問題
- フレームとは,返答を考える際に考慮する範囲のこと
- 対話システムのタイプ
- タスク指向型
- 非タスク指向型
- タスク指向型対話システムとして,天気応答システムを作成
- 対話行為タイプをSVMで,コンセプトをCRFで推測
- 対話行為タイプの推定モデルでは,学習データにTF-IDFを使用
- 強化学習
変更した内容
- チャットアプリを使用せず,プログラムを実行したターミナルで対話が行われるようにした
- 天気情報については,天気予報 API(livedoor 天気互換)を利用させていただきました
- 詳細な変更箇所はまとめられていない.変更したコードは,Githubにまとめている
感想
- 対話行為タイプでは,分散表現を使用してみてもよさそう
- 別のタスクを追加してみて理解を深めたい
- 強化学習は,別で勉強する
次にやること
- 非タスク試行型対話システムである3章を進める