【無料ですぐに作れる】Webフォームで仕事の効率化してみませんか?こちらは、Webに関連するエンジニア向けの記事です。当社のWeb関連技術の公開と採用活動のために掲載しています。(2017年12月1日更新)みなさんこんにちは、エンジニアのMです。これは当社の技術やAIに興味のある方に向けた日誌になります。今月も毎週更新していきます、よろしくお願いします。JavaとPythonの連携をするKuromojiをPythonから扱えるようにしたい、ということでJavaとPythonの連携について覚える。参考:(Qiita)PythonからJavaを呼び出す簡単な方法[リンク]こちらで解説している「py4j」を使ってKuromojiをサーバーとして起動し、Pythonから呼び出して使えるようにする。手順Windows環境で作業する。Anacondaをインストール済みなので、まずはpipでpy4jをインストールする。Pythonインストール先のshareフォルダ(例:C:\Python36\share)にpy4j0.xx.x.jarができていることを確認。辿って「外部JARの追加」から先程の.jarファイルを指定する。これでサンプルのAdditionApplication.javaを動かして、Pythonからクラスを利用できることができた。文を投げると分かち書きして返してくれる正規表現で記号、数字は勝手に除去する品詞の組み合わせは「名詞のみ」、「全部」の2通りだけと簡素な仕様とする。"|^「+$|^」+$|^。"これはKuromojiのテストです。記号「」は除去します。これでPythonから簡単にKuromojiを扱えるようになった。サーバーとして起動している状態なので、Pythonから呼び出して繰り返し利用することができる。あとはPython側でファイル入出力のコードを用意して、目的のパスやファイルを処理できるようにすれば良い。Eclipse上でしか動かせないのは不便なので、仮想CentOSマシンで動かそうとしてみたがなかなかうまくいかず。クラスパスについてまだまだ勉強が足りないようだ。Yahoo知恵袋のデータでdoc2vecを試す昨日はKuromojiを扱いやすくしたので、今日はそれを使って実験を進めてみようと思う。検索ワード「プリンタ」、「Android」について30件ずつ手動で拾ってきて形態素解析した後、doc2vecの結果を見てみる。一つの質問についてだけ、元の文章を少し変えたものを加えて試してみた。ある程度関連のある文章を並べていて、Kuromojiが名詞と判定した単語を抽出しているので、頻度の高い単語を切る必要はほとんどない。結果として、ほぼ同じ内容のはずの文章は類似度で上のほうに来るようにはなったものの、突出しているわけではなかった。今回のような少数の文章に対してはdoc2vec単体ではあまり効果を発揮できないのかもしれない。他のアイデアと組み合わせることでの可能性を探る必要がありそうだ。情報が得られそうなワードで検索し、論文や記事から自分の目的に合った手法を見つけることを目標とする。[リンク]以上を参考にWMDの実力を試してみた。今回はJuman++のほうを使った。wmdistanceを呼び出すときは単語リストを渡す必要があるので、入力された文をその場で分かち書きするのに使っている。このプリンタでレーベル印刷はできますか?距離:21.350387439460583知恵袋のテキストで試した流れで、プリンタとAndroidに関する文で試した結果こうなった。短い一文で試したが、そこそこ妥当な結果が得られた。携帯電話を選ぶ時に気をつけるべき点はありますか?距離:3.1761431100963127物だけ変えた文の距離がこれくらいだと、あまり信用はできない気もしてくる。面倒なパラメータ調整が不要なことは大きなメリットに感じる。ターミナルでWMDを試すことができるコードを公開する。wmd()同じ文を入力してテストしてみたが、特に結果が良くなった感じはしなかった。何か一つの手法で全部解決すれば良いのだが、そういうわけでもないのが自然言語処理の難しいところか。文字ベースのCNNによる文書分類の論文があるらしいので、読んでみる。今のマシンパワーでは日本語を扱いきれないと思うが、興味はある。[リンク]結果を見ると、ユーザーの投稿内容のような、精選されていない文に対する精度が高いことが分かる。単語ベースのアルゴリズムが、誤字脱字が多く見込まれる文への対応が弱いことはイメージしやすい。あらゆる文字の組み合わせに対応する以上、モデル作成の計算量は膨大なものとなる。日本語なら文字数は少なくなるが、文字の種類が多いので結果的に英語以上に計算は困難だろう。日本語に対してもCNNで分類している研究はあるようだ。[リンク]文字を画像として扱うという方法はなるほどと思った。漢字は図形であり、似た意味の字は同じ部首を持っていたりするので、次元削減のついでに特徴を抜き出すことができれば確かに都合がいい。文書間距離の計算を別モデルについてもしてみるWikipediaエンティティベクトルだけでなく、対象のテキストデータ群から学習したベクトル値も使って文書間距離を確認する。類似度を計りたいテキストを対象として学習させたデータなので、そのデータ群に対しては汎用的なものよりはフィットしたモデルのはず。gensimの学習値は正規化済みだと分かったので、併用するにはそれぞれの距離に対する重みを考えなければならない。各文書間の距離をリストアップして眺めてみる各文書間の距離(知恵袋からの30+30文書)を全通りの組合せについて計算して、その数字を眺めて情報を得たいと思う。見やすいようにレンジを揃えてある。同一カテゴリ間の距離より、別カテゴリ間の距離のほうが大きいことが分かる。サンプル数が少なくても、確かにある程度分離することができている。ミックスすることで精度を上げられそうではあるが、2通りだと計算にかかる時間が気にかかった。ある文書に対して最も距離的に近い文書を見つけ出すような計算には、あまり向かないかもしれない。モデルが大きくなるほど、メモリの消費量も相応に大きくなる。WMD以外の方法についてまた考えてみるWMDが比較的手軽に文書分類できることが分かったが、運用時にリソースの消費がそこそこ大きそうなので他の方法も検討してみる。類似文を探すということについて類似文を検索するという行為について、自分の認識にズレがあるのではということに気づいた。Androidについて教えてくださいiOSについて教えてくださいという2つの文があったとする。「何についての話か?」という見方をすれば、AndroidとiOSなので、ジャンル・カテゴリ的には近いが違う物について聞いている。「これは類似の文か?」という見方をすれば、AndroidとiOSの部分しか違いがないので、これは明らかに類似の文である。長い文であれば関連するワードの差異によって、類似ではないという判定になるかもしれない。このような短文だけで見れば、これは間違いなく類似の文である。認識のズレというのはまさにこのことである。何についての文か、というところと、文法的に類似の文か、というところで違うのに、全部まとめて「類似文」として処理させようとしていた。比較的短い文に対して何についての文か知りたいのであれば、単純に類似文検索の手法を持ち込むのは適切ではなかった。勉強としては良かったが、もう少し目的と手法について検討しながら進めるべきだったと思う。手法について考える何を持って類似性があるとみなすか、というところが重要なポイントとなる。「家電Aは値段の割に高性能でオススメ。文体:カジュアル文の形式:商品レビューテーマ:家電Aについてのようにタグ付けできるとする。家電Aについてのレビューが欲しければ、感情・文体は関係ないのでカテゴリ・文の形式・テーマについて分類して、完全一致したものを抽出すれば良い。テーマについては未知語が該当するケースも多いと思われるので、方法について検討する必要があるかもしれない。教師データとしてタグ付けを済ませた文章から、Doc2Vecで文章のベクトル値を得る。そのベクトル値についてディープラーニングによる教師あり学習によって、適切にそれぞれ分類できるよう学習させる。分類精度は十分に上げられそうだが、この方法は人力で教師データを用意しなければならないのが悩ましい。多くないデータ量で精度を上げるには悪くない方法だとは思うのだが。この方法について実際に運用するとしたら、新規文書のベクトル値を求めた後に行列演算でタグ付けして保存するだけなので、負荷は小さく済みそうだ。大きな辞書データを保持する必要があるので、メモリ消費量はそれなりか。人手で枠組み(タグの数、種類)を決める部分も検討を重ねる必要がある。感情をプラス・マイナスの2通りから喜怒哀楽の4通りにしたい、となった場合、一から学習させなければならないからだ。テーマ分析について先日の手法で一番難しいのが、文のテーマ(何について書いている文か)を推定することである。テーマとして抽出されるのは名詞しかありえないが、その名詞をどうやって抽出するか。パターンマッチングなら「XXは」、「XXが」などの場合のXXは文のテーマである可能性は高い。パターンマッチングだけでは柔軟性に欠ける。参考になりそうな先行研究を探して、応用できないか考えることにする。主題推定は難しそう読んだのは古めの論文が主だが、分析の仕方を工夫して精度を上げようとしているにも関わらず、実用上はアテにできそうにない精度であった。それだけ自然言語を機械に理解させるのは難しいということなのだろう。教師あり学習で分類できるだけ分類し、候補を絞り込んだ後に、コサイン類似度やWMDを用いてテーマが近そうなものを選択する、といった方法でもいいかもしれない。自分で実験済みの手法で解決できる可能性があるなら、試してみる価値はありそうだ。そもそも、DNNによる分類がうまくいくかどうかもまだ分からない。Word2Vec以前の案では最初の処理としてWord2Vecを使っているので、それ以降の処理についてもWord2Vecが持つ弱点(多義語、対義語に弱いなど)の影響は続く。念頭に置いておく必要がある。Learningのこと。準教師あり学習と呼ばれたりもする。データ量が多いと人手で全部にラベルを用意することはほぼ不可能なので、この手法が利用できるなら利用したい。MLのチュートリアルなどを読みながら、サービス内容について調べてみる。半教師あり学習続き日本語でも理解できるかどうかの内容を、英語で理解するのは非常に難しい。論文によると、MNISTでは劇的な効果が得られていたが、CIFAR-10ではそれほど効果が見られなかったという。問題が複雑になるほど、工夫を重ねても少ないラベル数で学習するのは難しいと考えて良さそうだ。調べ物続きなので手を動かしたいDoc2Vec+教師あり学習の有効性を確認するために、知恵袋データ(例の60件)に対してDNNによる分類を試してみる。print(model.docvecs.index_to_doctag(i))として、必要な情報を得られることを確認。データが足りないと思われるので、100件になるまで補充する。その作業の過程で、Androidにも関係があり、プリンタにも関係がある質問を見つけた。いう場合に排他で処理してしまうと、どちらか一方でしか検索できないことに気がついた。1つの文章の中に、質問と要望、ここが良くてここが悪い、といった違う内容の文が入るケースを想定すると、こちらで完全に切り分けてしまうのは都合が悪いようだ。タグで処理する場合タグが1,000種類くらいあって、テキストが100,000個くらいあっても、1個のテキストが持つタグの数は多くて10個程度だろう(うまく分類できていれば)。ほとんどの要素が0の行列なので、scipy.sparse等のライブラリを使って「疎行列」として扱ってやれば高速に処理できる。人力で教師データのためにタグ付けするのが厳しい作業だが、機械学習で法則を数十通りも見つけ出してもらうよりは早く終わるだろう。WMDを確認データ数を100件に増やし、出現回数が極端に少ない単語のみ除外した知恵袋データに対しても、WMDを確認する。同一カテゴリ間での距離のほうが少し近いという結果だった(平均で5~7%くらい)。今回は以前より単語数も多く、100×100件分のWMDを計算させると10分以上かかっていたので、やはり大規模な処理には向いていない。GensimWindowsからpipでインストールしたGensimがうまく動かない。pip経由ではダメなのだろうか。仕方ないので、docvecsだけ抜き出してpickle化して使うことにする。ニューラルネットワークによる分類データ分割をして、学習させることはできた。あまりにもデータ数が不足しているので、学習用データにすぐオーバーフィットしてしまう。Doc2Vecの時点でかなりの情報量が削減されている上に、うまく機能しているかどうかの判断も難しい。文章の特徴抽出ディープラーニングは特徴抽出が肝なので、他に使える方法が無いか考えてみる。Word2Vec(Doc2Vec)は情報をかなりシンプルにしている分、ディープラーニング向きでは無さそうだ。TensorFlowのVer1.4がリリースされたので更新する一部コードの互換性が無くなるが、しっかり更新しておく。類似文検索のタスクはDoc2Vecで少し間が空いたので、再検討してみた。文の類似度に関しては、素直にDoc2Vecで文をベクトル化して検索したほうが良いという結論に至った。別の分類タスクを用意する場合には、他の方法について検討する必要があるだろう。[リンク]こちらを参考にチャットボットを作ってみる。類似文検索などに関するアイデアが行き詰まり気味なので、少し違うことをやって頭をリフレッシュしたいと思う。MeCabのインストール定番中の定番の形態素解析器である「MeCab」を今までインストールしてこなかった。コードを借りてきて動かすためにインストールしようとしたのだが、一部詰まってしまったのでうまくいった手順を示す。[リンク]PythonからMeCabを使ってみる。directoryと表示されて読み込みに失敗した。そこで以下の.confファイルを作成する。/etc/ld.so.conf.d/(任意のファイル名).confとして、/usr/local/libとだけ記述して保存する。参考ページの方法で直接ld.so.confにパスを書き込んでも動作したが、他の構成に倣って.confファイルを追加した。これで問題なくMeCabをPythonからimportして使うことができるようになった。本題に入ることができる。API(およびtweepy)に関する知識は一切ないので、各コードの作者に感謝しつつ実行する。今後も対話データを使う可能性を考えて多めに取得しておく。3時間程度放置した後で対話データの容量を確認したら、約1.7MBだった。仮に17MB分確保しようと思ったら、あと27時間程かかる計算だ。今日一日はこれを回し続けることにする。Computers(DNC)待ち時間を利用して調べ物をしていたら、外部記憶を持つニューラルネットワーク、DNCに関する記事を見つけた。Machine(NTM)の後継にあたるものらしい。RNNやLSTMよりもさらに記憶力の向上したニューラルネットワーク、と解釈した。チャットボットに応用したら、過去のやり取りに基づいた会話がより高い精度でできそうだ。ソースコードを見る自分でコードをいじってみる時のためにソースコードを読んでみる。軽くコードの流れを追っただけではとても理解できそうになかった。対話データの取得には時間がかかるので、その間にコードを理解できるよう頑張ってみたほうが良さそうだ。[リンク]こちらのコンパイル済み「MeCab(64bit)」と「mecab-python-windows」をインストールするのが簡単だった。「Windows」の「Python」上で「MeCab」を使う、というピンポイントな需要にたまたま応えてくれていた作者の方に感謝したい。コピーしたらうまくいきました。いうコメント欄の情報に従ってmecab.hをコピーして、インストール作業を進める。全て終わったら再起動をして作業完了。これでチャットボットの学習作業をWindows側で実行できるはず。Echo」を予約しているということなので、スキルの作り方について調べてみる。公式でも丁寧に解説されているので、至極単純なものであればそれほど苦労せずに動かすことができそうだ。ここまでで取得できた対話データを使って学習させてみるtrain.pyと同じ階層に、「data」フォルダと「generated」フォルダを作成し、data_processor.pyを実行して辞書を作成する。フォルダをあらかじめ作成しておかないと、エラーが出て止まってしまう。data_processor.pyをWindows上のPycharmから実行したところ、いつもの文字コードエラーが出た。そのため、data_processor.pyは仮想CentOS側で実行した。次にtrain.pyをPycharmから実行すると、パスが見つからないと怒られてしまう。OK!こちらのパス指定が悪かったらしい。Pycharmから実行するときは気をつける必要がある。借りてきたコードで学習させるだけなのに随分とバタバタしてしまった。1050Tiを使って、500stepあたり4分かかった。MeCab+NEologdを試してみる短めの文章に自動でタグ付けする方法として、NEologdの解析結果を利用するのはどうだろうかと思ったので試してみた。一致する名詞、固有名詞があった時には、前者のほうが重要と考える。この場合は、出現頻度が低い名詞のほうが重要な可能性が高い。機械、部品といった一般的な単語と、製品の型番や製品名のような単語では、前者のほうが結果は一致しやすく、出現頻度が高い。後者は辞書に無い単語である可能性が高いので、解析結果は一致しづらく、また出現頻度も低い。同じアイテムに関する文を検出するだけなら、形態素解析が必ずしも正確である必要は無く、間違った分割の一致を取るだけで問題ない。この方法最大の欠点は、誤字の含まれる文(特に固有名詞の誤字)を抽出できない点である。短い文に対する、簡易的な文抽出手段としての提案となる。次は具体的な実装方法について考えていく。簡単化のために辞書の使い分けは無し(NEologdのみ)誤字への対応として、レーベンシュタイン距離を使って単語の(文字)類似性を計算に組み込む計算コストが掛かると思い、レーベンシュタイン距離については特に言及していなかったが、それほどの計算量にならなさそうなので入れることにした。程々にライブラリを活用しつつ、自分で実装できるところは実装する。後々のために、単語辞書などに関わる主要な部分はクラス化した。どこまでこちらのイメージ通りに機能してくれるだろうか。ある程度融通が利くように書いているつもりなので、精度がイマイチであればtf-idfを試したりするといったこともできるはず。評価値の合計に基づき、文の類似度を計算(文の長さに差があれば補正する)やっていることがWMDに近いせいか非常に計算が遅い。類似度の算出自体は大体期待通り。小規模で短めの文という制限はつくが、精度自体は悪くないと思う。進捗データのセーブ・ロード計算式の調整、非効率な計算の改善for文やif文を駆使して実装している都合上どうしても処理が遅い。ループの組合せを工夫したり、無駄な処理が発生しないようにcontinueを積極的に使うなどして少しづつ効率化させていく。結果昨日のバージョンと比較して、辞書作成は2倍以上、文の類似度算出は4倍以上高速化できた(元が遅すぎただけでもある)。疎行列のおかげでメモリは節約できている。)レーベンシュタイン距離を使わない場合、実質的に文章内の名詞で検索をかけているのとほぼ変わらない。最低限の機能は揃って、一区切り付いたように思う。Gensimなどのライブラリを思い浮かべながら、クラス構造を考えつつ実装したのはいい勉強になった。情報収集AIや人工知能についての記事がかなり増えている印象なので、調べながら参考になりそうなものを探す。学習を回していたチャットボットを試してみる約35MB分の対話データを使って学習させた。5時間以上回してStep数39000まで進んだので、この時点で試してみた。...Twitterから取得しただけあって、やり取りもそれっぽい。UNK(未知語?)が返ってくることが多く、あまりいいやり取りはできず。データが集まったわけなので、手直しできそうであれば直してみてもいいかもしれない。記事が役立ったらクリックをお願いしますフォームズ編集部フォーム作成クラウドサービス「Formzu(フォームズ)」を運営しているフォームズ株式会社です。オフィスで働く方、ホームページを運営されている皆様へ仕事の効率化、ビジネススキル、ITノウハウなど役立つ情報をお届けします。-->【フォーム作成クラウド】Webフォームで仕事を効率化したい方はこちらから最短30秒で作成。誰でもすぐに利用できます。