LoT ラブオンテック

非モテ男の、非モテ男による、【女の子にモテたい】非モテ男のためIT活用ブログ

プログラミング 人工知能AI

【C++】推論エンジンとエキスパートシステムの実装してみる

更新日:



AIというとPythonが多く使われますが、

今回はCで簡単なAIのアプリケーションを

実装して体験してみたいと思います。



エキスパートシステム

それは人工知能の技術を用いた

1種のアプリケーションです。

専門家の思考を模したシステムです。



人間は生活しているといつかのタイミングで

予期せぬことに見舞われることが多々あります。

例えば、病気やパソコントラブルなど。



もし病気であれば、

「お医者さんに病名や直し方を聞きたい」

そう思うはずです。



そこでエキスパートシステムは

事前に用意された専門家の知識をもとに、

入力(症状)から出力(病名)を求めます。



やらんとしていることはいたって単純です。



エキスパートシステムの実現には、

そのコア技術である推論エンジン

それの動力源となる知識ベース

必要になってきます。



推論エンジンだけあっても

エキスパートシステムは動きませんし、

知識ベースだけあっても

エキスパートシステムは動きません。




それではまず、

推論エンジンと知識ベースの

大まかな説明からです。

推論エンジンとは何か



推論エンジンは入力から出力を

導くための仕組みのことを言います。



Wikipediaの定義によると、

知識ベースから答えを求める仕組み

と表現されています。



これは検索エンジンに似ています。

入力(検索ワード)があって、

そこから出力(検索結果)を求めます。



推論エンジンを説明する上で、

以下の3つの言葉が必要です。

  • 知識ベース
  • オブジェクト
  • 属性(アトリビューション)



知識ベース
とは、

専門家の知識を詰め込んだ

データベースのようなイメージです。



この知識ベースには、あらかじめ

オブジェクトと属性の関係が登録されます。



病気で言うなら病名と症状です。

この病気はこういう症状をもっている、

逆に言うなら、

こういう症状であればこの病気だ

といったことを登録します。



厳密に定義するなら、


オブジェクト


保持する属性やルールを基に定義された名前


属性


オブジェクトを定義する助けとなる特別な性質



エキスパートシステムの

全体イメージを以下に示します。



エキスパートシステムでは、

属性をヒントにして知識ベースから、

推論エンジンによってオブジェクトを求めます。



求めたオブジェクトには一般的に、

「決定的」 deterministic

「確率的」 probabilistic

の2つに分けることが出来ます。



エキスパートシステムが求めた

オブジェクトは100%正しいか

それとも○%の確率であるかの違いです。



つまり確率論的な答えは、

断言が出来ず、あくまで可能性がある、

ということで不確実性を持っています。



多くの場合は決定論的な問題は少なく

むしろ確率論的な問題が多いです。



不確実性をもつ推論エンジンは、

コードが長くなるので、

ここでは決定的推論エンジンを

扱っていきます。



なお推論エンジンの実装にあたって

「後ろ向き推論」
を用いています。



推論法の詳しい説明を書くと、

より長い記事になってしまうので、

以下に簡単にご紹介だけします。


後ろ向き推論とは何か



後ろ向き推論とは、

「前向き推論」
の逆の手法です。



ここで前向き推論とは、

属性から(オブジェクト)推論結果を導く方法です。



後ろ向き推論は、

ある推論結果(オブジェクト)を

あらかじめ予想・仮定し、

それが正しいかどうか、

属性を集めて確認する方法です。



今回は分かりやすいように、

オブジェクトに対しその属性をもつか

持たないか、という簡単なシステムですが

もう少し複雑なシステムあれば、

ルールを明確に定義して推論結果を導きます。



Cでエキスパートシステムの実装


パーツごとに分けています。



※以下の参考図書中のコードを
 一部抜粋、改変しています。

「Cで学ぶAI」(マグロウヒル出版)
著者:渋谷恵津子、渋谷昇



まずは実行結果を見て、

全体的なイメージを掴みます。



実行すると最初に

メニューが現れます。

Enter / Query / Save / Load / eXit

の中から一つ選択します。



知識ベースを入力するために、

Enterを選択します。


適当に以下の

オブジェクトと属性を

知識ベースに登録します。



なお知識ベースの所在は、

実行ファイルと同じディレクトリ上です。

"expert.dat"というファイル名で

知識ベースが作成・登録されます。


オブジェクト 属性
Japan asia small advanced
China asia big developed
America north america big advanced


知識ベースの登録が完了したら、

エキスパートシステムへ

問い合わせを行います。



1回目の問い合わせです。

質問に対してyesかnoを答えます。


Chinaがヒットしました。

続いて知識ベースには登録されてない

オブジェクトになるようにあえて

意図的に答えてみます。



No object foundになりました。



これらはエキスパートシステムが

あるオブジェクトを一つ仮定して、

順にその属性を満たすかどうか

質問してきます。



もしyesであれば、

仮定したオブジェクトに登録された

次の属性に関数質問をしてきます。

もしnoであればその属性を除外します。



仮定したオブジェクトが異なっていても

ある属性は共通している場合があります。



例えば日本と中国の"asia"という属性です。

この場合は、最初に日本と仮定していて、

asiaですかの質問にnoと答え場合、

中国は仮定されなくなります。



このことはシステムの効率化を図ります。

同じ質問を繰り返していては、

正解までに時間がかかります。



ちなみに、オブジェクトの仮定は、

ヒューリスティック性を実装していないので、

システムは知識ベースに登録した順に、

オブジェクトを仮定していくことになります。




それでは実際にコードを見てみます。

インクルードとマクロ定義です。


オブジェクトと属性の関係は、

リスト構造をとっています。

オブジェクト構造体のメンバに

属性構造体のポインタが入ります。



また属性は1個ではないので、

属性構造体のメンバに

属性構造体のポインタが入ります。




main文です。



最初に初期化して、

メニュー関数を呼びます。



メニュー関数からの戻り値で、

どのメニューが実行されたか知ります。

switch文で、選択されたメニューに応じて

それぞれ処理する関数に移ります。






Enterメニューが選択された場合です。




queryメニューが押された場合です。



trailno 関数は、ユーザ(回答者)が

no と答えた属性を格納し、

新たな属性と一致するか確認します。

trailyes 関数は、逆に yes を扱います。



これらの関数は、回答者に対して、

同じ質問をするのを防ぐ働きがあります。






saveメニューが選択された場合です。

知識ベースを保存しておくことが出来ます。



load関数が選択された場合です。

保存した知識ベースをロードします。



以上です。

最後まで読んでいただきありがとうございました。




余談:


世界初(諸説あり)のエキスパートシステムは

1970年代にスタンフォード大学で

開発された、Mycin(マイシン)

呼ばれる感染症診断システムだそうです。



当時では、その推論結果の精度は

大成功な値だったそうですが、

専門家が機械を拒んだため、

実際の現場では使われなかったとか。


-プログラミング, 人工知能AI

Copyright© LoT ラブオンテック , 2020 All Rights Reserved Powered by STINGER.