こんにちは、GMOアドマーケティングのS.Rです。
前回は、Colabで大規模データを処理するpysparkというツールの環境を構築する方法を皆さんへ紹介しました。今回はcolabで自然言語処理に良く使われているword2vectorのモデルを利用する方法を皆さんへ紹介します。
1.環境構築
1) pysparkをインストールする
下記のコマンドでpysparkをインストールできます。
1 |
!pip install pyspark |
pysparkの環境構築については前回のブログを参照してください。
2) 形態素解析のツールMecabをインストールする
1 2 3 4 5 6 |
!apt-get -y install mecab libmecab-dev mecab-ipadic mecab-ipadic-utf8 !git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git !sudo apt install file !yes yes | mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -a !pip install mecab-python3 > /dev/null !pip install unidic-lite |
3) Wikipediaのテキストデータを解析するツールをインストールする
1 |
!pip install wikiextractor |
2.学習データをダウンロード
今回の例として日本語のWikipediaの記事を学習データとして使います。下記のURLからWikipediaの記事のデータをダウンロードできます。
1 |
!wget https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 |
Wikipediaの記事のデータをreformatする必要があります。
1 |
!python -m wikiextractor.WikiExtractor -b 500K -o wikipedia jawiki-latest-pages-articles.xml.bz2 |
3. ダウンロードされたWikipediaの記事を形態素解析する
まずMecabを使って形態素解析する関数を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import unicodedata import MeCab NEOLOGD_PATH = "/usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd" def mecab_parse(text): text = unicodedata.normalize('NFC', text) words = [] tagger = MeCab.Tagger(u'-d %s ' % NEOLOGD_PATH + u'-F %m,%H,%s,spliter||spliter') nodes = tagger.parse(text).split(u'spliter||spliter') for node in nodes: if node == 'EOS' or node == "": continue result = node.split(",") if len(result) < 7: continue if result[7] == '*': word = result[0] else: word = result[7] in_dict = result[-1] part = result[1] if part in ["名詞"]\ and len(word) > 0\ and in_dict != u"1": words.append(word.strip()) return words |
Wikipediaの記事から名詞のみで抽出します。今回は例としてwikipedia/AA/wiki_00だけでPandasのDataframeを作ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import pandas as pd articles = [] article_words = [] words = [] article = "" file1 = open('wikipedia/AA/wiki_00', 'r') lines = file1.readlines() for line in lines: if "<doc id=" in line: continue if "</doc>" in line: articles += [article] article_words += [words] words = [] article = "" continue article += line words += mecab_parse(line) wiki_data = pd.DataFrame.from_dict({"article_words": article_words, "article":articles}) wiki_data |
実行した結果は下記です。
4. word2vectorのmodelを学習する
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from pyspark.ml.feature import Word2Vec, Word2VecModel from pyspark.sql.types import StructField,ArrayType, StructType, StringType from pyspark.sql import SparkSession schema = StructType([ StructField("article_words", ArrayType(StringType()), True), StructField("article", StringType(), True)]) SPARK = SparkSession.builder \ .master("local[1]") \ .appName("IAB") \ .getOrCreate() wiki_data_df = SPARK.createDataFrame(wiki_data, schema=schema) VECTOR_SIZE = 50 word2model = Word2Vec(vectorSize=VECTOR_SIZE, minCount=0, inputCol="article_words", outputCol="vector").fit(wiki_data_df) |
5. 記事x Vectorを計算する
1 |
wiki_data_vector = word2model.transform(wiki_data_df).toPandas() |
6. エジプトと距離が近い TOP 10 の記事を抽出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from pyspark.sql.types import StructField,ArrayType, StructType, StringType schema = StructType([ StructField("article_words", ArrayType(StringType()), True)]) keyword_df = SPARK.createDataFrame( [[["エジプト"]]], schema=schema) result_df = word2model.transform(keyword_df).toPandas() keyword_vector = result_df["vector"].iloc[0].reshape(1, -1) from sklearn.metrics.pairwise import cosine_distances distances = [] for v in wiki_data_vector["vector"]: v_array = v.toArray().reshape(1, -1) distances += cosine_distances(keyword_vector, v_array).flatten().tolist() wiki_data_vector["cosine_distance"] = distances top10 = wiki_data_vector.sort_values(by=['cosine_distance']).head(10) top10[["article","cosine_distance"]] |
抽出された記事は下記です。
7. まとめ
今回はColabでpysparkのword2vectorの利用方法を皆さんへ紹介してみました。いかがでしたでしょうか。word2vectorは自然言語処理に良く使われているモデルです。もし今回のブログが皆さんの日々の自然言語処理に関する仕事にお役に立てば幸いです。