言語処理100本ノック2020年版を解いてみた【第7章:単語ベクトル 67】

東北大乾・岡崎研(現乾・鈴木研)で作成された、新人研修の一つであるプログラミング基礎勉強会の教材『言語処理100本ノック 2020年版』をPython(3.7)で解いた記事です。
今回は第7章:単語ベクトルの「67. k-meansクラスタリング」を解説します。

独学でPythonを勉強してきたので、間違いやもっと効率の良い方法があるかもしれません。
改善点を見つけた際はご指摘いただけると幸いです。

ソースコードはGitHubにも公開しています。

第7章:単語ベクトル

単語の意味を実ベクトルで表現する単語ベクトル(単語埋め込み)に関して,以下の処理を行うプログラムを作成せよ.

第7章: 単語ベクトル – 言語処理100本ノック 2020 (Rev 1) – NLP100 2020

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

国名に関する単語ベクトルを抽出し,k-meansクラスタリングをクラスタ数k=5として実行せよ.

第7章: 単語ベクトル – 言語処理100本ノック 2020 (Rev 1) – NLP100 2020
import pandas as pd
import numpy as np
from gensim.models import KeyedVectors
from sklearn.cluster import KMeans


CLUSTER_NUM = 5

# 国名データ:http://www.fao.org/countryprofiles/iso3list/en/
countries = pd.read_table("./input/countries.tsv")
countries = countries["Short name"]

model = KeyedVectors.load_word2vec_format("./input/GoogleNews-vectors-negative300.bin", binary=True)

country_vecs = []
country_names = []
for country in countries:
    if country in model:
        country_vecs.append(model[country])
        country_names.append(country)

kmeans = KMeans(n_clusters=CLUSTER_NUM, random_state=0)
kmeans.fit(country_vecs)
for i in range(CLUSTER_NUM):
    cluster = np.where(kmeans.labels_ == i)[0]
    print("cluster:", i)
    print(", ".join([country_names[j] for j in cluster]))

国名データは用意されていないので、外部から持ってきましょう。
ぼくの場合はCountry codes/names | FAO | Food and Agriculture Organization of the United Nationsから取得しました。

pandasのread_table()を使ってデータを読み込んで、Short name列を取得します。

国名1つずつ抽出し、読み込んだモデルに対してモデル内に国名があれば単語ベクトルと国名をリストに追加します。

学習用のデータの準備が完了したら、n_clustersのパラメーターを指定された5に設定してscikit-learnのk-meansクラスを呼び出します。

fit()メソッドを用いてデータをクラスタリングして結果を出力。
numpyのwhere()メソッドを用いて各ラベルのデータを出力しています。
最終的にクラスターのラベルとjoin()メソッドでクラスター内の国名を結合して解答となります。

まとめ:k-meansで任意のクラスターに分類!

今回は第7章:単語ベクトルの「67. k-meansクラスタリング」を解いてみました。

k-meansは分割したいクラスター数が決まっている場合に簡単に分類できて便利そうですね!
ただし、初期値の値によって結果が大きく異なる場合があるので、そこは要注意です…!

「ここはもっとこういう書き方がいいですよ!」「これはアンチパターンですよ!」など、言いたいことがある方はぜひコメントいただければと思います。

引き続きよろしくお願いします!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です