まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:nlc

この記事の最新版です:
ノーツでワトソンを体験!

上記記事は「IBM ノーツのデータベースコンテンツを IBM Watson の NLC(Natural Language Classifier)に学習させた上で問い合わせを行う」という内容でした。アクセスログを見る限り、そこそこの反響があったブログエントリでした。

が、ある時を境にして、この記事で提供していたサンプルが動かなくなってしまいました。直接の原因は別のブログエントリでも紹介した IBM Watson 側のセキュリティ仕様変更でした:
"javax.net.ssl.SSLException: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 64" エラー


上記記事でも紹介していますが、この回避策の1つがプロクシー的なサービスを作る、というものでした。今回、そのプロクシーサービスを IBM Bluemix 上に作った上でサンプルを改良しました。
2016111101

新しいサンプルはこちらです。使い方は変わっていません:
http://dotnsf.blog.jp/nlcdemo.zip

参考程度に、以前のサンプルはこちらです(注 現在は正しく動きません ノーツ9の FP8 を適用することで動くようになりました)
http://dotnsf.blog.jp/nlcdemo.old.zip



新しい nlcdemo.nsf では、リクエストを全て http://watsonapiproxy.mybluemix.net/nlcproxy 経由で Watson に送信するようにしています。この方法で JDK 1.6 からの HTTPS リクエストをエラーなく実行できるようにしています。




この記事の続きです:
Watson API Explorer の使いかた

上記記事で Watson API Explorer サービスの紹介をしました。今回はより実践的に Watson API を使ってみます。

今回対象にする Watson API は上記記事でも紹介した Natural Language Classifier (以下 NLC)とします。前回は学習前の(空の)データを確認しただけですが、今回は実際にデータを学習させた上で、学習データに対して問い合わせをする、という一連の機能を Watson API Explorer で確認する、という手順を行います。

この手順を紹介する上で、あらかじめ NLC サービスインスタンスを Bluemix 上に作成し、認証情報(username と password)を取得しておく必要があります。その手順については上記前回の記事を参照してください。

加えて今回はデータを学習させる手順が含まれるので、サンプルの学習用データを用意しました。以下のリンクをクリックして、nlc_api_training.zip をダウンロード&展開してください:
http://dotnsf.blog.jp/nlc_api_training.zip

展開すると2つのファイルが出来上がります。いずれもテキストファイル(JSON ファイルと CSV ファイル)なので、興味のある人はテキストエディタで中身を確認してみてください:
2016063001


では実際に Watson API Explorer で NLC を使ってみます。まずは NLC API のページに移動します:
https://watson-api-explorer.mybluemix.net/apis/natural-language-classifier-v1

そして取得済みの username と password を画面右上欄に入力します。これで準備完了:
2016063002


最初にデータを学習させてみますが、その前にまだ何も学習されていないことを確認しておきましょう。現在の状態を確認する API はリストの一番上にある GET /v1/classifiers です。ここをクリックして展開します:
2016063003


この API の説明やパラメータ、実行結果の意味などが表示されますが、この API はパラメータなしで実行するので、特に何も指定する項目はありません。そのまま "Try it out!" ボタンをクリックして実行します。するとこの API が実行され、その結果(Response Body)を見ると "classifiers" が空配列([])になっており、まだ何も学習されていないことがわかります:
2016063004


なお、この上記画面内の "Request URL" を見ると、同じ処理を curl で実行する場合のコマンド内容を確認できます。また "Response Headers" には REST API 実行結果に含まれている HTTP ヘッダの内容を確認することもできます。

もしもこのコマンドの実行結果が空配列ではなく何か含まれていて、次の学習コマンドを実行する前に内容をリセットする場合は、API リストの下から2番目にある DELETE /v1/classifiers/{classifier_id} を実行して現在の学習内容を削除できます。その方法は最後に紹介しますが、ここでは現在は何も学習していない状態であるとして以下を紹介します。

では NLC に学習データを送信してみましょう。新しいデータを学習させる場合の API は上から2番目の POST /v1/classifiers を使います:
2016063005


パラメータの説明を見ると、この API の実行には2つの情報を(POST データとして)与える必要があると書かれています。1つは training_meta_data という名前の JSON データで、もう1つは training_data という名前の CSV データです。実はこれらのサンプルが上記でサンプル zip ファイルを展開した中に含まれていた2つのファイルです。

training_meta_data のサンプルが demo_metadata.json です。サンプルファイルの中身は以下のようになっているはずです:
{"language":"ja","name":"dotnsf_nlc_demo"}

非常にシンプルな内容の JSON テキストです。"language" はこの後の学習データに使われている言語(日本語なので "ja" を指定)、また "name" はこの学習データに付ける名前(この例では "dotnsf_nlc_demo")です。"name" の内容は適当に変更しても構いません。

もう1つの training_data のサンプルが dwj.csv です。 これが学習データに相当するもので、こちらもテキストエディタで開くとわかりますが、以下の様な内容の CSV ファイルです:
Bluemix の Auto-Scaling サービスは、ターゲット環境の・・・,cloud
この記事では、IBM DevOps Services で使用されるスプリント・・・,cloud
  :
  :
Java 8 には、より簡単にプログラムを作成できるように・・・,java
  :
  :
ほとんどの Linux システムでは、仮想マシン (VM) を作成およびサポートするための・・・,linux
  :
  :

CSV の1行は2つだけの列で構成されており、1つ目が本文、2つ目は本文のカテゴリーになっています。つまり「(カテゴリー)の例として(本文)がある」ということを学習データとして与えています。これを1つのカテゴリーについて充分な(この dwj.csv では1つのカテゴリーにつき約100個の)本文を与えて、それを元に学習させている、ということです。

もう少し細かく説明すると、与えた本文は(training_meta_data で指定した「日本語」のルールで)単語に区切られ、品詞に分類した上でその出現頻度や傾向などから「カテゴリ(例えば cloud)とは、こういう特徴を持ったものだ」ということを自分で判断・理解して学習させています。このような例をカテゴリごとに大量に用意して、(上記サンプルでは)cloud とはこういうもの、java とはこういうもの、linux とはこういうもの、・・・といった内容を学習させる、そのための学習元データになっています。

したがって、上記の dwj.csv ファイルはそのままでも動くサンプルですが、新しい情報を書き加えたり、新しいカテゴリのデータを加えて与えたりしても動きます(更新後の内容を学習します)。興味があれば自分なりにカスタマイズしてみてください。


改めて、この2つのサンプルファイルを使って NLC の学習 API を実行してみます。Watson API Explorer のリスト上から2番目の POST /v1/classifiers を展開し、training_meta_data に demo_metadata.json を、training_data に dwj.csv を指定して、"Try it out!" をクリックします:
2016070101


すると指定した2つのファイルがアップロードされ、学習用の分類器(classifier)が新たに1つ生成されて学習が開始されます。"Response Body" にはこの新たに作成された分類器を識別するための ID("classifier_id"、以下の例では "2374f9x69-nlc-8772") が含まれているのでメモしておきましょう。また現時点では "status" が "Training" となっていることもわかります。これは「この分類器はまだ学習が終わっていない状態である(問い合わせできる状態にはなっていない)」ことを意味しています。なので学習が完了するまではしばらく待つ必要があります:
2016070101


なお上記の curl コマンドを見ると、2つのファイルが multipart/form-data 形式でアップロードされていることがわかります。実際にこの部分を REST API で作る際には multipart/form-data で POST するように実装する必要がある、ということもわかります。またメタデータで指定した "name" ("dotnsf_nlc_demo")はこの API の実行結果に現れていることもわかりますね。


特定の分類器の学習が完了しているかどうかを確認するための API も用意されています。リストの1番下にある GET /v1/classifier/{classifier_id} という API です。この API を展開し、パラメータの classifier_id 欄に先程作成した分類器の classifier_id(この例では "2374f9x69-nlc-8772") を指定して "Try it out!" ボタンをクリックします:
2016070102


実行結果の "Response Body" を確認します。下の結果ではまだ "status" が "Training" となっていて、学習が完了していないことがわかります:
2016070103


しばらく(ケースバイケースですが、15~30分程度)待って、この API を実行し、"status" が "Available" となっていれば与えたデータの学習が完了したことになります。こうなると学習済みの分類器に対する問い合わせが可能になります:
2016070105


なお、この状態で再度最初の GET /v1/classifiers API を実行すると、(最初に実行した時の結果は空配列でしたが)先程新たに生成した分類器が実行結果に含まれて返ってくることがわかるはずです:
2016070104


さて、学習が完了したので、Watson NLC に問い合わせを実行してみましょう。リストの上から3番目の GET /v1/classifiers/{classifier_id}/classify か、または4番目の POST /v1/classifiers/{classifier_id}/classify を使って問い合わせを行います。この2つの違いは HTTP メソッド(GET か POST か)と、問い合わせテキストの送信方法(パラメータかリクエスト本文か)です。どちらでもいいのですが、今回は後者の POST /v1/classifiers/{classifier_id}/classify を使ってみましょう。

リスト内の POST /v1/classifiers/{classifier_id}/classify を選んで展開し、classifier_id に作成した分類器の classfier_id(この例では "2374f9x69-nlc-8772")を、body には Watson NLC に問い合わせさせたい日本語テキスト文書を、それぞれ入力します。

今回問い合わせるテキストは「RedHat だけでなく Ubuntu も勉強しないとね」というものにします(変更しても構いません)。この日本語の自然言語テキストを先程学習させた NLC に対して分類をリクエストし、学習時に与えたデータに基いて「学習データに使ったカテゴリでいえば、どのカテゴリに属するテキストであるか?そしてそれはどのくらいの確信度があるのか?」を問い合わせます。

なお body には JSON テキストを指定する必要があり、そのテンプレートが右側にあるので、その内容に沿って、以下のように body を用意する必要があることに注意してください:
{
  "text": "RedHat だけでなく Ubuntu も勉強しないとね"
}

2016070106


そして最後に "Try it out!" をクリックします。正しく実行されると、以下の様な JSON テキストが "Response Body" に返ってくるはずです:
2016070101


ちなみに "Response Body" の全文はこんな感じでした:
{
  "classifier_id": "2374f9x69-nlc-8772",
  "url": "https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/2374f9x69-nlc-8772",
  "text": "RedHat だけでなく Ubuntu も勉強しないとね",
  "top_class": "linux",
  "classes": [
    {
      "class_name": "linux",
      "confidence": 0.5345447969025622
    },
    {
      "class_name": "xml",
      "confidence": 0.17404873174100038
    },
    {
      "class_name": "cloud",
      "confidence": 0.09516428245259624
    },
    {
      "class_name": "opensource",
      "confidence": 0.07239515901217708
    },
    {
      "class_name": "web",
      "confidence": 0.0611971709641311
    },
    {
      "class_name": "java",
      "confidence": 0.04321802457711143
    },
    {
      "class_name": "mobile",
      "confidence": 0.019431834350421725
    }
  ]
}

実行結果に相当するのは上記の赤字部分です。これを表形式でまとめると以下の様な結果だった、ということになります:
分類結果順位分類結果確信度(%)
1linux53.45447969025622
2xml17.404873174100038
3cloud9.516428245259624
4opensource7.239515901217708
5web6.11971709641311
6java4.321802457711143
7mobile1.9431834350421725


1位は約 53.45% という確信度を以っての "Linux" でした。7つのカテゴリからの選択で 50% 以上の確信があるということはかなり高いと言えます。また人間の普通の感覚としても「RedHat だけでなく Ubuntu も勉強しないとね」というテキストの分類結果が Linux というのは、自然な(正しい)結果であるように感じます。 改めて注目していただきたいのは、問い合わせ本文には一言も Linux という単語はなかったのに、Linux という分類結果が高い確信度と共に得られている、という点です。


最後に、滅多に使わないかもしれませんが、作成した分類器が不要になった場合に削除する方法も紹介しておきます。リストの下から2番目にある DELETE /v1/classifiers/{classifier_id} を展開し、classifier_id パラメータに自分の ID(この例では "2374f9x69-nlc-8772")を指定して "Try it out!" をクリックします:
2016070102


実行が成功しました。が、成功した場合は特に "Response Body" には削除されたかどうかがわかる情報は含まれてない感じ:
2016070103


本当に消えているかどうかは、一番最初のステータス確認 API を再度実行して、classifier_id が消えていることを確認する必要があります。↓こうなっていれば消えています:
2016070101


以上、Watson API Explorer を使って NLC を体験してみました。NLC がどんなものか、なんとなく理解できましたかね。

まあ、個人的には「curl でやっちまった方が早いじゃん」とも思ってますが、コマンドラインに慣れない人もいるだろうし、こういう Watson API Explorer のようなウェブインターフェースが用意された背景にはそれなりの需要があったのではないかと考えています。加えて、ドキュメントと動作確認機能が統合されているのは確かに便利ですよね。



なお、NLC の API そのものの詳細については以下のリファレンスを参照ください:
http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/natural-language-classifier/api/v1/


 

(注 ノーツ9の FP8 を適用することで、この記事のままでも正しく動くようになりました)

注 この記事の内容は作成当初の状況から変化があり、サンプルが正しく動かなくなっています
   新しい記事はこちらです http://dotnsf.blog.jp/archives/1062359514.html 



全国のノーツファンの皆様、こんにちは。そしてご無沙汰しております。

この度 IBM ノーツクライアントを使って、IBM Watson の学習機能や問い合わせ機能を体験できるサンプル NSF ファイルを作って公開してみました:

(注 動くように変更したサンプルはこちらです)



最初にお断りを。このデータベースで実際に Watson を動かして利用するには IBM Bluemix のアカウントが必要です。アカウント作成から30日間は無料で利用できたり、無料期間終了後にも無料枠が用意されていたりします。まだお持ちでない場合はぜひこの機会にアカウントを作成してみてください:
https://console.ng.bluemix.net/registration/


加えて、この記事で提供しているノーツのサンプルデータベースは(当たり前といえば当たり前ですが)ノーツクライアントがないと開くことはできません。ノーツクライアントをお持ちでない場合は、こちらのリンクなどからトライアル版をダウンロード&インストールするなどしてご用意ください。

以下、有効な IBM Bluemix アカウントをお持ちで、かつノーツクライアント導入済みであるという前提で紹介します。


利用にあたっては上記 URL からファイルをダウンロード&展開して、nlcdemo.nsf ファイルをノーツ9クライアントで開いてください(ノーツ9で動作確認してます)。なお ACL はデフォルトで管理者にしているので Domino Designer でも開けるはずです。設計に興味ある方は色々調べてください。改変上等!

使い方は NSF ファイル内の「アプリケーションの使い方」にも記載していますが、一応簡単にこちらでも概要と併せて紹介しておきます。

このノーツデータベースは「Watson NLC のデモ」を目的に作成しました。NLC は Natural Language Classifier の略で、IBM Bluemix を通じて提供している Watson API の1つです:
2016061001


NLC はその名が示す通り「自然言語(Natural Language)分類(Classify)」の API です。自然言語のテキスト文書を与えると、あらかじめ学習させた内容に基いたカテゴリに分類し、その結果を確信度合いの数値と共にアウトプットする、というものです。もちろん日本語に対応しています。この API の資料や価格情報などは以下を参照ください:
https://console.ng.bluemix.net/catalog/services/natural-language-classifier/

2016061002


実際にノーツのサンプルデータベースを使うには NLC の接続情報(インスタンスに接続するためのユーザー名とパスワード)が必要になります。ノーツクライアントで「アプリケーションの使い方」を開いて、NLC のインスタンスを作成し、その作成したインスタンスに接続するための username と password を確認してください:
2016061201


一方、ノーツのデータベース、特に「カテゴリビュー」と呼ばれる見出しで分類された一覧を持つデータベースはノーツで多く使われています。上記のサンプル NSF の CatView ビューでは IT 関連の日本語テキスト文書が約 700 件登録されており、それぞれの内容が7つのカテゴリに分類されて表示されているはずです:
2016061202

※ちなみにこのデータベースの中身は IBM developerWorks の技術カテゴリと文書をインポートして使っています


今回はこのカテゴリビューの内容をそのまま NLC に学習させます。例えば "Cloud" のカテゴリに分類されている約100件の文書の本文を使って "Cloud" というものを教えます。同様に "Java" カテゴリの文書を使って "Java" を教え、"Linux" カテゴリの文書を使って "Linux" を教え、・・・ といった具合です。

ここで重要なことは「一般論を教えるのではなく、あくまでこのデータベース内の(カテゴリビューの)情報だけを元に各用語を学習させる」ということです。なので NLC が例えば "Cloud" をどう解釈するのかは、このビュー内の "Cloud" カテゴリに属している文章の本文の内容と量、そして質にかかってきます。他の用語についても同様です。


ノーツは社内システムで使われることが多いため、社内業務の情報がまとまっているものです。場合によってはいわゆる「社内用語」の情報もカテゴライズされてまとまっていることもあると思います。そういった社内業務や社内用語を Watson NLC に覚えさせる、ということをイメージしてます。



この学習の際に IBM Bluemix のアカウントが必要です。上記の手順で確認した Watson NLC の接続情報としての username と password を、ノーツデータベース内の CatConfigView ビュー内にあるプロファイル文書に設定する必要があります。この辺りの手順は同DB内の「アプリケーションの使い方」を参照ください。
2016061203


Watson NLC の接続情報が設定できれば、CatView 内の文書をカテゴリごとに学習する準備が整ったことになります。同ビュー内の文書やカテゴリを編集してからでもいいのですが、変更しなくても学習は可能です。
なお、同ビューの内容やカテゴリを変更したり新しい文書を作成する場合は、必ずカテゴリを入力してから保存(編集モードで ESC キー)してしてください。カテゴリが入力されていない状態で保存すると、Watson への問い合わせが実行されるようにサンプルを作っているためです:
2016061204


Watson NLC への学習はノーツの「アクション」メニューから行います。まずは念のため学習状態をリセットしておきましょう。同データベースを開いている状態でメニューから アクション - LearningClear を実行して Watson NLC をリセットします:
2016061201


では実際に CatView の内容をそっくりそのまま Watson NLC に学習させてみます。メニューから アクション - LearningUpdate を実行します。これで CatView の全カテゴリの内容を、そこに属している文書の内容を使って学習します:
2016061202


Watson NLC の学習には少し時間がかかります(環境や状況にもよりますが30分弱)。学習状態を確認する方法を紹介します。まずメニューから ツール - Java デバッグコンソールの表示 を選んで、Java コンソールを表示します:
2016061203


Java コンソールはこのように表示されます。画面内をクリアにするには "Clear" を、コンソールを非表示にするには "Close" をクリックします:
2016061206


Java コンソールが表示されている状態でメニューから アクション - LearningStatus を実行します:
2016061205


すると Watson NLC に学習させた内容が現在どのようなステータスか(まだ学習途中なのか、既に学習済みで問い合わせ可能な状態になっているのか)を知ることができます。色々表示されますが、下図のように status = Available という表示になっていれば学習は完了し、問い合わせができるようになっていることを示しています(学習中の場合は status = Training と表示されます):
2016061204


学習が完了したことが確認できたら、今度は問い合わせを行います。学習に使っていない新しい文書を作った時に、その文書がどのカテゴリに属するのがふさわしいのかを人間が判断して入力するのではなく、学習した Watson NLC に問い合わせて(自動的に)判断させた上で保存する、という機能も実装しています。要は本文だけを入力すれば自動的に(既存データを使って学習した内容を元に)カテゴリを判断して決めてくれる、ということが可能になります。社内データを元に学習させているので、そのカテゴリが社内用語のように一般的には知られていないような用語であっても自動分類が可能です。


試しにこのような文書を CatView 内に新規に作成してみます。本文には「RedHat だけじゃなく、Ubuntu も勉強しないとね」という内容を入れ、カテゴリをわざと空にしています。この状態で ESC キーを押して保存すると、学習済みの Watson NLC に対して問い合わせが行われて、既に学習されている7つのカテゴリのどこに属するのがふさわしいのかを自動で判断させてみます:
2016061201


実際に保存すると(問い合わせをしているので少し時間がかかりますが)、文書が保存されます。(ビューが更新されてないので)おそらく一番下に(カテゴリ無し)として保存されていますが、実際の文書を確認すると "Linux" カテゴリに属していることが分かります。つまりこの内容は "Linux" の文書だと判断された、ということです。本文の中には一言も "Linux" という単語は含まれていなかったのですが、これまでに学習した内容から「これは Linux の文書だ」と判断された、ということを意味しています(なおビューを更新すると、この文書は Linux カテゴリの最後尾に移動するはずです):
2016061202


またこの時に Java コンソールを開いていると、実際に問い合わせしている様子を確認することができます。コンソールの最後の部分を見ると、この内容では 93.5% の確率で Linux だ、と判断されていたことが分かります。以下2位が約 1.7% で XML 、約 1.3 % で Web、といった感じで分類されていたことがわかります:
2016061203


これが Watson NLC の問い合わせ結果です。Watson NLC はあくまで与えられたテキストを学習済みのエンジンに対して問い合わせし、その結果を数値根拠と併せて返す、という機能だけを持っています。なのでその結果の1位だけを採用するのか、2位までを採用するのか、数値結果が特定の閾値を越えたもの全て採用するのか、・・・といった実際のアプリケーション挙動に関しては、開発者側で決めて実装することができるというものです。


以上がサンプル NSF ファイルの使い方の紹介でした。まずは Watson を体験する意味でもノーツユーザー様には一度使ってみていただきたいです。そして僕からもう2点お願いがあります。

まず1点目、今回提供したサンプル NSF ファイルはそのまま使っていただいても動くものを用意しています。ただし一般的に利用できるようにするため、分類の用語も "Cloud" や "Java" など一般的な IT 用語を使っています。でも上述のように Watson NLC が本当に威力を発揮するのは一般用語を学習させた場合ではなく、社内業務や社内用語を学習させて、社内システムのサポートができるようになった場合だと思っています。ある程度のデータの量がないと精度も上がらないのですが、サンプル NSF 内の文書やカテゴリを書き換えて(作り変えて)、独自のデータ文書の集まりにした場合でもこのサンプルは(その独自データを学習して動くように)作ってあるので、是非データをカスタマイズして動かしてみてほしいです。

次に、一応このサンプル NSF ファイルだけで学習から問い合わせまでの、Watson NLC の一通りの機能を体験することができるものになっています。でも Watson の本当の魅力とは、使い続けてデータを増やして、更に再学習させて、更に賢くして、また使ってデータを増やして、・・というサイクルにあると思っています。現役で使い続けているようなデータベースはもちろんですが、あまり使わなくなってしまったような業務データベースを、Watson の力で再活性化するような、そんな仕組みの一環としてこのサンプルが役立つことができたら本当に嬉しいです。



前回の続きです。

前回は機械学習のための日本語学習コンテンツを IBM developerWorks からの情報を元に生成しました。 今回はこのコンテンツを使って機械学習を行い、その上で実際にいくつか問い合わせをして期待しているような分類ができるかどうかを確認してみます。

なお、今回のコンテンツで使う dwj.csv 以外のファイルの一覧は、このエントリの最後にダウンロードリンクを用意しています。必要に応じて利用してください。


おさらいとして、今回行おうとしている作業は、以下の3段階です:
(1) 学習させるデータを収集する
(2) 収集データを学習させる
(3) 実際に利用する

前回の作業によって (1) の学習データを収集し、以下の様な2列フォーマットの CSV ファイル(dwj.csv)が機械学習用コンテンツとして手元にある、という段階になっているものとします:
React Native ゲームを作成し、・・・・・,opensource
iOS 開発用プラットフォームと・・・・・,opensource
Vagrant と PuPHPet のおかげで、・・・・,opensource
Bluemix 上にホストされる、Go ・・・・・,opensource
  :
  :
(学習コンテンツ),(分類カテゴリ)
  :
  :

このコンテンツが手元にない場合は前回の内容を参照して、用意しておいてください:
http://dotnsf.blog.jp/archives/1041438999.html


では、引き続き作業の (2) を行います。この dwj.csv ファイルの内容を Watson に学習させてみます。IBM Bluemix にログインし、Watson カテゴリの NLC(Natural Language Classifier) サービスをランタイムに追加するなどしてインスタンス化します:
2015100101


インスタンス化した後に資格情報を確認して、環境変数内の username と password の値を確認します(後で使うのでメモするか、保存しておきます):
2015100102


学習させる前に、この NLC サービスの API をリファレンスで確認しておきましょう:
http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/natural-language-classifier

2015100103

NLC には(2015/Oct/01 時点で)6つの API が用意されていることがわかります。それぞれの API の用途を簡単に紹介しておきます:
2015100104

HTTPメソッドAPI パス説明
POST/v1/classifiersコンテンツをポストして学習させる
GET/v1/classifiers現在の学習クラス一覧を確認する
POST/v1/classifiers/{classifier_id}/classify特定の学習クラスを指定して、テキストを分類する※
GET/v1/classifiers/{classifier_id}/classify
DELETE/v1/classifiers/{classifier_id}特定の学習クラスを削除する
GET/v1/classifiers/{classifier_id}特定の学習クラスの状態を確認する

※ POST と GET の違いはテキストの指定方法の違い


表の上から2番目の API は現在の学習クラス一覧を調べて確認するものです。まだ何も作っていない状態であれば一覧は空のはずです。作業前後での比較の意味で一度この API を実行してみましょう。ブラウザを開いて、以下の URL にアクセスします。なお URL 内の (username) 部分と (password) 部分は上記の NLC サービス環境変数内でメモしたものに書き換えてください:
https://(username):(password)@gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers

以下の様な画面になるはずです。 API の実行結果が JSON で返されますが、"classifiers" という変数の値は空の配列になっています。たしかにまだ学習は行われていない状態であることが確認できました。なお、このウィンドウは後でも使うので、このまま開いておいてください:
2015100104


作業 (2) の学習を行うのは、表の1番上にある /v1/classifiers への POST メソッドになります。上記リファレンスページの一番上にある /v1/classifiers への POST メソッドをクリックすると以下の様な説明が表示されます:
2015100101


これを見ると、このメソッドで2つのファイルをフォームデータとして送ることで学習指示を行うことができる、ということがわかります。2つのファイルのうちの1つは前回用意した学習コンテンツ(dwj.csv)で、これを training_data というパラメータで指定することが分かります。そしてもう1つは training_metadata というパラメータでメタデータ情報を指定する必要があることがわかります。この training_metadata で指定するファイルは以下の内容の JSON テキストファイル(training_metadata.json)を用意します(注 "dwj" 部分は名前なので任意):
{"language":"ja","name":"dwj"}

ではこの2つのファイルを使って Watson に学習させるための処理を指定する HTML ファイル(nlc_training.html)を1つローカルに用意します。上記のように /v1/classifiers に2つのファイルを POST することで学習させることができるので、それを実際に行うためのフォームを含む HTML にしています。なおテキスト内の (username) 部分と (password) 部分は上記の NLC サービス環境変数内でメモしたものに書き換えてください:
<html>
<body>
<form action="https://(username):(password)@gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers" method="post" enctype="multipart/form-data">
<table border="1">
<tr><th>Meta Data</th><td><input type="file" name="training_metadata"/></td></tr>
<tr><th>Data</th><td><input type="file" name="training_data"/></td></tr>
</table>
<input type="submit" value="submit">
</form>
</body>
</html>

この HTML ファイルをブラウザで開きます。Ctrl+O から HTML を指定するか、エクスプローラーなどからダブルクリックしたり、ドラッグ&ドロップすることでもブラウザで開くことができます:
2015100102


2つの参照ボタンをクリックして、Meta Data には training_metadata.json ファイルを、Data には dwj.csv をそれぞれ指定します。正しく指定できたことを確認して submit ボタンをクリックすると、指定した dwj.csv を元にした機械学習が開始します:
2015100103


submit ボタンをクリックした後の画面(の例)がこちら、この時点で機械学習が始まっていて、その id(classifier_id) が "FAA074-nlc-602" であることが分かります:
2015100101


この時点で上記の /v1/classifier API (学習クラス一覧)を再度実行してみます(まだウィンドウを閉じていなければ F5 でリロードします)。先程までは "classifiers" 変数の中身は空配列でしたが、今は学習中のクラスが存在しているため、結果がこのようになります:
2015100102


ここで表の一番下にある /v1/classifier/{classfier_id} への GET を実行して、この学習クラスの状態を確認してみましょう。新たにブラウザを開き、classfier_id の値を最後に指定して、以下の URL へアクセスします:
https://(username):(password)@gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/FAA074-nlc-602

するとこのような結果が表示されます。"status" の値が "Training" になっていて、この学習クラスは現時点で学習中である、ということがわかります。学習が終わるまでしばらく(今回の例であれば30分程度)待ちましょう:
2015100103


しばらくしてから同じ URL にアクセスして、この図のように "status" の値が "Training" から "Available" に変わることを確認してください。ここまでの状態になった段階で、3段階の作業の (2) までが完了したことを意味します:
2015100104



用意した日本語コンテンツによる機械学習が完了したことが確認できたので、最後に (3) の、学習させた内容を使って実際にテキスト分類ができるがどうかを確認してみましょう。

表で言うと3番目および4番目にある /v1/classifiers/{classifier_id}/classify API を使います({classifier_id} の部分に実際のクラスID(今回であれば FAA074-nlc-602)を指定する)。この API を POST で実行する時は本文で、GET で実行する時は text パラメータで、分類させたいテキストを指定して実行します。今回はブラウザでも確認できるよう後者の方法を使って確認してみます。

例えば、前回のエントリの導入部で試した「mongoDBっていいよね」というメッセージが、何に分類されるかを確認してみるには、ブラウザで以下の URL にアクセスします。メッセージを text パラメータで指定している点がポイントです:
https://(username):(password)@gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/FAA074-nlc-602/classify?text=mongoDBっていいよね

するとこのような結果がブラウザ画面に表示されました:
2015100105


見やすいように JSON に適宜改行を加えた結果がこちらです(赤字はコメント):
{
 "classifier_id":"FAA074-nlc-602",
 "url":"https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/FAA074-nlc-602",
 "text":"mongodBっていいよね", 与えたテキスト
 "top_class":"java",           最も可能性が高いと判断された分類結果(=java)
 "classes":[                   全結果とそれぞれの確信度
  {"class_name":"java","confidence":0.31087844561162503},       java = 31.1%
  {"class_name":"cloud","confidence":0.23414513131908235},      cloud = 23.4%
  {"class_name":"opensource","confidence":0.18726090536344517}, opensource = 18.7%
  {"class_name":"linux","confidence":0.14376505541140203},      linux = 14.4%
  {"class_name":"mobile","confidence":0.07936916665292562},     mobile = 8.0%
  {"class_name":"xml","confidence":0.044581295641519754}        xml = 4.5%
 ]
}

結論として、今回学習させたコンテンツをベースに「mongoDBっていいよね」というテキストを分類させると、これは "Java" に分類される可能性が最も高い(約31.1%)、と判断されました。続いて "Cloud"(約23.4%)、"OpenSource"(約18.7%)、"Linux"(約14.4%)、"Mobile"(約8.0%)、そして "XML"(約4.5%)という結果になりました。前回の話というか、当初の計画では、ここは "OpenSource" になって欲しかった所でした(苦笑)。

実際のところ、というか私個人的には「mongoDB といえばオープンソース、またはクラウドかな」という印象を持っているので、私の主観とは少し違う結果になりました。皆さんの考えとしてはいかがでしょう? 最も高い Java も 31.1% なので、その確信度としては必ずしも自信満々に回答しているわけではなさそうです。まあ、この結果を導きだすような学習コンテンツだった、ということになるんですかね。

いくつかのテキストを試して見た結果を載せておきます:
テキスト分類結果確信度(%)
mongoDBっていいよねJava31.1
Cloud23.4
OpenSource18.7
Linux23.4
Mobile8.0
XML4.5
Bluemixって知ってる?Cloud83.9
Java7.1
Mobile4.6
OpenSource3.4
Linux0.9
XML0.1
Ubuntuも勉強しなきゃLinux83.1
OpenSource5.2
Cloud5.0
XML2.4
Mobile2.1
Java2.0
人工知能は人間を超えるのか?Java34.7
Linux24.5
Cloud16.5
OpenSource16.2
Mobile7.1
XML1.0


どうでしょうね。なんとなくですが、確信度が高い(80%超え)結果は私個人の主観とも一致しているような分類ができていると思います。逆に1位でも確信度が低いと、必ずしも私の主観とは一致していないような気もしています。その意味では、そこそこな分類エンジンが出来たかな、という印象です。

以上、ここまでで作業工程の (3) も確認できました。 大作ブログエントリになってしまいましたが、現在 IBM Bluemix から提供されている日本語対応の言語分類エンジンの学習方法と利用方法、そしてオマケ的ですが、学習コンテンツの生成例まで併せて紹介しました。 繰り返しになりますが、学習コンテンツを作る際に、是非試される方の身近にあるもの(学校内/企業内のコンテンツなど)を使ってコンテンツを作った上でこのシステムを作っていただくと、その有用度についても身近でわかりやすく、もしかするとビジネス的にも有用な分類エンジンができるかもしれません。是非挑戦してみていただきたいです。


最後に、今回の2回ぶんのエントリで紹介したサンプルアプリケーション一式のソースコードを Github 上で公開しておきました。よろしければ clone なりダウンロードなりして参考にしてください:
https://github.com/dotnsf/nlc_sample


久しぶりに壮大な規模とテーマのブログに挑戦します。

最初に「何がやりたいのか」を書いておきます。例えば、
 「mongoDBっていいよね」
という日本語テキストを与えた時に、
 「それはオープンソースソフトウェアの話ですね」
と、何の話題についてのテキストだったのかを分類して答えてくれるような仕組みを作ります:
2015093001


Bluemix や Watson について、ある程度ご存知の方であれば気付かれたかもしれませんが、これを IBM のコグニティブエンジンを使って実装します。なので、実際には、
 「mongoDBっていいよね」
という日本語テキストを与えた時に、
 「それはオープンソースソフトウェアの話ですね(40%)」
 「あ、ウェブ開発の可能性もあります(30%)」
 「もしかするとクラウドの話題ですか?
(20%) それとも Linux?(10%)」
といった、他の可能性についても数値の根拠を出した上で候補を羅列してくれるような、そんな仕組みを作ってみようと思います:
2015093002


この仕組の実現には IBM Bluemix から提供されている Watson サービスの NLC(Natural Language Classifier) API を使います:
2015093003


NLC はテキストで与えられた文章の内容に対して、事前に定義(学習)したいくつかの分類クラスの中からマッチするものを選んで返してくれる、という API です。特徴としては、この「事前に定義(学習)」を自分で行うことができることと、日本語にも対応しているということが挙げられます。

作業としては、以下の3段階に分けておこないます:
(1) 学習させるデータを収集する
(2) 収集データを学習させる
(3) 実際に利用する


今回のエントリでは (1) までを行います(というか、準備します)。


さて、今回の目的は、どんな質問にもうまく分類してこたえてくれる万能ロボットを作るつもりはなく、あくまで「IT 系の会話を、どんな IT カテゴリの会話だったのか」に分類してくれるロボットを作ろうと思います。そのためには以下の2つが必要です:
[A] 会話の回答となるようないくつかのカテゴリの選定と、
[B] 各カテゴリのことを機械学習させるためのコンテンツ

例えば [A] で「Linux のことを勉強させたい!」と選ぶのであれば、どんな内容だったら Linux に関連していると判断できるのか?を学ばせるためのコンテンツが必要になる、という意味です。「Java のことも勉強させたい」のであれば、加えて Java を学ぶためのコンテンツが必要になります。 このカテゴリをどう決めて、各学習コンテンツをどうやって入手するか、というのが課題となります。

実際のビジネスで、業務データがある程度保存されているのであればそこから取り出して、業務のことを機械学習させる、というのがいいと思っています。ただ今回は「IT 系の会話」という、ある意味で一般的な内容なので、この一般的な内容をどこから取り出すか、という問題に直面します。 特にこういうブログで一般的な内容として紹介する際の高いハードルになったりします。

今回は(勝手にw)IBM developerWorks に協力してもらうことにしました。オープンな技術情報やサンプルコードなどを紹介するポータルサイトです。


特にこのページを見ると、いくつかのテクノロジーカテゴリごとの技術記事の RSS が提供されていることが分かります:
2015093004

(各 RSS フィードのリンク先(この例は Java technology))
2015093005


この仕組みを(勝手にw)使わせていただきます。要は IBM developerWorks  から提供されるいくつかのカテゴリごとの RSS を元に、(Java とか Linux とかモバイルとかの)カテゴリ毎の記事内容を取り出して、機械学習用コンテンツを作ることにします。

詳しくは次回紹介予定ですが、今回作る学習コンテンツは以下のような2列の CSV フォーマットで作ります:
学習コンテンツテキスト,カテゴリ


1列目の学習コンテンツテキストには、2列目のカテゴリについて学習させるためのテキストを記載します(例えばカテゴリが Java だとしたら、Java について書かれたテキスト)。必然的にある程度長いテキストになることが多いのですが、今回使う NLC API の仕様上、1文字以上1024 文字以下である必要があります。そして1度に学習させることができるコンテンツは5以上10000未満(つまり CSV 5 行以上 10000 行未満)という制約もあります。また CSV というフォーマットの特性上、学習コンテンツに改行やカンマを含めることはできません。細かくはもう少しありますが、今回の作業で問題になるとしたらこの辺りかなと思ってます。

なお、NLC の仕様についてはこちらのドキュメントを参照ください:
http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/nl-classifier/


この機械学習用コンテンツを上記の IBM developerWorks RSS から作ってしまおう、というのが今回のエントリの目的です。具体的にはこんな感じの PHP を作りました。これを PHP ウェブサーバーに(Bluemix であれば IBM DevOps Services や cf コマンドラインツールを使って)プッシュします:
<?php
// RSS を取得する対象
$sites = array( "opensource", "java", "cloud", "linux", "xml", "mobile" );

// 強制ダウンロード指定
header( 'Content-Type: application/force-download;' );
header( 'Content-Disposition: attachment; filename="dwj.csv"' );

for( $i = 0; $i < count( $sites ); $i ++ ){
  // RSS の URL
  $url = "http://www.ibm.com/developerworks/jp/views/" . $sites[$i] . "/rss/libraryview.jsp";
  
  $rss = file_get_contents( $url );
  $xml = simplexml_load_string( $rss );
  $items = $xml->channel->item;
  for( $j = 0; $j < count( $items ); $j ++ ){
    $item = $items[$j];
    $description = $item->description;

    // カンマを大文字に&改行を無視
    $description = str_replace( ",", ",", $description );
    $description = str_replace( "\n", "", $description );
    $description = str_replace( "\r", "", $description );

    $len = mb_strlen( $description );
    if( $len > 0 ){
      // $description が 1024 文字を超えていたら強制的に切る
      if( $len > 1024 ){
        $description = mb_substr( $description, 0 , 1024 );
      }

      // CSV のレコードを作成
      $line = $description . "," . $sites[$i] . "\n";
      echo $line;
    }
  }
}
@ob_flush();
@flush();
exit();
?>

一応、内容を紹介しておくと、IBM developerWorks のオープンソース(opensource)、Java(java)、クラウド(cloud)、Linux(linux)、XML(xml)、そしてモバイル(mobile)の各カテゴリごとに RSS の description の内容を取り出します。そしてその中身が1文字以上1024文字以内であれば、カテゴリ名を併せて CSV の1行となって出力される、というものです(1024文字を越えた場合は対象にしていませんが、今回の RSS では超えることがないので問題ないと思っています。ただ1024文字を超える可能性のあるコンテンツを扱う可能性がある場合は、(例えば1024文字で切るなどして)対処した上で出力する、といった改良をする必要があります)。このスクリプトがブラウザから呼び出された時に強制的に(CSV の)ダウンロードになるよう、HTTP ヘッダも調整しています。


そして、同 PHP ファイルをブラウザから呼び出すと、dwj.csv という CSV ファイルが動的に作成され、ダウンロードが始まります:
2015093006


ダウンロードした dwj.csv が目的の機械学習コンテンツになっています:
2015093007


これで上記の (1) 部分が揃いました。オープンソース、Java、クラウド、Linux、XML、そしてモバイル。6つのカテゴリごとに約100件ずつの日本語コンテンツ概要を得ることができました。次回はこれを機械学習させて、その上で日本語で IT 関連のメッセージを問いかけた際に、それが正しく分類されるかどうかを実際に確認して見る予定です。


(2015/Oct/02 追記)
続きはこちらです。



このページのトップヘ