2020年もあともう少し、 今年は世界中が大変な1年でした。今年は新型コロナウィルスとかあつもりとかアマビエとか鬼滅の刃とかいろいろあるけど、
これらの言葉がどんな言葉と類似しているかちょっとだけ興味深いです。
fasttext の準備
作業内容
wikipedia の情報でデータ作成
wikipediaのダウンロード
以下のコマンドで、wikipedia の情報をダウンロードします。
$ git clone https://github.com/attardi/wikiextractor.git
日本語版wikipediaのテキストデータを取得
以下のコマンドで、日本語の wikipedia 情報ダウンロードページにアクセスします。
$ wget https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2
wikipediaデータ整形
以下のコマンドで、wikipediaデータの整形を行います。
$ python -m wikiextractor.WikiExtractor -b 500M -o path/to/cprpus ../jawiki-latest-pages-articles.xml.bz2 INFO: Preprocessing '../jawiki-latest-pages-articles.xml.bz2' to collect template definitions: this may take some time. INFO: Preprocessed 100000 pages INFO: Preprocessed 200000 pages INFO: Preprocessed 300000 pages INFO: Preprocessed 400000 pages INFO: Preprocessed 500000 pages INFO: Preprocessed 600000 pages INFO: Preprocessed 700000 pages INFO: Preprocessed 800000 pages INFO: Preprocessed 900000 pages INFO: Preprocessed 1000000 pages INFO: Preprocessed 1100000 pages INFO: Preprocessed 1200000 pages INFO: Preprocessed 1300000 pages INFO: Preprocessed 1400000 pages INFO: Preprocessed 1500000 pages INFO: Preprocessed 1600000 pages INFO: Preprocessed 1700000 pages INFO: Preprocessed 1800000 pages INFO: Preprocessed 1900000 pages INFO: Preprocessed 2000000 pages INFO: Preprocessed 2100000 pages INFO: Preprocessed 2200000 pages INFO: Preprocessed 2300000 pages INFO: Preprocessed 2400000 pages INFO: Preprocessed 2500000 pages INFO: Loaded 88533 templates in 819.9s INFO: Starting page extraction from ../jawiki-latest-pages-articles.xml.bz2. INFO: Using 3 extract processes. INFO: Extracted 100000 articles (1112.8 art/s) INFO: Extracted 200000 articles (1630.0 art/s) INFO: Extracted 300000 articles (1888.5 art/s) INFO: Extracted 400000 articles (2153.1 art/s) INFO: Extracted 500000 articles (2304.0 art/s) INFO: Extracted 600000 articles (2445.7 art/s) INFO: Extracted 700000 articles (2452.0 art/s) INFO: Extracted 800000 articles (2439.3 art/s) INFO: Extracted 900000 articles (2442.4 art/s) INFO: Extracted 1000000 articles (2417.4 art/s) INFO: Extracted 1100000 articles (2355.2 art/s) INFO: Extracted 1200000 articles (2371.2 art/s) INFO: Extracted 1300000 articles (2052.3 art/s) INFO: Extracted 1400000 articles (2117.0 art/s) INFO: Extracted 1500000 articles (2223.3 art/s) INFO: Extracted 1600000 articles (2205.4 art/s) INFO: Extracted 1700000 articles (2269.3 art/s) INFO: Extracted 1800000 articles (2475.3 art/s) INFO: Extracted 1900000 articles (2410.3 art/s) INFO: Finished 3-process extraction of 1997224 articles in 934.8s (2136.5 art/s)
wiki.txt を作成する。(ファイルを一つにまとめます。)
$ cat wiki_0* > wiki.txt
mecab で分かち書き
mecab -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd/ -Owakati wiki.txt -o wiki_wakati.txt -b 32768
fasttext で評価
fasttext コマンドには以下のモードがあるようです。
モード | 概要 |
---|---|
supervised | ラベル付きの教師データから分類器を学習 |
quantize | ラベル付きの教師データから分類器を学習(メモリ使用量を減らすためモデルを量子化するバージョ) |
test | ラベル付きの教師データから分類器を学習 |
test-label | 学習した分類器と任意のデータに対してラベルごとに精度と感度を算出 |
predict | 学習した分類器で予測 |
predict-prob | 学習した分類器で予測 |
skipgram | skipgram アルゴリズムで単語ベクトルを学習 |
cbow | cbow アルゴリズムで単語ベクトルを学習 |
print-word-vectors | 学習した分類器と任意のデータに対してデータに含まれる単語のベクトルを出力 |
print-sentence-vectors | 学習した分類器と任意のデータに対してデータに含まれる文章の平均ベクトルを出力 |
nn | 学習した分類器に対して指定した単語の nearest neighbors を表示 |
analogies | 学習した分類器に対して指定した 単語A - 単語B + 単語C の nearest neighbors を表示 |
dump | 学習した分類器から情報をダンプ |
skipgram アルゴリズムで単語ベクトルを学習
入力ファイルはパスの通るところに配置します。
$ ./fasttext skipgram -input ../wiki_wakati.txt -output wiki.model -dim 300
テスト評価
単語と単語の近さを比較
猫は人よりも犬に近い。。。けど。。。人より草に近いのか。。。
ねこはひとよりも草に近い。。。のか。。。 >>> word_vecs.similarity('猫', '犬') 0.64618886 >>> word_vecs.similarity('猫', '人') 0.22936581 >>> word_vecs.similarity('猫', '魚') 0.3888138 >>> word_vecs.similarity('猫', '草') 0.32002676 >>> word_vecs.similarity('猫', '石') 0.17992988
特定の単語に似ているものを検索
結果はあとでのせてみよう。。。
$ python Python 3.9.0 (default, Dec 9 2020, 00:39:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from gensim.models import KeyedVectors >>> word_vecs = KeyedVectors.load_word2vec_format('~/fastText/wiki.model.vec', binary=False) >>> [print (i) for i in word_vecs.wv.most_similar(positive=['アンジャッシュ'])] ('アンジャッシュ・', 0.9140708446502686) ('児嶋', 0.605518102645874) ('コンビ・ココリコ', 0.5987504720687866) ('ドランクドラゴン', 0.5953443050384521) ('ザコシショウ', 0.5933820009231567) ('ぎやはぎを', 0.5783674716949463) ('オアシズ', 0.5728097558021545) ('キングオブコメディ', 0.5653537511825562) ('ハリウッドザコシショウ', 0.5607682466506958) ('ケンドーコバヤシ', 0.5593159198760986) >>> [print (i) for i in word_vecs.wv.most_similar(positive=['コロナ'])] ('ウイルス', 0.7096765041351318) ('新型', 0.7080405950546265) ('COVID', 0.6902177333831787) ('感染', 0.6101067662239075) ('インフルエンザ・パンデミック', 0.5907289385795593) ('インフルエンザ', 0.5904676914215088) ('ウイルスン', 0.5725395679473877) ('OVID', 0.5702617168426514) ('グローコロナ', 0.5675416588783264) ('2020', 0.5654521584510803) >>> [print (i) for i in word_vecs.wv.most_similar(positive=['アマビエ'])] ('アマビコ', 0.7256805896759033) ('重る', 0.5930653214454651) ('ゃどくろ', 0.53180992603302) ('物尽し', 0.5190485715866089) ('パヨカカムイ', 0.496351957321167) ('アスキーアートキャラクター', 0.4954875111579895) ('妖怪', 0.4913427233695984) ('オヤシロ', 0.49104052782058716) ('コスプレキャラ', 0.4896015524864197) ('ゃんばろう', 0.48786661028862)
流行語大賞で類似語を探してみる
アベノマスク
>>> [print (i) for i in word_vecs.wv.most_similar(positive=['アベノマスク'])] ('布マスク', 0.8525460958480835) ('布製マスク', 0.7562093734741211) ('やるやる詐欺', 0.7026486992835999) ('だてマスク', 0.6979610919952393) ('買ってはいけない', 0.6913561820983887) ('ネット報道', 0.6889148950576782) ('桜を見る会', 0.6832566261291504) ('サージカルマスク', 0.6794693470001221) ('安倍内閣メールマガジン', 0.6772198677062988) ('定額給付金', 0.6766181588172913)
鬼滅の刃
>>> [print (i) for i in word_vecs.wv.most_similar(positive=['鬼滅の刃'])] ('かぐや様は告らせたい', 0.7571939826011658) ('竈門炭治郎', 0.7550870776176453) ('かぐや様は告らせたい~天才たちの恋愛頭脳戦~', 0.7512186765670776) ('長門有希ちゃんの消失', 0.7411877512931824) ('オトナアニメ', 0.7390203475952148) ('ゆらぎ荘の幽奈さん', 0.7386441826820374) ('NARUTO-ナルト-疾風伝', 0.7342469692230225) ('やがて君になる', 0.7341461181640625) ('TVアニメ', 0.7319309115409851) ('鬼灯の冷徹', 0.7310565710067749)
アマビエ
>>> [print (i) for i in word_vecs.wv.most_similar(positive=['アマビエ'])] ('アマビコ', 0.783353328704834) ('あま絵', 0.7148388624191284) ('妖怪', 0.6937016248703003) ('提灯お化け', 0.6908571720123291) ('萌え絵', 0.6823587417602539) ('今昔画図続百鬼', 0.6806477308273315) ('画図百鬼夜行', 0.6705069541931152) ('オジギビト', 0.6696372032165527) ('萌え寺', 0.6682267785072327) ('エボラちゃん', 0.6672184467315674)
ソロキャンプ
>>> [print (i) for i in word_vecs.wv.most_similar(positive=['ソロキャンプ'])] ('ガールズサマーキャンプ', 0.8228516578674316) ('空中キャンプ', 0.7962427139282227) ('どきどきキャンプ', 0.7840174436569214) ('スキーキャンプ', 0.7768822908401489) ('デイキャンプ', 0.7664369344711304) ('ルーキーキャンプ', 0.7661372423171997) ('ハワイキャンプ', 0.7620877027511597) ('スポーツキャンプ', 0.7614426016807556) ('西村キャンプ場', 0.7521942853927612) ('キャンプソング', 0.7495759725570679)