機械学習を使って、数百の単語(及び複数の単語)を、意味のあるクラスタ(グループ)に分割するには、どうすればよいのか。ここ半年近く、キーワードのクラスタ分析に取り組んできたので、試行錯誤の過程を紹介します。人間であれば、最初に大まかに意味の近い語を分け、さらに細部に分けていくという方法をとる。ボトムアップに分類を作る方法としては、KJ法などがよく知られたところでしょうか。いえ、数百規模の標本数の語を、単語の意味を考えながら分類するというのは、とても骨の折れる作業で、時間もかかります。プロのアナリストであれば、時間は短縮されるにしても、労力を要することに違いはありません。このような目的の下、動いています。取り組んだ過程と共に紹介します。単語の分散表現クラスタ分析をするためには、分析対象となる「語」を定量的に表現する必要があります。犬や猫といった単語、鉛筆や消しゴムも全て数値に置き換える必要があります。機械学習すると、人が見て理解できる数値ではなくなりますが、機械が意味を読み取れるようにする、ということです。そのような、ベクトルによる定量的な表現については、分散表現と呼んだりしますが、分散表現を入手すれば、クラスタ分析の要件を満たすことになります。実装を開始するにあたり、word2vecを採用しました。word2vec登場以前は、コーパステキストを解析して、登場した頻度を単語別に数えることで分散表現の情報としてきました。一方で、近年のニューラルネットワーク技術の革新もあり、語の分散表現は、直接機械学習する方法が多くなっています。なる構造で、分散表現を手に入れます。こんな浅いモデルで学習できるのか?と驚きですが、共起しやすい語(正例)と共起しにくい語(負例)を、上手にサンプリングして教師データとすることにより、分散表現が安定するようです。学習後のモデルを使うと、多次元空間で位置が近い語を、コサイン距離を評価することもできます。「システム」に近い意味の語を10個、近い順に並べたい場合は、以下のように。0.676並んでいる単語は、直感的にも違和感のないものです。システムという語の近くには「機能」とか「デバイス」等の単語が共起しやすい、と解釈してよいわけです。学習結果は、使用したコーパスによっても、与えたパラメータによっても変わるため、個々に違ってきます。分ける単語が複数の場合や、文章など比較的長い語が入力された場合に、どのように対応するのか、というのも大きな課題ですが、ひとまず、複数のベクトルを加算して平均的に表現すると、しておきます。いずれにせよ、入力語の分散表現がありさえすれば、与えられた語を分類する枠組みをつくり、分類を機械に任せればよいわけです。・・・・といった計画でしたが、ここからが、長いトンネルの始まりでした。k-means法k-means法は、数あるクラスタ分析の手法の中でも、最もよく知られた手法で、scikit-learnなどのpythonライブラリを使えば比較的簡単に実装できます。ところが、与えられたキーワード群(数百)を分散表現にして、指定したクラスタ数に分けてみると、どうにも、うまくいきません。上手に分類できたかな、と思った結果が得られる一方で、さっぱりダメな結果が多く、意味の異なる語が混在するようなクラスタができたり、ほとんど同じ意味の同義語が、異なるクラスタに分かれてしまうなどの結果が頻発しました。実装上のミスやバグなのか、何かが根本的に間違っているのか・・・。分散表現からクラスタリングまで、いくつかの処理をパイプラインでつなぐので、工程のいずれか1つで情報劣化があれば、最終的な結果も台無しになるという構造です。問題が生じている箇所の特定と対策が必要なわけです。分散表現を改良する必要があるのかどうか。word2vecモデルの各種パラメータの調整と結果の確認・・・word2vecに限らず、機械学習モデルは、調整すべきパラメータが多々あります。それらが最適化されていないと、よい表現が手に入らない。グリッドサーチの手法で、パラメータの様々な組み合わせを試して、よさそうなパラメータを見つける、といった作業を進めました。doc2vecモデルによる検証word2vecの他に、Google発のdoc2vecと呼ばれるアルゴリズムもあり、こちらもword2vecと並んで比較的、目にすることが多いです。doc2vecは、ドキュメントをベクトル化する、という手法で、多数のドキュメントの中から似たドキュメントを特定することができます。ドキュメントに加えてword2vecと同じように、単語の分散表現も手に入るため、こちらも試しました。gensimライブラリを使って実装し、word2vecと同じように学習させた結果、word2vecに比べて、洗練された分散表現が得られたので、当面、doc2vecを使うことにしました。困ったことに、doc2vecは、逐次的な学習(モデルをアップデートしながら学習する手法)ができない、という点がネックで、大きなサイズのテキストを学習しようとすると、メモリが足りない、という問題に直面します(gensimライブラリのdoc2vecは、語彙のアップデートが無く、逐次更新ができない仕様)。Wikiコーパス全体を学習するにも、EC2インスタンスで1テラ規模のメモリが必要となり、そのようにして一括学習もしましたが、それで劇的に結果が向上するわけでもなく・・・。結局、word2vecに戻しました。コーパステキストが膨大なとき、word2vecであれば、アップデートの機能があるため、新しいコーパスを追加して、少しずつ学習内容を更新することができます。辞書の問題テキストを単語区切りにして分析できるようにする処理として「分かち書き」をしますが、MeCabの使い方が悪いと、単語ではないものを単語として認識したり、ひとつの語と認識すべきものも、分解してしまったりと、よくない挙動をします。このあたりを工夫して、改良したり等々。このあたりは他のメンバーの助けを借りつつ、現在も進行中です。アンサンブルが必要なのか個々の学習器の性能が低い場合に、それらの集合知で勝負する、というのが、機械学習の場合にはしばしば採用されるオーソドックスな方法です。(NMF)の考え方に基づく、アンサンブル法を実装しました。それでも改善が見られず。弱クラスタにすらなっていない分類器をいくつ寄せ集めてもノイズにすぎない、という状況に。LDAによるトピックモデル単語のベクトル表現ではなく、語の共起頻度を数え、潜在的なトピックで分析するという手法も試行しました。LDAは分散表現とクラスタ分析が一緒になったモデルのようなものです。トピックモデルの場合、長文を与えるほど、精度の高い結果が得られるものの、単語が1つの場合には、やや厳しい結果に。クラスタ分析の見直し結論から書くと、最も大きな原因は、最後の工程に相当するクラスタ分析にあったと考えています。word2vecで標準的とされる、分散表現の次元数200が高次元すぎる。標本間の距離が遠くなり、広大な空間に点が散らばって、適切にグルーピングができない。少なくとも人間が思い描くような結果につながらない。k-means法を使う場合、高次元空間は避けるべきで、word2vecの高次元の出力をそのまま使うのは、相性が悪い、と考えられます。k-meansの場合、どのクラスタも共分散構造が等しいため、柔軟なクラスタが作れない。クラスタ毎に共分散(散らばり)が異なるような分類手法を使いたい。そこで、クラスタ分析をする以前に元の分散表現を入手する際に、そもそも低次元にしておく主成分分析(PCA)を使って、圧縮をするとある方法論を用いて圧縮するなどの手法を試しました。クラスタ分析に対しては、k-meansではなく、別の分布モデルに切り替えました。これにより、凝集性が高くクラスタに分けやすい分散表現を手に入れ、標本として単語を与えた場合には、まとまりのよいクラスタが作れるようになりました。現在、β版としてキーワードマップの中に組み込まれています。β版までTweet関連記事2018-12-04センチメント分析と1次元CNN開発部Sです。今回は自然言語処理の中でも、教師あり深層学習...2018-07-23プログラミング未経験だった私が、エンジニアとして働いた1年間を振り返る開発部の瀧です。私事ではありますが、弊社株式会社Coreに入社...2018-05-10知っていると少し自慢できるVimの便利コマンドCore開発部の加藤です。»プロフィール株式会社CINCのエンジニアチームです。日々マーケティングツールの開発やR&Dを行っています。月別アーカイブスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。