gensim-word2vecでベクトル空間を試す
gensim-word2vecでベクトル空間を試す(2)
gensim-word2vecでベクトル空間を試す(3)
(続きです)
さて、この辺でword2vecの学習元データ(日本語Wikipediaソースを分かち書きにしたもの)の中身を確かめてみたくなった。
何で今まで放っておいたのか、というツッコミは頭を掻くとして…
分かち書きの出現頻度を数えてみた。
〜〜〜〜 〜〜〜〜 〜〜〜〜
次に、出現頻度順の上位の約590語(出現頻度が40回までのもの)を対象にして、これらがランダムな分野から取られていると仮定して、単語間距離による多次元尺度法による分析を試みる。
2通りの作図をする。1つは全体を概観する、もう1つは詳細を見る、というものである。
全体を概観すると、下図のようになる。全体は縦軸が非常に薄い扁平な分布であり、縦軸の値はおよそ1e-06から-5e07程度であるのに対して、横軸は10から-10程度である。
次に、詳細を見る。
ブラウザでこの図をクリックし、拡大表示することで、ある程度図の内容が確認できると思う。
(2015-07-19)
上の図がよく分からないので、全ボキャブラリを、k-meansでクラスタ化してみる
scikit-learnsパッケージにあるk-means (元はsci.pyを呼び出しているらしいが)を使った xmeansというパッケージがあったので、使ってみる。
xmeansのポイントは、k-meansでのクラスタ数kをいろいろと試して、いいものを見つける、という部分。詳細は
それで、既にボキャブラリの中の語のベクトルを書き出したcsv形式のファイルが作ってあるので、 それを読み込んでk-meansに食わせることになる。
プログラム:
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' 昔作った出現回数トップ500語のリストをファイルwp500words.outからCSVとして読み込む。 このファイルはCSV形式で各行が、第1欄に"語", 第2欄以降200欄にnumpyベクトル となっている。 読んだ結果は、連想配列words{語, numpyベクトル}に入れる。 次に、これをxclusterで、クラスタ化し、matplotlibで表示する。 ''' import sys, string, codecs import csv import numpy as np import xmeans sys.stdout = codecs.getwriter('utf_8')(sys.stdout) argvs = sys.argv; argc = len(argvs) # ベクトルをファイルから読み込む if (argc==2): infname = argvs[1] else: infname = "wp500words.out" print infname with open(infname, "rb") as f: dat = [] reader = csv.reader(f) for row in reader: dat.append(row[1:]) ndat = np.array(dat, dtype=float) print ndat.shape x_means = xmeans.XMeans(random_state = 1).fit(ndat) print(x_means.labels_) print(x_means.cluster_centers_) print(x_means.cluster_log_likelihoods_) print(x_means.cluster_sizes_)
また、中で呼んでいるxmeans.pyは
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 以下の論文で提案された改良x-means法の実装 クラスター数を自動決定するk-meansアルゴリズムの拡張について http://www.rd.dnc.ac.jp/~tunenori/doc/xmeans_euc.pdf """ import numpy as np from scipy import stats from sklearn.cluster import KMeans class XMeans: """ x-means法を行うクラス """ def __init__(self, k_init = 2, **k_means_args): """ k_init : The initial number of clusters applied to KMeans() """ self.k_init = k_init self.k_means_args = k_means_args def fit(self, X): """ x-means法を使ってデータXをクラスタリングする X : array-like or sparse matrix, shape=(n_samples, n_features) """ self.__clusters = [] clusters = self.Cluster.build(X, KMeans(self.k_init, **self.k_means_args).fit(X)) self.__recursively_split(clusters) self.labels_ = np.empty(X.shape[0], dtype = np.intp) for i, c in enumerate(self.__clusters): self.labels_[c.index] = i self.cluster_centers_ = np.array([c.center for c in self.__clusters]) self.cluster_log_likelihoods_ = np.array([c.log_likelihood() for c in self.__clusters]) self.cluster_sizes_ = np.array([c.size for c in self.__clusters]) return self def __recursively_split(self, clusters): """ 引数のclustersを再帰的に分割する clusters : list-like object, which contains instances of 'XMeans.Cluster' """ for cluster in clusters: if cluster.size <= 3: self.__clusters.append(cluster) continue k_means = KMeans(2, **self.k_means_args).fit(cluster.data) c1, c2 = self.Cluster.build(cluster.data, k_means, cluster.index) beta = np.linalg.norm(c1.center - c2.center) / np.sqrt(np.linalg.det(c1.cov) + np.linalg.det(c2.cov)) alpha = 0.5 / stats.norm.cdf(beta) bic = -2 * (cluster.size * np.log(alpha) + c1.log_likelihood() + c2.log_likelihood()) + 2 * cluster.df * np.log(cluster.size) if bic < cluster.bic(): self.__recursively_split([c1, c2]) else: self.__clusters.append(cluster) class Cluster: """ k-means法によって生成されたクラスタに関する情報を持ち、尤度やBICの計算を行うクラス """ @classmethod def build(cls, X, k_means, index = None): if index == None: index = np.array(range(0, X.shape[0])) labels = range(0, k_means.get_params()["n_clusters"]) return tuple(cls(X, index, k_means, label) for label in labels) # index: Xの各行におけるサンプルが元データの何行目のものかを示すベクトル def __init__(self, X, index, k_means, label): self.data = X[k_means.labels_ == label] self.index = index[k_means.labels_ == label] self.size = self.data.shape[0] self.df = self.data.shape[1] * (self.data.shape[1] + 3) / 2 self.center = k_means.cluster_centers_[label] self.cov = np.cov(self.data.T) def log_likelihood(self): return sum(stats.multivariate_normal.logpdf(x, self.center, self.cov) for x in self.data) def bic(self): return -2 * self.log_likelihood() + self.df * np.log(self.size) if __name__ == "__main__": import matplotlib.pyplot as plt # データの準備 x = np.array([np.random.normal(loc, 0.1, 20) for loc in np.repeat([1,2], 2)]).flatten() y = np.array([np.random.normal(loc, 0.1, 20) for loc in np.tile([1,2], 2)]).flatten() # クラスタリングの実行 x_means = XMeans(random_state = 1).fit(np.c_[x,y]) print(x_means.labels_) print(x_means.cluster_centers_) print(x_means.cluster_log_likelihoods_) print(x_means.cluster_sizes_) # 結果をプロット #plt.rcParams["font.family"] = "Hiragino Kaku Gothic Pro"VL Gothic plt.rcParams["font.family"] = "VL Gothic" plt.scatter(x, y, c = x_means.labels_, s = 30) plt.scatter(x_means.cluster_centers_[:,0], x_means.cluster_centers_[:,1], c = "r", marker = "+", s = 100) plt.xlim(0, 3) plt.ylim(0, 3) plt.title(u"改良x-means法の実行結果 参考: 石岡(2000)") plt.show() # plt.savefig("clustering.png", dpi = 200)
結果は、
上位ボキャブラリ wp500words.out の場合
(590, 100)
[1 1 0 0 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 1 1 0 0 1 0 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 0 1 0 0 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 0 1 1 1 0 0 1 0 0 1 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 0 0 1 1 1 1 0 1 1 0 0 1 0 1 1 0 0 1 1 1 1 1 1 1 1 1 0 1 1 0 1 0 1 0 1 0 0 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 0 0 1 0 0 0 0 1 0 0 1 1 1 0 1 1 1 0 0 0 1 1 0 1 0 1 0 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 1 0 1 0 0 1 0 1 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 0 1 1 0 0 0 1 1 1 1 0 0 1 1 1 0 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 0 1 1 0 1 1 0 1 1 0 1 0 1 1 0 1 0 1 1 0 0 1 0 1 1 0 0 1 1 0 1 0 1 1 0 0 0 0 0 0 1 0 1 0 1 1 0 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 1 0 0 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0] [[ -1.20686099e-01 3.85187179e-02 1.38309300e-01 1.10604316e-01 -4.75689712e-02 3.10646304e-02 9.41132463e-02 -5.70251271e-02 -8.26290200e-02 1.69705502e-01 -5.27724118e-03 3.47696863e-02 7.51235630e-02 -3.38987530e-02 -2.77249460e-01 1.00363509e-01 -7.61209042e-02 -1.08001802e-01 2.00861811e-01 -4.92251180e-02 -2.04249165e-02 -6.98459397e-02 -7.74254784e-03 1.65775033e-01 2.03269792e-02 -1.14642509e-01 -1.43948051e-02 2.36037434e-01 1.24181231e-01 1.23971916e-01 3.40378137e-02 -1.15228243e-01 -5.64316890e-02 3.92804168e-03 5.02002672e-02 1.71132601e-01 5.68151706e-03 1.73304358e-01 9.76300130e-02 1.59595452e-01 -7.55954265e-02 3.01412379e-03 5.26031980e-02 9.21203577e-02 -9.96372887e-02 1.58033987e-01 7.82006470e-02 -4.98887212e-02 -1.39622893e-01 -1.14794670e-01 -4.94301317e-02 -3.65500695e-02 -9.27763663e-02 1.42568130e-01 -1.49269712e-01 1.11659365e-02 -2.93288459e-02 5.18730953e-04 -5.80049784e-02 -1.40768767e-01 2.38481340e-01 -3.24637766e-02 -1.22973551e-01 1.26524352e-01 1.76933846e-01 -2.21941069e-02 -8.08499012e-03 1.28241439e-02 -2.09521374e-02 1.58220951e-01 -7.32549001e-02 -1.67406742e-01 1.06393727e-01 -3.26073499e-02 5.64578209e-02 4.93067892e-02 -7.39306547e-02 -3.08722195e-02 -1.44130732e-01 -9.19578088e-02 8.68038241e-02 -4.44418239e-02 -2.07526746e-01 5.08312192e-02 -2.48574692e-02 -8.06796804e-02 -1.59373350e-01 5.75102444e-02 2.98243344e-02 -2.03769129e-01 -4.87509188e-02 -9.31687239e-02 -7.31808008e-02 8.51248470e-02 -2.93075279e-02 1.88361095e-01 -1.66319117e-01 -3.41247258e-02 5.20694389e-02 3.65269337e-02] [ 1.31880479e-02 -2.54030544e-02 -9.85077906e-03 1.33283218e-01 -8.82072404e-02 1.29692509e-01 -5.42415829e-02 1.18031027e-01 9.78549139e-02 1.12305881e-01 9.13690381e-02 -1.31832874e-01 8.37297763e-02 2.41835173e-02 -8.54147521e-02 -1.39736877e-01 -1.85013070e-02 -4.06359359e-02 1.84170983e-01 -7.40005078e-02 5.69715734e-03 -2.68203533e-01 7.33174624e-02 -5.22390048e-02 -1.90901346e-01 -8.09358819e-02 5.72223504e-02 2.23685524e-01 9.29161701e-02 1.19009357e-01 -1.02789471e-02 -1.25032568e-01 6.85472149e-02 -1.26003613e-02 7.71010544e-02 2.23108091e-01 -2.62769098e-02 8.61013968e-02 9.17636307e-02 8.78758788e-02 -7.91155440e-02 -5.66718362e-02 1.04390166e-01 1.73663330e-01 5.72330463e-02 2.19457060e-01 -1.67473094e-01 1.31863359e-01 -1.11859081e-01 -1.11725822e-01 1.78922039e-01 1.44327744e-02 -7.59846351e-02 -1.46366834e-02 1.44038041e-03 -7.34339256e-02 -5.20506598e-02 2.01296802e-02 -1.05705819e-01 3.48269317e-02 1.55090163e-01 5.37089877e-03 -5.55236702e-02 5.55721898e-02 3.36478897e-02 8.93140895e-02 3.65625906e-02 7.35926388e-02 1.09131269e-04 6.64482816e-02 -8.57760260e-02 -6.93624111e-02 7.34368843e-04 -8.45565492e-02 1.94706984e-01 -1.40949526e-01 -2.20409663e-02 -9.78588215e-02 -4.52674513e-02 -1.08962615e-01 3.48923050e-02 -1.28841058e-01 -1.87955668e-01 1.02655352e-02 -8.59925034e-02 7.16263888e-02 -3.71724417e-02 -6.65355592e-02 -2.43770339e-01 -5.06753503e-03 -6.83220400e-02 4.93701893e-02 -1.31725846e-01 1.24237397e-01 8.62606164e-02 1.87323804e-02 -9.43093694e-04 1.34606443e-01 -4.25687426e-02 6.45941934e-02]] [ 16208.85417643 10888.41537073] [322 268]
ということで、2クラスタ(それぞれが322語, 268語)にしかならかなった。 おそらくは非常に分散していて、クラスタとして認識できなかったと思われる。
全ボキャブラリ wpallwords.out の場合
(5176, 100) [1 1 1 ..., 1 0 1] [[-0.13191395 -0.0248849 0.1430598 0.12306257 -0.07450798 0.00646811 0.09359275 -0.07826383 -0.04159682 0.19700889 0.03652305 0.06700165 0.10931797 -0.03293728 -0.25659822 0.09524981 -0.05388804 -0.13426066 0.26013381 -0.06362121 -0.04405031 -0.10492961 -0.00140841 0.20102812 0.00657807 -0.08544728 0.08140551 0.25900133 0.07079124 0.08577857 0.03910614 -0.10753588 -0.05729731 0.01935761 0.11222613 0.1467138 -0.00473657 0.06138889 0.07425032 0.16794309 -0.06690123 -0.03610357 0.05897139 0.01083048 -0.04415719 0.1494636 0.06852383 0.05837666 -0.09962659 -0.10883703 -0.06343212 0.00797467 -0.05952508 0.15421827 -0.17280034 0.04149284 -0.02401073 -0.02972178 -0.08935874 -0.17432829 0.19173001 0.04249168 -0.06739018 0.07295972 0.18923592 -0.05475225 0.01638102 0.06062523 -0.05627156 0.11068116 -0.07386442 -0.17519372 0.09368976 -0.06474553 0.03360312 0.03506369 -0.05209505 -0.03938096 -0.1331233 -0.05373295 0.04537114 -0.05383895 -0.19732957 0.05895715 -0.03302607 -0.06516841 -0.14248325 0.08375861 0.04440468 -0.21176673 -0.01356284 -0.12578804 -0.02089717 0.05496296 -0.03791425 0.23603258 -0.11518421 -0.00337393 0.04839361 0.02624207] [-0.02066534 -0.01158693 0.03691795 0.09540584 -0.05042948 0.12406175 -0.04131038 0.0781226 0.07254279 0.05508153 0.03313755 -0.13510344 0.04733497 0.01709512 -0.08509257 -0.12919603 -0.05339178 -0.00826791 0.04803555 -0.08020149 -0.01233557 -0.21500708 0.04565839 -0.01903055 -0.13970072 -0.10251378 0.01163783 0.13408184 0.10450967 0.12126194 0.00817289 -0.04455414 0.08958532 -0.0274446 0.06401944 0.14714249 0.02249278 0.04116854 0.05052156 0.07348924 -0.0211888 -0.08057152 -0.00375203 0.1371551 0.05578472 0.10381077 -0.1196903 0.12013696 -0.0610813 -0.06193025 0.11480575 0.01288549 -0.04077632 -0.00266693 0.01593739 -0.04324223 0.04660021 -0.09035241 -0.09708149 0.02909314 0.08207993 0.01998113 -0.01133956 0.03398011 0.0310528 0.04943719 -0.00622721 0.07239436 0.02638805 -0.0364055 -0.13151013 -0.0766993 -0.03492899 -0.07233917 0.13025182 -0.0292393 -0.04808092 -0.0524468 -0.04153711 -0.06361494 -0.01272261 -0.01143723 -0.13510149 0.01049757 -0.06178603 0.07670733 0.00937329 -0.03125577 -0.1496305 0.03684528 -0.12286579 0.03122464 -0.07037145 0.07408756 0.04710795 0.01280504 0.01431312 0.05152565 -0.01090218 -0.0506355 ] [-0.11184239 -0.28264037 0.32677876 0.14855827 -0.21353295 0.263305 -0.18366362 0.37962839 -0.01381245 0.0355929 -0.27796656 -0.12545008 -0.13272248 0.11515194 -0.17814173 -0.53011036 0.18568002 0.32117757 -0.0150351 -0.20357954 -0.04223859 0.16294926 -0.2658966 0.38009089 0.21100864 -0.37237772 -0.29567207 0.21866073 0.28875229 -0.04777135 0.13560663 -0.03867145 -0.22243745 -0.20730813 -0.06147448 0.08736833 0.02659063 0.06632055 -0.09043126 0.0277067 0.32708776 -0.12565948 0.22277999 0.1079998 0.0331694 0.05499604 0.13138529 -0.05932007 0.04301388 0.07686359 -0.02671375 -0.01229028 0.00598564 -0.48022952 -0.21276585 0.0013294 -0.01768171 0.22690265 0.20604533 0.11481116 -0.08836293 0.15036193 -0.06484719 -0.21860142 -0.05953721 0.14216542 0.13847516 0.07291732 0.01729672 -0.27492737 0.28349704 -0.22654794 -0.05379034 0.09650781 0.0385203 0.2528412 -0.06989203 -0.13764652 0.24784211 -0.18245202 -0.09886073 -0.12844509 -0.10419787 -0.08720143 0.30057128 -0.11195836 0.22308901 0.08907373 -0.11001518 -0.04157664 0.08767545 0.00814359 -0.22805293 -0.29677902 -0.11712225 0.03854134 0.0756648 -0.21597487 -0.01663512 -0.08178534]] [ 73649.74187201 33936.68768974 8591.77371155] [2406 2411 359]
ということで、3クラスタ(それぞれが2406語, 2411語, 359語)になった。 この場合も、上位500語と同様に、クラスタ数が非常に少ない。分散した結果になっている と思われる。