メロンとメロンパンを、キカイが探す物語


# **背景**

## JavaとJavaScriptは、メロンとメロンパンくらい違う

先日下記の記事を拝見した。

[JavaとJavaScriptの「別物感」を印象づけるフレーズ集](https://qiita.com/suin/items/1e4791ac4fca4885eb73)

**メロンとメロンパンくらい違う！！**

**インドとインドネシアくらい違う！！**

JavaとJavaScriptの違いを正確に表現しているのかどうかは、私にはどーでもいいが、
冒頭一致しているのに、意味が全く違う言葉ってどんなものがあるの？
という点に興味を持った。

「釣り」と「釣り堀」、「日本」と「日本刀」みたいなものはつまらない。
**意味が違えば違うほど、インパクトがあって面白い** 

何かの会話の拍子に、
「いやー、それってメロンとメロンパンくらい違うよー」
なんて切り返しはちょっとシャレが効いているんじゃない？
しかも毎回違うパターンで切り返すと楽しそう。
~~明日からすぐに使えるフレーズ特集~~

しかし、面白い例は、**全然思いつかない**・・・。

**そうだ！プログラムでこの言葉の組み合わせを探してみよう！**

## しかし、意外と見つけるのが難しかった

辞書に含まれている単語リストに対して、条件を設定して検索するだけで、
簡単に見つかるよね、どんなのがあるかなー、
くらいで思っていたし、記事で公開するつもりも全く無かったが・・・。

単純な力技だけだと、なんと、
 **1,981,320** 組 も見つかってしまった。（詳細後述）
 
 そして、そのほとんどは、「意味の無い、つまらない組み合わせ」
　 （「アメリカ」と「アメリカ合衆国」などのようなもの）と、
聞いたこともないようなマイナー単語ばかりであった。

つまり、**力技ではゴミが200万件に見つかるだけ**である。
ゴミの中からどのように面白い組を選抜するのか、
それなりに工夫を要したので、
その工夫の流れをつれづれなるままに書いてみようと思う。

**メロンとメロンパン、的な言葉を見つける旅**が今回のテーマ。

**まさに、究極どうでもいいッ！！！**

**メロンとメロンパンを、~~キチガイが~~キカイが探す物語**の始まりである。

~~（メロンとメロンパンだけに）
「むしゃむしゃして」やった。そして「公開」している。~~

## 先に最終結果の一部をチラ見せ

**「ちょっと何言ってるか分からない。」**
というマトモな人に向けて、最終的に出てくる例の一部をチラ見せる。

以下のような単語の組をキカイが探してくれた、という、
愛と勇気と努力とほんの少しの感動の物語なのだ。

* 「スパイ」と「スパイラル」
* 「ワープ」と「ワープロ」
* 「当たり」と「当たり前」
* 「コーラ」と「コーラン」
* 「バッタ」と「バッター」

（※自分では全く思いつかなかった。）

音が似ている、の定義はいろいろあるが、今回は、
【単語「A」「B」について、「B」が「A」の音で始まっていること】とする。
この関係があるのに、同じ文章に入らないほど意味が違う場合に、
面白いのではないか？

> 「アンパンマン、新しい顔よ、それっ！」
>  バタ子の**スパイラル**ボールが**当たり**、俺の顔を変えてゆく。くるくるくる。
>  新しい顔、新しい名前、新しい経歴、そして新しいミッション。
>   **スパイ**の仕事はいつも、新しい顔に**当たり前**のように慣れることから始まるんだ。

~~無理に同じ文章に入れるとこんなことになってしまう。~~


# **本投稿の内容**

* メロンとメロンパン、的な冒頭が一緒でも意味が違う言葉を、がんばって探す工夫の日誌
* 明日からすぐに会話で使える、**オシャレな日本語が沢山見つかる！**
* 自然言語処理や、機械学習を、最も**低次元なダジャレ的レベル**で**高度に活用！**
* 工夫していく過程で(たまたま)見つかった、他のテーマにも役立ちそうなノウハウを記載
    * Mecabの辞書(ipadic-neologd)に対する知見
    * 常識的に良く知られている単語かどうかの判断方法の簡易実装
    * Word2Vecの言語空間に対する知見　　などなど。
* コードの実行環境は全て、Windows10 + Python3 +JupyterNotebook を前提。


# **最初に力技でやってみる**

## 単語辞書の準備

まず、元となる単語データリストを得ることにする。
（ここでは一例を示しているが、ただの大量の単語リストなので、どんな作り方でも良い）

以前、Word2Vecのモデルを作成したことがあったため、
今回はそれに含まれている単語＝**約83万語**を元となる単語リストとする。

Word2Vecのモデルに含まれている単語のリストは、以下のように取り出せる。
「メロン」から始まる語句も検索して表示してみた。

```py3:単語リストの抽出
#Word2Vecのmodelに登録されている単語のリストを取り出す。
voc = model.wv.vocab.keys()

# 何語登録されているのか、単語登録数を出す。
print(len(voc))

# 特定語句から始まる単語を抽出する。
for x in voc:
    if x.startswith("メロン"):
        print(x)
```

```:結果
830626
メロン
メロンブックス
メロンソーダ
メロン財閥
メロンパン
メロンパンナ
メロン記念日
メロン熊
メロンジュース
メロン・フィナンシャル
メロント
メロン・リキュール
メロン・アリーナ
```

このWord2Vecのmodelは、
mecab＆mecabの辞書（ipadic-neologd）を使って、
日本語版Wikipediaのデータを分かち書きしたものを、機械学習したモデルである。

* Word2Vecとは何か、はググればすぐ出るので省略。
* Word2Vecを使った他の遊び方は、以下の私の以前の投稿もご参照：
    * [「赤の他人」の対義語は「白い恋人」 これを自動生成したい物語](https://qiita.com/youwht/items/f21325ff62603e8664e6)
* Word2Vecのモデルの作り方（機械学習の方法）は、以下の投稿の方法とほぼ同様なので省略
    * [平成の次の元号を、AIだけで決めさせる物語](https://qiita.com/youwht/items/0b204c3575c94fc786b8)

よって、語彙量としては、
「ipadic-neologdの辞書に登録されており、かつ、
　日本語版Wikipediaで数回以上出現した単語」
 ということになる。
 
が、 しょーじき、**何か良くわからない単語が結構ある**。
 ~~君のことじゃないよ、メロンパンナちゃん~~ 

**この、よく分からない単語群を消したい。**

## 常識的に知られている単語か判断をするロジック

良く知られている単語＝何度も使われている使用頻度の高い単語、という仮定を元に、
ある単語が、**Wikipedia上で何回出現したのか**、を数え上げておき、
その結果を参照出来るようにする。

```py3:単語の出現回数の数え上げ
%%time

import pandas as pd
import codecs
import pickle
    
#辞書型の変数の定義
freqdict = {}
All_Tangosuu = 0

#以下は、Wikipediaのデータを、mecab-ipadic-neologdで分かち書きしたテキスト
#数GBあってかなり重いため、メモリ溢れ対策に、１行ずつ読んでいく。
with codecs.open(r"ItiGyouGotoKiji_wakati_NEOLOGD.txt","r", "utf-8") as f:
    for line in f.readlines():
        for word in line.split():
            try:
                #初めて出た語なら０から始める。で、１を追加する。
                freqdict.setdefault(word, 0.)
                freqdict[word] += 1
                All_Tangosuu+=1
            except:
                pass

#実験。単語の出現回数を返す辞書を作れた。
print(All_Tangosuu)
print(freqdict[u"テスト"])
print(freqdict[u"メロン"])

#数GBのファイル操作を繰り返したくないので、
#pickleで結果をファイル出力しておくと、後で再利用しやすい。
with open(r'freqdict_wiki_all.dump', mode='wb') as f:
    pickle.dump(freqdict, f)
```

```:結果
468982549
14323.0
940.0
Wall time: 5min 44s
```

上記の結果を見ると、
Wikipedia上の全468,982,549個の単語を読み込み、辞書型の変数を作成したということ。
例えば、「テスト」という単語は、14,323回、
「メロン」という単語は、940回、Wikipedia上に出現したことになる。

> 補足： pythonによる単語の数え上げロジックは、ググると各種見つかるが、
> 多くのロジックは、wikipedia全件＝数GBのデータを数え上げるのに適していない。
> 小規模のテキストならば処理が終了するが、大規模ではメモリエラーになるケースが多い。
> readlines()での読み込みや、辞書型の変数を使っている理由はそれである。

**これを使えば、知られている単語かどうかは、出現頻度の値を見て、
機械的に判断することが出来るのではないか！？**

※word2vecのモデル内にも、学習時の出現回数が格納されているのではないかという気もするが
　簡単な参照方法が分からなかったので、どなたかご存知の方はお教えくださいませ。

さきほどのメロンの結果に適用してみると・・・

```py3:単語リストの抽出＋出現頻度記載
# 特定語を含まれている辞書単語を取り出す。
for x in voc:
    if x.startswith("メロン"):
        print(x+u"\t"+ str(freqdict_load[x]))
```

```:結果
メロン	940.0
メロンブックス	88.0
メロンソーダ	23.0
メロン財閥	31.0
メロンパン	103.0
メロンパンナ	26.0
メロン記念日	100.0
メロン熊	10.0
メロンジュース	19.0
メロン・フィナンシャル	14.0
メロント	10.0
メロン・リキュール	7.0
メロン・アリーナ	7.0
```

このように、メロンパンは100を超えるが、
「メロント」とか「メロン熊」は、かなりマイナーな単語ということになる。
~~さようなら、メロンパンナちゃん~~

あくまでもwikipedia上での登場回数であるため、
日本で知らない人はいないであろう「メロンソーダ」も値は低い。
この辺は追及するとキリがないため、簡易判定が出来るようになった、として先に進む。

> この結果データは別のテーマでも使いやすい気がする。
> ex.      [「赤の他人」の対義語は「白い恋人」 これを自動生成したい物語](https://qiita.com/youwht/items/f21325ff62603e8664e6)
> の対義語生成において、出現頻度の低すぎる単語が生成されてしまう場合は、
> 意味が分からないのでリトライするとか。


## す～ぱ～力技全件検索（最初の絶望）

さて、単語辞書の準備と、出現頻度（知られている度）の数値化は出来た。
さきほどの単語リストを使って、
「〇〇〇」という単語と、
「〇〇〇△△」みたいな、〇〇〇で始まる単語のペアを、全件探索する。
見つかった単語ペアに対しては、それぞれ出現頻度を計算して、リストに付与しておく。


```py3:す～ぱ～力技全件検索
%%time
#word2vecモデルから登録されている単語のリストを取り出す。
voc = model.wv.vocab.keys()
#以下のような感じのふつーのリストで良い。
#voc =[u"メロン",u"メロンパン",u"ウィスキー",u"コーヒー",u"テスト"]

result_list=[]
sintyoku=0

# 「word_start」で始まっている、自分自身以外の全単語を取得する。
# 見つかったペアについては、それぞれ、出現頻度（常識度）を計算しておく。
for word_start in voc:
    for word_big in voc:
        if word_big.startswith(word_start) and word_big != word_start:
            result = [word_start, word_big, freqdict_load[word_start], freqdict_load[word_big]]
            result_list.append(result)
    sintyoku+=1
    if sintyoku % 2000 ==0:
        print(sintyoku)

print(len(result_list))

#pickleで結果をファイル出力しておくと、後で再利用しやすい。
with open(r'hukumu_list_wiki_all.dump', mode='wb') as f:
    pickle.dump(result_list, f)
```

```:結果
※2000件処理ごとに出力していた経過ログは省略

1981320
Wall time: 1d 11h 57min 30s
```

**じつに、３６時間くらいかかった。**

83万×83万の全探索型でテキトーに作ったために、~~仕方ないよね。~~本当はもっと工夫した方がよい。

そしてなによりも、**200万件ほどの組が見つかってしまった。**

83万語というINPUTの個数よりも多く、１単語につき平均で2.5単語くらいあるということ。
えっ！？ちょっと予想外に多くなりすぎ、失敗臭が漂う。ぷ～ん。

> なお、今回は、「startswith」関数で、冒頭が一致という条件で検索しているが、
> ここを、アナグラムが一致、とか、ローマ字に直して一字違いとか、
> いろいろ変更すれば、様々なジョークに応用が効きそうだ。
> この取り組みが成功すれば、将来的には。

## 力技の結果で出た課題

200万件もあると見る気が失せるが、サンプリングして、
どのようなデータが入っているのかを眺めることにする。

```py3:リストから適当な番号の値を見てみる。
print(result_list[10104])
print(result_list[1000102])
print(result_list[1010102])
print(result_list[1080102])
print(result_list[1580105])
```

```:結果
['上', '上京会寧府', 251741.0, 15.0]
['ト', 'トスカニーニ', 1841.0, 291.0]
['3500', '3500km', 992.0, 15.0]
['ヴィー', 'ヴィーゼンブルク', 143.0, 13.0]
['ユ', 'ユン・ジョンヒ', 216.0, 5.0]

（※後ろの数字は「wikipedia上での出現頻度」）
```


うん？

* 「一文字」の単語があって、その文字で始まる語句が全て登録されている
* 3500とか数字が単語扱いになっている
* めちゃくちゃマイナーな固有名詞的なものが多数含まれている

**課題が山積み**である。

Mecab-ipadic-neologdの辞書の性質として、
形態素解析のために、かなりマイナーな語句なども登録されており、
**今回のような「一般的な語句が欲しい」という用途には向いていない。**
ということが見えてきた。

「全量」調べてやるぜ、的な意図で、語彙数でこの辞書から単語を見たのだが、
もうちょっと別な単語リストから始めたほうが良かったかもしれない。

ということで、**本プロジェクトは失敗**に終わりましたとさ。

がんばって３６時間も大気圏で燃え続けた愛機に申し訳ない・・・。

>「少佐ー。助けてください。減速できません。」
>「クラウン、ザクには大気圏を突破する性能はない…気の毒だが…
>　しかしクラウン、無駄死にではないぞ！」

~~無駄死にだったよね。~~

# **戦いとは常に２手３手先を考えて行うものだ**

無駄死ににさせないためにも、ここから挽回をはかる。
~~シャア、はかったな！シャア！~~

## 予め仕込んでおいた「出現頻度」や文字数でフィルタ

データをリスト形式で保持しておいたため、いろいろ加工が可能だ。
文字数として、３文字以上の単語に限るという条件と、
メロンパンは100程度の出現頻度であったため、出現頻度100以上という条件を
追加してフィルタリングを行う。

```py3:出力された200万のリストから、条件を追加してフィルタをかける
ok_result_list=[]

#長さが３文字以上、出現頻度（常識度）の値が共に１００以上
for result in result_list:
    if len(result[0])>2 and result[2]>100 and result[3]>100:
        ok_result_list.append(result)

print(len(ok_result_list))
```

```:結果
29877
```

**「３万組」**となり、かなり手が届く数字になってきた。

## 再度サンプリング調査で課題を確認

```py3:リストから適当な番号の値を見てみる。
print(ok_result_list[100])
print(ok_result_list[500])
print(ok_result_list[1000])
print(ok_result_list[5000])
print(ok_result_list[7000])
print(ok_result_list[10000])
print(ok_result_list[12000])
print(ok_result_list[15000])
print(ok_result_list[17000])
print(ok_result_list[18000])
print(ok_result_list[20000])
print(ok_result_list[21000])
print(ok_result_list[22000])
print(ok_result_list[25000])
```

```:結果
['アメリカ合衆国', 'アメリカ合衆国陸軍', 83907.0, 292.0]
['イギリス', 'イギリス国籍', 107808.0, 126.0]
['イラク', 'イラク軍', 7668.0, 750.0]
['ウイルス', 'ウイルス感染', 6936.0, 392.0]
['上り詰め', '上り詰める', 507.0, 153.0]
['153', '1536年', 1327.0, 700.0]
['film', 'films', 1305.0, 381.0]
['アルマ', 'アルマン', 372.0, 202.0]
['127', '1273年', 1621.0, 228.0]
['motor', 'motorola', 608.0, 107.0]
['robert', 'roberts', 1050.0, 193.0]
['ニンテンドーdsi', 'ニンテンドーdsiウェア', 146.0, 116.0]
['伊集院', '伊集院町', 1024.0, 154.0]
['不信任', '不信任決議', 633.0, 195.0]
```

まだまだ課題は多い。全く面白くない。
上記を見ても、**メロンパンやインドネシアへの道は果てしなく遠い**。

* 国名＋軍、とか、ウィルス＋感染、不信任＋決議、みたいな単語をどう除外する？？
* 数字系や、動詞の活用的なところも除外する必要あり（品詞判定がよさそう）
* 良くわからない単語や、英単語なども多い。


## 従属関係にある単語は「出現頻度」の差が大きいことに注目

例えば、「アメリカ合衆国」と「アメリカ合衆国陸軍」の間には、
出現頻度（常識度）としいて、数百倍の違いが出ているのが分かる。
「イラク」と「イラク軍」、や、「ウィルス」と「ウィルス感染」、も同様である。
「従属関係」的な単語の場合は、
元の語句の方が圧倒的に多く使われているのではないか？
ということで、差が１０倍以上ついている場合は除外、というルールを加えた。
（※「不信任」と「不信任案決議」、は１０倍差がついていないので、これでは除けない）
また、出現頻度（常識度）の、２単語の合計が1000以上である、という条件も加えた。

```py3:フィルタ条件を追加
neo_ok_result_list=[]

#長さが３文字以上、常識度の値が共に１００以上
#
for result in result_list:
    if len(result[0])>2 and result[2]>100 and result[3]>100 and result[2]+result[3]>1000 and result[2]/result[3] <10:
        sabun=result[1][len(result[0]):]
        check_hinsi()
        new_result=[result[0],result[1],sabun]
        neo_ok_result_list.append(new_result)

print(len(neo_ok_result_list))
```

```:結果
8950
```

**9,000組以下**になり、絞りは効いているが、サンプル抽出してもまだまだダメ。

```py3:リストから適当な番号の値を見てみる。
print(neo_ok_result_list[100])
print(neo_ok_result_list[500])
print(neo_ok_result_list[1000])
print(neo_ok_result_list[5000])
print(neo_ok_result_list[7000])
```

```:結果
['反政府', '反政府デモ', 1093.0, 258.0]
['結び付け', '結び付ける', 1185.0, 271.0]
['ジャンク', 'ジャンクション', 599.0, 2207.0]
['エイベックス', 'エイベックス・エンタテインメント', 899.0, 114.0]
['多国籍', '多国籍企業', 494.0, 533.0]
```

## 品詞判定を追加し、動詞、固有名詞、数などを除外する。

ここで、品詞判定を追加することにした。
品詞判定の方法は、以下の記事で両方とも使っているcheck_hinsi関数を使う。

* [「赤の他人」の対義語は「白い恋人」 これを自動生成したい物語](https://qiita.com/youwht/items/f21325ff62603e8664e6)
*  [平成の次の元号を、AIだけで決めさせる物語](https://qiita.com/youwht/items/0b204c3575c94fc786b8)  

これをMecab-ipadic-neologdの辞書有りで動かす。（３回目なのでコード再掲は控える）
（なお、Word2Vecモデルの生成時に使った辞書と、品詞判定用の辞書は合わせること。）



```py3:品詞フィルターの追加
neo_ok_result_list=[]

#長さが３文字以上、常識度の値が共に１００以上
for result in result_list:
    if len(result[0])>2 and result[2]>100 and result[3]>100 and result[2]+result[3]>1000 and result[2]/result[3] <10:
        start_word_bunseki=check_hinsi(result[0])
        end_word_bunseki=check_hinsi(result[1])
        #共に名詞の場合という条件を追加
        if start_word_bunseki[0][2].startswith("名詞") and end_word_bunseki[0][2].startswith("名詞") \
        and not(start_word_bunseki[0][2].startswith("名詞-数")) \
        and not(start_word_bunseki[0][2].startswith("名詞-固有名詞")) \
        and not(end_word_bunseki[0][2].startswith("名詞-固有名詞")):
            new_result=[result[0],result[1],result[2],result[3]]
            neo_ok_result_list.append(new_result)

print(len(neo_ok_result_list))
```

```:結果
598
```

**600**を切った。
やっと、全量を見ることが出来るレベルの数になってきた。
~~どうせここで名詞だけに絞るならば、
最初から辞書中の名詞だけで始めたほうが良かったかもしれない~~

早速一部を見てみよう。

```py3:最初の20個を抽出して見てみる。
neo_ok_result_list[:20]
```

```:結果
[['フィン', 'フィンガー', 2045.0, 393.0],
 ['キリスト教', 'キリスト教徒', 18628.0, 3395.0],
 ['当たり', '当たり前', 13651.0, 1504.0],
 ['ランク', 'ランクイン', 6283.0, 6323.0],
 ['アンチ', 'アンチテーゼ', 1090.0, 278.0],
 ['アンチ', 'アンチモン', 1090.0, 330.0],
 ['いくつ', 'いくつか', 4098.0, 42078.0],
 ['データ', 'データベース', 43814.0, 5341.0],
 ['ロック', 'ロックバンド', 16344.0, 7331.0],
 ['カントリー', 'カントリークラブ', 2792.0, 475.0],
 ['パラメータ', 'パラメーター', 3661.0, 712.0],
 ['中性子', '中性子星', 2110.0, 476.0],
 ['ウィンド', 'ウィンドウ', 477.0, 1945.0],
 ['モーター', 'モータースポーツ', 5481.0, 2514.0],
 ['プロレス', 'プロレスラー', 6723.0, 5374.0],
 ['サイド', 'サイドバック', 7412.0, 1045.0],
 ['ローラー', 'ローラーコースター', 1262.0, 191.0],
 ['ローラー', 'ローラースケート', 1262.0, 241.0],
 ['シティ', 'シティー', 6678.0, 1035.0],
 ['エックス', 'エックス線', 969.0, 125.0]]
 ```

**ここまで来ても全く面白くない・・・ッ！！！**

「キリスト教」と「キリスト教徒」
「データ」と「データベース」
「プロレス」と「プロレスラー」

辞書を単純に検索処理するとこういう結果になるのだ。
形態素解析用辞書の性質を理解する一助になった。

~~この腐敗した世界に堕とされた～
こんなもののために生まれたんじゃない~~


# **最終切り札「Word2Vec」の投入**

**切り札は先に見せるな、見せるならさらに奥の手を持て**

## 面白さ向上フィルタの導入

そもそも最初にWord2Vecモデルから単語リストを生成していた理由は、
こうなることをある程度予測していたから。

面白い組み合わせだけを抽出するために、２点の条件のフィルタを追加する。

**１点目：長い単語の文字数が、短い単語の文字数の２倍より少ないこと**

これは、「モーター」と「モータースポーツ」とか、
「ローラー」と「ローラーコースター」のように、
後ろに続く文字数が多すぎて面白みに欠けるものをフィルタする条件。

**２点目：２単語間のコサイン類似度が一定値以下であること**

Word2Vecの類似度計算によって、
「意味上遠い位置にある単語かどうか」の判断が出来る。
元の単語リストをWord2Vecモデルから作っているため、
どの単語もモデル内にある単語であることは保証されている。
（そうでない場合はエラーハンドリングも入れる。）
~~戦いとは常に２手３手先を考えて行うものだ~~


```py3:切り札Word2Vecの投入
from operator import itemgetter

neo_ok_result_list=[]

#長さが３文字以上、常識度の値が共に１００以上
for result in result_list:
    if len(result[0])>2 and result[2]>100 and result[3]>100 and result[2]+result[3]>1000 and result[2]/result[3] <10:
        start_word_bunseki=check_hinsi(result[0])
        end_word_bunseki=check_hinsi(result[1])
        #共に名詞の場合という条件を追加
        if start_word_bunseki[0][2].startswith("名詞") and end_word_bunseki[0][2].startswith("名詞") \
        and not(start_word_bunseki[0][2].startswith("名詞-数")) \
        and not(start_word_bunseki[0][2].startswith("名詞-固有名詞")) \
        and not(end_word_bunseki[0][2].startswith("名詞-固有名詞")) \
        and len(result[0])*2 > len(result[1]):
            #Word2Vecで二語間の類似度を計算。一定以上似ているものは使わない。
            sim_do = model.similarity(result[0], result[1])
            if(sim_do < 0.11):
                new_result=[result[0],result[1],sim_do,result[2],result[3]]
                neo_ok_result_list.append(new_result)

#似ている度（sim_do）でソート（import itemgetterはこのため）
neo_ok_result_list.sort(key=itemgetter(2))

print(len(neo_ok_result_list))
```

```:結果
65
```

**65組**まで絞れた。
一旦これをゴールとする。

> 補足：お気づきだとは思うが、これまでの全ての絞り込みは全て、
> 「200万件」ほどあった元のデータに対して、
> 条件をプログラムに追加していく形で実装している。
> （結果を出すだけなら、最初の重い処理＋最後の処理だけでOKということ）
> つまり、200万 ⇒ 3万 ⇒ 9千 ⇒ 6百 ⇒ 65、と実施していったのではなく、
> 200万⇒3万、200万⇒9千、200万⇒6百、200万⇒65、と実施したのだ。
> 前者の方法では、例えばこの段階にきて、
> やっぱり出現頻度を300以上でフィルタしよう、などと、
> 最初の方のフィルタ条件を変更するのが面倒になってしまう。
> 200万件と言えど数秒で加工処理できるため、
> **データ分析時には、元データを直接加工していくのではなく、**
> **元データを加工するための処理の方を加工していく**ことが試行錯誤のコツであろう。


# **☆最終結果発表☆**

最終結果を全件表示してみる。
３番目の長い少数表示は、二語間のコサイン類似度。
４番目の整数は、左側の短い方の単語の出現頻度
５番目の整数は、右側の長い方の単語の出現頻度、を表している。

```:結果
neo_ok_result_list
[['スキー', 'スキーム', -0.13419515208393215, 7165.0, 1126.0],
 ['ニュー', 'ニューロン', -0.10364912838437884, 5815.0, 897.0],
 ['スキャン', 'スキャンダル', -0.092226018285575098, 1195.0, 2442.0],
 ['スパイ', 'スパイラル', -0.088847844319257407, 4753.0, 563.0],
 ['ベンチ', 'ベンチャー', -0.088824330928503434, 3899.0, 827.0],
 ['インカ', 'インカレ', -0.085762866261240772, 618.0, 1161.0],
 ['コントラ', 'コントラスト', -0.063370582339257783, 317.0, 826.0],
 ['ライタ', 'ライター', -0.060918882692749594, 105.0, 4923.0],
 ['バイオ', 'バイオリン', -0.059216860907986724, 1276.0, 1096.0],
 ['インチ', 'インチキ', -0.058612502502542588, 1711.0, 284.0],
 ['センサ', 'センサス', -0.057743565788065158, 1283.0, 245.0],
 ['モール', 'モールス', -0.05137301517377077, 2671.0, 384.0],
 ['マンガ', 'マンガン', -0.046533229961732189, 3080.0, 1080.0],
 ['ハング', 'ハングル', -0.031048912685036914, 165.0, 1503.0],
 ['クランク', 'クランクイン', -0.030758980290170358, 1236.0, 504.0],
 ['スポーク', 'スポークスマン', -0.024774720306551101, 777.0, 646.0],
 ['ショウ', 'ショウガ', -0.014971404474667813, 1348.0, 461.0],
 ['グリー', 'グリーン車', -0.014076241876123601, 349.0, 1532.0],
 ['タンカ', 'タンカー', -0.0044118449282145207, 101.0, 2624.0],
 ['カルテ', 'カルテット', 0.0016574398616411093, 330.0, 676.0],
 ['コンパ', 'コンパクト', 0.010144779595334514, 111.0, 4542.0],
 ['メモリ', 'メモリアル', 0.012577233970092142, 7354.0, 1343.0],
 ['ひょう', 'ひょうきん', 0.016368080213603552, 1162.0, 183.0],
 ['ワープ', 'ワープロ', 0.01783541467664003, 1182.0, 476.0],
 ['レジスタ', 'レジスタンス', 0.018659673649099581, 2133.0, 1465.0],
 ['バイアス', 'バイアスロン', 0.020848788324299802, 926.0, 300.0],
 ['当たり', '当たり前', 0.021246857728952878, 13651.0, 1504.0],
 ['ロース', 'ロースター', 0.024721282973940478, 243.0, 2015.0],
 ['クローズ', 'クローズアップ', 0.027729053399044083, 555.0, 774.0],
 ['エンド', 'エンドウ', 0.027949340431128469, 2150.0, 234.0],
 ['コーラ', 'コーラン', 0.032696259344374548, 795.0, 487.0],
 ['アトリ', 'アトリエ', 0.03642163730262455, 215.0, 1865.0],
 ['スロー', 'スローガン', 0.037184666854842938, 1116.0, 3021.0],
 ['コンパ', 'コンパイラ', 0.039925274983369632, 111.0, 2142.0],
 ['フォン', 'フォント', 0.040694686201804671, 3136.0, 2883.0],
 ['エキス', 'エキストラ', 0.043398418401401226, 628.0, 1393.0],
 ['クレー', 'クレーム', 0.044159983012578674, 635.0, 1293.0],
 ['ノーマル', 'ノーマルヒル', 0.048197207046704674, 1372.0, 486.0],
 ['マイクロ', 'マイクロバス', 0.049433007924390773, 1474.0, 494.0],
 ['カンパ', 'カンパニー', 0.051049131726611525, 259.0, 3656.0],
 ['トレード', 'トレードマーク', 0.05219481536254203, 8945.0, 1686.0],
 ['コンテ', 'コンテナ', 0.055752775619473859, 729.0, 4970.0],
 ['ボディー', 'ボディーガード', 0.058728405600372784, 1320.0, 402.0],
 ['インター', 'インターセプト', 0.067499083735317988, 2412.0, 1593.0],
 ['ギャラ', 'ギャラリー', 0.069130402283790207, 917.0, 3768.0],
 ['ファーム', 'ファームウェア', 0.072107443225489287, 1960.0, 544.0],
 ['バッタ', 'バッター', 0.072800521656752215, 624.0, 418.0],
 ['コンビ', 'コンビニ', 0.076142533629960873, 11734.0, 1724.0],
 ['カフェ', 'カフェイン', 0.078036825831140577, 4445.0, 627.0],
 ['てんか', 'てんかん', 0.081548987481624188, 153.0, 1016.0],
 ['ドラマ', 'ドラマー', 0.081668314180719223, 27711.0, 4582.0],
 ['スパイ', 'スパイク', 0.087543831427898094, 4753.0, 1736.0],
 ['コントラ', 'コントラバス', 0.08900678169480801, 317.0, 852.0],
 ['ファンク', 'ファンクラブ', 0.090254464908833196, 1233.0, 2317.0],
 ['スロー', 'スロープ', 0.093195844997826877, 1116.0, 1223.0],
 ['マント', 'マントル', 0.094835109248456256, 1188.0, 796.0],
 ['ゴール', 'ゴールド', 0.094935500605960704, 13392.0, 3735.0],
 ['コンテ', 'コンテスト', 0.095299028190915097, 729.0, 5992.0],
 ['オーラ', 'オーランド', 0.096462142161427802, 1068.0, 781.0],
 ['オーバー', 'オーバーホール', 0.096966179089308741, 2251.0, 1663.0],
 ['タイト', 'タイトル', 0.097158854421062535, 324.0, 58715.0],
 ['スパイ', 'スパイス', 0.10037446570115835, 4753.0, 864.0],
 ['インテリ', 'インテリア', 0.10107180698995391, 506.0, 1887.0],
 ['クレー', 'クレーター', 0.10263301932079097, 635.0, 2354.0],
 ['アウト', 'アウトドア', 0.1071467840487291, 3914.0, 876.0]]
 ```

この長い旅もとうとう最後である。
~~「メロンとメロンパン・ツアー御一行様」は、
きさまにとどめを刺して全滅の最後というわけだな……~~

多少の良くわからない組も残っているものの、
最初にチラ見せしていた以下の単語以外にも結構面白いものが出現していると思う。

* 「スパイ」と「スパイラル」
* 「ワープ」と「ワープロ」
* 「当たり」と「当たり前」
* 「コーラ」と「コーラン」
* 「バッタ」と「バッター」

面白そうな組の例：

* 「バイオ」と「バイオリン」
* 「インチ」と「インチキ」
* 「マンガ」と「マンガン」
* 「コンパ」と「コンパイラ」
* 「ひょう」と「ひょうきん」
* 「カンパ」と「カンパニー」
* 「ドラマ」と「ドラマー」
* 「インテリ」と「インテリア」


#  **あとがき**

## 成果

軽い気持ちで試そうとしたテーマが、
思ったよりも深い検討を必要としてしまった。
途中であきらめかけたこともあった。
だが、あきらめてしまっては何も残らない。
~~成功したところで何が残るのか分からないテーマ~~

最後までたどり着いた今、胸を張ってこう言おう！

 「JavaとJavaScriptなんて同じようなもんだろ？」
 「いや、インテリとインテリアぐらい違うよ！」
 「いや、ドラマとドラマーぐらい違うよ！」
 「いや、コンパとコンパイラぐらい違うよ！」
 「いや、バッタとバッターぐらい違うよ！」
「いや、・・・・・」
**今なら５０倍にして言い返せる。**

## ポエム

今回は、「音」が似ているのに思いもよらない組み合わせ、を
くっ付けて、面白いと思うものを作るという試みであった。

> **「斬新なアイデア」**は、**「笑い」**とよく似ていて、
> どちらも、**思いもよらなかったもの同士が結びつくこと**によって生じる。
> ただし、本当に無関係なもの同士は、結んでもくっ付かないので意味が無い。
> 　　　　　　　　　　～ 　Char Fuitter (1847～1912 オランダ)　～

新しい発想、新しいアイデアを生む人は、
脳の構造として、一見無関係な概念同士にシナプスが張り巡らされている。
瞬時に「飛んだ」発想が出来るのはこのためで、
「飛んだ」後で現実側に戻って来れれば天才と呼ばれるのだが、
戻ってこれない場合も~~もっとずっと~~多いので、天才とナントカは紙一重と言われる。
「飛んだ」とは「常識外の」「常識を壊した」着眼である。
こうした脳の構造になっている人は、普段から変な概念が繋がり、
常識外の行動が増加するため、変人奇人などと表現されることも増加する。
~~（※実際は天才と呼ばれないただの変人の方が多い）~~


宇宙に大きなパネルを打ち上げるために、
「折り紙」の技法を活用して、広い表面積を持つ素材を小さな立体にして打ち上げる、
という研究が進んでいると聞く。
「人工衛星」と「折り紙」は、一見全く無関係に思えるが、
それを結び付けたところが素晴らしい発想なのだと思う。
~~（※アマゾンも素晴らしい「発送」で成功をおさめた）~~

コロンブスが立てた卵を見て、
「なんだ、そんなことなら誰でも出来るよ」と言わずに、
どんな常識が破壊されたのか、考えてみて欲しい。

無関係なものを、おかしな形で結びつけること、
これは、脳にシナプスを増加させ、常識の壁を破りやすくする、
斬新なアイデアを得やすくする、一つの良い方法なのだ。
「笑い」や「遊び」は老化防止の良い薬である。
今回は日本語の音という単純な紐づけ遊びであった。
新しく発見した単語の組み合わせでも、試行錯誤の過程についてでも、
本稿を読んだ人の脳の刺激に一役かえれば幸いと思う。

> 人類の進化は「遊び」からはじまる。
> こんな「遊び」が出来るならば、というアイデアに触発される人がでて、
> 生活にも役に立つような「発明」が生まれるのだ。
> 　　　　　　　　　　～ 　Char Fuitter (1847～1912 オランダ)　～

---

この物語はフィクションです。
登場する人物・団体・名称等は架空であり、
実在のものとは関係ありません。
アンパンマンはスパイの顔は持っていません。
取り替えた古い顔はこの後スタッフがおいしく頂きました。
Char Fuitter （チャー・フイター）は架空の人物です。