Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
ルールベースから
機械学習への道
2015-09-16
サイボウズラボ
西尾泰和
このスライドはサイボウズ社内の機械学習勉強会で話した内容から
社内のデータなどのスライドを削除して再構成したものです。
このスライドの目的
ルールベースは多くのプログラマができている。
機械学習への橋渡しを詳細に解説することで
ツールとして機械学習を活用できる人を増やす。
2
「ルール」とは
将来的にいろいろな抽象化がされるが
今のところは「TrueかFalseを返すコード」
と思っていい。
3
if (これはルール) { … }
def foo(x):
… return True
return False
# これもルール
*.py[cod]
*$py.class
*.so
env/
.eggs/
正規表現の羅列もルール
ルールはたくさんある
すでに皆さんの書いているコードの中にも
ルールはたくさんあるはず
「複雑な判断」が必要なケースでは
たくさんの細かいルールをまとめて
大きな複雑な判断を行っているはず
「まとめる」とは何か?
4
まとめかたの例(単純なもの)
「ルール1、ルール2、…ルールnのうち
どれかがTrueの時にTrueを返す」
=全部をorでつなぐ
「ルール1、ルール2、…ルールnの
すべてがTrueの時にTrueを返す」
=全部andでつなぐ
5
andとor
6
Falseを0、Trueを1と置き換えてみると…
andとorの別表現
7
論理式を数式に
「全部or/andでつなぐ」
という論理式は
「足して閾値と比較する」
というコードに変換できる。
その書き換えに何のメリットが?
8
あいまいさの表現
「ルールx1, x2, x3…は時々誤爆するから
単体ではあんまり信用出来ないけど、
3個以上Trueになってる時はTrueを返したい」
= Σ(xi) > 2.5
これを論理式で書こうとするとめんどくさい。
シンプルに表現できる表現方法を使うことで
思考を節約する。
9
もっと複雑なケース
10
例1 一部信用出来ないルール
「ルールx1, x2, …は十分信用できるので
どれか一つがTrueならTrueを返していいけど
ルールx5, x6, …はn個以上Trueじゃないと
信用出来ない」
これのシンプルな例としてx1 or (x2 and x3)を考
える。x1は単体で信用できるが、x2とx3信頼出来
ないので両方Trueの時だけにしたい。
11
x1を2倍する
12
例1のまとめ
信用できるルールほど大きな「重み」が付く。
この表現方法のことを以下しばらく
「重み付き和の方法」と呼ぶ。
13
例2 例外があるルール
「ルールx1, x2…のどれかがTrueならTrueを返す
ただし例外としてルールx5がTrueの時を除く」
これのシンプルな形として(x1 or x2) and (not x3)
を考える。x3がTrueの場合を例外として、x1かx2
がTrueならTrueを返す。
14
x3が1の時Falseなので
15
同じように右肩上がりで切りたい
x3を-2倍してみる
16
例2のまとめ
否定には「負の重み」が付く。
17
例3 もっと複雑なルール
Q:
任意の論理式が重み付き和の方法で表現できる?
→YesともNoとも言える、ちょっと補足が必要。
例として
x1 xor x2 = (x1 or x2) and not (x1 and x2)
を考えてみよう。
18
境界線を引けない(線形非分離)
19
ルールを追加する
たとえば新しくx3というルールを追加する
x3 = x1 and x2
そうすると
x1 xor x2 = (x1 or x2) and not (x1 and x2)
= (x1 or x2) and (not x3)
これは例2と同じになる。
20
例3のまとめ
重み付き和の方法で表現できない論理式もある。
そんな時は「ルールの組み合わせ」を
新しいルールとして追加すれば良い。
21
ここまでの流れ
複雑な判断が必要なケースでは
細かいルールを「まとめ」て使っている。
その細かいルールのまとめかたには
andとorで論理的にまとめる方法の他に、
重み付き和の方法がある。
後者のほうがあいまいな判断に使いやすい。
22
重みをどうやって決めるのか?
1. とりあえず全部1にする
(今「全部and」や「全部or」なら
良くはなっても悪くはならない)
2. 手で適当に指定する
(このルールは誤爆多いから信用出来ない
とか書いた人がわかっているケース)
3. 重みを機械的に決める
=機械学習
23
機械学習の(教師あり学習の)例
24
予測
1. 入力に重みをかけて足しあわせ(Σ)
その結果が閾値θより大きいかどうかで
TrueかFalseを出力する
25
比較
2. その「予測結果」が正解と同じか
どうかをチェックする。
(正解は人間が与える)
26
重みを調整
3. 予測結果と正解が異なっていた場合
正しくなる方向へと重みを調整する
27
重みの調整の例
1. 正解はFなのにTと予測した
2. つまりΣの結果が大きすぎる
3. wi * xi が大きいiについて
wiをちょっと減らす
28
雑な方法だけど
これでもちゃんと学習する
元祖人工ニューロン
1943年、McCullochとPittsが神経細胞の振る舞い
にヒントを得て論理計算が可能なモデルを提案*
それは「入力に重みを付けて足しあわせ、閾値を
超えたら1の出力を出す」というものだった。
つまりここまで「重み付き和の方法」と呼んでき
たものは実は「McCulloch&Pitts型人工ニューロ
ン」(MCP)だった。
29
* ‘A logical calculus of the ideas immanent in nervous activity’
大きく分けて2つの路線がある
30
McCalloch-Pitts人工ニューロン
補足
細かいことを言えば機械学習の各手法はもっと
複雑に枝分かれや合流をしているのだけど今回
は「大きく分けて積み重ねていく系とそうでな
いのがあって、話題のDeepLearningは積み重ね
る系だけど、今回は枯れた技術であるロジス
ティック回帰を使う」ぐらいの理解でOK
(細かいことの例: 人工ニューロンを元に1958年にパーセプトロンが発表され
るが、その当時のパーセプトロンは3層のものでも入力層と中間層の間はラン
ダム結線で元祖と同じように線形非分離な問題が解けなかった。1969年にそ
れを指摘されて研究が下火になるが、1974年~1986年に誤差逆伝搬法の
ニューラルネットへの応用が発表され、多層のパーセプトロンがまともに学
習できるようになった。一方、ロジスティック回帰は人工ニューロンとは無
関係に1958年に発表されたが、後に2層の単純パーセプトロンと等価であるこ
とが示された)
31
ロジスティック回帰(LR)
・MCPはTrue/Falseを出力したが
LRは確率値を出力する。
・MCPの入力は0/1だったが、
LRは実数値で良い(けど今回は0/1で使う)
32
実際の流れ
「XXXするとよさそうなものがあったらYYY」と
いうユーザストーリーを実現する方法を考える
1. 「XXXするとよさそうなものがあったら」に注
目した
2.「XXXするとよさそう」を「判断」するコード
が必要と考えた
33
以降伏字が多くなりますがご容赦を
実際の流れ
3. とりあえず適当にXXXっぽいキーワードで検索
して眺めた
4. XXXっぽい発言がたくさんあるスレッドを発見
したのでファイルに書き出した
5. それを眺めながら適当にルールを書いた
34
ルールの例
(削除されました)
35
重み
6. 「ルールの重みをどう決めるか?」→まずは全
部の重みを1とした
7. 重みづけして足し合わせた値でソートしてどん
な感じか観察した
36
スコアの高いもの
(削除されました)
37
スコアの低いもの
(削除されました)
38
適当に教師データを作る
8. さっきのランキングの上の方と下の方を見て
正解がTになる例とFになる例を150件ほど別ファ
イルに転記
9. そのデータでロジスティック回帰
39
正解データを読んでLRを学習
40
file_yes = codecs.open(‘XXX.txt', 'r', 'utf-8')
file_no = codecs.open('not_XXX.txt', 'r', 'utf-8')
xs = []
ys = []
for line in file_yes:
line = preprocess(line)
xs.append(make_feature_vector(line))
ys.append(1)
for line in file_no:
line = preprocess(line)
xs.append(make_feature_vector(line))
ys.append(0)
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(xs, ys)
特徴ベクトルの作り方
41
from rules import rules
def make_feature_vector(s):
fv = []
for f in rules:
rs = f(s)
if rs:
fv.append(1)
else:
fv.append(0)
return fv
能動学習
10. 正解を教えてないデータについて、ロジス
ティック回帰で予測をさせて、確率が0.5に近い
順に表示させてみた(つまり現状の教師データで
はTかFか判断がつかないものを表示)
11. 0.5に近い順に1行ずつ表示して、僕が対話的
にy/nを入力し、教師データに追加するようにし
た
12. 眺めながら、場合によってはルールのほうを
追加した
42
例
(削除されました)
43
対話的に学習データを追加
44
unknown = codecs.open(‘SOMETHING.txt', 'r', 'utf-8')
buf = []
for line in unknown:
s = preprocess(line)
v = make_feature_vector(s)
score = model.predict_proba(v)[0][1]
buf.append((abs(0.5 - score), score, s, line))
buf.sort()
for _dum, score, s, line in buf:
print u"{:.2f}".format(score),
print line.strip()
yn = raw_input('y/n?>')
if yn == 'y':
codecs.open(‘XXX.txt', 'a', 'utf-8').write(line)
elif yn == 'n':
codecs.open('not_XXX.txt', 'a', 'utf-8').write(line)
else:
print 'passed'
まとめ
ルールベースから機械学習への橋渡しのために
・ルールベースで書く
・均等重みでランキング
・ランキングを元に教師データを作成
・その教師データでロジスティック回帰を学習
・学習したロジスティック回帰を使って
能動学習でテストデータを改善
という流れを解説した。
45

More Related Content

ルールベースから機械学習への道 公開用