接着剤の精進日記

競プロでの精進や研究に関係したことを書いていきます。

Wikipediaコーパスを使った,word2vecのモデル作成

はじめに

今回は,word2vecのモデルをWikipediaの記事本文を使って作成していきます.
以下参考記事です.ほとんど以下の記事に沿って進めました.
qiita.com

環境

Linux(CentOS7)
Python3.6
今回はLinuxサーバ上で行いましたが,Macなどのターミナルでも同様にできると思います.

コーパスの準備

コーパス作成の流れ
1.日本語版Wikipedia記事のXMLをダウンロードする
2.WikiExtractorというツールを利用し,XMLファイルから記事本文だけを抽出する

まず最初に,WikiExtractorをgitからcloneしてきます.

git clone https://github.com/attardi/wikiextractor.git

wikiextractorというディレクトリができているので移動します.

cd wikiextractor

次に,Wikipedia記事のXMLファイルをダウンロードします.

curl https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 -o jawiki-latest-pages-articles.xml.bz2

とすることでダウンロードできます.
容量が約2GBほどあるので,時間がかかります.

ダウンロードが終わったら,先ほどcloneしてきたWikiExtractorを使用し,
XMLファイルから,記事本文を抽出します.
使い方は以下の通り,インストールし,コマンドを入力することで抽出できます.

sudo python setup.py install
python WikiExtractor.py jawiki-latest-pages-articles.xml.bz2

先程と同様抽出に時間がかかるので,しばらく待ちましょう.
抽出が終わると,textというディレクトリが新たにできます.

作成されたtextディレクトリには,複数ファイルに分割されているので
それを一つのtxtファイルにまとめます.

find text/ | grep wiki | awk '{system("cat "$0" >> wiki.txt")}'

とすることでwiki.txtという一つのファイルに出力できます.

以上でコーパスの準備は終わりです.

word2vecのモデル作成

コーパスを作成したので,これを利用してword2vecのモデルを作成します.

モデルの作成には,gensimを使用します.
pipでインストールできます.

pip install --upgrade gensim

gensimでモデルを作成する際には,コーパスわかち書きにする必要があるので
mecabを用いて,コーパスをわかち書きにします.
mecabのインストール方法は以下の記事などを参考にしてください.
qiita.com

mecabがインストールされたら,以下のコマンドでコーパスをわかち書きにします.

mecab -Owakati wiki.txt -o wiki_wakati.txt -b 16384

デフォルトの設定だと,MeCab Error “input-buffer overflow. The line is split. use -b #SIZE option.”
というエラーが発生してしまったので -b 16384というオプションをつけています.
このエラーは1行あたりの文字列が(デフォルトの) 8192 文字を超えた時に表示されるみたいです.
"-b"オプションを付けてバッファ・サイズ(一時処理領域)を(デフォルトの2倍の)16384文字にしています.

参考記事でも挙げられていますが,作成されたwiki_wakati.txtにはバイナリ文字が含まれています.
nkfを利用して,utf-8に変換します.
nkfが入っていない場合は以下のコマンドでインストールできます(CentOS7)

sudo yum localinstall -y http://mirror.centos.org/centos/6/os/x86_64/Packages/nkf-2.0.8b-6.2.el6.x86_64.rpm

使い方は以下の通り.

nkf -w --overwrite wiki_wakati.txt

これでutf-8のtxtファイルができたのでモデル作成ができます.
モデル作成のために,make_models.pyを作成します.

vi make_models.py

以下を記述します.

from gensim.models import word2vec
import logging

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.Text8Corpus('./wiki_wakati.txt')

model = word2vec.Word2Vec(sentences, size=200, min_count=20, window=15)
model.save("./wiki.model")

make_models.pyが作成できたら,プログラムを実行します.

python make_models.py

しばらくすると,プログラムが終了し,wiki.modelが出来上がります.

おわりに

今回は,Wikipediaの記事を利用して,word2vecのモデルを作成してみました.
最初は難しそうな印象でしたが,調べてみると意外と簡単そうだったのでやってみました.
せっかく作ったので,実際に使って,遊んでみたいと思います.

グラフィカルなエンティティリンキングサイト「Serelex」

はじめに

面白そうなサイトを知ったのでただ紹介すると言うだけです
serelex.cental.be

どんなサイト?

「Serelex」というサイトで Finds semantically related wordsとあるように
ある単語を入力すると、その単語と意味的に繋がりのある語がグラフィカルに表示されるというサイトです。
f:id:tkm-kyudo:20180416191549p:plain

使ってみる

個人的な趣味でtouhou(東方project)と入力してみる。
結果は以下のようになる。
f:id:tkm-kyudo:20180416192222p:plain

ちゃんとvideo gameと紐付いているのがわかる。
個人的にこれが面白いと思った。
darkstalkers(ヴァンパイアシリーズの英題らしい)と
紐付いているのは、レミリアやフランドールが吸血鬼(ヴァンパイア)だからだろうか。

表示されているエンティティをクリックすると、
クリックしたエンティティの繋がりが表示される。
(ここではdarkstalkersをクリックした)
f:id:tkm-kyudo:20180416192603p:plain
litelary classicsやtitleは『吸血鬼ドラキュラ』繋がりだろう。
yatsura(うる星やつら)はよくわからなかったのでググったところ
どうもドラキュラ伯爵が出てくる話があったみたいで、それでリンクが繋がっているのだと思う。

使ってみて

今回はtouhou(東方project)という、かなり限定された単語を入力してみた。
かなり有名とは言え、同人ゲームというジャンルの1ゲームではあったが、
それなりにエンティティリンキングがされていた。
一般的に使われる語句などはもっとリンクが多いし、有用なのではないかと思う。

使いみち

純粋に単語を入力して、どんな繋がりがあるかを見るだけでも結構楽しいと思う。
APIが公開されているので、機械学習とかをさせる際に知識ベースとして利用できるかもしれない。
個人的には、後者の使い方を模索してみたいと思った。

終わりに

本当はtwitterで簡単に呟いて終わるつもりだったのだが、
何故か何回やってもエラーが起こってしまったので(リンクの問題か?)
内容は薄いがブログとして書くことにしました。
なぜこのサイトのURLはhttpなのだろう、そこは割と疑問ではある。
興味が湧いたのならぜひ使ってみてください。

言語処理学会第24回年次大会(NLP2018)に参加してきました.

はじめに

f:id:tkm-kyudo:20180317143710j:plain
3/12(月)~3/16(金)の間行われていた言語処理学会(NLP2018)に参加してきました。
言語処理学会への参加は聴講自体初めてでしたが、
いつのまにやら発表することになっていて、発表もしてきました。
初めての学会の参加+5日間フル参加したので疲れましたが、
勉強になることも多く、たくさんの刺激を受けて楽しかったです。

www.anlp.jp

岡山について

NLP2018に参加するにあたって、初めて岡山に来ました。
感想としては、思ってた以上に都会でした。
駅付近には飲み屋とか、大きなショッピングモールとかがたくさんあって純粋にいいなと思いました。
最初の3日間は教授たちに連れられて(学生は自分だけ)ご飯を食べました。
学生1人が教授6人に囲まれてご飯を食べるというなかなかない状況もありましたが、
色々なお話(教授たちの裏話とかも笑)聞けたので貴重な体験だったかなと思います。
学生ではまずいかないようなお店にも連れて行っていただきました。
ごちそうさまです・・・。美味しかった。

f:id:tkm-kyudo:20180317143742j:plainf:id:tkm-kyudo:20180317143800j:plain

言語処理学会

自分は初めての参加でしたが、今回は参加者が今までで一番多かったらしく約1000人規模だったとか。
学生の参加だけではなく、企業の方の一般参加なんかも多かったみたいですね。
初日の最後にはスポンサーイブニングなるものがあって、企業が学生と飲み物片手に歓談してました。
教授から聞くに今年が初めて?だったらしく、企業が言語処理に精通している学生が欲しいというのはあるみたいですね。
最近は売り手市場の傾向もありますし、データサイエンティストなんかも引く手数多ですね。

発表

2日目の午後に自分の発表がありました。
口頭発表ではなく、ポスター発表だったので、特に緊張はしませんでした。
参加者が多かったためか、80分間ずっと立ちっぱなし、話しっぱなしで大変疲れました・・・。
f:id:tkm-kyudo:20180316090407j:plain
『地方議会会議録における発言文の推定』というタイトルで
発表させていただきましたが、意外と興味持っていただけてよかったです。
発表してる時に色々質問や意見も頂きましたが、無難にはできたかな。
聞きに来てくださった方々ありがとうございました。

他の方の発表を聞いて

自分の研究したい分野が対話なので、主に対話セッションを聞いてました。
他にも面白そうな発表が多かったので対話セッションだけではなくて
いろんな分野をつまみ食いするような感じで会場を転々としながら聴講しました。
言語処理学会は結構レベルが高いらしく、聞いてて面白い発表が多かったです。
自分が気になったり、面白いなと思ったものは、
Twitterの多軸的感情情報を利用した株価の予測』
『RNN系列変換モデルを用いた高階論理式からの文生成』
『自然な対話継続のための推移する話題推定』
『感情を含む特徴変化情報付き対話コーパスの構築とそれを用いた対話の自然さ推定』
などがありました。
上記以外にもたくさん面白いものがあったり、
気になったけど時間的に聞けなかったものも多くありましたので、
論文の方で確認してみようと思います。

ワークショップ

ワークショップは『形態素解析の今とこれから』に参加しました。
ワークショップでは形態素解析開発者(解析機や辞書作成者)の方々の
開発した経緯や、こういう人に使って欲しいなど、
普段あまり知ることのできない開発側の意図を知ることができて有意義でした。
あとはSudachiが結構注目を浴びていたかなという印象。
Sudachiは名前だけしか知らなかったので、調べたり、実際に使ってみたりします。
ワークショップのタイトル通り、形態素解析のこれまでの経緯や生まれた意図、
そして今後の課題も含めてより深く知ることができました。

全体的な感想

初めてこのような学会に参加して、他の方々の発表を聞いた感想としては
機械学習などはRNNが流行っているような感じがありました。
エンコーダ・デコーダ、アテンションを使ってというようなものが
結構多く見かけたのが記憶に残ってます。
自分のやりたいことに使えそうな手法とか考え方も多くあったので
上手く自分の研究に生かしたいと思いました。
それと同時に自分のやりたいことと近いことをしている人もいなかったので
チャンスかなと思うので、他の人にやられる前にやりたいですね笑。

つらつらと述べてきましたが、参加してよかったと思いました。
とても勉強になったとともに楽しんで参加できました。
来年も発表か、聴講のみかわからないけれど参加したいです。

Xonshを導入してみた

はじめに

なぜ、Xonshを導入しようかと思ったかと言うと
TwitterのTLで話題に上がってて気になったので導入してみることに。
何やら日本語の記事が少ないので売名ができるらしい
自分と同じように興味を持った人へのハードルを下げるために導入記事を書いてみることにします。

この記事は Xonsh Advent Calendar 2017 の記事です。

Xonshとは

導入する前にXonshとはなんぞやと言うことを簡単に調べてみる。
XonshはPythonで作られたもので、Unixライクなシェル言語でコマンドプロンプトらしい。
クロスプラットフォームでもあるとか。
vaaaaaanquish.hatenablog.com

環境

Window10Home
Anaconda4.4.0
Python3.6.3
Anaconda Prompt使用

導入

早速導入していくために公式のインストール手順を見ていこう。
Windows Guide — xonsh 0.6.0.dev151 documentation
condaパッケージマネージャーを使うと簡単らしい。
Anacondaは使っているから、せっかくなのでそちらの方法を試してみよう。
Python3.4以降にしか対応していないようなので注意。
legacy Python (2.7)には対応していないと言っているので
みんなも小学生に馬鹿にされないように3系を使おう!

さて、インストールするには以下のコマンドを叩けばいいみたい。

conda config --add channels conda-forge
conda install xonsh

無事インストールが終わったので起動。

f:id:tkm-kyudo:20171216231540p:plain

無事導入が終わりました。

使ってみる

導入が思いの外簡単でしたね。
せっかくなので使ってみよう。
Tutorial — xonsh 0.6.0.dev151 documentation

1 + 1
>2
import sys
print(sys.version)
>3.6.3 |Anaconda custom (64-bit)| (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)]

こんな感じでPythonインタプリタとしても使えるみたい。
もちろん関数の定義も可能

def f():
    return "xonsh"

f()
>'xonsh'

インデントを勝手にやってくれるのでいちいちスペースやTABを叩かなくて良いのは地味に便利。

環境変数

環境変数も使うことができる。
使うには環境変数の名前の前に$をつける。

$PWD
'C:/Users/username'

好きなように環境変数を作ったり消したりもできる。

$GOAL = 'Pythonista'
print($GOAL)
>Pythonista
del $GOAL
print($GOAL)
>KeyError: 'Unknown environment variable: $GOAL'

導入してみた感想

導入してみて、チュートリアルをやった程度であるが、
これはなかなか面白そうだと感じた。
ただ、シェルスクリプトにあまり詳しくないので
他の方のAdvent Calendarの記事を見て勉強してみようと思う。

終わりに

今回はWinで導入してみて、思っていたよりも簡単に導入できた。
しばらく勉強や使ってみたりして、使えそうならMacにも導入してみたいと思う。
みんなもこれでXonshライフをエンジョイしよう。

他の方の記事は以下から。
qiita.com

Kaggleのtitanic問題に挑戦

はじめに

機械学習やデータサイエンスの勉強をし始めてなんとなくわかってきたので、
アウトプットとしてKaggle初心者がTitanicチュートリアルに挑戦してみました。

Kaggleとは

Kaggleは、世界中のデータサイエンティストに対し、企業からコンペ形式でお題を与えられます。
お題に関するデータが与えられるのでデータサイエンティスト達はそれらを分析して、予測結果を提出します。
その予測結果が高かったものが、上位者となり、順位によっては賞金がもらえるというものです。
https://www.kaggle.com/

Titanicチュートリアル

今回は、Titanicチュートリアルに挑戦しました。
あの有名なタイタニック号の乗船者たちのデータから、
生存者たちを予測するというものです。

分析環境

言語:Python3.6.1(anaconda4.4.0)
環境:jupyter notebook

データの前処理

各問題では、train.csvファイルとtest.csvファイルが提供されるので、それらをダウンロードした後、データを読み込みます。

import pandas as pd
import numpy as np
df_train = pd.read_csv("train.csv")
df_test = pd.read_csv("test.csv")
df_train.head(3)

f:id:tkm-kyudo:20171203160257p:plain

一先ず欠損データの確認をします。

df_train.isnull().sum()
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64

上記のようにAge,Cabin,Embarkedに欠損値があることがわかりました。
今回は、Cabinを除外、Embarkedの欠損値がある行を除外、Ageは平均値で補完することにしました。

Cabinの除外

df_train = df_train.drop('Cabin',axis=1)
df_test = df_test.drop('Cabin', axis=1)

Embarkedの欠損値がある行を除外

df_train = df_train.dropna(subset=['Embarked'])
df_test = df_test.dropna(subset=['Embarked'])

Ageの欠損値を平均値で補完

df_train['Age'].fillna(df_train['Age'].mean(),inplace=True)
df_test['Age'].fillna(df_test['Age'].mean(),inplace=True)

欠損値の確認

df_train.head(3)
PassengerId    0
Survived       0
Pclass         0
Name           0
Sex            0
Age            0
SibSp          0
Parch          0
Ticket         0
Fare           0
Embarked       0
dtype: int64

これで欠損値はなくなりました。

先程のデータを確認すると、Name,Sex,Ticketが文字データなので
これらも処理しなければいけません。
まず、male=0,female=1と置き換えます。

df_train= df_train.replace("male",0).replace("female",1).replace("S",0).replace("C",1).replace("Q",2)
df_test= df_test.replace("male",0).replace("female",1).replace("S",0).replace("C",1).replace("Q",2)

NameとTicketについては、今回は除外することにしました。
NameとTicketの列を除外

df_train = df_train.drop('Name',axis=1)
df_test = df_test.drop('Name', axis=1)
df_train = df_train.drop('Ticket',axis=1)
df_test = df_test.drop('Ticket', axis=1)

以上で、trainデータは以下のようになりました。
f:id:tkm-kyudo:20171203162231p:plain
trainデータは大丈夫そうです。

念のためtestデータを確認しておきましょう。

df_test.isnull().sum()
PassengerId    0
Pclass         0
Sex            0
Age            0
SibSp          0
Parch          0
Fare           1
Embarked       0
dtype: int64

testデータではFareが1つ欠けていたので、これも補完します。

df_test["Fare"].fillna(df_test["Fare"].mean(),inplace=True)
<||

*データの読み込み
前処理が完了したので、データを読み込ませます。
>||
x_train = df_train.values[:, 2:]#Pclass以降の変数
y_train  = df_train.values[:, 1]#正解データ
x_test = df_test.values[:, 1:]

データ解析・モデリング

データの処理、読み込みが終わったので、モデリングして、データの解析をします。
今回は線形SVMをしようしました。
ランダムフォレストやK近傍法なども試しましたが、線形SVMが一番精度が高く出ました。
線形SVMでは入力データを標準化(平均0,標準偏差1)します。

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(x_train)
x_train_std = sc.transform(x_train)
x_test_std = sc.transform(x_test)

標準化したデータを線形SVMに適用し、生存を予測する。

svm = SVC(kernel='linear', random_state=0, gamma=0.05, C=1.0)
svm.fit(x_train_std, y_train)
svm_accuracy = svm.predict(x_test_std)

予測したものをCSVファイルに書き出す

import csv
with open("svm_predict_result_data.csv", "w") as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerow(["PassengerId", "Survived"])
    for pid, survived in zip(df_test.values[:,0].astype(int), svm_accuracy.astype(int)):
        writer.writerow([pid, survived])

予測結果

先程のCSVデータをKaggleに提出すると、
f:id:tkm-kyudo:20171203163751p:plain
正答率0.79904,順位1766(9525人中)と上位18.5%に入ることができました。(2017/12/03時点)

やってみた感想

今回は、初めてということで、拙くてもいいのでデータ分析した結果を提出するということを目標にやってみた。
これまでの過程を見て分かる通りそれほど難しいことはしておらず、データもかなり除外している。
しかし、それでも上位18.5%と悪くない結果を得ることができた。

今後の挑戦について

今回は自力でやることを重視していたので、Kernelには目を通していない。
Kernelとは、Kaglleの強い人達が、どう分析したらスコアが上がったなどの情報を共有してくれているものである。
今後は、コンペなどに参加しつつ、Kernelを見ながら、上位者たちの考え方、解法を学んでいく。
一先ずの目標として、コンペでメダルを1つ取るのを目標に頑張りたい。