Special Contents
図研プリサイトがもっと分かる!

Column
— ナレッジ活用コラム —

ナレッジは学ばず遊んで覚える。「Word2Vec」で遊んでみた。

著者:図研プリサイト 富田雄貴

こんにちは、富田と申します。当社ナレッジ製品開発チームのエンジニアです。

最近流行している機械学習の応用のひとつであるWord2Vecを使いちょっと言葉で遊んでみようと思います。

Word2Vecについて

Word2Vecはテキスト処理を行い入力すると、テキストに含まれる単語1つ1つに対して特徴ベクトルを出力します。取得した特徴ベクトルは加算や減算を行う事で合成された単語がなんであるかを計算できたり類似した単語を抽出できたりします。

加減算でいうと、たとえば以下のような関係が有名です。

column05_1.png

人間が介在することなしに関係を構築できることが、この手法の特徴になります。

準備

以下のサイトの記述を下に日本語Wikipediaの記事から学習データを用意します。

・・・しようとしたのですが、丸1日たっても学習が終わらなかったため以下のサイトから学習済みのモデルをダウンロードしました。

モデルの取り扱いはDeepLearning4jを利用します。早速モデルを読み込ませて試してみます。

類似語の抽出

指定した単語に近い単語を抽出してみます。

				
指定した単語:「ナレッジ」
抽出した結果: [ナレッジマネジメント, バランスト・スコアカード, グローバル・ソーシング, コンサルティング, プロビジョニング, ソフトウェアファクトリー, コンテンツマネジメントシステム, SIer, ソーシャル・キャピタル, ファシリテーション]
				
			
				
指定した単語:「カラス」
抽出した結果: [フクロウ, 鳥, アリドリ, オオルリ, ハヤブサ, カワガラス, カザリドリ, カワセミ, ホシガラス, コクチョウ]
				
			
				
指定した単語:「CAD」
抽出した結果: [DCAD, AutoCAD, CAE, CATIA, ArchiCAD, CAM, ソフトウェア, コンピュータグラフィックス, モデリング, CADR]
				
			
				
指定した単語:「バイク」
抽出した結果: [オートバイ, スクーター, モトクロス, 自転車, モーターサイクル, レーサー, レーシングカート, オフロード, 二輪車, マウンテンバイク]	
				
			

なかなか面白い結果になっているのではないでしょうか。

似ている(差し替えが可能な)単語を探すだけでなく単語が持つベクトルの加減算を行う事で、単語同士の関係を探ることもできます。

加算

単語を加算することで合成したときの結果を取得できます。ためしに「カラス」に場所や柄などをつけてみます。

				
計算式 :「川」 + 「カラス」
計算結果: [カワガラス, 支流, カワセミ, 河口, ソバト, エレシル, 河畔, コガモ, コサギ, イラティ]
				
			

カワガラスは河川や渓流に住むカワガラス科の鳥です。

				
計算式 :「斑点」 + 「カラス」
計算結果: [ホシガラス, 斑紋, 黒い, 黒く, 白い, ガビチョウ, ヒメシジミ, ジャノメチョウ, ヒドリガモ, アオゲラ]
				
			

ホシガラスは、体に斑点模様のあるカラス科の鳥です。

どちらもよく抽出できているようです。

加算と減算

また「A-B+C」という演算を行うことで【「B」にとっての「A」は「C」にとっての何であるか】を探ることができます。

				
計算式 :「カタナ」 - 「スズキ」 + 「カワサキ」
計算結果: [GPz, FZR, ZXR, カワサキ・ニンジャ, GPZ, ZZR, カワサキマッハ, ゼッツー, GSX, YZF]
				
			

いい感じに抽出できています。

				
計算式 :「CATIA」 - 「ダッソー・システムズ」 + 「Autodesk」
計算結果: [AutoCAD, Softimage, SolidWorks, LightWave, Maya, Poser, LuxRender, Render, Photoshop, Discreet]
				
			

正しくAutodesk社の3D CADである、AutoCADが抽出されました。

				
計算式 :「東京」 - 「日本」 + 「イギリス」
計算結果: [ロンドン, キングストン・アポン・テムズ, ブライトン, グラスゴー, バーミンガム, キングストン, リバプール, リヴァプール, サウサンプトン, コヴェントリー]
				
			

問題なく、イギリスの首都「ロンドン」が一番目に表示されました。同じようにいくつかの国で試してみます。

				
計算式 :「東京」 - 「日本」 + 「フランス」
計算結果: [パリ, トゥールーズ, リヨン, トゥールコワン, マルセイユ, ブリュッセル, ストラスブール, ボルドー, エーヌ, フレンヌ]
				
			

問題なく、「パリ」が一番目に表示されました。

				
計算式 :「東京」 - 「日本」 + 「イタリア」
計算結果: [ミラノ, フィレンツェ, ボローニャ, ヴェローナ, パレルモ, ウィーン, ナポリ, パドヴァ, サヴォーナ, ブレーシャ]
				
			

イタリアの場合、うまく「ローマ」が抽出されていません。なぜでしょうか。「ローマ」の関連語句を検索します。

				
計算式 :「ローマ」
計算結果: [ローマ帝国, ミルウィウス, オスティア, ビザンティウム, 教皇, ユリウス・クラウディウス, フラミニウス, パラティウム, ハドリアヌス, マクセンティウス]
				
			

このように「ローマ」が使用された首都という文脈以外に「ローマ帝国」や「ローマ教皇」と様々にあるためです。

単語の分散表現を使用する際には、用途に合わせて学習元のデータを選ばなければいけない事がわかります。

クラスタリング

得られたベクトルを k平均法でクラスタリングしてみます。

全ての単語について実行すると時間がかかってしまうので、ベクトルが生成された単語から30000語をランダム抽出し、1000クラスタに分類させました。

コードは以下のようになります。

				
File wordFile = new File( "rsc/model.vec" );
WordVectors vec = WordVectorSerializer.readWord2VecModel( wordFile );
List words = new ArrayList( vec.vocab().words() );
Collections.shuffle( words );
words = words.subList( 0, 30000 );
INDArray weights = vec.getWordVectors( words );
KMeansClustering kmc = KMeansClustering.setup( 1000, 10, "euclidean" );
List pointsLst = Point.toPoints( weights );
ClusterSet cs = kmc.applyTo( pointsLst );
				
			

クラスタリングを実行した結果は以下のようになります。

				
クラスター1,[ヨセフ, アベル, ヨベル, アビメレク, ナタナエル, レビ, ベニヤ, 悔い改め, ヨナタン, ヘロデ・アンティパス, ナフタリ, エリシャ, 創世...]
クラスター2,[藻岩下, 知内, 張碓, 常呂川, モエレ沼, 滝ノ沢, 幣舞, 江別, 大通東, ウトロ, 蘭越, 斜里, 多度志, 月寒, 香深, 島松...]
クラスター3,[バカロレア, 理数, 休暇, 理系, 塾生, 全寮, 年生, 小学, 次生, 学年, 入塾, 講義, 修得, 合宿, 課程...]
クラスター4,[駆け落ち, 男, 別れ, 大金持ち, 猟銃, 落ち合い, 転がり込む, 連れ出し, 帰り際, 年男, 隠れ家, 血塗れ, 倦怠期, 不倫...]
クラスター5,[濁川, 広瀬川, 大沢川, 摺上川, 阿賀川, 大石川, 江合川, 黒沢川, 吾妻川, 鮭川, 雄物川...]
クラスター6,[Ⅳ, IV, VIII, IX, XII, Ⅶ...]
				
			

なかなか面白い結果になっています。(クラスター4の結果がヤバい・・・) 感覚的には人間が分類したのと近い感じでグループ化されています。

まとめ

想像していたより人間の感覚に近い形で情報が取得でき驚きました。

自然言語処理技術とし、今回使用した単語をベクトル化する手法を応用し 文章をベクトル化するDoc2Vecなどもあるようです。今回は自前でモデルを用意できず学習パラメータの違いまで手が回らなかったのが反省点になります。今後自前で学習データを用意して、データのクレンジングや学習パラメータの調整手法を学んでいこうと思います。