Angluinの L∗ はオートマトン学習 (automata learning) のアルゴリズムとして最も有名なものです。
以前、このブログでもAngluinの L∗ について説明しました。
L∗ は歴史のあるアルゴリズムのため、派生アルゴリズムがいくつか存在します。
この記事ではAngluinの L∗ について簡単に説明した上で、派生アルゴリズムとしてRivest-SchapireとKearns-Vaziraniを紹介します。
- Rivest-Schapireは L∗ の反例 (counterexample) の解析手法の提案で、二分探索を用いて反例の中のobservation tableに追加すべき接頭辞を探すことで、計算量を改善します。
- Kearns-Vaziraniはobservation tableを置き換えるデータ構造としてdiscrimination treeというデータ構造を提案するものです。
これらの手法により L∗ の様々な効率が改善できます。
想定読者: オートマトン理論やオートマトン学習について理解・関心がある。
準備
真偽値とは true,false のことで、この2つからなる集合を B={true,false} で表します。
Σ をアルファベットとして固定し、その元を文字と呼びます。
文字を1列に並べたものを文字列と呼び、空文字列を ε で表します。
文字列全体からなる集合を Σ∗ で表します。
2つの文字列 w1,w2∈Σ∗ の結合を w1⋅w2 で表しますが、単に w1w2 と表すこともあります。
定義 (DFA):
決定性有限状態オートマトン (DFA) A とは4つ組 A=(Q,q0,F,δ) で、それぞれ
- Q は有限の状態集合、
- q0∈Q は初期状態、F⊆F は受理状態の集合、
- δ:Q×Σ→Q は遷移関数を意味します。
遷移関数 δ は δ(q,ε)=q,δ(q,σw)=δ(δ(q,σ),w) (σ∈Σ,w∈Σ∗)として文字列に拡張されます。
DFA A の出力関数 γ:Q×Σ∗→B は δ(q0,w)∈F のとき true、δ(q0,w)∈/F のとき false を返す関数とします。
Angluinの L∗
まず始めに、Angluinの L∗ について簡単に説明します。
Angluinの L∗ は[Angluin, 1987]で提案されたオートマトン学習 (automata learning) のアルゴリズムです。
L∗ は、学習対象の (正規) 言語について、次の2つのクエリーに応答できる MAT (minimally adequate teacher) と呼ばれる教師を与えることで、言語をDFAとして学習します。
- MEMBER(w) (membership query): w が学習対象の言語に含まれるかどうかを真偽値で返す。
- EQUIV(H) (equivalence query): 学習中の仮説 (hypothesis) のオートマトン H が学習対象の言語に等しいか判定する。等しい場合 true を返し、異なる場合はその反例となる文字列 (一方に含まれて一方に含まれないような文字列) を返す。
observation table
L∗ の重要なデータ構造であるobservation tableと、consistencyとclosednessという概念について説明します。
定義 (observation table): observation tableは3つ組 (S,E,T) のことで、それぞれ次のような値となります。
- S はprefix-closedな接頭辞の集合で、E は接尾辞の集合です。S がprefix-closedとは、文字列 s=σ1σ2⋯σn が S に含まれているとき、s の接頭辞 ε,σ1,σ1σ2,⋯,s がすべて S に含まれることを意味します1。
- T は (S∪(S⋅Σ))⋅E→B の関数で、 T(s⋅e)=MEMBER(s⋅e) となるように更新されます。
補助的な関数として row:(S∪(S⋅Σ))→BE を次のように定義します。
row(s)=e↦T(s⋅e)
ここで e↦F(e) は e を引数とする関数を表します。
各 s∈S に対する row(s) の値が、仮説 (対応するDFA) での状態に相当します。
observation tableは次のconsistencyとclosednessという制約を満たしているとき、仮説 (対応するDFA) を考えることができます。
定義 (consistency):
「observation table (S,E,T) がconsistentである」とは、s1,s2∈S が row(s1)=row(s2) のとき、すべての σ∈Σ について row(s1⋅σ)=row(s2⋅σ) であることを表します。
定義 (closedness):
「observation table (S,E,T) がclosedである」とは、s∈S と σ∈Σ について row(s⋅σ)=row(t) となる t∈S が存在することを表します。
つまり、
- consistencyは、row(s1)=row(s2) なら2つの接頭辞 s1,s2∈S が表す状態は同じはずだが、1文字遷移した先が異なる、といった変な状態にはならない、ということを意味し、
- closednessは、s の遷移先に対応する接頭辞が S に存在せず遷移できない、ということが起こらないことを意味します。
observation tableがconsistentかつclosedであるとき、対応する仮説 (hypothesis) のDFAが考えられます。
定義 (hypothesis): consistent かつ closed である observation table (S,E,T) に対応する仮説 (hypothesis) のDFA H=(Q,q0,F,δ) は次のように定義されます。
- 状態の集合 Q={row(s)∣s∈S}、
- 初期状態 q0=row(ε)、
- 受理状態の集合 F={row(s)∣s∈S∧T(s)=true}、
- 遷移関数 δ(row(s),σ)=row(s⋅σ)。
注意: closedなため遷移関数 δ
の遷移先は正しく定義されます。また、consistentなので row(s)
の値が同じ接頭辞 s∈S
が複数ある場合に、どれを選んでも同値なDFAになります。
疑問1: s∈S と e∈E のすべての組み合せが T
に追加されていますが、区別するためには共通するものは省略できそうに思えます。この直観を実現するには、どのようなデータ構造が効率的でしょうか?
アルゴリズム
observation tableをconsistentかつclosedになるように更新して仮説 H を構築し、equivalence queryを投げて、返ってきた反例でobservation tableを修正する、ということを繰り返すのが L∗ の実際の流れになります。
[Angluin, 1987]の§2.2には疑似コードが掲載されています。
下のAlgorithm 1 (Angluin) は、その疑似コードをより具体的に書き直したものになります。
Algorithm 1 Angluin's L∗
function Angluin(MEMBER,EQUIV)
S,E←{ε}
T(t)←MEMBER(t) for each t∈{ε}∪Σ
repeat
while (S,E,T) is not consistent or not closed do
if (S,E,T) is not consistent then
Find s1,s2∈S, σ∈Σ, and e∈E
s.t. row(s1)=row(s2) and T(s1⋅σ⋅e)=T(s2⋅σ⋅e)
E←E∪{σ⋅e}
T(t⋅σ⋅e)←MEMBER(t⋅σ⋅e) for each t∈S∪(S⋅Σ)
end if
if (S,E,T) is not closed then
Find s∈S and σ∈Σ
s.t. row(s⋅σ)=row(s′) for all s′∈S
S←S∪{s⋅σ}
T(s⋅σ⋅d)←MEMBER(s⋅σ⋅d) for each d∈E∪(Σ⋅E)
end if
end while
Let H be a hypothesis automaton for (S,E,T)
if EQUIV(H)=true then
Let P be a set of all prefixes of EQUIV(H)
S←S∪P
T(t⋅e)←MEMBER(t⋅e) for each t∈P∪(P⋅Σ) and e∈E
end if
until EQUIV(H)=true
return H
end function
このアルゴリズムは正しく動作し停止します。
まず、一番外側の繰り返しの終了条件から、停止した場合、正しいオートマトンを返すのは明らかです。
そして、学習結果のオートマトンの状態数を n とすると、1周毎に新しい row(s) の値が1つは増えていくはずなので、高々 n 回の繰り返しで停止するはずです。
次に計算効率として、MEMBER(w) が呼ばれる回数を考えてみます。
MEMBER(w) は T の値を更新する際に呼び出されるので、T に記録される文字列の個数を数えれば良さそうです。
T に記録される文字列は (S∪(S⋅Σ))⋅E なので、S や E がどのように更新されるのかに注目してみます。
ここで、EQUIV(H) の返す反例の長さの最大値を m、アルファベットの大きさを k とします。
- S はclosedでない場合に1つ値が追加され、EQUIV(H) は反例を返した場合に反例の接頭辞がすべて追加されます。
closedでない場合の追加は高々 n−1 回起こり、反例は一度に最大 m 個の追加が高々 n−1 回起こります。
S は最初に空文字列で初期化されているので +1 されて、∣S∣ は高々 n+m(n−1) と分かります。
- E はconsistentでない場合に1つ値が追加され、この追加はclosedでない場合と同様に高々 n−1 回起こります。
∣E∣ も最初に空文字列で初期化されているので、∣E∣ は高々 n と分かります。
よって、∣(S∪(S⋅Σ))⋅E∣ は高々 (k+1)(n+m(n−1))n=O(kn2m) となります。
疑問2: 反例に対してすべての接頭辞を S
に追加していますが、これは本当に必要なのでしょうか?
また、どうしてconsistentでない状況が発生してしまうのでしょうか?
Rivest-Schapire
Rivest-Schapireは1993年にRivest2とSchapireが発表した、Angluinの L∗ アルゴリズムの改良手法です。
[Rivest & Schapire, 1993]で発表されたもの3で、L∗ の反例を解析する部分に対する改良方法を提案しています。
というのも疑問2で提示したように、Angluinのアルゴリズムでは反例の全ての接頭辞をobservation tableへと追加していますが、これは明らかに無駄になります。
そこで、反例の接頭辞のうちobservation tableに追加すべきものを反例の解析によって見つけ、学習を効率的にしたのが、Rivest-Schapireになります。
注意:
[Rivest & Schapire, 1993]のタイトルは "Inference of finite automata using homing sequences" です。
homing sequenceというアイディアを導入することで、学習対象のオートマトンをリセットせずに学習する方法を提案するのが論文の主題となっています。
リセットというのは学習対象のオートマトンを初期状態に戻すことです。
例えば「現実に動作しているロボットの挙動を学習したい」といったシチュエーションでは、ロボットを MEMBER の呼び出しの度に初期位置に戻していては非効率的です。
そこでhoming sequenceという、出力を見ることでどの状態にいるのか区別できる文字列を使うことで、どのような状態からでも学習できるようにしています。
今日Rivest-Schapireとして顧みられるのは反例の解析についてのアイディアですが、こちらのアイディアも興味深いものですので、下の折り畳みで少し解説しておきます。
homing sequenceの詳細
学習対象のオートマトンは強連結 (strongly connected) であると仮定します。
これは、ある状態から任意の状態へ適当な文字列で遷移できることを意味します。
行ったきりで戻ってこれない状態を、リセットせずに学習できたら驚きなので、この仮定は妥当だと思います。
次に、いくつか記法を導入します。
状態 q と文字列 w について、q(w)=δ(q,w) と定義します。
さらに w=σ1…σn のとき、q⟨w⟩=γ(q,ε)γ(q,σ1)γ(q,σ1σ2)…γ(q,σ1…σn) と定義します。
このときhoming sequence hとは、次の条件を満たすような文字列のことです。
∀q1,q2∈Q.q1⟨h⟩=q2⟨h⟩⇒q1(h)=q2(h)つまり、出力列を見ることで、どの状態からも遷移先の状態が区別できるような文字列がhoming sequenceになります。
各homing sequenceの出力についてobservation tableを作り学習を進めていくことで、リセットをせずに学習をすることができます。
ただし、最初から正しいhoming sequenceが与えられるわけではないため、仮のhoming sequenceで学習をしながら、矛盾が生じたら新しくhoming sequenceを作り直す、といった工夫が求められます4。
注意:
このように[Rivest & Schapire, 1993]は今日Rivest-Schapireと呼ばれるアイディアとは異なるものを中心に説明しており、さらにdiversity-based representationsのようなあまり一般的でない概念についてもかなりのページを割いて説明していて、重要なアイディアを読み取るのが難しい論文になっています。
実際にRivest-Schapireの反例の解析のアイディアについて説明しているのは20から22ページ目の§4.5 "Improving Angluin's L∗ algorithm"の辺りなのですが、ここに辿り着く前に力尽きてしまうことも多いでしょう。
Rivest-Schapireの主要なアイディアである反例の解析については、近年書かれた[Isberner & Steffen, 2014]で詳しく解説されているので、こちらを代わりに参考にするといいのではないかと思います。
今回の説明も、こちらの論文の説明を多くの部分で参考にしています。
反例の分析
それではRivest-Schapireで導入された反例の分析について説明していきます。
前述の通り、Angluinの L∗ アルゴリズムでは反例のすべての接頭辞が S に追加されます。
しかしこの場合、同じ状態を表す (row(s) の値が同じ) 接頭辞が S に追加される可能性があります。
そのような接頭辞の S への追加は無駄なので、ちゃんと新しい状態を表す接頭辞のみを S に追加したいわけです。
例として L={an ∣ n=0(mod4)} を学習する場合を考えてみます。
このとき、最初の繰り返しでは E1={ε} で、仮説のオートマトン H1 とobservation tableの表 T1 は次のようになります5。
S∪(S⋅Σ) / E | ε |
---|
ε | true |
a | false |
a⋅a | false |
これに対する反例の文字列は EQUIV(H1)=aaaa となります。
この反例の接頭辞のうち、新しい状態を表すものを S に追加しようと思うと、問題が生じます。
というのも、接尾辞の集合は E1={ε} なので、EQUIV(H1) のどの接頭辞を取っても既存の row(s) と異なる値にはなりません。
そのため、反例の接頭辞を新しい状態を表すように追加する場合、E に新しい接尾辞を追加する必要もあることが分かります。
この E に追加する接尾辞も反例から取れると良さそうです。
そこで、反例の文字列を接頭辞と接尾辞に分解して、S と E に追加することを考えます。
ここで、新しい状態が生まれる反例の接頭辞と接尾辞の追加の仕方は、次の2通りが考えられます。
- s=aa,e=aa
- s′=aaa,e′=a
しかし、ここで s′=aaa,e′=a を追加すると、S がprefix-closedではなくなってしまいます。
そのため、追加できるのは s=aa,e=aa となります。
これらを追加した場合の仮説のオートマトン H2 とobservation tableの表 T2 は次のようになります。
S∪(S⋅Σ) / E | ε | aa |
---|
ε | true | false |
a | false | false |
aa | false | true |
aa⋅a | false | false |
これに対する反例の文字列も EQUIV(H2)=aaaa であり、今度は s′=aaa,e′=a を追加できます。
最終的に、仮説のオートマトン H3 とobservation tableの表 T3 は次のようになります。
S∪(S⋅Σ) / E | ε | aa | a |
---|
ε | true | false | false |
a | false | false | false |
aa | false | true | false |
aaa | false | false | true |
aaa⋅a | true | false | false |
そして、H3 は学習対象の言語と一致するため、EQUIV(H3)=true となり、学習が終了します。
というわけで、EQUIV(H) により反例が返ってきたときに、反例をいい感じの位置で分割して、S と E に追加していけばいいことが分かります。
この反例をいい感じの位置で分解することを反例の解析と呼ぶことにします。
反例の解析を行う愚直なアルゴリズムは線形探索で反例の文字列の先頭から確認していく方法です。
具体的には次のようなアルゴリズム (Linear-Split) になります。
Algorithm 2 An algorithm for analyzing a counterexample using linear search
function Linear-Split(w,H,MEMBER)
i←1
while true do
i←i+1
Let s be w1w2⋯wi−1 and e be wiwi+1⋯w∣w∣
if MEMBER(w)=MEMBER(⌊s⌋H⋅e) then
Let s′ be w1w2⋯wi−2
return (⌊s′⌋H⋅wi−1,e)
end if
end while
end function
ここで、⌊w⌋H は δ(q0,w)=row(s) となる s を一意に表すものとします。
この関数の戻り値は2つ組 (s,e) で、s が S に追加する接頭辞、e が E に追加する接尾辞になります。
引数として渡されるのが反例の文字列であれば、この関数は正しく値を返します。
重要なのが、接頭辞として返している値が、単に反例の文字列の接頭辞を返すわけではなく、⌊s′⌋Hwi−1 を返しているところです。
このような値を返すことで、S がprefix-closedであるように接頭辞を追加していくことができます。
しかし、この方法では最悪の場合、反例の文字列の長さだけ MEMBER(w) を呼び出す必要があり、効率の面ではAngluinのアルゴリズムからあまり変わっていません。
これを改善するにはどうすればよいでしょうか?
二分探索による解析
上の線形探索で探している条件は MEMBER(w)=MEMBER(⌊s⌋H⋅e) で、返す接頭辞は ⌊s′⌋Hwi−1 でした。
線形探索なので、s の1つ前の接頭辞 s′ では MEMBER(w)=MEMBER(⌊s′⌋H⋅wi−1⋅e) であることから、この探索の条件は次のようにも書けるはずです。
MEMBER(⌊s′⌋H⋅wi−1⋅e)=MEMBER(⌊s⌋H⋅e)
この条件を満たすときは、s1=⌊s′⌋H⋅wi−1 と s2=⌊s⌋H は、E に e を追加したときに row(s1)=row(s2) となります。
つまり、この条件を満たす位置を見つけられれば、S,E に追加する意味のある (s,e) の組を返せます。
次に、w は反例の文字列なので、MEMBER(w)=MEMBER(⌊ε⌋Hw) で MEMBER(w)=MEMBER(⌊w⌋H) であることに注目します。
これを不変条件とした二分探索として、次のようなアルゴリズム (Split) が考えられます。
Algorithm 3 An algorithm for analyzing a counterexample using binary search
function Split(w,H,MEMBER)
low←1
high←∣w∣+1
while high−low>1 do
Let mid be ⌊2low+high⌋
Let s be w1w2⋯wmid−1 and e be wmidwmid+1⋯w∣w∣
if MEMBER(w)=MEMBER(⌊s⌋H⋅e) then
low←mid
else
high←mid
end if
end while
Let s′ be w1w2⋯wlow−1 and e be whighwhigh+1⋯w∣w∣
return (⌊s′⌋H⋅wlow,e)
end function
Split では、次の不変条件を満たすように二分探索をしています。
- MEMBER(w)=MEMBER(⌊w1⋯wlow−1⌋H⋅wlow⋯w∣w∣)
- MEMBER(w)=MEMBER(⌊w1⋯whigh−1⌋H⋅whigh⋯w∣w∣)
よって、Split は正しく S,E に追加する (s,e) を返すようになっています。
最後に反例の解析を取り入れた L∗ の改良版のアルゴリズム (Rivest-Schapire) を疑似コードで示します。
Algorithm 4 Rivest and Schapire's L∗
function Rivest-Schapire(MEMBER,EQUIV)
S,E←{ε}
T(t)←MEMBER(t) for each t∈{ε}∪Σ
repeat
while (S,E,T) is not closed do
Find s∈S and σ∈Σ
s.t. row(s⋅σ)=row(s′) for all s′∈S
S←S∪{s⋅σ}
T(s⋅σ⋅d)←MEMBER(s⋅σ⋅d) for each d∈E∪(Σ⋅E)
end while
Let H be a hypothesis automaton for (S,E,T)
if EQUIV(H)=true then
Let (s,e) be Split(EQUIV(H),H,MEMBER)
T(t⋅e)←MEMBER(t⋅e) for each t∈S∪(S⋅Σ)
T(s⋅d)←MEMBER(s⋅d) for each d∈E∪(Σ⋅E)
S←S∪{s} and E←E∪{e}
end if
until EQUIV(H)=true
return H
end function
S に不要な文字列を追加しないようになった結果、consistencyのチェックが必要無くなっています。
さらに Split で二分探索を用いるようにしていることから、MEMBER の呼び出し回数は O(kn2+nlogm) となります (closedにするのに高々 O(kn) 回の呼び出しがあり、Rivest-Schapire で logm 回の呼び出しがあるのを n 回繰り返すのでこのようになります)。
以上がRivest-Schapireのアイディアの説明になります。
Kearns-Vazirani
ここからはKearns-Vaziraniについて説明していきます。
Kearns-VaziraniはKearnsとVaziraniが1994年に出版したAn introduction to computational learning theoryという本 ([Kearns & Vazirani, 1994]) のChapter 8. Learning Finite Automata by Experimentationで説明された L∗ の変種の1つです。
L∗ ではobservation tableを用いて MEMBER(w) の結果を記録し、どの接頭辞と接尾辞の組み合わせで状態が区別できるかを判断します。
ですが、Kearns-Vaziraniではdiscrimination treeというデータ構造を用いてこれらの情報を管理します6。
Rivest-Schapireの例で出した仮説のオートマトン H3 に対応するobservation tableの表 T3 をもう一度見てください。
S∪(S⋅Σ) / E | ε | aa | a |
---|
ε | true | false | false |
a | false | false | false |
aa | false | true | false |
aaa | false | false | true |
aaa⋅a | true | false | false |
この表をよく見ると、false で埋められている部分が多く、ほとんどの接頭辞が1つの接尾辞をつなげたときに受理されるかどうかで区別できています。
具体的には、
- row(ε) かどうかは ε をつなげて受理されるかどうかで区別できる (row(ε)=row(aaa⋅a) なことに注意)、
- row(aa) かどうかは aa をつなげて受理されるかどうかで区別できる、
- row(aaa) かどうかは a をつなげて受理されるかどうかで区別できる。
そして、どれでも受理されないとき row(a) だと分かります。
この区別の流れをフローチャートにすると次のようになります。
そして、このフローチャートは決定木のように見えないでしょうか?
また、observation tableの表による表現は疑問1で上げたように、木による表現と比べると無駄が多いのではないかというように思えます。
この考察を元に、observation tableに記録する情報を木構造を用いて管理するのがKearns-Vaziraniになります。
discrimination tree
まずはdiscrimination treeを定義します。
定義 (discrimination tree):
discrimination treeとは3つ組 (S,D,T) で、それぞれ
- S は接頭辞の集合、D は接頭辞を区別するための文字列の集合で、どちらも ε を含み、
- T は二分木で、節は D の要素でラベル付けされていて、葉は S の要素でラベル付けされています。S の要素は葉にちょうど1回現れるものとします。
誤解がない場合、二分木 T のみでdiscrimination treeを表すことにします。
次に、discrimination treeに対する操作として Sift を定義します。
Sift は次のような関数です。
Algorithm 5 The "sift" function for discrimination trees
function Sift(s,T)
Let N be the root node of T
while N is a branch node do
Let d be the label string of N
if MEMBER(s⋅d) then
N← the right (true) node of N
else
N← the left (false) node of N
end if
end while
return the label string of the leaf node N
end function
直感的には、Sift は与えられた文字列 s と節にラベル付けられた文字列 d をつなげて MEMBER(s⋅d) を呼び出し、その結果で二分木を辿っていき、葉に到達したらそのラベルを返す関数になっています。
この Sift を使って、discrimintation treeに対応する仮説のオートマトンを定義します。
定義 (hypothesis for discrimination trees):
Discrimination tree T に対応する仮説のDFA H=(Q,q0,F,T) は次のように定義されます。
- Q=S,q0=ε,F={s∈S ∣ MEMBER(s)=true}、
- δ(s,σ)=Sift(s⋅σ,T)
そして、反例の文字列を受け取ってdiscrimination treeを更新する手続き (Update-Tree) を定義します。
Algorithm 6 A procedure to update a discrimination tree with a given counterexample string
procedure Update-Tree(w,T)
Let H=(Q,q0,F,δ) be a hypothesis automaton of T
p′,s′←ε
for i:=2,⋯,∣w∣ do
Let p be w1⋯wi
Let s be Sift(p,T) and s^ be δ(q0,p)
if s=s^ then
Let d∈D be a label string to distinguish between s and s^
s.t. MEMBER(s⋅d)=MEMBER(s^⋅d)
Let N1 be a new leaf node labelled with s′
and N2 be a new leaf node labelled with p′
Let N be a new branch node labelled with wi⋅d and connected to N1 and N2.
Replace the lead node labelled with s′ by the new node N.
return
end if
p′←p and s′←s
end for
end procedure
Update-Tree の中では次のようなことをしています。
- s=Sift(w1⋯wi,T),s^=δ(q0,w1⋯wi) として s=s^ となる位置を探す
- MEMBER(s⋅d)=MEMBER(s^⋅d) となる文字列 d∈D を探す
- 1つ前の接頭辞 p′=w1⋯wi−1 に対する Sift の結果 s′=Sift(p′,T) に対応する葉ノードを、次のような節ノードで置換する
- wi⋅d でラベル付けられている
- s′ でラベル付けられた葉ノードと p′ でラベル付けられた葉ノードに接続している
この説明だけでは分かりにくいので図で説明します。
これは、Rivest-Schapireの例で出した仮説のオートマトン H2 に対応するdiscrimination tree T2 の図です。
これに対する反例の文字列は w=aaaa で、 Update-Tree(w,T) を呼んだ場合を考えます。
w の各接頭辞に対する δ や Sift の戻り値を計算します。
- s1=Sift(aaaa,T)=aa,s^1=δ(q0,aaaa)=aa
- s2=Sift(aaaa,T)=aa,s^2=δ(q0,aaaa)=aa
- s3=Sift(aaaa,T)=aa,s^3=δ(q0,aaaa)=aa
- s4=Sift(aaaa,T)=εa,s^4=δ(q0,aaaa)=aa
よって s4=s^4 なので s3=a のノードを次のようなノードで置換します。
- MEMBER(s4⋅d)=MEMBER(s^4⋅d) となる文字列 d∈D が d=ε なので、節ノードのラベルは a⋅d=a
- 葉ノードは true 側が aaa でラベル付けられたもので、false 側が a でラベル付けられたものが接続される
そして、最終的にdiscrimination treeは次の図のようになります。
赤いノードが新しく追加された (置換された) ノードになります。
やっていることとしては、Rivest-Schapireのときの線形探索による反例の解析と同じようなものです。
注意:
ここまで読んできた人であれば、「どうしてこんなややこしい反例の解析をしているのだろう。Rivest-Schapireの方法でいいじゃないか」と疑問に思うのではないでしょうか。
実際Kearns-VaziraniにRivest-Schapireのような二分探索による反例の解析を組み合わせることも可能なはずですし、現代のオートマトン学習のアルゴリズムは実際そのようなもの+αになっているはずです (observation pack [Howar, 2012]、TTTなど)。
個人的な意見ですが、この辺りは歴史的な経緯が大きいのではないかと思います。
[Kearns & Vazirani, 1994]では、[Rivest & Schapire, 1993]で考察された、リセットしないで学習する方法についても議論していることから、目を通していないということは無いと思います。
しかし、かなり詳細な部分なので見落としていたか、[Kearns & Vazirani, 1994]は教科書なので、敢えて触れなかったのではないかと考えられます。
また、この追加の仕方をすると D がsuffix-closedな集合になり、含まれる文字列の長さが高々学習対象のオートマトンの状態数程度になることが保証できます。
異常に長い反例の文字列が返されたときも問題になりにくいという意味で、こちらのやり方にも価値があるのではないかとも思います。
Update-Tree が正しく動作することを確かめるには、新しく S に追加した p′=w1⋯wi−1 と s′=Sift(p′,T) が、wi⋅d で区別できている、つまり、次の式を満たしていることを確認したいです。
MEMBER(s′⋅wi⋅d)=MEMBER(p′⋅wi⋅d)
これには Sift と MEMBER の関係を表す次の補題を用います。
補題:
discrimination tree T と文字列 w∈Σ∗ とし、d∈D を Sift(w,T) 中で到達する節ノードのラベルの文字列とします。
このとき、次の式が成り立ちます。
MEMBER(Sift(w,T)⋅d)=MEMBER(w⋅d)
これは Sift の二分木の辿り方を考えれば自明なものです。
d は s=Sift(p′wi,T) と s^=δ(q0,p′wi) を区別する文字列であることから、
MEMBER(δ(q0,p′wi)⋅d)=MEMBER(Sift(p′wi,T)⋅d)
この式の右辺に補題を用いて、
MEMBER(Sift(p′wi,T)⋅d)=MEMBER(p′⋅wi⋅d)
左辺は、まず拡張された δ の定義が δ(q,wσ)=δ(δ(q,w),σ) (w∈Σ∗,σ∈Σ) であり、さらにdiscrimination treeの仮説のオートマトンが Sift で定義されていること、Update-Tree の繰り返しから s′=Sift(p′,T)=δ(q0,p′) であることに注意すると、補題を用いて
MEMBER(δ(q0,p′wi)⋅d)=MEMBER(δ(δ(q0,p′),wi)⋅d)=MEMBER(Sift(δ(q0,p′)⋅wi,T)⋅d)=MEMBER(δ(q0,p′)⋅wi⋅d)=MEMBER(Sift(p′,T)⋅wi⋅d)=MEMBER(s′⋅wi⋅d)
となり、目的の式が得られます。
最後に、これらの手続き・関数を使って、実際の学習のアルゴリズムを定義します。
Algorithm 7 Kearns and Vazirani's L∗ algorithm using a disrimination tree
function Kearns-Vazirani(MEMBER,EQUIV)
if MEMBER(ε)=true then
H←({ε},ε,{ε},(ε,σ)↦ε for σ∈Σ)
else
H←({ε},ε,∅,(ε,σ)↦ε for σ∈Σ)
end if
if EQUIV(H)=true then
end if
w←EQUIV(H)
Let T be a discrimination tree having a root node labelled with ε
two leaves labelled with w and ε
repeat
Let H be a hypothesis automaton of T
if EQUIV(H)=true then
w←EQUIV(H)
Call Update-Tree(w,T)
end if
until EQUIV(H)=true
return H
end function
最初の方が妙にややこしいですが、空文字列で自明なオートマトンを作って、それに対して EQUIV(H) を呼び、反例の文字列と合わせてdiscrimination treeを構築しています。
また、本体の繰り返しの部分は EQUIV(H) を呼んで、反例の文字列 w と Update-Tree(w,T) を呼び出して、discrimination treeを更新していきます。
このアルゴリズム中での MEMBER(w) の呼び出し回数は O(kn2+n2m) となります。
理由はRivest-Schapireのときと同じで二分探索でなく線形探索をしている分、logm が m になっています。
このようにdiscrimination treeを用いてオートマトン学習を行うのがKearns-Vaziraniになります。
あとがき
今回はAngluinの L∗ アルゴリズムと、その派生アルゴリズムのRivest-SchapireとKearns-Vaziraniについて説明しました。
Angluinの L∗ アルゴリズムは有名なものなのでご存知の方も多いと思うのですが、元論文に載っているアルゴリズムが接頭辞をすべて追加するものであることや、それに対して反例の解析という手法があることはあまり知られていないのではないでしょうか。
また L∗ と言えばobservation tableを使うものとして知られていますが、discrimination treeというデータ構造を使うことで、さらに効率的に学習ができることも興味深いです。
反例の解析については[Isberner & Steffen, 2014]で、今回説明した二分探索による反例の解析以外にも、exponential searchのような手法など、様々なアイディアが示されています。
近年の L∗ を改良したアルゴリズムとしては、observation pack [Howar, 2012] やTTT [Isberner et al., 2014] が有名です。
これらは、今回説明したRivest-SchapireとKearns-Vaziraniをベースとしたアルゴリズムとなっています。
他にも L# と呼ばれるapartnessという概念を導入したオートマトン学習の手法も提案されています [Vaandrager, 2022]。
この記事を書くのに3週間近くかかってしまったのですが、なんとかまとめることができました。
途中、Mermaidの図を表示できる機能をblogに追加したりしていて、中々大変でした。
こちらについてもどこかで説明できればと思います。
それでは、最後まで目を通していただきありがとうございました。
更新履歴
- 2024/08/09: 初版公開。
- 2024/08/10: MEMBER と Sift についての補題についてのあやしい記述を修正。Kearns-Vaziraniの計算量についての記述を追加。
- 2024/08/11: 細かなtypoを修正。
- 2024/08/19: Rivest-Schapireの説明の分かりにくい部分とあやしい部分を修正。
参考文献
[Angluin, 1987]:
Angluin, Dana. "Learning regular sets from queries and counterexamples." Information and computation 75.2 (1987): 87-106.
https://dl.acm.org/doi/10.1016/0890-5401%2887%2990052-6
[Rivest & Schapire, 1993]:
Rivest, Schapire. "Rivest RL, Schapire RE, Inference of finite automata using homing sequences." Machine Learning: From Theory to Applications (1993): 51-73.
https://www.sciencedirect.com/science/article/pii/S0890540183710217
[Isberner & Steffen, 2014]:
Isberner, Malte, and Bernhard Steffen. "An abstract framework for counterexample analysis in active automata learning." International Conference on Grammatical Inference. PMLR, 2014.
https://proceedings.mlr.press/v34/isberner14a
- [Kearns & Vazirani, 1994]
Kearns, Michael J., and Umesh Vazirani. An introduction to computational learning theory. MIT press, 1994.
https://direct.mit.edu/books/monograph/2604
- [Howar, 2012]
Howar, Falk M. "Active learning of interface programs." (2012).
https://d-nb.info/1099294959/34
- [Isberner et al., 2014]
Isberner, Malte, Falk Howar, and Bernhard Steffen. "The TTT algorithm: a redundancy-free approach to active automata learning." Runtime Verification: 5th International Conference, RV 2014, Toronto, ON, Canada, September 22-25, 2014. Proceedings 5. Springer International Publishing, 2014.
https://link.springer.com/chapter/10.1007/978-3-319-11164-3_26
- [Vaandrager, 2022]
Vaandrager, Frits, et al. "A new approach for active automata learning based on apartness." International Conference on Tools and Algorithms for the Construction and Analysis of Systems. Cham: Springer International Publishing, 2022.
https://link.springer.com/chapter/10.1007/978-3-030-99524-9_12