面白いデータを探して

適当に書く。間違えていたら教えてください。

DeepWalkでニコニコ動画のタグをベクトル化してみる

前回の記事でDeepWalkの実装を試してみたので、今回はこれを使ってニコニコ動画のタグをベクトル化してみました。
netres-bigdata.hatenablog.com



実装

設計

ニコニコ動画は動画1つに対して、タグを10個まで着けられるようになっています。
たとえば、「サッカースーパープレー集」という動画に「サッカー、スポーツ、スーパープレー、、、、」のように10個までのその動画の特徴を表すタグが付いているようなイメージです。

前回の記事の通り、DeepWalkはグラフ構造の頂点をベクトル化する手法です。
したがって、動画とタグを下の図のように1つのグラフとしてみます。
このグラフに対してDeepWalkを使って動画とタグをベクトル空間に埋め込んでみます。*1

f:id:netres:20180706184256p:plain

データ

ニコニコ動画のデータはAPIを使って取ることができます。
http://site.nicovideo.jp/search-api-docs/search.html
今回はこれを使って、「ゲーム」カテゴリの再生数トップ1600の動画のタイトルとタグの情報を取ってきて利用しました。*2
下のソースコードでは取ってきたデータをniconico.txtというファイルに

'動画タイトル1','タグ1 タグ2 タグ3 ,,,'
'動画タイトル2','タグ2 タグ2 タグ3 ,,,'
,,,,,,

という形式で保存してあることを仮定しています。

ソースコード

import networkx as nx
from gensim.models import Word2Vec as word2vec
import random

# Random Walk を生成するメソッド
# input:
# G Graph(networkx)
# num_of_walk それぞれの頂点から何本のwalkを作るか
# length_of_wake それぞれのwalkの長さ
# output: random walk
def make_random_walks(G, num_of_walk, length_of_walk):
  walks = list()
  for i in range(num_of_walk):
    node_list = list(G.nodes())
    for node in node_list:
      now_node = node
      walk = list()
      walk.append(str(node))
      for j in range(length_of_walk):
        next_node = random.choice(list(G.neighbors(now_node)))
        walk.append(str(next_node))
        now_node = node
      walks.append(walk)
  return walks

# グラフを作る
G = nx.Graph()
title_list = list() # タイトルのリスト
tag_list = list() # タグのリスト
with open("niconico.txt", "r") as f:
  lines = f.readlines()
  for line in lines:
    line = line.split("\n")[0]
    line = line.split("','")
    title_list.append(line[0][1:])
    tags = line[1][:-1].split()
    for tag in tags:
      G.add_edge(line[0], tag)
      if not tag in tag_list:
        tag_list.append(tag)

# ランダムウォークの生成
walks = make_random_walks(G, 30, 10)
# 学習 100次元ベクトル空間に埋め込む
model = word2vec(walks, min_count=0, size=100, window=5, workers=1)
# モデルの保存
model.save("niconico.model")

試してみる

学習したモデルがについていくつか試してみます。
あるタグ(target)に対して、そのタグからの距離が近いタグtop10を出力してみます。
distanceはベクトル空間上の距離です。

例1

target:VOICEROID実況プレイ
1 tag:弦巻マキ実況プレイ distance:5.953795
2 tag:結月ゆかり実況プレイ distance:6.019185
3 tag:もやししゃも distance:6.898383
4 tag:弦巻マキと結月ゆかりの未確認ゲーム日和 distance:6.938107
5 tag:琴葉茜・葵実況プレイ distance:8.381700
6 tag:保証対象外の人 distance:9.278260
7 tag:Steam distance:9.560921
8 tag:VOICEROID実況プレイPart1リンク distance:9.796451
9 tag:VOICEROID+_琴葉_茜・葵 distance:10.449387
10 tag:東北ずん子 distance:10.749527

例2

target:VOCALOID
1 tag:初音ミク distance:6.097374
2 tag:ミクオリジナル曲 distance:6.578449
3 tag:黒うさPカラオケ動画リンク distance:7.268161
4 tag:ニコカラ distance:7.451599
5 tag:DAM&JOY配信中 distance:7.592217
6 tag:黒うさP distance:7.681200
7 tag:VOCALOID伝説入り distance:7.809139
8 tag:ボカロカラオケDB distance:7.870297
9 tag:VOCALOID殿堂入り distance:7.918666
10 tag:VOCALOIDゲーム化計画 distance:7.925536

例3

target:ゼルダの伝説
1 tag:ゼルダの伝説ブレスオブザワイルド distance:2.339339
2 tag:ゲームセンターDX distance:2.470769
3 tag:NX distance:2.818095
4 tag:ニンテンドースイッチ distance:2.874692
5 tag:濱口優 distance:2.903633
6 tag:スーパーマリオオデッセイ distance:2.973674
7 tag:伝説のスタフィー distance:3.006712
8 tag:青沼英二 distance:3.042078
9 tag:NintendoSwitch distance:3.089008
10 tag:CM distance:3.100342

例4

target:サッカー
1 tag:イナズマイレブン distance:3.834117
2 tag:原宿時代の精鋭 distance:3.900559
3 tag:かかと落とし distance:3.961666
4 tag:集団リンチ distance:4.149393
5 tag:五体大満足 distance:4.297897
6 tag:少林サッカー distance:4.492642
7 tag:三国太一 distance:4.522351
8 tag:FIFA distance:4.554486
9 tag:審判仕事しろ distance:4.749338
10 tag:ロックマン distance:4.764637

例5

target:任天堂
1 tag:ゲームセンターCX distance:9.614812
2 tag:Nintendo_Switch distance:9.621600
3 tag:濱口優 distance:9.637425
4 tag:ポケットモンスター distance:9.800506
5 tag:ゲームPV distance:9.819017
6 tag:ニンテンドースイッチ distance:9.948117
7 tag:ゼルダの伝説 distance:10.031701
8 tag:ゲームセンターDX distance:10.069140
9 tag:ゼルダの伝説ブレスオブザワイルド distance:10.210435
10 tag:ゲームCM50連発 distance:10.309316

割とそれっぽい結果が出ているのではないでしょうか。

結果

DeepWalkを使ってタグをベクトル空間に埋め込んで見たところ、何となくいい感じの結果が得られました。

*1:このように隣り合う全ての頂点を異なる2色で塗り分けることができるグラフを2部グラフと言います。

*2:取ったデータを公開していいものなのかわからなかったため、使ったデータ本体は公開しません。