迷惑メール検出エージェント

指導教官 坂本直志助教授
03kc088 藤井将弘

目次

第一章 はじめに

 近年、インターネットの急速な普及により様々なサービスが利用できる。例えば、ネットオークション、ネット通販、チャット、インターネット電話などである。 しかし、コンピュータが多機能になればなるほど、ユーザは目的達成のために、それらのサービスを使うのに複雑な操作が必要になってくる。 なぜなら、これらのサービスはメニューやアイコンなどを選択し、目的の機能を選ぶように設計されている。 この方式では、すべての機能に対してメニュー項目あるいはアイコンが必要になるので、高機能なサービスほど項目が増えてしまう。その結果1つ1つの機能を示す項目の情報量は減り、操作性は落ちる。 このため、従来のソフトウェアとは違うアプローチでユーザの操作性を上げる工夫が必要となる。

 人工知能の分野ではユーザの代わりとなって、能動的に状況を判断し、適切な処理をしてくれるソフトウェアのことをエージェントという。 現在、現実に存在するエージェントは、人間の頭脳を持つほど知的に状況判断をするような高度なものは開発されていない。 しかし、特定分野に関してのみ有効なアルゴリズムが開発され、Microsoft Officeのアシスタント等のように、ユーザの知的活動を代行してくれるソフトウェアが開発されている。 このような現実に存在しているエージェントは、ユーザフレンドリな対応をし、知的に状況判断をし、ユーザのして欲しい面倒な操作を代行してくれる。 例えば、エージェントがユーザの思考や感情を読んで、それに準じた適切な判断をする。ポストペットなどのアニメーションを表示するなど、インタフェイスに工夫がされている。また、エージェントがユーザと対話をし、ユーザの求めている操作を導くなどである。 エージェントには、従来のソフトウェアがユーザに与える煩雑な操作を、簡単な操作でできることが期待されている。

 さて、本研究では迷惑メールについて着目した。これはメール受信者が受信することを期待していないメールである。近年、大量に送られてくるようになっており、社会問題となっている。1日に100通以上の迷惑メールを受け取っているメール受信者もいるほどである。 また、迷惑メールというのは人によって判断基準が違う。なぜなら、迷惑メールというのは、受信者にとって不必要なものを指し、受信者にとって、不必要なメールというのは当然、受信者ごとに異なるからである。 したがって、膨大な量の迷惑メールを受信するメール受信者が本当に必要としているメールを読んで見つけ出すのは、非常に困難で煩わしいといえる。

 本研究では、メール受信者にプログラミングなどの負担をかけずに、メール受信者個別に対応し、迷惑メールを判定するエージェントを作成した。 そのため、本研究では、メール受信者が迷惑メールを判定することによって、エージェントがメール受信者の迷惑メールのルールを学習するモデルを採用した。 エージェントが迷惑メールのルールを学習することによって、これから送られてくる未知のメールに対しても迷惑メールかそうでないかを判断できるわけである。

 また、本研究ではメールソフトを一から作るのではなく、Mozilla Thunderbirdというmozilla社が開発したフリーのメールソフトのプラグインとして作成する。 Mozilla Thunderbirdには、拡張機能として新しい機能を取り付けることができる。拡張機能としての新たな処理内容を付加することはおろか、ユーザインタフェイスの構造、見た目の部分まで新しく拡張機能として構成できる。 本研究では、メールを受信する部分においてはMozilla Thunderbirdの既存の機能を用い、迷惑メールを判定する機能としては、Mozilla Thunderbirdの拡張機能として作成した。 なお、開発期間が限られていたため、迷惑メールを判定するエージェントの構造は満たしてはいるものの、エージェントとして、ポストペットなどのアニメーションを用いるなど、インタフェイスなどを工夫することができなかった。

第二章 コンピュータエージェント

2-1 コンピュータエージェントとは

 エージェントとは、「代理人」という意味を持つ。コンピュータエージェントとはユーザに代わって、ユーザのして欲しい面倒な作業や複雑な仕事を代行してくれるソフトウェアプログラムである。 このようなソフトウェアは下記のようなアイデアを内包している。

コンピュータエージェントとは、利用者の目的達成のために能動的に状況を判断し適切な処理をするソフトウェアプログラムである。 例えば、利用者と対話をし、利用者の発言によりさらに詳細な質問をするなどして、利用者の希望の操作を、通常行うコンピュータへの指示より単純かつ的確に行うなどである。

この発想自体は新しいものではない。映画に登場するコンピュータは、人間と対話したり、自動的に状況判断を行う。このような映画の中には、日常的に存在するコンピュータは人間の少ない操作により高度な処理を行う。しかし、現実に存在しているwindowsやofficeなどは映画に出てくるコンピュータほど高度な処理は行えず、この分野はまだまだ普及していない。

2-2 コンピュータエージェントの構造

 人間は感覚器官により情報を収集し、脳で処理をし、運動器官により、情報(行動)などを出力する。このアナロジーによりコンピュータエージェントの構成は説明される。すなわち、コンピュータエージェントは、環境からセンサなどにより知覚し、知覚した情報をAIアルゴリズムなどにより推論し、エフェクタを通して環境に作用している(図1)。 ここでセンサ、AIアルゴリズム、エフェクタとは以下のようなものである。


図1 コンピュータエージェントの構造

2-3 エージェントの具体例

ここでは現実のコンピュータにおけるエージェントの例を示す。

2-3-1 RoboCupサッカーシミュレーション

RoboCupサッカーのシミュレーションリーグでは22個のプレイヤーを演じるエージェントを用意し、サッカーを競い合うものである。 RoboCupはサーバ/クライアントモデルで構成されている。 サーバが環境(ボール、プレイヤー、ゴールなどの位置情報)を、クライアントであるエージェント(プレイヤー)に提供する。 エージェントは、サーバから与えられた情報を元に目的(ボールを相手ゴールに入れる)を知的に判断し、プレイヤーの操作をサーバへ送る。

この環境から情報を得て、知的に判断し、環境へ働きかけることはエージェントの性質を満たしている。 しかし、RoboCupサッカーは、クライアントとサーバとが対話するエージェントシステムであり、利用者とは直接対話しない。したがって、本論文で目標とする、利用者の代理人として、利用者と対話しながら、コンピュータを単純な操作で複雑な機能を持たせるには関連していない。

2-3-2 Officeのアシスタント

Microsoft社のWord、ExcelなどにはOfficeにはヘルプドキュメントにアクセスするためのエージェントがある。 これはアバターとして、イルカの形をした「カイルくん」を表示し、利用者はこのアバターをインタフェイスとして利用し、対話をする。 カイルくんは利用者の様々な操作に対して、アニメーションにより動き、関係項目の提示などを行う。 またこのカイルくんをクリックすると質問できるようになっている。 カイルくんに質問をすると、質問項目から、ヘルプドキュメントに対して検索を行い、いくつかの答えを返す仕組みになっている。 例えば、"文字の大きさを変えるには"と質問すると、"同じ行内で文字列の配置を変える"、"行頭文字を段落番号に段落番号を行頭文字に変更する"などの答えの項目が出てくる。このようにカイルくんは、インタフェイスの部分がイルカという動物の形をしており、自然言語を用いて利用者と対話ができる。 そして利用者の投げかける言葉から推論を行い、利用者が求めている答えを導き出すことができる。

但し、このカイルくんは一般的な利用者にとって不評である。 カイルくんへの質問は単純にあいまい検索されるだけなので、たくさんの解答の項目が利用者に提示されることになる。 そのため、その中から利用者が適切な答えを探す必要が出てくるので、利用者にとっては煩わしく感じることがあるからである。 これは利用者が求めるほど、エージェントが知的に働いていないという解釈もできる。現状でエージェントが普及していないのはこうした利用者が求めるエージェントの性質と現実のコンピュータエージェントの性質との乖離にあるのかもしれない。

2-4 エージェントに求められる機能

エージェントに求められる機能は以下のようなものである。

・人工知能(AI)を内蔵しており、知的な判断ができる。

例えば、人間は繰り返し、似たような支持をする際、繰り返しになる部分を省略したい。そのため、この「似たような」指示の部分をエージェントが計算できることが期待される。 また、人間は複数のデータに対して、傾向を認識できる。例えば、本当に必要なメールとそうでない迷惑メールの例を見ると、人間なら未知のメールもどちらに分類されるか、たいてい判断できる。 このように実データから傾向やルールを抽出できることが期待される。

・利用者がソフトウェアを擬人化できるようにインタフェイスが工夫されている。

例えばマイクロソフトのOfficeでは「アシスタント」という名前でヘルプシステムに動物や人物のアニメーションをアバターとして表示している。 このアバターは利用者側にとってエージェントと認識しやすいので、エージェントとの対話を自然に行うことができる。

・ 自然言語を用いて利用者と対話する。

通常のソフトウェアは1つの動作を行うのに完璧な指示を必要とする。一方、コンピュータエージェントでは、自然言語を用いて利用者と対話をする。 対話は利用者の自然な発想を促し、利用者は必要な指示をエージェントからの求めに応じてするだけで、本来期待しているコンピュータの動作を導くのに適している。

2-5 学習エージェント

学習エージェントとは自ら経験を用いることによって意思決定のルールを獲得するエージェントである。このようなエージェントには学習アルゴリズムが組み込まれている。学習エージェントは良い経験を積まないと適切な意思決定ができない。そのため事前の学習法には模範解答である学習データを用いる方法、教師を用いる方法などがある。

又、現在の学習アルゴリズムには以下のものがある。

2-5-1 ニューラルネットワーク

ニューラルネットワークとは、人間の脳の脳細胞のつながりのネットワークをモデルにした学習アルゴリズムである。 はじめに人間の脳の計算方法について説明する。人間の脳は図2のような神経細胞が繋がってできている。


図2 神経細胞
・細胞体(soma)

核などが含まれている部分で、神経細胞の本体といえる部分。

・樹状突起(dendrite)

細胞体から伸びだした多数の枝のような部分で、神経細胞の入力端子にあたるところ。

・軸索(axon)

細胞体から伸びだし、一般に太くて枝わかれしない。神経細胞の出力端子にあたる部分。

・シナプス(synapse)

他の神経細胞をつなげる役割をする。軸索の先端にあるシナプスにより他の神経細胞へ信号を送る。他の神経細胞から入力信号を受け取るには、樹状突起によりシナプスを通して、信号を受け取る。

・信号伝達のしくみ

神経細胞が受けた刺激が神経細胞のしきい値を超えれば、神経細胞は興奮し、信号を伝えようとする(これを発火と呼ぶ)。 発火した神経細胞は電気的な信号が軸索を介してシナプスに伝わる。シナプスは神経伝達物質を出し、他の神経細胞に信号を伝達する。 神経細胞は入力信号によっては、しきい値を超えず、発火しないこともある。発火した場合のみ、他の神経細胞に信号を伝達する。 なお、神経細胞は発火することにより、しきい値を下げる。 そうすることによって、神経細胞が発火しやすくなり、連続した神経細胞同士の結びつきが強くなり、伝達がスムーズになる。人間の脳は、このような神経細胞のネットワークで構成されている。これは経験を記憶することになるので、学習と関連があると考えられている。


 一方、ニューラルネットワークの伝達のしくみもこのアナロジーにより説明される。 ニューラルネットワークでは図3のように一種の状態遷移図のような形をしている(ただしループはない)。 ネットワークの各頂点は、ユニットと呼ばれ、ある種の神経細胞の動きをシミュレートしている。 つまり、各ユニットは入力された値を加算し、その和がしきい値を超えた場合のみ出力をする。 また、ニューラルネットワークでもユニットのしきい値を下げることによって学習を行う。

この仕組みを利用し、覚えさせたい事例の模範解答を入力ユニットにあらかじめ読み込ませることにより、事例を学習させることができる。模範解答を入力ユニットに読み込ませ、その入力に対して、各ユニットのしきい値を下げる。そうすることにより、出力ユニットには模範解答が得られやすくなる。 このように学習したニューラルネットワークは、未知の入力に対しても推論し、良い答えを出すようになる。


図3 ニューラルネットワークの構成図

2-5-1 ベイズによる学習アルゴリズム

ベイズによる学習アルゴリズムでは、条件付確率に対するベイズの定理を応用する。ベイズの定理とは、つまり完全に現実の世界から集められたデータに基づいて、新たな未知のデータの推測を行う。過去にデータの数があればあるほど、より確実な推測が実現できる。 未知のデータの推測の結果は次のベイズの確率の式によって算出される。

P(xi|y) =P(xi,y)P(y) =P(xi,y)ΣjP(xj,y) =P(y|xi)P(xi)ΣjP(y|xj)P(xj)

[式の説明]

P(xi)... 事象 xi が発生する確率
P(y)... 事象 y が発生する確率
P(xi|y)... 事象 y が発生している場合に事象 xi が発生する確率
P(xi,y)... 事象 xi 事象 y の両方とも起こる確率
P(y|xi)... 事象 xi が発生している場合に、事象 y が発生する確率
ただし、 ΣjP(xj)=1 , xixj=φ

となる。つまり、過去に与えられた状態 xi である場合に状態 y である確率に基づき、状態 y を観測したときに状態 xi である確率を算出する手法である。

例えば、今熱が出ている患者が目の前にいるとして、その発熱の原因を推定しようと考えるとする。発熱の原因としては、風邪、インフルエンザ、その他様々な病気が考えられる。 ベイズ理論を用いて、発熱の原因が風邪なのか、インフルエンザなのか、風邪でもインフルエンザでもない(その他の)病気によるものなのかを導くとする。


図4 発熱の原因

この場合、発熱から病気を推定するのであるが、これは、一般的には、結果から原因を推定するということになる。結果から原因を推定する場合、ある結果のときにある原因である確率が最も大きいような原因を選ぶということである。これは条件付確率であり、以下のようにあらわせる。

P( 発熱 | 風邪 )
P( 発熱 | インフルエンザ )
P( 発熱 | その他 )
P( 風邪 )
P( インフルエンザ )
P( その他 )

これらの値は今までの診療記録を元に統計処理により求めることができる。では患者が発熱している時に、各病気の確率は次のようになる。

P( 風邪 | 発熱 ) = P( 発熱 | 風邪 ) P ( 風邪 ) P ( 発熱 )
P( インフルエンザ | 発熱 ) = P( 発熱 | インフルエンザ ) P ( インフルエンザ ) P ( 発熱 )
P( その他 | 発熱 ) = P( 発熱 | その他 ) P ( その他 ) P ( 発熱 )

ただし各記号は以下のとおりである。

P( 発熱 )              発熱する確率
P( 風邪 )              風邪になる確率
P( インフルエンザ )        インフルエンザになる確率
P( その他 )             その他の病気になる確率
P( 発熱 | 風邪 )           風邪のときに発熱する確率
P( 発熱 | インフルエンザ )     インフルエンザのときに発熱する確率
P( 発熱 | その他 )          その他の病気のときに発熱する確率

例えば、これらの値が

P( 風邪 ) = 0.5
P( インフルエンザ ) = 0.1
P( その他 ) = 0.4
P( 発熱 | 風邪 ) = 0.8
P( 発熱 | インフルエンザ ) = 0.7
P( 発熱 | その他 ) = 0.4

であるとすると、これより

P( 発熱 | 風邪 ) P ( 風邪 ) = 0.4
P( 発熱 | インフルエンザ ) P ( インフルエンザ ) = 0.07
P( その他 | その他 ) P ( その他 ) = 0.16

となる。ベイズの定理の式の分母に相当する P( 発熱)

Σ病気∈{風邪、インフルエンザ、その他}P(病気発熱)

であるので

P(発熱)=0.63

なる。患者が発熱しているときに、風邪、インフルエンザ、その他の病気である確率は、

P( 風邪 | 発熱 ) = 0.4 0.63 = 0.6349
P( インフルエンザ | 発熱 ) = 0.07 0.63 = 0.1111
P( その他 | 発熱 ) = 0.16 0.63 = 0.2540

となる。よって患者が発熱する原因は風邪である確率が大きいと分かる。このアルゴリズムを用いることによって、未知の出来事に対しても過去のデータを用いることにより推測が可能となる。

2-5-3 遺伝的アルゴリズム

遺伝的アルゴリズムとは、生物が環境に適応して進化していく過程を工学的に模倣した学習アルゴリズムである。生物は双方の親の遺伝子を交換し、受け継ぐことにより進化していく。また、生物は進化の中で、環境に適応すると生き残り、適応しないと死滅する。 このような考え方を応用したのが遺伝的アルゴリズムである。

また遺伝的アルゴリズムはダーウィンの進化論をモチーフにしている。

ダーウィンの進化論は概略すると以下のようなものである。

「地球には、いろいろな個体がいる。そして環境に応じて、より優秀な個体だけが子孫を残すことができ、劣等な個体は淘汰される。また、残った個体は突然変異を起こす場合があって、前の世代よりも優秀になることも、逆になることもある。こうしたことを繰り返して、我々は進化してきた」

ここで優秀な個体というものは「環境に適応し、優れた生存能力を持つ者」である。 また、優れた者の子は、優れた親の遺伝子を受け継いでいるため、やはり優れた者である可能性が高いとされる。また、遺伝子に突然変異が起こることによってより優れた者になる可能性もある。

こうして集団から、環境に適応できなかった者の遺伝子が消え去り、環境に適応した者の遺伝子が増えていくことで集団全体が進化していくわけである。

さて、遺伝的アルゴリズムは、ある関数 f(x) が最適となるような x を求める際にこの生物の遺伝にする進化の仕組みを応用したものである。

f(x) f(x) を最適とする候補 x1 ... xn を遺伝子とみたて、適応度の低いものを取り除き、又、残った遺伝子から適当なペアを作りそのペアから新しい遺伝子を作るということを繰り返し、環境に適応する遺伝子を求めるアルゴリズムである。

2-5-4 決定木生成アルゴリズム

決定木とはデータを様々な条件を基準に木の枝葉のように分類していくときに使われる。決定木は図5のようなものであり、図5を上下逆転させると木のような形になるので「決定木」と呼ばれる。図5は天候(天気、湿度、風の状態)を基準に、ゴルフをするかしないかを決定木に分類したものである。


図5 決定木の例

図5のようなモデルが生成できれば、入力側に、天候(天気、湿度、風の状態)が与えられると、出力側では、ゴルフをするかしないかを分類することができる。たとえば、入力に天気=「晴れ」、湿度=「90」、風=「なし」 という情報が与えられれば、出力側で「ゴルフをしない」と答えが出せるわけである。

図5のようなモデルを生成する方法として、以前は分野ごとの専門家が分割するポイントを経験や知識により考え、決定木に相当するプログラムを作っていた。しかし、データが膨大であればあるほど、決定木を生成するプログラムも煩雑になってしまうし、プログラマーの負担も大きくなる。

そこで決定木を自動生成するアルゴリズムが考えられた。決定木を自動生成するプログラムを以下に示す。

・C4.5

C4.5とはデータの表から決定木を創るプログラムでJ.R.Quinlanが作成したものである。 ゴルフをした時と、しなかった時の天気、湿度、風の状態(図6)の表をプログラムに入力すると、図5のような決定木を導くことができる。


図6 入力データ

そして図7のような入力データが来たときに、図5の決定木を用いて答え(ゴルフをするか)を導くことができる。


図7 C4.5による推測

第三章 ソフトウェア設計

3-1 はじめに

本研究では、電子メールから迷惑メール(SPAM)を排除するようなエージェントを作成する。 利用者は入手したメールに対して、迷惑メール(以下SPAM)か非迷惑メール(以下HAM)かをエージェントに教えるとエージェントはメール内の単語構成などを学習する。 ある程度学習すると、利用者が指定する特定のメールに対してSPAMである確率を計算する。エージェントの使う学習アルゴリズムはベイズの定理に基づいたものである。 なお、開発期間が限られていたため、エージェントとしての基本構造は満たしているものユーザインタフェイスなどを工夫することができなかった。 なお、開発プラットホームはmozilla thunderbirdというフリーのメールソフトの機能拡張として作成した。 使用言語は、XUL、JavaScript、CSS、XPCOMなどである。

3-2 基本構造

ユーザが入手したメールに対して「SPAM」「HAM」と指定すると図8のように迷惑メールのspamフォルダとhamフォルダが生成され、ユーザが指定したメールは、spamフォルダやhamフォルダへと格納されるようになる。


図8 spamフォルダ、hamフォルダ

ある程度、spamフォルダ、hamフォルダへとメールが溜まれば、入手したメールに対して、SPAMかどうかを自動判定できる。

つまり、図9のようにspamフォルダとhamフォルダに入っているメッセージのすべての単語の頻度を取り、確率という形で統計情報を得る。その統計情報を元に新しく受信したメールに出現する単語の確率を計算し、SPAM率を得るというものである。


図9 spam、hamの統計情報

3-3 ベイズ理論によるアルゴリズム

エージェントを製作する上で用いた学習アルゴリズムはベイズ理論に基づいたものである。このアルゴリズムはSPAM率を算出するために用いる。SPAM率を算出するアルゴリズムを説明していく。

電子メールの中にある単語ωが含まれている確率を Pr[ω] とする。単語同士の関連付けがあるため、複数の単語 ω1,ω2...ωk がメールに含まれる確率は一般には独立ではないが、ここでは独立と仮定することにする。すると、複数の単語が一つのメールに含まれる確率は Pr[ω1,...,ωk]=Pr[ω1]Pr[ω2]...Pr[ωk]=Πi=1kPr[ωi] となる。

新しく受信したメールに含まれる単語を ω1,ω2...ωk と仮定する。するとこれらの単語が1つのメールに含まれる確率は、 Pr[ω1,...,ωk]=Pr[ω1]Pr[ω2]...Pr[ωk]=Πi=1kPr[ωi] となる。

ω1,ω2...ωk が含まれているメールがSPAMである確率 Pr[SPAM|ω1,...,ωk] 、新しく受信したメールがSPAMである確率をBayesの定理を使って求めることができる。計算式は以下のようになる。

Pr[SPAM|ω1,...,ωk]=Pr[SPAMかつω1,...,ωk]Pr[ω1,...,ωk] =Pr[SPAM]Pr[ω1,...,ωk|SPAM]Pr[SPAM]Pr[ω1,...,ωk|SPAM]+Pr[HAM]Pr[ω1,...,ωk|HAM]

ここで分子の式で分子分母を割ると次式になる。

=11+Pr[HAM]Pr[ω1,...,ωk|HAM]Pr[SPAM]Pr[ω1,...,ωk|SPAM] =11+Pr[HAM]Pr[SPAM]Πi=1kPr[ωi|HAM]Pr[ωi|SPAM]

ここで、サンプルを使ったベイズ推定を行うと考える。すると、テストにするメールから得られた単語 ω1,...,ωk に対して、 Pr[HAM]Pr[SPAM] はそれぞれ、サンプル中のHAM、SPAMの割合をさし、 Pr[ωi|SPAM]Pr[ωi|HAM] はそれぞれHAM、SPAMのサンプル中で ωi が1つ以上含まれているメールの割合を指すことになる。

3-4 プラットフォーム

本研究では、拡張機能をつけることが可能であるMozilla社の Thunderbirdを使用した。 Thunderbirdは図10のような構成をしており、メニューバー、ツールバー、ステータスパネルにボタンやラベルなどのアイコンを、フォルダペイン、スレッドペイン、メッセージペインを右クリックしたときのコンテキストメニューに項目を追加することができる。

x
図10 開発プラットフォーム

実際Thunderbirdに拡張を行うにはXUL、JavaScript、CSS、XPCOMを用いる。 XULはボタンやラベルなどのGUI部品を、JavaScriptはは、GUI部品が押されたときなどのイベント処理をCSSはXULで定義したGUI部品の装飾を行う。またXPCOMはJavaScriptではできない特殊な機能を提供している。

以下に各技術について詳しく説明をしていく。

3-4-1 XUL

XULファイルはXML-Based User-Interface Languageの略であり、XMLベースの構造記述言語である。XULはHTMLのようにタグを使って要素を記述する。様々なGUI部品(ドロップダウンメニュー、スクロールバーなど)を標準で利用できる。XULの一般的な書き方を以下に述べる。

・XULの記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://sample/skin/sample.css" type="text/css"?>

<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<script src="saveMsg.js"/>
<script src="saveMsg.js"/>
<script src="Indicate_Probability.js"/>
<script src="convertURIToFilePath.js"/>
<script src="moveToFolder.js"/>
<script src="writeTo.js"/>

<toolbarpalette id="MailToolbarPalette">
 <toolbarbutton id="myextension-button1"
                      class="toolbarbutton-1"
                      label="JUDGE"
                      onmousedown="saveMsg()"
                      onmouseup="Indicate_Probability()">
 </toolbarbutton>
</toolbarpalette>

1〜2行目:1行目はXMLファイルであることを示し、2行目はCSSファイルの読み込みをしている。
4行目:作成した拡張機能をThunderbirdの新たな機能として関連付けをしている。
6〜11行目:JavaScriptファイルの読み込みをしている。
13〜20行目:ツールバーにGUI部品(ボタン)を取り付ける記述である。14、15、16行目でid、class、labelを宣言し、17、18行目でボタンが押された時と、押されたボタンが離された時の処理として、JavaScriptファイルの関数名を記述することにより、その関数名の処理を実行できる。

3-4-2 JavaScript

JavaScriptはNetscape Communications社の開発した言語で、本来はHTMLに組み込み、動的なページを作成するためのものだが、ThunderbirdではXULに組み込むことによって動的な処理を行えるようになる。 またJavaScriptは以下のような性質を持つ言語である。

・オブジェクト指向言語

オブジェクトとは物理的、概念的にまとまった"もの"、"人"のことである。私たちは日常、いろいろな"もの"、"人"に囲まれて生活している。たとえば、仕事をするときに、「電話で、お客さんから注文が入ったので、契約書を作成した。」など"もの"を使ったり、"人"と会話したりする。これらすべての"もの"、"人"がオブジェクトになる。 オブジェクトは、下記2つの特徴がある。

たとえば、「人間」というオブジェクトについて考えると、「人間」は幼児の時もあれば、社会人の時もあればと、様々な状態を持っている。また、「人間」は走ったり食べ物を食べたり言葉を話したりといろいろな動作、振る舞いを行うことが出来る。このようにオブジェクトはいくつかの状態を持ち、また様々な振る舞いを起こすことが出来る。 オブジェクト指向言語とは、状態をプロパティ、振る舞いをメソッドとして備えた言語である。下記にJavaScriptのプログラムを示す。

・JavaScriptの記述

1
2
3
4
5
6
7
8
9
function fnc1(){
  var obj = new Object();

function fnc2(){
  alert("SPAM");
}
  obj.saySpam = fnc2;
  obj.saySpam();
}

2行目:変数objにオブジェクトを生成する。
4〜6行目:文字列「SPAM」を警告ダイアログにて表示する関数を作る
7〜8行目:7行目で変数objに、saySpamというプロパティを生成し、obj.saySpamに関数fnc2の内容を与え、8行目でfnc2の関数を呼び出すメソッドを記述する。

3-4-3 CSS

CSS(Cascading Style Sheets)とはHTML文書(XML文書)の表示方法(レンダリング)を指定する仕組みである。しかし、ThunderbirdではXULで指定したGUI部品の表示方法も指定することができるよう拡張されている。具体的には、#id{属性:値}でXULのidに対して画像などスタイル情報を与えることができる。 以下にプログラムを示す。

1
2
3
#myextension-button1{
list-style-image: url(spamcheck.png);
}

XULで指定したid、myextension-button1に、spamcheck.pngの画像を貼り付ける処理をしている。

3-4-4 XPCOM

XPCOMとはThunderbirdのAPIでJavaScriptにより利用できる。JavaScriptではファイル入出力が規定されておらず、ファイル入出力を行うにはXPCOMを用いる必要がある。 XPCOMを呼び出すには2つの手順を踏む必要がある。

これによりファイル入出力などで必要なXPCOMの関数を呼び出すことができるようになる。XPCOMを用いたJavaScriptのプログラムの例として、指定したファイルを削除するプログラム以下に示す。

1
2
3
4
5
6
7
function deleteMsg()
{
  aFile =Components.classes["@mozilla.org/file/local;1"].createInstance();
  if (aFile) aFile.QueryInterface(Components.interfaces.nsILocalFile);
  aFile.initWithPath("/mozilla/testfile.txt");
  aFile.remove(true);
}

3〜4行目:3行目のclassesプロパティから文字列"@mozilla.org/file/local;1"を参照することにより、ファイルコンポーネントを取得し、4行目のQueryInterface()によってファイルコンポーネントが含んでいるインタフェイスnsILocalFileを取得している。
5〜6行目:5行目で削除するファイルのパスを与え、6行目でそのファイルを削除している。

第四章 作成したエージェントについて

4-1 はじめに

本研究ではメール受信者がSPAM、HAMの例をエージェントに教え、その例を元にこれから送られてくる未知のメールに対し、SPAMかHAMかを判定するソフトウェアを作成する。
開発プラットフォームは3-4章で説明したmozilla thunderbirdというフリーのメールソフトであり、拡張機能として使用した言語はXUL、JavaScript、CSS、XPCOMである。

4-2 使用方法

作成したソフトウェアの使用方法は「学習」「判定」の2通りある。それぞれの使用方法を以下に述べる。

4-2-1 学習

受けとったメールに対し、図11の「SPAMボタン」「HAMボタン」を押すことによって、指定したメールを学習フォルダのspam、hamフォルダに入れ、spam、hamのサンプルとして登録する。 サンプルとして登録することによって、エージェントが学習をする。


図11 学習のしくみ

4-2-2 判定

spam,hamのサンプルとしてある程度学習させた後、図12の「JUDGEボタン」を押すことによって、新たに受信したメールのSPAM率を学習フォルダのspamフォルダ、hamフォルダの単語の統計情報により図13のように警告ダイアログという形で表す。


図12 判定のしくみ

図13 警告ダイアログ

4-3 プログラムの説明

作成したプログラムは大きく分けて以下の4つの部分からなる。

4-3-1 インタフェイスの部分

インタフェイスの部分は、図14のようにThunderbirdのツールバーに拡張機能としてspam、ham、judgeの3つのボタンを作成した。


図14 インタフェイス

図14のようにツールバーにボタンを作成するにはXUL、CSS言語を用いる。
本研究では、base.xul、style.cssというファイルを作成してインタフェイスを構成した。

・base.xul(7章付録base.xulを参照)

このプログラムでは、拡張機能をThunderbirdの機能の一部として関連付けを定義し、また必要なファイル、JavaScript、CSSファイルなどを読み込み、それからGUI部品の生成をしている。

2行目:CSSの読み込み
3行目:拡張機能をThunderbirdの機能の一部として関連付けを定義
5〜10行目:JavaScriptの読み込み
14〜19行目:ツールバーにjudgeボタンを生成する部分。id、label、classを宣言し、onmousedown、onmouseupによりイベント処理としてspam率を算出する処理の関数を定義している。
21〜25行目:ツールバーにspamボタンを生成する部分。id、label、classを宣言し、onclickによりイベント処理として指定したメールをspamフォルダへコピーする処理の関数を定義している。
27〜31行目:ツールバーにhamボタンを生成する部分。id、label、classを宣言し、onclickによりイベント処理として指定したメールをhamフォルダへコピーする処理の関数を定義している。
・style.css(7章付録style.cssを参照)

このプログラムでは、base.xulで作成したspam、ham、judgeボタンに画像を与えている。

1〜3行目:judgeボタンに図15のspamcheck.pngの画像を与える。
5〜7行目:spamボタンに図16のjump_folder24SPAM.pngの画像を与える。
9〜11行目:hamボタンに図17のjump_folder24HAM.pngの画像を与える。

図15 spamcheck.png

図16 jump_folder24SPAM.png

図17 jump_folder24HAM.png

4-3-2 spamボタン、hamボタンの機能の部分

指定したメールをspamフォルダ、hamフォルダにコピーをするというのがspamボタン、hamボタンの機能である。 spamボタン、hamボタンをクリックすると、指定したメールをThunderbirdの画面上ではspamまたは、hamフォルダへコピーするが、実際spam、hamフォルダは図18のフォルダの場所にspam、hamというファイル名でボタンが押される度、その指定されたメールの内容を上書きしている。


図18 spamフォルダ、hamフォルダの保存場所

実際、メールをspamフォルダ、hamフォルダにコピーするのは、プログラムmoveToSpamFolder.jsの関数toSPAMfolder()とプログラムmoveToHamFolder.jsの関数toHAMfolder()である。spamボタンがクリックされた時、関数toSpamFolder()が、hamボタンがクリックされた時、関数toHamFolder()が呼び出される。

・moveToSpamFolder.js(7章付録moveToSpamFolder.jsを参照)

・関数toSPAMfolder()の処理内容

6行目でThunderbirdのspamフォルダのURIを記述し、7,8行目で6行目で指定したspamフォルダのURIを元に、指定したメールをspamフォルダへコピーする。
・moveToHamFolder.js(7章付録moveToHamFolder.jsを参照)

・関数toHamFolder()の処理内容

6行目でThunderbirdのhamフォルダのURIを記述し、7,8行目で6行目で記述したhamフォルダのURIを元に、指定したメールをhamフォルダへコピーする。

4-3-3 Judgeボタンの機能の部分

指定したメールのspam率を警告ダイアログにて表すというのがjudgeボタンの機能である。judgeボタンにマウスボタンが押されると指定したメールをファイルに保存し、押されているjudgeボタンが放されるとそのメールを読み込みspam率を警告ダイアログにて表示するようになっており、マウスボタンが押された時と、放された時の2回のイベント処理によって実現できる。

4-3-3-1 Judgeボタンにマウスボタンが押された時の処理

judgeボタンにマウスボタンが押されるとspam率を判定するメールのファイルが図19のフォルダへ一時的に保存される。この処理はプログラムSaveMsg.jsの関数saveMsg()によって行われる。

・saveMsg.js(7章付録saveMsg.jsを参照)

・関数saveMsg()の処理内容

6行目:spam率を判定するメールのURIを読み込む。
7行目:そのメールのURIを元に図19のフォルダへ保存する時の保存名を取得する。
9〜11行目:7行目で取得した保存名でそのメールを図19のフォルダへ保存している。

図19 spam率を判定するメールの保存場所

4-3-3-2 Judgeボタンにマウスボタンが放された時の処理

押されているjudgeボタンからマウスボタンが放されると図19のspamファイル、hamファイル、spam率を判定するメールのファイルを読み込む。そしてspamファイル、hamファイルからSPAM中の単語頻度とHAM中の単語頻度の統計P(単語|SPAM)P(単語|HAM) をとり、その統計情報を元に、spam率を判定するメールのSPAM率を算出する。この処理はプログラムIndicate_Probability.jsの3つの関数spamファイル、hamファイルからSPAM中の単語頻度とHAM中の単語頻度の統計を取得する関数Get_Word_Event_Probability()、spam率を算出する関数Arithmetic()、実際にspam率を警告ダイアログにて表示する関数Indicate_Spam_Rate()によって行われる。

・Indicate_Probability.js(7章付録Indicate_Probability.jsを参照)

・関数Get_Word_Event_Probability()の処理内容

3〜6行目:図19のspamファイルのパスを取得する。
8〜31行目:8行目はspamファイルの内容を読み込み、9行目はspamファイルの内容を単語ごとに分割している。10行目の変数S_totalはspamメール件数、11行目の変数S_hindoはspamファイルの単語すべてに対してその単語がspamメールに現れた件数を指している。 また、spamファイルの内容は図20のような形式でFrom - 曜日 月 日付 時間 年を境に違う内容のメールが書かれている。そのため、SPAMメールのすべての件数と、spamファイルに現れた単語に対してその単語が入っているspamメールの件数をカウントするには、以下の方法を取る必要がある。

spamファイルに初めて単語が現れた場合はその単語の発生頻度を1とする。
spamファイルに文字列「From - 曜日 月 日付 時間 年」が現れるまでに同一の単語が2回以上現れた場合は、その単語の頻度を1回はカウントするが、また次に文字列「From - 曜日 月 日付 時間 年」が現れるまで2回以上カウントしない。

この処理を13行目〜31行目で行い、spamメールの件数、spamファイルに現れたすべての単語に対してその単語が入っているspamメールの件数を記録する。

34〜37行目:図19のhamファイルのパスを取得する。
39〜62行目:39行目はhamファイルの内容を読み込み、40行目はhamファイルの内容を単語ごとに分割している。41行目のH_totalはhamメール件数、42行目のH_hindoはhamファイルの単語すべてに対してその単語がhamメールに現れた件数を指している。 また、hamファイルの内容は図20のような形式でFrom - 曜日 月 日付 時間 年を境に違う内容のメールが書かれている。そのため、HAMメールのすべての件数と、hamファイルに現れた単語に対してその単語が入っていhamメールの件数をカウントするには、以下の方法を取る必要がある。

hamファイルに初めて単語が現れた場合はその単語の発生頻度を1とする。
hamファイルに文字列「From - 曜日 月 日付 時間 年」が現れるまでに同一の単語が2回以上現れた場合は、その単語の頻度は1回はカウントするが、また次に文字列「From - 曜日 月 日付 時間 年」が現れるまで2回以上カウントしない。

この処理を44行目〜62行目で行い、hamメールの件数、hamファイルに現れたすべての単語に対してその単語が入っているhamメールの件数を記録する。

・関数Arithmetic()の処理内容

69〜72行目:関数saveMsg()で保存したファイルの保存名を取得するため、71行目でspam率を判定するメールのURIを得、72行目でそのURIからそのメールの保存名を得る。
74〜77行目:69〜72行目で得た保存名を付与することによって、図19のspam率を判定するメールのパスを得る。
80〜112行目:80行目でspam率を判定するメールを読み込み、81行目でそのメールの内容を単語ごとに区切る。82行目の変数Sはspam率を判定するメールの各単語において、SPAMメールにその単語が現れる確率、83行目の変数Hはspam率を判定するメールの各単語において、HAMメールにその単語が現れる確率を指している。85〜112行目では本研究で用いたベイズの定理
Pr[SPAM|ω1,...,ωk]=Pr[SPAMかつω1,...,ωk]Pr[ω1,...,ωk] =Pr[SPAM]Pr[ω1,...,ωk|SPAM]Pr[SPAM]Pr[ω1,...,ωk|SPAM]+Pr[HAM]Pr[ω1,...,ωk|HAM]= 11+Pr[HAM]Pr[ω1,...,ωk|HAM]Pr[SPAM]Pr[ω1,...,ωk|SPAM] =11+Pr[HAM]Pr[SPAM]Πi=1kPr[ωi|HAM]Pr[ωi|SPAM]
を計算し、spam率を返している。

ただし、spamファイル、hamファイル両方に含まれていない単語がspam率を判定するファイルに含まれている場合は、その単語は確率計算をせず、spam率を判定するメールの単語がspamファイルだけに無ければ、その単語がspamに現れる確率は0.01、またspam率を判定するメールの単語がhamファイルだけに無ければ、その単語がhamに現れる確率は0.01としてベイズの定理を計算する。

・関数Indicate_Spam_Rate()の処理内容

119行目:関数Get_Word_Event_Probability()を呼び出す。
120行目:関数Arithmetic()を呼び出し、関数Arithmetic()が返すSPAM率を警告ダイアログにて表示する。
121行目:関数saveMsg()によって保存した図19のspam率を判定するメールを削除する。

図20 spamファイル、hamファイルの形式

4-3-3-3 ファイル入力のために用いたプログラム

judgeボタンを押してメールのSPAM率を得るには、図19のspamファイル、hamファイル、spam率を判定するメールファイルを読み込む必要がある。ファイルを読み込むために本研究では2本のプログラムを用いた。読み込みたいファイルのパスをThunderbirdのXPCOM用のパスに変換するプログラムconvertURIToFilePath.jsと、実際にファイルを読み込むプログラムreadFrom.jsである。

・convertURIToFilePath.js(7章付録convertURIToFilePath.jsを参照)

・関数convertURIToFilePath()の処理内容

URIを引数と指定することによって、5〜7行目で引数として指定されたURIを元にXPCOM用のパスを取得しパスを返している。

・readFrom.js(7章付録readFrom.jsを参照)

・関数readFrom()の処理内容

関数convertURIToFilePath()によってXPCOM用に変換したパスを引数と指定することによって、そのパスのファイルの内容を取得し、返している。

第五章 評価

5-1 はじめに

本研究の目的は、これから送られてくる未知のメールがspamかhamなのかを自動的に分類するソフトウェアを作るというものである。 そのため理想的なのは、ユーザが少しのメールのサンプル量をソフトウェア側に学習させただけで、ソフトウェア側が高精度な判断をすることである。 本研究では、メールのサンプル数をいくつか与えたときに、どれだけspamとhamを分類できたかで評価を行う。

5-2 実験

実際にソフトウェア側に図21の35通のSPAMメールと図22の3通のHAMメールを学習させた時に、新たに図23のSPAMメール30通とHAMメール5通を受信させ、それらのメールのSPAM率を算出し、どの程度spamとhamを分類できたかを記録する。


図21 サンプルのspamメール35通

図22 サンプルのspamメール3通


図23 未知のメール35通

また、メールの判定基準としては、エージェントが警告ダイアログでのspam率が0.5以上であると判定した場合はそのメールはspam、0.5未満と判定した場合はそのメールはhamであるとする。

実験の結果、未知のspamメールでは30通中24通spamと判定し、未知のhamメールでは5通中5通hamと判定した。

5-3 評価

エージェントとして、ユーザごとの「迷惑」を学習し、38通という少ないサンプル数でspamを80%判定、(hamは100%)判定することができた。
しかし、エージェントとしての基本構造は満たしてはいるものの、ユーザインタフェイスがボタンであり、アニメーションをつけるなど工夫をすることはできなかった。

第六章 まとめ

ユーザがSPAMメールを読まずとも、SPAMメールを見分けることができるエージェントをThunderbirdのプラグインとして作成した。テストを行ったところ、簡単な学習でSPAMを80%減らすことができた。ただし、作成したソフトウェアはエージェントの基本構造は満たしてはいるものの、ユーザインタフェイスがただのボタンであり、エージェントとしてアニメーションを付けるなどの工夫をすることができなかった。また、今回作成したソフトウェアは英文のメールしか判定することができない。 そのため、今後はユーザインタフェイスを工夫し、ユーザフレンドリな実現を目指していくとともに、日本語にも対応できるように研究をしていきたい。

第七章 付録

作成したエージェントのプログラムを示す。

base.xul

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://sample/skin/style.css" type="text/css"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<script src="saveMsg.js"/>
<script src="readFrom.js"/>
<script src="Indicate_Probability.js"/>
<script src="convertURIToFilePath.js"/>
<script src="moveToSpamFolder.js"/>
<script src="moveToHamFolder.js"/>

<toolbarpalette id="MailToolbarPalette">

      <toolbarbutton id="myextension-button1"
                        class="toolbarbutton-1"
                        label="JUDGE" 
                        onmousedown="saveMsg()"
                        onmouseup="Indicate_Spam_Rate()">
    </toolbarbutton>

    <toolbarbutton id="myextension-button2"
                      label="spam"
                      class="toolbarbutton-1"
                      oncommand="toSPAMfolder()">
    </toolbarbutton>

    <toolbarbutton id="myextension-button3"
                      label="ham"
                      class="toolbarbutton-1"
                      oncommand="toHAMfolder()">
    </toolbarbutton>

</toolbarpalette>

</overlay>

style.css

#myextension-button1{
     list-style-image: url(spamcheck.png);
}

#myextension-button2{
     list-style-image: url(jump_folder24SPAM.png);
}

#myextension-button3{
     list-style-image: url(jump_folder24HAM.png);
}

moveToSpamFolder.js

function toSPAMfolder()
{
try {
    // get the msg folder we're copying messages into

    var destUri ='mailbox://nobody@Local%20Folders/spam/';
    var destResource = RDF.GetResource(destUri);
    gDBView.doCommandWithFolder(nsMsgViewCommandType.copyMessages, destResource);
  }
  catch (ex) {
    dump("MsgMoveMessage failed: " + ex + "\n");
  }
}

moveToHamFolder.js

function toHAMfolder()
{
  try {
    // get the msg folder we're copying messages into
   
    var destUri ='mailbox://nobody@Local%20Folders/ham';
    var destResource = RDF.GetResource(destUri);
    gDBView.doCommandWithFolder(nsMsgViewCommandType.copyMessages, destResource);
  }
  catch (ex) {
    dump("MsgMoveMessage failed: " + ex + "\n");
  }
}

saveMsg.js

function saveMsg()
{
  try {
    var messenger = Components.classes["@mozilla.org/messenger;1"].createInstance();
        messenger = messenger.QueryInterface(Components.interfaces.nsIMessenger);
    var uri = GetFirstSelectedMessage();
    var subject = messenger.messageServiceFromURI(uri).messageURIToMsgHdr(uri).messageKey;

    var destUri ='mailbox://nobody@Local%20Folders/'+subject;
    var destResource = RDF.GetResource(destUri);
    gDBView.doCommandWithFolder(nsMsgViewCommandType.copyMessages, destResource);

  }
  catch (ex) {
    dump("MsgCopyMessage failed: " + ex + "\n");
  }
}

Indicate_Probability.js

function Get_Word_Event_Probability()
{
spamfile=convertURIToFilePath("file:///H:/Documents and Settings/fujii/Application Data/Thunderbird/Profiles/7fe4tlfj.default/Mail/Local Folders/spam/");
spamfiles = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
  if (!spamfiles) return false;
spamfiles.initWithPath(spamfile);

SpamWord = readFrom(spamfiles);
S_word = SpamWord.match(/\S+/g);
S_total=0;
S_hindo = new Object;
S_flag = new Object;
for (s = 0; s < S_word.length; s++){
    if((S_word[s].match(/From/)) && (S_word[s+1].match(/-/)) && (S_word[s+2].match(/Sun|Mon|Tue|Wed|Thu|Fri|Sat/)) &&
        (S_word[s+3].match(/Jan|Feb|Mar|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/))){
        for (t = 0; t < S_word.length; t++){
        S_flag[S_word[t]] = false;
        }
        S_total++;
    }
    if(!(S_flag[S_word[s]] == true)){
        if(isNaN(S_hindo[S_word[s]])){
            S_hindo[S_word[s]] = 1;
            S_flag[S_word[s]] = true;

        }else{
            S_hindo[S_word[s]]++;
            S_flag[S_word[s]] = true;
        }
    }
}


hamfile=convertURIToFilePath("file:///H:/Documents and Settings/fujii/Application Data/Thunderbird/Profiles/7fe4tlfj.default/Mail/Local Folders/ham/");
hamfiles = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
  if (!hamfiles) return false;
hamfiles.initWithPath(hamfile);

HamWord = readFrom(hamfiles);
H_word = HamWord.match(/\S+/g);
H_total= 0;
H_hindo = new Object();
H_flag = new Object();
for (h = 0; h < H_word.length; h++){
    if((H_word[h].match(/From/)) && (H_word[h+1].match(/-/)) && (H_word[h+2].match(/Sun|Mon|Tue|Wed|Thu|Fri|Sat/)) &&
        (H_word[h+3].match(/Jan|Feb|Mar|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/))){
        for (t = 0; t < H_word.length; t++){
        H_flag[H_word[t]] = false;
        }
        H_total++;
    }
    if(!(H_flag[H_word[h]] == true)){
       if(isNaN(H_hindo[H_word[h]])){
            H_hindo[H_word[h]] = 1;
            H_flag[H_word[h]] = true;

       }else{
            H_hindo[H_word[h]]++;
            H_flag[H_word[h]] = true;
       }
    }
}

}

function Arithmetic()
{

messenger = Components.classes["@mozilla.org/messenger;1"].createInstance();
messenger = messenger.QueryInterface(Components.interfaces.nsIMessenger);
uri = GetFirstSelectedMessage();
subject = messenger.messageServiceFromURI(uri).messageURIToMsgHdr(uri).messageKey;

newfile=convertURIToFilePath("file:///H:/Documents and Settings/fujii/Application Data/Thunderbird/Profiles/7fe4tlfj.default/Mail/Local Folders/"+subject+'/');
newfiles = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
  if (!newfiles) return false;
newfiles.initWithPath(newfile);


var NewWord = readFrom(newfiles);
var N_word = NewWord.match(/\S+/g);
var S;
var H;
var SH=0;
for (n =0; n<N_word.length; n++){

if(isNaN(S_hindo[N_word[n]])){
  S_hindo[N_word[n]]=0;
}
if(isNaN(H_hindo[N_word[n]])){
  H_hindo[N_word[n]]=0;
}
S=S_hindo[N_word[n]]/S_total;
H=H_hindo[N_word[n]]/H_total;
if(S+H>0.01){
 if(S <0.01){
              S=0.01;
        }
 if(H <0.01){
              H=0.01;
        }
    S=Math.log(S);
    H=Math.log(H);
    SH +=(H-S);
  }
}
if(SH>=300)return 0;
if(SH<=-300)return 1;
SSHH = Math.exp(SH);
HS = H_total/S_total;

return(1/(1+(HS*SSHH)));

}


function Indicate_Spam_Rate()
{
Get_Word_Event_Probability();
alert(Arithmetic());
newfiles.remove(true);

}

convertURIToFilePath.js

function convertURIToFilePath(aURI) {
 
 const ioService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
 var fileHandler = ioService.getProtocolHandler('file').QueryInterface(Components.interfaces.nsIFileProtocolHandler);
 var tempLocalFile = fileHandler.getFileFromURLSpec(aURI); // 「 URL 文字列からファイルを得る」機能
 
 return tempLocalFile.path;
  // ファイルのパスを帰す
}

readFrom.js

function readFrom(aFile) // nsILocalFile の形でファイルオブジェクトを渡す
{
 var stream = Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream);
 try {
  stream.init(aFile, 1, 0, false); // open as "read only"

  var scriptableStream = Components.classes['@mozilla.org/scriptableinputstream;1'].createInstance(Components.interfaces.nsIScriptableInputStream);
      scriptableStream.init(stream);

  var fileSize = scriptableStream.available();
  var fileContents = scriptableStream.read(fileSize);

      scriptableStream.close();
      stream.close();

   return fileContents;
   
   }
   catch(e) {
      return null;
   }
}

第八章 参考文献

  1. エージェントアプローチ 人工知能 Stuart Russell・Peter Norvig 著 古川康一 監訳 共立出版
  2. 人工知能システムの構成 基礎からエージェントまで 小倉久和・小高知宏 著 近代科学社
  3. マッチ箱の脳(AI) 使える人工知能のお話 森川 幸人 著 新紀元社
  4. 改訂第3版 JavaScriptポケットリファレンス Pocket reference 古籏 一浩 著 技術評論者
  5. ニューラルネットワーク入門 http://mars.elcom.nitech.ac.jp/java-cai/neuro/kindof.html
  6. 決定木による分類モデルとは? http://musashi.sourceforge.jp/tutorial/mining/xtclassify/model.html
  7. スパムへの対策 ---A Plan for Spam http://www.shiro.dreamhost.com/scheme/trans/spam-j.html
  8. Mozilla develop center http://developer.mozilla.org/ja/docs/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8
  9. Firefox/Thunderbird用拡張機能の開発ノウハウ紹介 http://piro.sakura.ne.jp/xul/doc/mj_seminar2/
  10. XPCOM Interfaces http://www.xulplanet.com/references/xpcomref/