Posted at

word2vecを使って「意識高い系」の正体を探る


背景

意識高い系構文ってありますよね。

「今日のアジェンダは例の件のスキームについてコンセンサスを云々」

みたいな奴です。

散々ネット上でもネタにされていますが、正直何を言っているのが全然意味がわからないです。このわかりづらい事この上ない文章を、どうにかして全うな日本語に戻せないものかと考えたのが事の発端でした。

19卒なのにまだフリーターやっている事とかもっと考えるべきことは他にある。


「アジェンダ - 議題 = ?」

意識高い系構文を仕事もせずに眺めていた僕は考えました。そもそも意識高い系構文を意識高い系足らしめる要因はなんなのか。単純に文章内の名詞をカタカナに変換するだけで良いのか、いやそれではただのルー語ではないのか。意識高い系言語と普通の日本語の差は一体何なのか。

そこで一つ実験をしてみることにしました。

語と語の差を調べたいと言えば、有名な「word2vec」の出番です。

word2vecという単語を知っている人ならば大体の方が知っていそうな「王様 - 男 + 女 = 女王」という有名な例があります。

単語の分散表現を用いてベクトル演算ができるという物ですね。

これを用いて、意識高い系言語から言い換え可能な日本語の差をとれば、「意識高い系の正体」を可視化することができるのではないかと考えました。

そして「意識高い系構文」から「意識高い系の正体」を引けば全うな日本語に戻せるのではないかとも。

だんだん自分でも何を言っているのかわからなくなってきた。

実際にやってみましょう。

例として、意識高い系言語に「アジェンダ」を、言い換え可能な日本語に「議題」を用います。

word2vecモデルは、東北大学の乾・岡崎研究室で公開されている、日本語Wikipediaで学習された2017年度版モデル( http://www.cl.ecei.tohoku.ac.jp/~m-suzuki/jawiki_vector/ )を用いました。

> model = gensim.models.KeyedVectors.load_word2vec_format('./entity_vector/entity_vector.model.bin',binary=True)

> print(model.most_similar(positive=['アジェンダ'],negative=["議題"],topn=15))

[('ロボティクス', 0.5401641130447388),
('ヒューマン', 0.5401196479797363),
('フューチャー', 0.5354647636413574),
('ラボラトリー', 0.5315040349960327),
('プラネット', 0.530506432056427),
('noiz', 0.5228562355041504),
('クリエイト', 0.52137690782547),
('ヴァーチャル', 0.5207430720329285),
('トロニクス', 0.516675591468811),
('ビッグデータ', 0.5160026550292969),
('ユビキタス', 0.5153427720069885),
('インテリジェント', 0.5117069482803345),
('IoT', 0.5090150237083435),
('ニューロ', 0.5069350004196167),
('ラボ', 0.506872296333313)]

わからなくもないけれど微妙なレベル。

個人的にはインテリジェントとかがもっと上に来るのを期待していた。

「日本語」 + 「聡明さ」 = 「意識高い系言語」 とかならだいぶわかりやすい。

ちなみにfasttextで同じことをすると一番最初にクリエイティブが出て来るので、直感的にはこちらの方が納得感があった。

「日本語」 + 「創造性」 = 「意識高い系言語」 とか、わからなくもない。

せっかくなのでもう一つ。

意識高い系言語に「イノベーション」を、言い換え可能な日本語に「技術革新」を用います。

> model.most_similar(positive=['イノベーション'],negative=["技術革新"],topn=15)

[('生涯学習', 0.5205152034759521),
('ナレッジ', 0.5183844566345215),
('ウェルネス', 0.5110455751419067),
('クリエイターズ', 0.5037054419517517),
('サポートセンター', 0.4995102882385254),
('スタディーズ', 0.49416717886924744),
('サイエンス', 0.49364593625068665),
('コーディネータ', 0.4899948239326477),
('NPO法人', 0.4891522526741028),
('[八王子_(ラジオドラマ)]', 0.4882795214653015),
('地域創造', 0.4877467453479767),
('お茶の水', 0.48104554414749146),
('ラボ', 0.4790295362472534),
('マネジメント研究科', 0.4764450788497925),
('センタ', 0.4755684733390808)]

やはりそこはかとなく知識関係が上位に来ている気はします。


方針

実験結果から既に多大な不安はありますが、なんとなく「意識高い系」を表す単語が上位に来ている気がしますので、これを足がかりにして「意識高い系」の正体を探っていきましょう。複数の意識高い系言語に対し、上記の演算を行い、共通して出現する単語を探していきます。

そのためにまず、「意識高い系言語集合」を作り、各単語に足して対になる言い換え可能な日本語を収集して「意識高い系言語辞書」を作ります。


辞書作成とデータの可視化

当初の考えでは、tf-idfを用いて意識高い系言語集合を作ろうと考えていたのですが、いいコーパスが見当たらなかったので断念。「意識高い系 例文」で検索して、人手で辞書を作成。まずは50語程収集してデータを可視化してみます。

まずはPCAで次元削減して二次元平面状にプロット。

# -*- coding: utf-8 -*-

import gensim
import pandas as pd
import codecs
from sklearn.decomposition import PCA
import matplotlib
import matplotlib.pyplot as plt
from IPython.display import display
import sys
from sklearn.manifold import TSNE

def convert_vector(x,model):
vector = 0
try:
vector = model[x]
return vector
except:
print(x + " : key_error")
sys.stdout.flush()
return 0
model = gensim.models.KeyedVectors.load_word2vec_format('./entity_vector/entity_vector.model.bin',binary=True)

with codecs.open("business_dict.csv","r","cp932","ignore") as file:
df = pd.read_table(file,delimiter=",")
df["isikitakai_vec"] = df["key"].apply(lambda x : convert_vector(x,model))
df["paraphrase_vec"] = df["value"].apply(lambda x : convert_vector(x,model))

isikitakai_dict = {}
paraphrase_dict = {}
for key,column in df.iterrows():
isikitakai_dict[column["key"]] = column["isikitakai_vec"]
paraphrase_dict[column["value"]] = column["paraphrase_vec"]
isikitakai_df = pd.DataFrame(isikitakai_dict)
paraphrase_df = pd.DataFrame(paraphrase_dict)
vector_df = pd.concat([isikitakai_df,paraphrase_df],axis=1)

pca = PCA(n_components=2)
isikitakai_coordinate = pca.fit_transform(isikitakai_df.iloc[:,:-1].values)
paraphrase_coordinate = pca.fit_transform(paraphrase_df.iloc[:,:-1].values)

fig_pca = plt.figure()
for coordinate in isikitakai_coordinate:
x = coordinate[0]
y = coordinate[1]
ax = fig_pca.add_subplot(1,1,1)
ax.scatter(x,y,c="red")
for coordinate in paraphrase_coordinate:
x = coordinate[0]
y = coordinate[1]
ax = fig_pca.add_subplot(1,1,1)
ax.scatter(x,y,c="blue")
fig_pca.show()

qiita_0407_1.png

うーん、いまいち。

赤くプロットしたものが意識高い系言語、青くプロットしたものが言い換え可能な日本語に置き換えた語ですが、あまり綺麗に分かれていません。意識高い系言語は一箇所に集まっていて、これはword2vecで意識高い系言語を入力するとあまり関係のない意識高い系言語も出力されていたので体感としては納得感があリます。

続いてt-SNEで次元圧縮をしてプロットしてみます。

tsne_model = TSNE(n_components=2)

isikitakai_coordinate_tsne = tsne_model.fit_transform(isikitakai_df.iloc[:,:-1].values)
paraphrase_coordinate_tsne =tsne_model.fit_transform(paraphrase_df.iloc[:,:-1].values)

fig_tsne = plt.figure()
for coordinate in isikitakai_coordinate_tsne:
x = coordinate[0]
y = coordinate[1]
ax = fig_tsne.add_subplot(1,1,1)
ax.scatter(x,y,c="red")
for coordinate in paraphrase_coordinate_tsne:
x = coordinate[0]
y = coordinate[1]
ax = fig_tsne.add_subplot(1,1,1)
ax.scatter(x,y,c="blue")
fig_tsne.show()

qiita0407_2.png

相変わらず微妙な結果ですが、PCAよりも見やすいので対となる語同士を結んで見ましょう。

count = 0

fig_tsne = plt.figure()
for coordinate in isikitakai_coordinate_tsne:
x = coordinate[0]
y = coordinate[1]
ax = fig_tsne.add_subplot(1,1,1)
ax.scatter(x,y,c="red")
for coordinate in paraphrase_coordinate_tsne:
x = coordinate[0]
y = coordinate[1]
ax = fig_tsne.add_subplot(1,1,1)
ax.scatter(x,y,c="blue")
for coodinate_1 in isikitakai_coordinate_tsne:
coordinate_2 = paraphrase_coordinate_tsne[count]
ax = fig_tsne.add_subplot(1,1,1)
if coodinate_1[0] - coordinate_2[0] < 0:
ax.plot((coodinate_1[0],coordinate_2[0]),(coodinate_1[1],coordinate_2[1]),c="green")
print(isikitakai_df)
else:
ax.plot((coodinate_1[0],coordinate_2[0]),(coodinate_1[1],coordinate_2[1]),c="black")
count += 1
if count > 20:
break
fig_tsne.show()

qiita0407_3.png

全部プロットすると見づらいのでとりあえず20本だけプロットしてみます。

黒い線は意識高い系言語が言い換え可能な言語より右側にプロットされており、緑色の線は意識高い系言語が言い換え可能な言語より左側にプロットされています。こうしてみると、特に法則は見出せないので、「意識高い系の正体」の存在が怪しくなってきました。


word2vecによるスコア付け

この辺りで大分諦めムードが漂っていますが、気を取り直してword2vecによってスコア付けをし、「意識高い系の正体」と思われる単語を実際に探してみます。

スコア付けの方法は、順位を考慮して 「1 - (出現順位 - 1) * 0.05」 で計算し、上位10件を出力とします。

import gensim

import pandas as pd
import codecs

with codecs.open("business_dict.csv","r","cp932","ignore") as file:
df = pd.read_table(file,delimiter=",")
model = gensim.models.KeyedVectors.load_word2vec_format('./entity_vector/entity_vector.model.bin',binary=True)

count = 0
score_dict = {}
for key,column in df.iterrows():
word_list = model.most_similar(positive=[column["key"]],negative=[column["value"]],topn=20)
appear_count = 0
for word_tuple in word_list:
word = word_tuple[0]
if word not in score_dict.keys():
score_dict[word] = 1 - 0.05 * float(appear_count)
else:
score_dict[word] = score_dict[word] + 1 - 0.05 * float(appear_count)
appear_count += 1
count += 1
for k, v in sorted(score_dict.items(), key=lambda x: -x[1]):
print(str(k) + ": " + str(v))

#出力結果
-、: 2.0
ユア: 1.9
ポリシー: 1.5499999999999998
アセンブリ: 1.5499999999999998
プロパティ: 1.5
ディメンション: 1.4000000000000001
フューチャー: 1.2999999999999998
セレクタ: 1.25
ムーブ: 1.05
九州松下電器: 1.0

上二つは除外するとして、意識高い系を意識高い系足らしめる要因はポリシーである、というのは意外と悪くない結果かもしれません。

ただ、今回は集めた「意識高い系言語」が少なすぎたため、信頼性に足る結果とは言い難いです。長くなって来たので、次回は「意識高い系言語」をもっと集めて実験を行おうと思います。また、次元削減をした結果を元に、「意識高い系言語」と「言い換え可能な日本語」の関係性を使って、「意識高い系言語集合」を4つの集合にクラスタリングし、各集合に対して「意識高い系の正体」を探してみようと思います。

本当に次回はあるのか?


まとめ

人生で一番多く意識高いって書いた気がする。