ナイーブ・ベイズ分類器で機械に善悪を教える(草稿段階)

##コンピューターに善悪を教える方法
タイトルの通り、コンピューターに**「善悪を教える」**方法を確立していきたいと思います。これが実現すれば機械が非・倫理的な人間に代わって倫理的な正しい判断を自動でできることになり、犯罪の軽減やテロの抑止等々、社会の改善に大きく貢献することができるでしょう。私の知識の限界もあり今回は簡単なナイーブ・ベイズ分類ができるライブラリーを用いていますが、ゆくゆくは機械学習全般に応用できるように枠組みを整えていきたいと思います。

##そもそもコンピューター教えたい善悪・倫理とは？
まず、コンピューターに教えてあげたい倫理とはいかなる倫理かを明確にします。
コンピューターに百科辞書的に人間の行為全般の、あるいは哲学的・文化的な善し悪しをすべて理解させるのは非常に難しいので（本気でそれを目指している人もいるでしょうが）実践的・応用的な面は捨象しまずは普遍的に当てはまるような「善さ・正しさ」というものを考えてみたいと思います。

##義務倫理学が機械学習に適している
結論から言うと、コンピューターに学習させるのに最も適しているのは[ドイツの哲学者・イマニュエル＝カント](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%9E%E3%83%8C%E3%82%A8%E3%83%AB%E3%83%BB%E3%82%AB%E3%83%B3%E3%83%88)の提唱したような**[義務倫理学](https://en.wikipedia.org/wiki/Deontological_ethics)**です。
義務倫理学においては、善し悪しの基準となる「公理」に相当する文章はすべて**「～すべきである」**、**「～でなければならない」**という英語の**”I must...”**, **“We must not...”**といった様態で表されます。仮にこのような倫理学的な正しさに関して言及するテキストを**「倫理的言明」**とし、「実際のところは…なんだけど」といった**「事実的言明」**とは明確に区別されるとしましょう。我々が分類器に学習させたいのはこの倫理的言明を含んだテキストです。

##義務倫理学における倫理的言明の分類
諸説ありますが、倫理的言明には大きく分けて次の2カテゴリーに分けられます。
「ナイフで刺されて殺されようと絶対に嘘はつかない」という**定言命法**、そして「お金をくれるんだったら助けてあげてもいいよ」という**仮言命法**です。
「絶対に嘘はつかない」というテキストは、言い方を変えれば**「無条件に嘘をつく行為は禁止する」**という言明であり（それが正しいかどうかは別として）定言的な倫理的言明となっています。
それに対して「お金をくれるならヒトを助ける」というテキストは**「金銭を獲得できるという条件のもとに人助けを行う」**という言明であり、特定の前提付きの倫理的言明となっています。こちらも諸説ありますが、仮言的な倫理的言明は義務倫理学においてはそもそも倫理的でないか、もしくは積極的に非・倫理的な言明であると認識されています。

定言的・仮言的の区別の他にも「どのような定言的な倫理的言明が普遍的に妥当するか？」に関してのカテゴリーがあります。かなり大雑把になってしまいますが、主要な3点は以下の通りです。

>１、他者の命令によるものではなく、自律的に判断ができる**（主体的に判断ができる）**
２、義務の倫理に基づいている**（”must”, ”have to”, ”should”といった発話内行為・命令法の形を取っている）**
３、言明の主体・対象となる領域に普遍性がある**（矛盾しない）**

##分類器にセンテンスが”must”を含んでいるかどうかを学習させる
問題を簡単にするため、今回は初歩的でも倫理的な判断ができるかどうかを検証してみましょう。
そもそも**「入力されたテキストが事実の言明か、それとも倫理的な言明か」**を区別出来ようにする必要があります。そこでナイーブ・ベイズ分類器を実装できるライブラリーを用いてテキストが事実の言明か、倫理の言明かを分類させます。まずは、10行の直接法の英文と、その様態を"must"に変えたほぼ同じ文章の違いを判定できるようにします。
`
import nltk
nltk.download('punkt')
import numpy as np
import matplotlib.pyplot as plt
from textblob import TextBlob
from textblob.classifiers import NaiveBayesClassifier 
with open("analysed/actual_statement_pos.txt","r", encoding="utf8", errors='ignore')as f:
    entire_txt = f.read()
    """stm = entire_txt.split(".")""" 
    stm = entire_txt.splitlines()
    print("Text lines =", len(stm))
with open("analysed/ethical_statement_pos.txt","r", encoding="utf8", errors='ignore')as f:
    entire_txt2 = f.read()
    """stm = entire_txt.split(".")""" 
    stm2 = entire_txt2.splitlines()
    print("Text lines =", len(stm2))
`
>Text lines = 10
Text lines = 10

`
for i,item in enumerate(stm):
    train = [ 
        (stm[i], "act"), 
        (stm2[i], "etc"), 
    ]   
cl = NaiveBayesClassifier(train)
state1 = "We are trying to be ethical"
state2 = "We must be trying to be ethical"
state1_class = cl.classify(state1)
state2_class = cl.classify(state2)
print(state1,"<<- Text | Classified ->> ", state1_class)
print(state2,"<<- Text | Classified ->> ", state2_class)
`
>We are trying to be ethical <<- Text | Classified ->>  act
We must be trying to be ethical <<- Text | Classified ->>  etc

"We are..."という文章は事実の言明として、対して"We must be..."という文章は倫理の言明として判定されました。
これで少なくとも**初歩的な事実の言明・倫理の言明を区別できる**ようになりました。

##判定対象の倫理的言明が学習させた倫理的言明と合致・類似するかを判定する
次に、肝心の我々が判定させたい倫理の言明が分類器によって「正しい」と判定されるかを検証します。
持論ですが、倫理的な判断を正しく理解させるには文章の内容に加えて**その文章の極性（肯定的か否定的か）**も理解させる必要があります。
例えば*”We must not kill ourselves”*という、自殺を禁止する言明を分類器に教えたとしても*”We must kill ourselves”*というテキストとの単語の一致率は80%となるため分類器は**この自殺を奨励するセンテンスを「80%の割合で倫理的に正しい」と誤解する**恐れがあります。これを防ぐには、言明そのものに加えて上に述べた文章の極性も分類上のラベルに加えます。つまり**正しい倫理的言明との一致度は高くても極性に齟齬がある場合は非・倫理的な言明であるとみなすようにする**のです。極性に加え「主体的に判断ができる」ことも重要ですが現段階では参考程度としておきます。

>※この段階でTextBlobのセンチメント分析を利用する予定でしたが、検証の結果使えないと判断したので極性を表すラベルは名義特徴量としてetc_pos, etc_negとしています。TextBlobを用いたセンチメント分析に関しては、[こちら](https://qiita.com/KSKNemoto/items/28a817d57706d536d625)の記事をご覧ください。

`
with open("analysed/ethical_statement_pos.txt","r", encoding="utf8", errors='ignore')as f:
    entire_txt = f.read()
    stm_pos = entire_txt.splitlines()
    print("Text lines =", len(stm_pos))
with open("analysed/ethical_statement_neg.txt","r", encoding="utf8", errors='ignore')as f:
    entire_txt2 = f.read()
    stm_neg = entire_txt2.splitlines()
    print("Text lines =", len(stm_neg))
for i,item in enumerate(stm_pos):
    train2 = [ 
        (stm_pos[i], "etc_pos"), 
        (stm_neg[i], "etc_neg"), 
    ] 
`
`
cl2 = NaiveBayesClassifier(train2)
state3 = "We must be trying to be ethical"
state4 = "We must not be trying to be ethical"
state3_class = cl2.classify(state3)
state4_class = cl2.classify(state4)
print(state3,"<<- Text | Classified ->> ", state3_class)
print(state4,"<<- Text | Classified ->> ", state4_class)
`

>We must be trying to be ethical <<- Text | Classified ->>  etc_pos
We must not be trying to be ethical <<- Text | Classified ->>  etc_neg

「我々は倫理的であろうとするべきである」は「正しい」言明、
「我々は倫理的であろうとする必要はない」は「正しくない」言明と判定されました。
これでこの分類器は少なくとも10行のセンテンスから**「何が正しくて、何が正しくないのか」を学習した**といっても過言ではないでしょう。

(今回の記事のGitHubは[こちら](https://github.com/Nymn/Ethical-Machine-Project))

#今後の展望

・判定に使っているTextBlobの分類器がブラックボックスなので、自作のナイーブ・ベイズ分類器を作成し一致度や特徴量を可視化できるようにしたいと考えています。
・上にも書きましたが、分類に掛けられるカテゴリーデータを増やして精度を上げたいと考えてます。少なくとも極性を順序特徴量として学習させてみたいところです。
・当然ですが10行のセンテンスだけから善悪を判断させるのはいくら何でも心もとないので、分類器に学習させる事実的言明・倫理的言明を増やしていきたいと思います。