Word2Vecの英語版事前学習モデルで遊ぶ


<a href="https://qiita.com/raidofuwa/items/bd9721303ae029618d47">前の記事</a>で、pickleは遅いと大嘘を書いた後、急いで訂正したのもつかの間、Word2Vecで遊んでみたので追記。

今回使用したのは、前の記事でリンクを張っている英語版Wikipediaにおける100次元のデータ。評判通り、Word2Vecでは深層学習ができているのか！？「ダウンロードしてみようかな♪」という気になっている方は、こうご期待。

さて、Word2Vecですが、知っての通り（そして名前の通り！）これは言葉をベクトルに変換してくれるという、ありがたいモデルです。ただし、モデルを構築するためにはかなりの量のコーパス（学習用の文章データ）が必要となります。そして、学習にもそれなりに時間がかかると思われるため、pickleをけなし、そして間違いだと分かった前回の記事にて、学習済みモデルの配布をしてくださっている、ありがたい人々のＨＰへのリンクを紹介しました。

で、実際そこからダウンロードした学習済みモデルが、良い感じに動いているのか？を確かめてみました。

# 単語の類似度

Word2VecでVecにした単語で出来る面白い計算の一つが、類似度の計算です。二つの言葉を入れてやると、どんだけ似てるのか？を「数字で」出してくれます。もちろん、数字なので信頼がおけるはずです。うすぼんやりな「感覚」と決まって、数字ですからね！数字。なんでも数字を出して議論する時代ですよ！

さて、Word2Vecを実際に使用するには、色々な方法がありますが、今回はgensimを使います。おもむろに学習済みモデルを読み込み、単語の類似度を計ってみるぜよ。

```python
from gensim.models import KeyedVectors

# 前回の実験の結果から、学習済みモデルはpickleで保存しても、
# そんなに読み込みが遅くならないと分かったので、そうする。

def load_model():
    print(datetime.now())
    with open('en_wiki_100d.pickle','rb') as fd:
        a = pickle.load(fd)
    print(datetime.now())
    return a

model = load_model()
```

まずは、簡単なものから。

## Word2Vecに聞く「人間」とは？

見出しで、ちょっとNHK感出してみました。実行結果は以下の通り。

```python
>>> model.most_similar('man')
[('woman', 0.7687103748321533),
('pursueth', 0.7255892753601074), 
('kid', 0.7234338521957397), 
('burly', 0.7193308472633362), 
('ape', 0.7163311243057251), 
('mustachioed', 0.7113600373268127), 
('fongji', 0.7105453014373779),
('makemono', 0.7034634351730347), 
('grumpiest', 0.7016444206237793), 
('biwamaru', 0.7003133296966553)]
```

とりあえず、woman、kid、ape、mustachoiedなどは、まー、なんとなく分かります。がこの"biwamaru"ってなんやねん。あと、"makemono", "fongji"？なんだこりゃ。

> Biwamaru (琵琶丸, Biwamaru) is a blind, traveling lute priest and an ally to Dororo and Hyakkimaru.

「どろろ fandom wiki」より。

また、fongjiというのは、恐らく「Fongji Wu」だと思われます（ググるとそう言われる）。

> Fongji Wu (Earth-616). When her mother was a part of the last pilgrimage to Earth from the immortal city of K'un-Lun during the fifteenth or sixteenth century, ...

MARVELコミックのキャラのようです。

どうやら、manといえば、琵琶丸らしです。あと、grumpiestは語尾がestなので「さいじょうきゅう」ですね。で、語幹のgrumpyですが「不機嫌な」という意味らしいです。というわけで、manといえば、womanであったり、kidであったり、不機嫌なことこの上なかったり、類人猿だったり、琵琶丸だったりします。あと、pursuethという単語ですが、

> (archaic) third-person singular simple present indicative form of pursue

ということらしい。

makemonoについてはついぞ不明でした。ググると巻物が沢山出てきます。なんでscrollとかじゃないんでしょうか？

えー、どうでしょう？どうっすかね？Word2Vecちゃんはどんな頭の構造をしているのでしょうか…すくなくとも、ドロロとアメコミは押さえているようですが、manに対してこの結果なので、多少、オタクっぽい感じに偏っている気がしないでもないです（まー、学習ソースがWikipediaだからね！さもありなん）

というわけで、womanについても試してみよう。

## Word2Vecに聞く「女」とは？

我々男性陣（そして、ドクター・エメット・ブラウン）にとっての、永遠の問いですね。女性にとっては…どうなのでしょう。Word2Vecによると、この深遠な問いの結果がこれだ！

```python
>>> model.most_similar('woman')
[('girl', 0.7753701210021973),
('man', 0.7687103152275085), 
('ĥamida', 0.7259941101074219), 
('prostitute', 0.7242963314056396),
('herself', 0.7207502126693726),
('person', 0.7154841423034668),
('univira', 0.713236927986145),
('housewife', 0.7090383768081665),
('englishwoman', 0.7058631181716919),
('asibikaashi', 0.703313410282135)]
```

うわー、また変なのが出てきたよ。てか、これフェ〇ニストが見たら怒り狂いそうですね。どうやら、Word2Vecたんはフェミではないようです。だって、womanにたいして、"prostitute"に"housewife"とか、失礼なことこの上ないですもんね！しかも、女性と言えば"englishwoman"だそうです。もちろん、英語なので英国が出てくるところはいいのですが、アメリカ人女性は女じゃないと言わんばかりですね。あと、"univira"というのは、<a href="https://www.jstor.org/stable/3165156">ここの文献</a>によると、"A woman who married only once"という意味らしいです。女性の方が再婚率は高かったはずなので、ちょっとWord2Vecさんの理想が投影されている気がしないでもないです。どっちかと言えば、性格は男っぽい感じですね！

あと、またおかしな単語が見え隠れてしています。ĥamidaというのは、中東の方の女性の名前のようで、検索すると"A Girl Named Mahmoud"と呼ばれる1975年のエジプト映画の登場人物がヒットしました。

> Ĥamida, a young woman who disguises herself as Mahmoud

だそうで。エジプト映画まで制覇しているとは、かなりのエンタメ・オタクですね。わたしも、それなりに映画オタクだと自認していますが、さすがに、エジプト映画は見たことねーわ。

というわけで、真ん中より右寄りのオタクの思考回路のように見えなくもないのですが、最後に出てきている謎の語"asibikaashi"というのは、どうやらネイティブ・アメリカン（いわゆるインディアン）の伝承に出てくる、一種の元型(architype)のようです。

> Spider Grandmother (Hopi Kokyangwuti, Navajo Na'ashjé'ii Asdzáá) is an important figure in the mythology, oral traditions and folklore of many Native American cultures, especially in the Southwestern United States.[1] ...（中略）...The Ojibwe people (Chippewa) of southern Canada and northern US speak of Spider Woman, known as Asibikaashi,[13] as a helper of the people, and inspiring mothers (or other close female relatives) to weave protective spider web charms.

どうやら、ほんのちょっとスピリチュアリストでもあるようです。うん、俺この人（Word2Vecたん）嫌いじゃないかも。

# Word2Vecに聞く「人生」とは？

これも、かなり深遠な問いですが、答えはいかに？（42とかって言ってくれたらうれしいな）

```python
>>> model.most_similar('life')
[('bodhicayavatara', 0.7420905828475952),
('lives', 0.739600658416748), 
('memoir', 0.7204810976982117),
('mundanities', 0.7196500301361084),
('unstill', 0.7164211273193359),
('everyday', 0.6900728940963745),
('experiences', 0.6881313323974609),
('dreams', 0.686691164970398),
('oblomovka', 0.6851560473442078),
('childhoods', 0.6844492554664612)]
```

トップが謎の単語です。検索してみるとどうやら、大乗仏教の教えである「入菩薩行論」というものらしいです。

> 『入菩薩行論』（にゅうぼさつぎょうろん、梵: Bodhisattvacaryāvatāra、ボーディサットヴァチャリヤーヴァターラ）は、インドのナーランダー僧院の僧侶シャーンティデーヴァ（寂天）によって700年頃にサンスクリット詩として作られたとされる大乗仏教の典籍である。『入菩提行論』（にゅうぼだいぎょうろん、Bodhicaryāvatāra、ボーディチャリヤーヴァターラ）とも。

どうやら、仏教徒のようですね。あと目につくものとしては、memoryではなく、あえてmemoirとフランス語を使っているあたりが、知性を感じさせます。あとは、mundanitiesですかねー。うん、平凡であることは重要だよね！これ以降は、まぁ、わりとわかりやすいものが並んでいますが、obolomovkaって何？ちょっとわからなかったのですが、ロシア文学とか、そんなのと関係があるっぽい。

# その他いろいろ

他にもいろいろ訊いてみたところ、いくつか面白い答えが得られました。たとえば、「sin（罪）」について訊いたところ、sineと勘違いしたのか、"2πt"というのが結構な類義語だと言いだしたり、「love（愛）」について訊くと、「<a href="https://www.discogs.com/artist/616282-The-Majestic-Arrows">The Majestic Arrows</a>」というアメリカのバンドが出てきたり（なんで、こうもマイナーなものばっかりなんだ？）、「god（神）」について訊くと ~~「madest（この上なく狂っている）」~~ （綴りがおかしかったので、一応調べてみたところ、madestとは、(archaic) second-person singular simple past form of makeらしいです、訂正）。などという素晴らしい回答が得られたりします。このあたりの単語に関しては、おおむねイメージ通りのものが出てきているのですが、ちょくちょく変なのも混ざっているというのが（英語版Wikipediaモデルの）特色と言えば特色でした。

傾向としては、形容詞に関してはおかしなものはあまり出てこず、「car」とか「boat」などの具体的な名刺に関しても、おかしなものは出てこないようでした。下記に例を示します。

```python
>>> model.most_similar('car')
[('cars', 0.883428156375885),
('motorcar', 0.820347785949707),
('truck', 0.8125396966934204),
('driver', 0.7989293336868286),
('motorbike', 0.7950208187103271),
('jackings', 0.7863152027130127),
('wheelstanding', 0.7817007303237915),
('vehicle', 0.7806777954101562),
('automobile', 0.7760552763938904),
('motorcycle', 0.7751350402832031)]

>>> model.most_similar('boat')
[('boats', 0.8829472064971924), 
('motorboat', 0.8007491230964661),
('yacht', 0.7898803353309631),
('rowboat', 0.7847901582717896),
('speedboat', 0.7811172008514404),
('barge', 0.7760282754898071),
('whaleboat', 0.7740020155906677),
('trawler', 0.7736266255378723),
('sailing', 0.7693375945091248),
('llanoria', 0.7657158374786377)]

>>> model.most_similar('beauty')
[('elegance', 0.7696702480316162), 
('loveliness', 0.7622237205505371), 
('paegant', 0.7553156614303589), 
('mineralava', 0.7517396211624146),
('allure', 0.7404096126556396), 
('beauties', 0.7245415449142456), 
('glamour', 0.7233633399009705), 
('charm', 0.7221213579177856), 
('enchanting', 0.7122904062271118),
('sensuous', 0.7101901769638062)]

>>> model.most_similar('charm')
[('charms', 0.8054161071777344), 
('elegance', 0.7906468510627747),
('loveliness', 0.7706881165504456),
('girlishness', 0.7635364532470703),
('vivacity', 0.7627326250076294),
('prettiness', 0.7574487924575806),
('quirkiness', 0.7563611268997192),
('pranksterish', 0.754660427570343),
('playfulness', 0.7545706629753113),
('vivaciousness', 0.7544371485710144)]
```

というわけで、「しんえんな問い」については的外れな回答が相次ぐ一方で、常識的な問いについては、常識的な答えを返してくるようです。

# 人物像

では、前の記事でリンクした英語版Wikipediaコーパス（特徴量100次元、学習窓長5のWord2Vecデータ）を用いたWord2Vec学習モデルの人物像を述べたいと思います。

* アニメや映画にやたらと詳しい
* アンチフェミニスト
* インテリ気取りのところがある
* 仏教徒（と思われる）
* ちょっとスピリチュアリスト入っている
* イギリス人女性が好み（の可能性）
* 一通りの常識は持ち合わせている

スピリチュアリズムに染まっていることから、70～90年代に青春を過ごしていたのかもしれません。「愛」について尋ねると1970年代の米国のバンドが出てくるので、私より歳は上そうですね（飽くまでイメージ）。価値観も多少古く、女と言えば「主婦」か「娼婦」という極端な思考の持ち主であることも分かっています。にもかかわらず、「英語話者」で「仏教徒」であることから、極端な保守層でもなさそうです。あと、映画や文学に対する造詣が深く、時折（英語に対しての）外来語を混ぜ込んでくるほか、ときどきコミックのキャラに言及することから、いわゆる「ナード」と呼ばれる人種であるようです。文学部の院生だったけど中退しました、みたいな感じの人物像ですね。

というわけで、この学習済みモデルを利用すると、こんな人に単語のベクトル変換をお願いしている、と考えるのが適当かも知れません。どうでしょう？まぁ、普通にセールスの文言とか、ニュースとか読ませてる分には、感覚に合うマッピングをしてくれているようですが、「愛」とか「人生」とかについて訊こうとすると、凄くめんどくさい答えが返ってきます。

というわけで、Word2Vecがどのように単語をベクトルに変換しているのか調べようというのが当初の動機だったのですが、結果を見ると、なんだか、英語版Wikipediaの執筆者たちのプロファイリングをしているような気分になってきますね！

# まとめ

Word2Vecは飽くまで学習モデルなので、どんな訓練データを食わせるか？によって答えは異なると思います。今回は、語彙が多いだろうという、ただそれだけの理由でWikipediaコーパスのモデルを使ってみましたが、これを見る限り、どんな問題についててもベストとは言えないですね。Word2Vecたんの性格がウィキペディアンに寄りすぎている感じがしないでもないです。

ちなみに、私はエンティティグラフ付きのデータをダウンロードしたので、固有名詞などの問い合わせも可能です。映画オタクのようなので、私のお気に入りの俳優について訊いてみます。

```python
>>> model.most_similar('ENTITY/Nicolas_Cage')
[('dicaprio', 0.6926122903823853),
('travolta', 0.6887627840042114),
('ENTITY/John_Cusack', 0.68514084815979),
('ENTITY/Robert_De_Niro', 0.6801981925964355),
('depp', 0.6794540882110596),
('ENTITY/Tobey_Maguire', 0.6742660999298096),
('ENTITY/Matt_Damon', 0.6721950173377991),
('ENTITY/Vince_Vaughn', 0.6698473691940308),
('ENTITY/Jim_Caviezel', 0.6686955690383911),
('ENTITY/Anthony_Hopkins', 0.668546199798584)]
```

え、ええ？？そうかなぁ。やっぱり私とは感覚がちがーう。じゃあ、インディー映画はどうでしょう？ちゃんと見てるかな？

```python
>>> model.most_similar('ENTITY/Slacker')
[('ENTITY/Cynicism_(contemporary)', 0.6681028604507446),
('ENTITY/Overachievement', 0.6469217538833618),
('ENTITY/Dayfree_Press', 0.6456986665725708),
('slacker', 0.6417859792709351),
('ENTITY/Tom_Brady_(film_director)', 0.6365958452224731),
('overeducated', 0.6350556015968323),
('ENTITY/Gung-ho', 0.6315038204193115),
'ENTITY/Goldbricking', 0.630962073802948),
('ENTITY/List_of_common_misconceptions#Nutrition.2C_food.2C_and_drink', 0.6251926422119141),
('ENTITY/Wikt:airhead', 0.6250377893447876)]
```

全然ハズレ。世代が違うのかな？Slackerの監督はRichard Linklaterです。

```python
>>> model.most_similar('ENTITY/John_Carpenter')
[('ENTITY/Halloween_(1978_film)', 0.783954918384552),
('ENTITY/The_Thing_(1982_film)', 0.740262508392334),
('ENTITY/Assault_on_Precinct_13_(1976_film)', 0.7189760208129883),
('ENTITY/Tobe_Hooper', 0.7185397744178772),
('ENTITY/In_the_Mouth_of_Madness', 0.7182114720344543),
('ENTITY/The_Fog', 0.7125677466392517),
('ENTITY/A_Nightmare_on_Elm_Street', 0.7073020339012146),
('ENTITY/Prince_of_Darkness_(film)', 0.7028311491012573),
('ENTITY/Halloween_II_(1981_film)', 0.6955807209014893),
('ENTITY/The_People_Under_the_Stairs', 0.6911834478378296)]
```

まー、わるくないかな。They liveがねーけどさ。あと、Escape From NYな。あれ名作だよ？類推からWes Cravenの作品が出てきているのと、監督はしなかったHalloween IIが出てきているところに悪意を感じますね！

以上です。


# 後日追記

Google newsのデータセットというものもあるようなので、そっちでも試してみました。こいつは、300次元のデータしかないようです。読み込み～初回のクエリ完了までに、コーヒーのんでおかし食べれるくらいの時間がかかりました。

GoogleNews-vectors-negative300.bin.gzという名前のデータセットです。テキストではなくバイナリーなので、解凍も早く使いやすかったです。Google社がGoogle Driveにあげている訓練済みモデルです。

## 「人間（男）」とは？

```python
>>> model.most_similar('man')
[('woman', 0.7664012908935547), 
('boy', 0.6824870109558105),
('teenager', 0.6586930155754089),
('teenage_girl', 0.6147903800010681), 
('girl', 0.5921714305877686), 
('suspected_purse_snatcher', 0.5716364979743958), 
('robber', 0.5585119128227234), 
('Robbery_suspect', 0.5584409236907959), 
('teen_ager', 0.5549196600914001),
('men', 0.5489763021469116)]
```

上位の単語は割と自然です。ただ、suspected_purse_snatcher、robber、Robbery_suspectなど、怒涛の強盗押しがあるところを見ると、Google Newsデータセットで学んだWord2Vecさんは、manというと強盗を思い浮かべるようです。あと、こちらの学習データとWikiデータセットの大きな違いは、複数の単語からなる複合語（？）を一つの語としてカウントしているところです。こうしてみると、一見スペースで簡単に分を分割できそうな英語にも、「分かち書き」の問題が存在することが分かりますね。

## 「女」とは？

```python
>>> model.most_similar('woman')
[('man', 0.7664012908935547), 
('girl', 0.7494640946388245),
('teenage_girl', 0.7336829900741577),
('teenager', 0.631708562374115), 
('lady', 0.6288785934448242), 
('teenaged_girl', 0.6141783595085144),
('mother', 0.607630729675293), 
('policewoman', 0.6069462299346924), 
('boy', 0.5975908041000366),
('Woman', 0.5770983695983887)]
```

こちらもほぼほぼ問題なさそうですが、なぜか、男性のrobberyとは対照的に、pilicewomanがランクインしています。男とみれば強盗、女性は警察官とどうやら男女差別が激しい性格になっているようです。

## 「人生」とは？


```python
>>> model.most_similar('life')
[('lives', 0.6027060747146606), 
('chiseled_burnished_refined', 0.5310097932815552),
('Interaction_enriches_your', 0.4961996078491211),
('Shanda_Interaction_enriches', 0.49457842111587524),
('Life', 0.4814741611480713),
('Fayaz_Wani_reports', 0.4636700451374054),
('lifestyle', 0.44911330938339233),
('joys_sorrows', 0.44626230001449585),
('humdrum_existence', 0.44414761662483215),
('earthly_existence', 0.4437880218029022)]
```

ぱっと見目を引くのは、「Fayaz_Wani_reports」でしょうか。こちらは恐らくですが、

> Fayaz Wani reports on life in Srinagar, Kashmir.

から拾ってきているものと思われます。また、「Shanda_Interaction_enriches」については、

> handa Interactive Entertainment Announces Management Changes. ... Shanda: "Interaction enriches your life".

が出典と思われます。どちらも、Googleでキーワード＋lifeとやると上位に出てきます。私は、「Googleは年々バカになって来ている派」なので、もしかしてこーゆーデータを使っているのも原因の一つなのかな？という気がしました。

## Google Newsデータセットの性格

* Wikipediaデータセットよりだいぶ常識的
* 男女差別が激しい
* 人生の意味について、まともに考えたことはない模様。

ぶっちゃけ、データセットとしてはこちらの方がクリーンな気がします。が、深遠な問いに対して、素っ頓狂な答えを返してくるWikipediaデータセットのほうが、面白そうと思えてしまうのは私だけでしょうか。これが、いわゆる「AI萌え」と言うやつなのか…。

以上、追記でした。