北野坂備忘録

主にインストールやプログラミングのメモを載せています。

言語処理100本ノック 2015年版 (96-99)

96. 国名に関するベクトルの抽出

word2vecの学習結果から,国名に関するベクトルのみを抜き出せ.

国名って以前やりましたよね。
81で作った国名リストがあるのでそれを使います。
問題はU.Sみたいな前のリストに入れていない国名をどうするか。
後の設問を見る限り今回は考えなくていいかな……。

#!/usr/bin/env python

import codecs
import re
import numpy as np
import copy

def getallvec(): #全ベクトル読み込み
  npxdict = {}
  fin = codecs.open('90vec.txt', 'r', 'utf_8')
  for line in fin: #読み込み
    string = re.split(" ",line[:-1])
    a = [float(x) for x in string[1:301] ]
    npxdict[string[0]] = copy.deepcopy(np.array(a))
  return npxdict

if __name__ == "__main__":

  worddict = getallvec()

  fin = codecs.open('96c.txt', 'r', 'utf_8')
  for line in fin: #読み込み
    country = line[:-1]
    if country in worddict:
      npa = worddict[country]
      print(country,end=" ")
      for y in npa:
        print(y,end=" ")
      print("")

97. k-meansクラスタリング

96の単語ベクトルに対して,k-meansクラスタリングクラスタ数k=5として実行せよ

k-meansを使ったクラスタリングもRでは経験あるんですがPythonではやったことないなあ。
scikit-learnにはあると思うな……。KMeansというそのままの名前のモジュールがありました。
今までは単語ベクトルを辞書にして持たせていましたが、KMeansで使うにはnumpyのarrayにしなくてはなりません。
getallvec関数を少々変更していきます。

#!/usr/bin/env python

import codecs
import re
import copy
import numpy as np
from sklearn.cluster import KMeans

def getallvec(): #全ベクトル読み込み
  namelist = []
  npxlist = [] 
  fin = codecs.open('96.txt', 'r', 'utf_8')
  for line in fin: #読み込み
    string = re.split(" ",line[:-1])
    a = [float(x) for x in string[1:301] ]
    namelist.append(string[0])
    npxlist.append(copy.deepcopy(np.array(a)))
  npxarray = np.array(npxlist)
  return namelist,npxarray

if __name__ == "__main__":

  namelist,npxarray = getallvec()
#k-meansクラスタリング
  kmeans_model = KMeans(n_clusters=5, random_state=10).fit(npxarray)
  labels = kmeans_model.labels_
  n=0
  for label in labels:
    print(label, namelist[n]) 
    n += 1
結果
1 Afghanistan
0 Albania
0 Algeria
4 American_Samoa
4 Andorra
0 Angola
4 Antarctica
4 Antigua_and_Barbuda
1 Argentina
(略)

98. Ward法によるクラスタリング

96の単語ベクトルに対して,Ward法による階層型クラスタリングを実行せよ.さらに,クラスタリング結果をデンドログラムとして可視化せよ.

どうやらPythonでは階層型クラスタリングは scikit-learnを使うのではなく scipy.cluster.hierarchyを使う模様。デンドログラムも一発で書いてくれます。

#!/usr/bin/env python

import codecs
import re
import copy
import numpy as np
import scipy
from matplotlib.pyplot import show
from scipy.cluster.hierarchy import ward, dendrogram

def getallvec(): #全ベクトル読み込み
  namelist = []
  npxlist = [] 
  fin = codecs.open('96.txt', 'r', 'utf_8')
  for line in fin: #読み込み
    string = re.split(" ",line[:-1])
    a = [float(x) for x in string[1:301] ]
    namelist.append(string[0])
    npxlist.append(copy.deepcopy(np.array(a)))
  npxarray = np.array(npxlist)
  return namelist,npxarray

if __name__ == "__main__":

  namelist,npxarray = getallvec()
#Ward法で階層クラスタリング
  result_w = scipy.cluster.hierarchy.ward(npxarray)
#描画
  dendrogram(result_w)
  show()
結果

f:id:kenichia:20160317221531p:plain

99. t-SNEによる可視化

96の単語ベクトルに対して,ベクトル空間をt-SNEで可視化せよ.

t-SNEはscikit-learnにあります(sklearn.manifold.TSNE)。

#!/usr/bin/env python

import codecs
import re
import copy
import numpy as np
from sklearn.manifold import TSNE
from matplotlib import pyplot as plt

def getallvec(): #全ベクトル読み込み
  namelist = []
  npxlist = [] 
  fin = codecs.open('96.txt', 'r', 'utf_8')
  for line in fin: #読み込み
    string = re.split(" ",line[:-1])
    a = [float(x) for x in string[1:301] ]
    namelist.append(string[0])
    npxlist.append(copy.deepcopy(np.array(a)))
  npxarray = np.array(npxlist)
  return namelist,npxarray

if __name__ == "__main__":

  namelist,npxarray = getallvec()
#t-SNE
  model = TSNE(n_components=2)
  tsne_result = model.fit_transform(npxarray)
#表示
  plt.plot(tsne_result[:,0], tsne_result[:,1], ".")
  plt.show()
結果

f:id:kenichia:20160317221549p:plain
んー?クラスタ化されてないような。これでいいのかな……?
うーん。最後の最後でなにか不完全燃焼な感じがします。

はい、ではこれで「言語処理100本ノック 2015」全問終了です。python3の勉強にはちょうど良かったですね。
一番難しいのは「1/10サンプリングを用いた85. 主成分分析による次元圧縮」じゃないでしょうか。私は1/100のほうしかやっていませんが、それでも苦労しました。挑戦するにしてもノートPC上のVMWare+CentOS内ではさすがに厳しいものがありますし、学生の身でクラウドも使いにくいので、やるのならサーバ上でやってみたいと思います。