word2vecでemojiからiモード絵文字に変換する

# tr;dr

CAの平成最後のハッカソンでemojiからiモード絵文字に変換するシステムを自然言語処理と機械学習を使って実装したので，紹介する．形態素解析にはMeCab,機械学習にはWord2Vecを用いた．emojiとiモード絵文字を一度ベクトルし，コサイン類似度を用いて，類似度が高いiモード絵文字を出した．このような手法を用いることで，約1000個あるemojiすべてを約170個のiモード絵文字に変換できる.

![iモード絵文字_結果.003.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156101/b7462435-3a8e-52b7-f3f4-550f4bce2c0d.jpeg)

# どうやるか

[emoji-ja](https://github.com/yagays/emoji-ja)を使って，emojiのラベルを獲得する．そして，単語をベクトルを獲得する．次にiモード絵文字のラベルをベクトル化し，emojiのラベルと類似度の高いiモード絵文字を提案する

# 使う技術

- MeCab
- Word2vec
- selenium(スクレイピング)
- urllib(画像ダウンロード)

# 方法

## 1.スクレイピングでiモード絵文字をダウンロード

https://www.nttdocomo.co.jp/service/developer/make/content/pictograph/basic/index.htmlからスクレイピングしてダウンロードする

```python
from selenium import webdriver
import urllib.request


driver = webdriver.Chrome("chromedriverのディレクトリ")
driver.get("https://www.nttdocomo.co.jp/service/developer/make/content/pictograph/basic/index.html")

# 画像のURL
src = driver.find_element_by_xpath("""//*[@id="maincol"]/div[1]/div/div/table/tbody/tr[4]/td[2]/img""").get_attribute("src")
# 画像の名前
alt = driver.find_element_by_xpath("""//*[@id="maincol"]/div[1]/div/div/table/tbody/tr[4]/td[7]/span""")

# 画像をダウンロードし画像の名前で保存
urllib.request.urlretrieve(src, save_dir+alt+'.png')
```

これを176枚分繰り返す

```python
for i in range(4,180):
    xpath_src = """//*[@id="maincol"]/div[1]/div/div/table/tbody/tr[{}]/td[2]/img""".format(i)
    xpath_alt = """//*[@id="maincol"]/div[1]/div/div/table/tbody/tr[{}]/td[7]/span""".format(i)
    src = driver.find_element_by_xpath(xpath_src).get_attribute("src")
    alt = driver.find_element_by_xpath(xpath_alt).text
    urllib.request.urlretrieve(src, save_dir+alt+'.png')
```

## 2.word2vecの学習済みモデルを読み込む

[http://www.cl.ecei.tohoku.ac.jp/~m-suzuki/jawiki_vector/](http://www.cl.ecei.tohoku.ac.jp/~m-suzuki/jawiki_vector/)から[20170201.tar.bz2](http://www.cl.ecei.tohoku.ac.jp/~m-suzuki/jawiki_vector/data/20170201.tar.bz2) (2017年2月1日版, 1.3GB, 解凍後 2.6GB)をダウンロードし，

モデルを読み込む．

```python
from gensim.models import KeyedVectors

model_dir = "entity_vector.model.bin"

model = KeyedVectors.load_word2vec_format(model_dir, binary=True)
```

## 3.emojiをベクトル化する

📙UNICODE絵文字の日本語読み/キーワード/分類辞書📙

https://github.com/yagays/emoji-ja

を使用して，emojiの日本語読みを獲得する．

中身はこんな感じである．今回は"keywords"にあたる部分を使用した．

```json
"🍺": {
        "keywords": [
            "ジョッキ",
            "バー",
            "ビール",
            "ビールジョッキ",
            "居酒屋"
        ],
        "short_name": "ビールジョッキ",
        "group": "飲み物と食べ物",
        "subgroup": "飲み物"
}
```

emoji_ja.jsonを読み込む

```python
# emojiの読み込み
emoji_dir = "{emoji_ja.jsonのパス}"
emoji_json_file = open(emoji_dir, "r")
emoji_json = json.load(emoji_json_file)
```

emojiに対する日本語のリストを取得

```python
def emoji_to_text_lists(emoji):
    text_lists = emoji_json[emoji]["keywords"]
    return text_lists
##こんなのが返ってくるよ的な記述
```

emojiをベクトル化(無駄に再帰を使ってみた卍)

```python
def emoji_to_vector(word_list, word_i=0):
    if word_i > 10:
        return np.zeros(200)
    try:
        vector = model.wv[word_list[word_i]]
    except:
        word_i = word_i + 1
        vector = emoji_to_vector(word_list, word_i)
    return vector
```

## 4.iモード絵文字をベクトル化

iモード絵文字のファイルを読み込んで，名前だけのリストを作る．

```python
from glob import glob
# imode_emojiの読み込み
imode_emoji_paths = glob("imode_emoji_data/*")

imode_emoji_lists = []
# ファイルパスから名前だけのリストを作成する
for imode_emoji_file_path in imode_emoji_paths:
    imode_emoji_lists.append(os.path.splitext(os.path.basename(imode_emoji_file_path))[0])
```

iモード絵文字の名前をベクトル化する関数を用意する

```python
def imode_emoji_to_vector(text):
    try:
        imode_emoji_vector = model.wv[text]
    except:
        imode_emoji_vector = np.zeros(200)
    return imode_emoji_vector
```

## 5.類似度計算式の関数を用意する

今回，コサイン類似度計算式を用意した．

```python
def cos_sim(v1, v2):
    return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
```

## 6.emojiから最も類似度が高いiモード絵文字を出す

emojiを引数に，iモード絵文字のファイル名を返す関数を用意した．

~~できれば，最適化したい~~

```python
def emoji_to_imode_emoji(emoji):
    max_simi_rate = 0
    max_simi_word = ""
    emoji_vector = emoji_to_vector(emoji_to_text_lists(emoji))

    for imode_emoji_name in imode_emoji_lists:
        # print(imode_emoji_name)
        imode_emoji_vector = imode_emoji_to_vector(imode_emoji_name)
        simi_rate = cos_sim(emoji_vector, imode_emoji_vector)
        if max_simi_rate < simi_rate:
            max_simi_rate = simi_rate
            max_simi_word = imode_emoji_name

    return max_simi_word + ".png"
```

# 結果

## いい結果

![iモード絵文字_結果.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156101/bfc599e3-2d02-8e52-63ae-498e80003012.jpeg)


## 悪い結果

![iモード絵文字_結果.002.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156101/f8131530-ea56-f120-7e4d-d59629ce83aa.jpeg)


# まとめ

- 自然言語処理と機械学習を用いて，emojiをiモード絵文字に変換した．
- 割といい結果が出たと思う（定量化はしてない）
- "モバQ","iモード"などに対応するemojiを見つけたい

# 最後に

今回，平成最後のハッカソンにて，「平成のコミュニケーション手段を体験するシステム」を開発するために，このようなものを開発することができました．

僕のシステムが出した結果をいい感じにWebアプリで表示してくれるにしてくれた[@kubo_programer](https://twitter.com/kubo_programer)さん，[@ptero1d](https://twitter.com/ptero1d)さん，一緒にチームを組んでくれてありがとうございました．

そして，平成最後のハッカソンを企画してくださったCyberAgentの皆さんありがとうございました．
感謝の意を込めて，タップルに課金して恋愛楽しみます！（笑）
ソースコードは[こちら](https://github.com/KohheiAdachi/heisei_chat_ml)です.