Node-REDでWatson NLCの学習と分類をする

## はじめに
Node-REDでNLC(IBM Watson Natural Language Classifier)のチャットボットが作りたかったのですが、前提として学習させなければならないので、共通課題として、学習のさせ方と分類についてを、切り出して投稿しておきます。

### 前提
- IBM IDを持っていて、Bluemixにログインができる状態。
- BluemixでNode-REDを作成していて、アクセスできる状態。まだの場合：[Bluemixでnode-redを立ち上げる](https://qiita.com/KURO-BLACK/items/77af2c98940320ca6ce9)
- NLCの仕組みを理解していることが望ましいですが、していなくても問題ありません。

## NLCの作成
[IBM Bluemix](https://console.bluemix.net/)にログインし、カタログからNatural Language Classifierを選択します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/ee817798-2ff9-55c5-52a7-547c7bb11e80.png" width=80%>

価格プランを見ると、1インスタンス、4トレーニング、1000呼び出しまでが無料とあります。今回は1度試してみる程度ですので、無料枠でおさまる計算ですね（投稿時点。最新は公式でご確認ください）。なおサービス名は何でもよいのですが、自分はあとからわかるような名前で入力して、作成するようにしてください。

## サービスのバインド
[Bluemix Console](https://console.bluemix.net/)より作成済のNode-REDを開き、『接続』から『既存に接続』を選択し、先ほど作成したNLCを指定します。
![IMG_0250.PNG](https://qiita-image-store.s3.amazonaws.com/0/192662/d4dd0bc9-2cf8-969f-040a-e9f00b064088.png)

前項『NLCの作成』をせずここで『新規に接続』しても同じ結果になります。

## Node-REDの開発
### Training
さっそくNode-REDのパレットよりNLCを見つけて、配置します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/1b272982-e11f-b3c3-e8ae-8b11c9dc379a.png" width=20%>

ダブルクリックで開き、ModeをTrain、LanguageをJapaneseとしておきます。名前は何でもいいです。バインドされているので、これでNLCの呼び出しが可能です。ちなみに複数バインドされていた場合、新しい方に接続されるようです（仕様未確認）。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/fb06b086-4708-3993-1e40-f709593ed813.png" width=50%>

次に、学習するデータを用意します。機械学習における教師データとか呼ばれるものですね。公式文書を見ると、学習データはcsvをUTF-8で用意し、1カラム目にTextを、2カラム目にClassを記載し、カンマで分割しなさいとあります。用意されているNode-REDのノードでは、以下のように投入すれば学習されますので、最後の3つだけ意識しておいてください。ここではテーマを携帯ショップのチャットボットとしてさらりと済ませてしまいますが、やり始めると深いところですので、機会を見つけて別の記事で紹介したいと思います。

``` Node-RED:training_data
こんにちは,挨拶
こんばんは,挨拶
はじめまして,挨拶
よろしく,挨拶
どうも,挨拶
新規契約したい,新規契約
携帯電話がほしい,新規契約
契約したい,新規契約
乗り換えがしたい,MNP
番号を継続したい,MNP
MNPがしたい,MNP
解約したい,解約
携帯をやめたい,解約
契約解除したい,解約
```

我ながら、例えの悪いテーマです。これを、今回はTemplateノードに仕込んで学習させてみます。パレットからTemplateをドラッグしてドロップ、開いて上のテキストをテンプレートに貼り付けます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/e21f1b53-0af9-e905-4746-89c2192a1944.png" width=50%>

完了を押して戻ると、以下のように名前が適用されています。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/af2eff2c-b490-7483-17a1-b65f6659cd8f.png" width=50%>

これだけではNode-REDは、いつ動いていいかわからないので、トリガーをInjectノードで教えてあげます。timestamp??気にしないでください。今回は学習データ投げるきっかけとしてのみ動作しますので、中身は無関係です。さらに学習をしたあとにできる分類器（NLCの実体）の情報が必要になるので、Debugノードを配置してから、トリガーをキックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/1e57b2fe-2905-f69e-c5b2-73680e0f2331.png" width=80%>

『デプロイ』したあとに、timestampの左側にあるボタンを押してみてください。下記のメッセージが出ると思います。※これは冒頭の価格プランで見た『トレーニング・イベント』にあたります。むやみに押さないよう注意してください！
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/b0e03d3b-a66d-3a93-45d4-39130bebd09c.png" width=50%>

同時に、デバッグタブには下記のようなメッセージが表示されますので、内容を控えておいてください。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/909d88c1-e826-5e8e-31db-e720f49bb180.png" width=50%>

トレーニングは数分から数十分待たされますので、その間に他のノードを開発してしまいます。せっかくなのでトレーニングのノードは残し、コメントをつけておきましょう。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/f3c32c7c-60b0-79e4-62b5-b7caca77514b.png" width=80%>


### Classify
NLCとはその名の通り、自然言語の分類サービスです。この『Classify』が分類であり、学習済のNLCを呼び出し、分類することになります。準備するのはTraining同様、パレットに用意されたNLCのノードです。先ほど、Trainingの際にDebugノードに吐き出された"classifier_id"を入力し、完了を押してください。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/0b8d760f-e427-d71b-aa46-4a4facff4094.png" width=50%>

Training同様に、InputとOutputを作っていきます。通常、アプリケーションとしてはUIとしてWeb画面やメッセージングアプリとの接続をしてやる必要がありますが、長くなるので割愛し、InjectとDebugノードを使って済ませます。LINEやSlackなどのアプリと接続したい方は、下部の記事を参考に、結合していただければと思います。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/2a2b88d6-5376-f27b-8af8-f5eb80268b06.png" width=80%>

ここで、Injectノードは先ほどとは違い、分類したいテキストそのものを送信する必要がありますので、開いて『ペイロード』に分類したいテキストを記載します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/894a3cf6-d45a-d3ff-7fe9-2b6a6ba3e2a3.png" width=50%>

完了を押してノードを接続、デプロイしたあとに『こんにちは』の左にあるボタンを押してみましょう。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/7f06857d-4196-bb19-7323-0cdc7c2a19e5.png" width=80%>

先ほどと同じようにメッセージが、画面上とデバッグタブに表示されたと思います。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/98cecfef-b1fc-054b-a626-f88a267b0c1c.png" width=50%>

msg.payload.top_classが『挨拶』ですね。『こんにちは』は学習データにそのものが存在したので、msg.payload.classes[0].confidenceより、NLCの確信度(confidence)が1（100％）で返却されていることがわかります。学習データそのものであくても1が返ることもありますが、いずれにせよ学習データと非常に近いものだと理解してください。

### Answerとの紐付け
Injectより日本語を入力すると、Classifyしてくれるところまでできました。次に、分類されたClassに対応する回答を紐づけるノードを追加していきます。一般的にはDBサービスを使うことになりますが、今回は簡易に、Switchノードで実現します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/581dac59-3607-286f-c3aa-1f845da04707.png" width=30%>

Switchノードを開いて、下記のように設定します。先ほどデバッグタブで確認した通り、msg.payload.top_classに『最も確からしい分類結果』が格納されていることがわかりましたので、ここの値によって、処理を変更するというルールにします。otheriseは発生しない想定ですが、一応書いておきます。また複数の条件を満たすことはありませんので、『最初に合致した条件で終了』としておきます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/3bb7ae39-3258-234d-8ea7-9ff1c0fce75d.png" width=50%>

このSwitchノードを配置すると、以下のように分岐ができます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/b7945a3e-ed57-22c1-154a-b9d4359a1b1b.png" width=80%>

さらに分岐した先にChangeノードを配置し、回答を紐付けてみます。以下は『挨拶』に分岐された先に接続するノードです。これを例に、5つのChangeノードを配置してください。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/29851c7a-a45f-0e4a-d0b2-75981e7afc83.png" width=50%>

このようになったら完了です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/81aa9a3b-bde4-2413-c328-dbbf8508f5ed.png" width=80%>

再度こんにちはの左にあるボタンを押してみます。Classと紐付けた回答が格納されていることがわかります。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/73ab14cd-34fc-8766-b7d4-ee82d4bb5230.png" width=50%>

こんにちはだけじゃ面白くないので、Inputを『解約したいんだけど』に変更してみましょう。Injectノードのペイロードに文字を入れ、完了 → デプロイをし、ボタンを押します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/2b1b5cda-6e82-2488-3dec-ffa90dd6700a.png" width=50%>

解約の分類に適応した回答が返されました。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/e6936398-c192-242b-349c-cd9404299cf1.png" width=50%>

ちなみにConfidenceは0.98とのこと。『解約したい』が学習データに存在したので、さすがに間違えなかったようです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/192662/b630e13f-a427-2014-5d8b-60f85da67b13.png" width=50%>

## LINE@との接続
今回は手抜きでInput/Outputを、それぞれInject/Debugノードで実装しましたが、チャットボットの場合UIの開発が必要になります。下記を参照するとLINE＠での接続ができますので、よかったら結合してみてください。

[Watson ConversationでLINEのチャットボットを作ってみる（前編）](https://qiita.com/KURO-BLACK/items/9eba2d49ff79f3778583)
[Watson ConversationでLINEのチャットボットを作ってみる（後編）](https://qiita.com/KURO-BLACK/items/923830d259a5e12cad5b)

## おわりに
NLCの使い方ということでざっと書いてきましたが、学習データの作り方やチャットボットにおけるテーマやスコープの切り方にはあまり触れられませんでした。各々重要な点ですので、どこかであらためて触れたいと考えています。