Golangで言語処理100本ノック2015 第8章: 機械学習
言語処理100本ノック 2015の第8章: 機械学習の10問です。
本章では,Bo Pang氏とLillian Lee氏が公開しているMovie Review Dataのsentence polarity dataset v1.0を用い,文を肯定的(ポジティブ)もしくは否定的(ネガティブ)に分類するタスク(極性分析)に取り組む.
70. データの入手・整形
文に関する極性分析の正解データを用い,以下の要領で正解データ(sentiment.txt)を作成せよ.
- rt-polarity.posの各行の先頭に"+1 "という文字列を追加する(極性ラベル"+1"とスペースに続けて肯定的な文の内容が続く)
- rt-polarity.negの各行の先頭に"-1 "という文字列を追加する(極性ラベル"-1"とスペースに続けて否定的な文の内容が続く)
- 上述1と2の内容を結合(concatenate)し,行をランダムに並び替える sentiment.txtを作成したら,正例(肯定的な文)の数と負例(否定的な文)の数を確認せよ.
gist7abcc67e5e41ca5b7de31020c28aac7a
# go run q70.go positive: 5331 negative: 5331 // 最初の5文のみ抜粋 # head -n 5 ../data/sentiment.txt +1 you might want to take a reality check before you pay the full ticket price to see " simone , " and consider a dvd rental instead . +1 birthday girl doesn't try to surprise us with plot twists , but rather seems to enjoy its own transparency . +1 efteriades gives the neighborhood -- scenery , vibe and all -- the cinematic equivalent of a big , tender hug . -1 the unceasing sadism is so graphically excessive , the director just ends up exposing his own obsession . +1 works as pretty contagious fun .
教師データの作成ですが、実装内容自体は、今までやってきた内容で十分対応できます。
71. ストップワード
英語のストップワードのリスト(ストップリスト)を適当に作成せよ.さらに,引数に与えられた単語(文字列)がストップリストに含まれている場合は真,それ以外は偽を返す関数を実装せよ.さらに,その関数に対するテストを記述せよ.
giste459315cbddf0b696e9ec4241b349ac1
gist035fa3046d847cc7f82c2123e8282792
// PATHだけ書き換えています # go test . ok _<PATH>/goNLP100knock2015/src/q71 0.007s
E Oracle Textのストップリストとpythonのライブラリを参考にしました。
72-77は同じ問題として扱ったほうが見通しがいいのでまとめます。
72. 素性抽出
極性分析に有用そうな素性を各自で設計し,学習データから素性を抽出せよ.素性としては,レビューからストップワードを除去し,各単語をステミング処理したものが最低限のベースラインとなるであろう.
73. 学習
72で抽出した素性を用いて,ロジスティック回帰モデルを学習せよ.
74. 予測
73で学習したロジスティック回帰モデルを用い,与えられた文の極性ラベル(正例なら"+1",負例なら"-1")と,その予測確率を計算するプログラムを実装せよ.
75. 素性の重み
73で学習したロジスティック回帰モデルの中で,重みの高い素性トップ10と,重みの低い素性トップ10を確認せよ
76. ラベル付け
学習データに対してロジスティック回帰モデルを適用し,正解のラベル,予測されたラベル,予測確率をタブ区切り形式で出力せよ.
77. 正解率の計測
76の出力を受け取り,予測の正解率,正例に関する適合率,再現率,F1スコアを求めるプログラムを作成せよ.
gist3159bfb9a6735815106e74f20eba411d
# go run q72to77.go **** labeling and the probablity **** No. correct predicted probability -------------------------------------------- [ 0 ] -1 -1 0.00022938614422040216 [ 1 ] +1 +1 0.980844143721765 [ 2 ] -1 -1 0.00708968717145575 [ 3 ] +1 +1 0.6373159883859113 [ 4 ] +1 +1 0.9916602446447373 [ 5 ] +1 -1 0.03358930745405741 [ 6 ] +1 +1 0.9719198377002579 [ 7 ] -1 -1 0.01690622239135617 [ 8 ] -1 -1 0.18087393421803644 [ 9 ] +1 +1 0.9819855696689674 **** 10 highest weighted words **** rank word weight -------------------------------------------- [ 0 ] engross 4.153318843524091 [ 1 ] rare 3.9660695001044313 [ 2 ] enjoy 3.646668750763667 [ 3 ] beauti 3.5124131099641485 [ 4 ] refreshingli 3.4833226288262464 [ 5 ] memori 3.2698092911328422 [ 6 ] move 3.181494225222411 [ 7 ] consider 3.171432544641585 [ 8 ] smart 3.1655141347852407 [ 9 ] refresh 3.1581078779050067 **** 10 lowest weighted words **** rank word weight -------------------------------------------- [ 0 ] dull -4.366239700419224 [ 1 ] neither -4.070251251158453 [ 2 ] name -4.016387870547353 [ 3 ] littl -3.534095627137484 [ 4 ] bore -3.4944640249118266 [ 5 ] badli -3.397328927368818 [ 6 ] worst -3.3778081685478982 [ 7 ] sort -3.3675428257686875 [ 8 ] bare -3.3492559829926902 [ 9 ] colleg -3.3407574407648783 **** rates **** accuracy rate: 0.812886888013506 precision rate: 0.8719892952720785 recall rate: 0.733445882573626 F1 score: 0.7967396841569028
予測率が上がらないと思ったら学習フェーズでデータX
が参照渡しになっていて、ScaleVec
によって更新されてしまっていました。値渡しかどうかは気をつけないとダメですね。
78. 5分割交差検定
76-77の実験では,学習に用いた事例を評価にも用いたため,正当な評価とは言えない.すなわち,分類器が訓練事例を丸暗記する際の性能を評価しており,モデルの汎化性能を測定していない.そこで,5分割交差検定により,極性分類の正解率,適合率,再現率,F1スコアを求めよ.
gist44a00f5d2f3cfeaf00c39b54c41e5d80
# go run q78.go **** rates ( 0 / 5 ) **** accuracy rate: 0.70042194092827 precision rate: 0.7175974710221286 recall rate: 0.6473384030418251 F1 score: 0.6806596701649176 **** rates ( 1 / 5 ) **** accuracy rate: 0.6980778246601032 precision rate: 0.7402597402597403 recall rate: 0.6286764705882353 F1 score: 0.679920477137177 **** rates ( 2 / 5 ) **** accuracy rate: 0.7018284106891702 precision rate: 0.7192982456140351 recall rate: 0.6569274269557022 F1 score: 0.6866995073891625 **** rates ( 3 / 5 ) **** accuracy rate: 0.6957337083919363 precision rate: 0.7040816326530612 recall rate: 0.657769304099142 F1 score: 0.6801379990142927 **** rates ( 4 / 5 ) **** accuracy rate: 0.6873239436619718 precision rate: 0.6619828259172521 recall rate: 0.7844588344125809 F1 score: 0.7180355630821337
学習データをそのまま判別データとすると8割だったので、もっと落ちるかと思いましたが、7割程度の判別率が出てますね。
79. 適合率-再現率グラフの描画
ロジスティック回帰モデルの分類の閾値を変化させることで,適合率-再現率グラフを描画せよ.
gistdc829ce8a45d892126337e30c6bdf184
感想
機械学習の流れ自体は、学生時代に触っていたので頭に入っているものの素性など、NLP特有の用語で少し戸惑いました。あと2値分類といえば、SVMばかりだったのでロジスティック回帰も改めて勉強して整理できたのでよかったです。
いつも通りコードはGithubにも置いてあります。
Reference
はてなブログでベクトルをbold表記したい[markdown]
zplugのautosuggestionsのカラー設定方法
fishコマンドとbash/zshコマンドの微妙な差異で時間を浪費するのをやめるべく、zshに戻る決心をしました。 一方でzshでも、AutoSuggestionを使いたく、 zsh-autosuggestions を導入したものの、デフォルトの色が見えないほど薄かったので変える方法をまとめます。
変え方
READMEに
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE
を設定すればよいとあります。
今回はzplugでzplug "zsh-users/zsh-autosuggestions"
と設定したため、
設定ファイルは、~/.zplug/repos/zsh-users/zsh-autosuggestions/zsh-autosuggestions.zsh
にあると思います。
READMEを見てもfg=8
がデフォルトだという情報しか載っておらず、
好みの色にするためにはどうすればいいのか一見わかりませんでしたが、
色指定は、oh-my-zshなどで使われているcolor code tableと同じようです。
こちらの下部にテーブルがあります。
自分は、背景がダークカラーのため、以下のように設定しています。
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=242'
References
Golangで言語処理100本ノック2015 第7章: データベース
言語処理100本ノック 2015の第7章: データベースの10問です。
redisとMongoDBを使うことにします。
redis
// 起動 # redis-server /usr/local/etc/redis.conf // cli # redis-cli
MongoDB
// 起動 # sudo mongod --dbpath /var/lib/mongodb --logpath /var/log/mongodb.log // cli # mongo
60. KVSの構築
Key-Value-Store (KVS) を用い,アーティスト名(name)から活動場所(area)を検索するためのデータベースを構築せよ.
gist103c8ead51aad42cfc5b6686caa2039a
bufioのdefault sizeである4096だとReadLine()
しきれないところがあるのでNewReaderSize()
を使っています。
Goでredisを扱うためには、redigoを使っています。
また、set
を使ってKVSを構築すると同じアーティスト名が存在した場合に、上書きされてしまうのでのちのQ62,66で結果に不整合が生じます。
61. KVSの検索
60で構築したデータベースを用い,特定の(指定された)アーティストの活動場所を取得せよ.
giste6d4ca51b7b23914fadd5bdc0ec93c75
// 存在するアーティスト # go run q61.go supercell Japan // 存在しないアーティスト # go run q61.go hoge ` hoge ` is not found.
Q60でKVSの構築は済んでいるので、標準入力で受け取ったアーティストを検索するのみです。検索アーティストは趣味です。2015年当時のデータなので最近のアーティストはないようですが、知っているアーティストで検索すると引っかかるので楽しいです。
62. KVS内の反復処理
60で構築したデータベースを用い,活動場所が「Japan」となっているアーティスト数を求めよ.
gist6ac674e08083ff19c9154084b3d4787d
# go run q62.go 22821
keys *
で全keyを取得して、それを反復してareaを検索しました。
63. オブジェクトを値に格納したKVS
KVSを用い,アーティスト名(name)からタグと被タグ数(タグ付けされた回数)のリストを検索するためのデータベースを構築せよ.さらに,ここで構築したデータベースを用い,アーティスト名からタグと被タグ数を検索せよ.
gista57f35c159e2693ca841051ecbc390ef
# go run q63.go "Fear of War" count |tag -------------------- 1 | punk 1 | sweden 1 | hardcore 1 | fagersta
list型でtagを入れました。検索は適当に複数タグがあるアーティストにしてみました。
64. MongoDBの構築
アーティスト情報(artist.json.gz)をデータベースに登録せよ.さらに,次のフィールドでインデックスを作成せよ: name, aliases.name, tags.value, rating.value
gistb4ce4fe18042ae02c8eafe941f59548b
# go run q64.go before: 392.39824ms after: 1.308422ms
Indexをはる前後でのname
でのクエリの実行時間を測定してみましたが、速くなっていますね。aliases.name
, tags.value
, rating.value
にはIndexをはらずに、name
のみIndexをはると800us程度になるので、むやみやたらにIndexをはればいいわけではないですね。
GolangでMongoDBを扱うためのbsonについては以前記事にまとめましたので、そちらも御覧ください。
65. MongoDBの検索
MongoDBのインタラクティブシェルを用いて,"Queen"というアーティストに関する情報を取得せよ.さらに,これと同様の処理を行うプログラムを実装せよ.
// インタラクティブシェル > db.artist.find({"name": "Queen"}) { "_id" : ObjectId("59aa3c32bb03c3f9e15a51ce"), "name" : "Queen", "tags" : [ { "count" : 1, "value" : "kamen rider w" }, { "count" : 1, "value" : "related-akb48" } ], "rating" : { "count" : 0, "value" : 0 }, "sortname" : "Queen", "ended" : true, "gid" : "420ca290-76c5-41af-999e-564d7c71f1a7", "id" : 701492, "area" : "Japan", "aliases" : [ { "name" : "Queen", "sortname" : "Queen" } ], "begin" : { "year" : 0, "month" : 0, "date" : 0 }, "end" : { "year" : 0, "month" : 0, "date" : 0 }, "gender" : "Female", "type" : "Character" } { "_id" : ObjectId("59aa3c3abb03c3f9e15bdf28"), "name" : "Queen", "tags" : [ { "count" : 2, "value" : "hard rock" }, { "count" : 1, "value" : "70s" }, { "count" : 1, "value" : "queen family" }, { "count" : 1, "value" : "90s" }, { "count" : 1, "value" : "80s" }, { "count" : 1, "value" : "glam rock" }, { "count" : 4, "value" : "british" }, { "count" : 1, "value" : "english" }, { "count" : 2, "value" : "uk" }, { "count" : 1, "value" : "pop/rock" }, { "count" : 1, "value" : "pop-rock" }, { "count" : 1, "value" : "britannique" }, { "count" : 1, "value" : "classic pop and rock" }, { "count" : 1, "value" : "queen" }, { "count" : 1, "value" : "united kingdom" }, { "count" : 1, "value" : "langham 1 studio bbc" }, { "count" : 1, "value" : "kind of magic" }, { "count" : 1, "value" : "band" }, { "count" : 6, "value" : "rock" }, { "count" : 1, "value" : "platinum" } ], "rating" : { "count" : 24, "value" : 92 }, "sortname" : "Queen", "ended" : true, "gid" : "0383dadf-2a4e-4d10-a46a-e9e041da8eb3", "id" : 192, "area" : "United Kingdom", "aliases" : [ { "name" : "女王", "sortname" : "女王" } ], "begin" : { "year" : 1970, "month" : 6, "date" : 27 }, "end" : { "year" : 0, "month" : 0, "date" : 0 }, "gender" : "", "type" : "Group" } { "_id" : ObjectId("59aa3c4bbb03c3f9e15f53d9"), "name" : "Queen", "tags" : [ ], "rating" : { "count" : 0, "value" : 0 }, "sortname" : "Queen", "ended" : true, "gid" : "5eecaf18-02ec-47af-a4f2-7831db373419", "id" : 992994, "area" : "", "aliases" : [ ], "begin" : { "year" : 0, "month" : 0, "date" : 0 }, "end" : { "year" : 0, "month" : 0, "date" : 0 }, "gender" : "", "type" : "" }
gist2f86dd77e7d54026d04bf478bff96fb0
# go run q65.go {Queen [{1 kamen rider w} {1 related-akb48}] {0 0} Queen true 420ca290-76c5-41af-999e-564d7c71f1a7 701492 Japan [{Queen Queen}] {0 0 0} {0 0 0} Female Character} {Queen [{2 hard rock} {1 70s} {1 queen family} {1 90s} {1 80s} {1 glam rock} {4 british} {1 english} {2 uk} {1 pop/rock} {1 pop-rock} {1 britannique} {1 classic pop and rock} {1 queen} {1 united kingdom} {1 langham 1 studio bbc} {1 kind of magic} {1 band} {6 rock} {1 platinum}] {24 92} Queen true 0383dadf-2a4e-4d10-a46a-e9e041da8eb3 192 United Kingdom [{女王 女王}] {1970 6 27} {0 0 0} Group} {Queen [] {0 0} Queen true 5eecaf18-02ec-47af-a4f2-7831db373419 992994 [] {0 0 0} {0 0 0} }
Q64で構築したDBのクエリを投げるだけです。
66. 検索件数の取得
MongoDBのインタラクティブシェルを用いて,活動場所が「Japan」となっているアーティスト数を求めよ.
> db.artist.find({"area": "Japan"}).count() 22821
67. 複数のドキュメントの取得
特定の(指定した)別名を持つアーティストを検索せよ.
gist2ae3e6047aa223568e14a7abef7bd9b5
# go run q67.go supercell {supercell [] {3 100} supercell true 9b15ff5e-5bd1-43c2-821d-e31240aad334 311779 Japan [{超级单体 超级单体} {supercell スーパーセル}] {2007 0 0} {0 0 0} Group}
ほぼQ65と同じですね。
68. ソート
"dance"というタグを付与されたアーティストの中でレーティングの投票数が多いアーティスト・トップ10を求めよ.
gist6ae30eb5984a5b4699604fe6baa6eb0d
# go run q68.go Madonna Björk The Prodigy Rihanna Britney Spears Maroon 5 Adam Lambert Fatboy Slim Basement Jaxx Gigi D’Agostino Cornershop Duran Duran
sortパッケージがgo1.8以上で変わっていたのは知っていたものの試していなかったので触れてよかったです。
69. Webアプリケーションの作成
ユーザから入力された検索条件に合致するアーティストの情報を表示するWebアプリケーションを作成せよ.アーティスト名,アーティストの別名,タグ等で検索条件を指定し,アーティスト情報のリストをレーティングの高い順などで整列して表示せよ.
gistb97736d9ce01ae3766f919d2d749fcb6
テンプレートファイルは以下です。
gist3d7903a98687bfcf6e5ce9f49be189a3
gist308ac9755a102f56f44f9f1eb7307304
どうやらginというHttpRouterが有名そうなので、今回はginを使って、検索フォームから検索し、テーブルで結果を表示するようにしてみました。
CLIからq69.go
を実行した状態で、ブラウザでhttp://localhost:8080/index
へアクセスすると以下のように表示されます。
検索してあげるとこんな感じです。空欄は元データが入っていないところです。
初めてgin
を使ってみましたが、c.JSON
などとすると簡単にjsonを返せるようなのでAPIサーバも書けそうです。
今回のフォームからユーザに入力させる形式のところはインジェクション対策は何もしていないのでこのままでは使えないですが、Goでひと通り書いてみて勉強になりました。
感想
redisは軽くしか触れたことがなかったので、復習も兼ねて勉強になりました。Q68まではサクサク進みますが、Q69は重めですね。実りが多かったのでよかったですが。
いつも通りコードはGithubにも置いてあります。
Reference
Golangでロジスティック回帰
技評連載の機械学習 はじめようを拝見したので、Golangでロジスティック回帰を実装してみます。
イメージしやすいように結果の散布図を先に載せます。 赤と青がそれぞれ正解ラベルを表しており、緑色の実践が学習した判別境界です。
問題設定
以下のように2次元平面上で、一様乱数を生成します。
// テストデータの用意 rand.Seed(time.Now().UnixNano()) x1 := make([]float64, N) x2 := make([]float64, N) for i := 0; i < N; i++ { x1[i] = 10*rand.Float64() - 5 x2[i] = 10*rand.Float64() - 5 }
直線を境界として、生成した乱数に対して、
: ,
:
とラベル付けします。
境界線である直線は、特徴ベクトルと 学習したい重みを用いて、 と書けます。 直線なので に近づくことを期待して、を学習するのが目標となります。
方針
式の導出などは機械学習 はじめよう に書かれているため、詳細はそちらを見ていただくとして、 を学習するためには、結局、以下を実装すればよいことになります。
ここでは学習率、はシグモイド関数です。
また特徴量は、元データが線形分離可能であることからも、特徴ベクトルとすれば十分でしょう。第1成分の1
はいわゆる切片を表しています。
実装
実装は以下のようになりました。
結果を図示するためにgonum/plotを使っています。なのでちょっとコードは長いです。
行列やベクトルも同じくgonumのgonum/matを使っています。ちなみにgonum/matrixは既にメンテナンスされておらず、今回用いたgonum/mat
に移行しているようです。
教師データとテストデータはそれぞれ1000個ずつにしています。
giste98445af5552e366cfcb57e81722a0c2
結果
学習した重み\boldsymbol{w}と、教師データ/テストデータを判別した結果は以下です。
// 学習結果 // 参考) 真値: [-1, 2, 3] &{{1 [-0.5416022992823583 1.6422051384123924 -2.760912629909472]} 3} // 判別結果 training data: 0.986 new data: 0.982
判別はシグモイド関数の値が0.5を境界として行っています。false positive/negativeをどれくらい許容できる/できないでチューニングも可能です。
結果を見る限り、ある程度は真値に近い値になっていますね。判別結果も新たに生成したデータであっても教師データと同程度の判別率を達成できているのがわかります。
感想
Golangで実装したかったので実装してみましたが、gonum/mat
のようなパッケージを使うと[]float64
からmat.VecDense
型への変換などもあって、さくっと書くには少し面倒ですね。そこら辺は動的型付けの言語のほうがよさそうです。
あとは、ロジスティック回帰の理解があやふやだったので、実装してある程度整理できたのでよかったです。特徴量の設計によって非線形の分布に対しても、うまく線形分離可能な空間に飛ばせればロジスティック回帰でかなりの精度が出そうですね。その関数を探すのが大変ですが。。。
References
GithubのGraphQLを触ったメモ書き
最近GraphQLなる言葉をよく見るようになったので、調べつつ、習うより慣れろで触ってみたのでその形跡を残します。
GraphQLとは
GraphQLを読んだ印象としては、API越しのQuery languageと理解しました。 RESTの次のパラダイムはGraphQLかにもあるようにREST APIとの対比で語られているようです。
自分でもなんらかのサービスで提供されているAPIを叩くことがありますが、レスポンスには実際に欲しいデータだけでなく、余分なデータも含まれています。リクエストを投げる時点で欲しい情報をクエリパラメタとして渡してあげることで、必要な情報だけをレスポンスとして得られるのが利点と考えます。 RESTの次のパラダイムはGraphQLかでは、その他の問題も完結にまとめられているのでわかりやすいです。
GithubのExploreで触ってみる
GithubがGUIでGraphQLを触れるExploreを提供してくれているので、実際に触って所感を掴みましょう。 クエリのReferenceはこちら。
以下は「自分のレポジトリを更新順に並べ、最初のn個を取得」するクエリです。
変数を$n
として受け取らせています。
また、viewer
がログインしているユーザ(自分自身)を表します。
// query query($n: Int!){ viewer { repositories(orderBy: {field: UPDATED_AT, direction: DESC}, first: $n) { edges { node { name } } } } } // variables { "n": 3 }
これを実行すると以下のようにjsonでレスポンスが返ってきます。
{ "data": { "viewer": { "repositories": { "edges": [ { "node": { "name": "goSExpression-sample" } }, { "node": { "name": "poloniex" } }, { "node": { "name": "goXML" } } ] } } } }
型がある
GraphQLでは型も定義されており、今回の例だと
repositories
のorderBy
フィールドはRepositoryOrder
型になります。
ReferenceにもあるようにRepositoryOrderField
型のfield
とOrderDirection
型のdirection
をメンバとして持っています。
なので以下のようにhoge
という誤った型のクエリをわざと発行してみます。
query($n: Int!){ viewer { repositories(orderBy: hoge, first: $n) { edges { node { name } } } } }
すると以下のように、型が違うエラーが返ってくる実装になっていました。
{ "data": null, "errors": [ { "message": "Argument 'orderBy' on Field 'repositories' has an invalid value. Expected type 'RepositoryOrder'.", "locations": [ { "line": 3, "column": 5 } ] } ] }
感想
とりあえず触ってみたというレベルですが、GraphQLでした。今後RESTを置き換えていくのかはわかりませんが、型があり、必要な情報だけを取ってこれるというのは場面によっては有効そうです。 RESTがこれだけ世の中に溢れていることを考えると、RESTからの移行をどうやって設計するのかなど考えるのは楽しそうですね。
Reference
Golangで言語処理100本ノック2015 第6章: 英語テキストの処理
言語処理100本ノック 2015の第6章: 英語テキストの処理の10問です。
50. 文区切り
(. or ; or : or ? or !) → 空白文字 → 英大文字というパターンを文の区切りと見なし,入力された文書を1行1文の形式で出力せよ.
gist4437579cb8e6b64166d0de27b1ce49b4
// 最初の7文のみ抜粋 # go run q50.go Natural language processing From Wikipedia, the free encyclopedia Natural language processing (NLP) is a field of computer science, artificial intelligence, and linguistics concerned with the interactions between computers and human (natural) languages. As such, NLP is related to the area of humani-computer interaction. History The history of NLP generally starts in the 1950s, although work can be found from earlier periods. In 1950, Alan Turing published an article titled "Computing Machinery and Intelligence" which proposed what is now called the Turing test as a criterion of intelligence.
golangでは、lookaheadをサポートしていないので、次の一文のCapitalを回してあげるのがめんどうでした。
51. 単語の切り出し
空白を単語の区切りとみなし,50の出力を入力として受け取り,1行1単語の形式で出力せよ.ただし,文の終端では空行を出力せよ.
// q50の結果をtxtに保存しておく # go run q50.go > ../data/q50_out.txt
gist154c531bd00e06627a06871620015ece
// 最初の3文のみ抜粋 # go run q51.go Natural language processing From Wikipedia, the free encyclopedia Natural language processing (NLP) is a field of computer science, artificial intelligence, and linguistics concerned with the interactions between computers and human (natural) languages. As such, NLP is related to the area of humani-computer interaction.
Split
するだけなので余裕ですね。
52. ステミング
51の出力を入力として受け取り,Porterのステミングアルゴリズムを適用し,単語と語幹をタブ区切り形式で出力せよ. Pythonでは,Porterのステミングアルゴリズムの実装としてstemmingモジュールを利用するとよい.
// q51の結果をtxtに保存しておく # go run q51.go > ../data/q51_out.txt
gist8a0fc9ac1d9432a9da14bd87d91476ae
# go run q52.go // 最初の3文のみ抜粋 Natural natur language languag processing process From from Wikipedia, wikipedia, the the free free encyclopedia encyclopedia Natural natur language languag processing process (NLP) (nlp) is is a a field field of of computer comput science, science, artificial artifici intelligence, intelligence, and and linguistics linguist concerned concern with with the the interactions interact between between computers comput and and human human (natural) (natural) languages. languages. As as such, such, NLP nlp is is related relat to to the the area area of of humani-computer humani-comput interaction. interaction.
golangでのstemming実装としてGo Porter Stemmerを使いました。
53. Tokenization
Stanford Core NLPを用い,入力テキストの解析結果をXML形式で得よ.また,このXMLファイルを読み込み,入力テキストを1行1単語の形式で出力せよ.
// 公式サイトからDownloadし、zipを解凍したフォルダで以下のshellを実行すると、実行したディレクトリにxmlファイルが生成される # cd stanford-corenlp-full-2017-06-09 # ./corenlp.sh -annotators tokenize,ssplit,pos,lemma,ner,parse,dcoref -outputFormat xml -file <YOUR_PATH_TO>/nlp.txt # mv ./nlp.txt.xml ../data // xmlから自動的にgo structを作り出す # chidley -G -e "" ../data/nlp.txt.xml
gist9672a32d376e48be9bf55571c799db31
// 最初の1文のみ抜粋 # go run q53.go Natural language processing From Wikipedia , the free encyclopedia Natural language processing -LRB- NLP -RRB- is a field of computer science , artificial intelligence , and linguistics concerned with the interactions between computers and human -LRB- natural -RRB- languages .
Stanford Core NLPを初めて触ったので実行の仕方がわからなくて苦労しました。 golangで実装するのはxmlの読み込みからです。 前処理にも書きましたが、自分でgo structを定義し直すのは面倒なので、chidleyを使って自動生成させています。
54. 品詞タグ付け
Stanford Core NLPの解析結果XMLを読み込み,単語,レンマ,品詞をタブ区切り形式で出力せよ.
gist701c1fdd47b0777c7a6c8cbb1f663bb5
# go run q54.go Natural natural JJ language language NN processing processing NN From from IN Wikipedia Wikipedia NNP , , , the the DT free free JJ encyclopedia encyclopedia NN Natural natural JJ language language NN processing processing NN -LRB- -lrb- -LRB- NLP nlp NN -RRB- -rrb- -RRB- is be VBZ a a DT field field NN of of IN computer computer NN science science NN , , , artificial artificial JJ intelligence intelligence NN , , , and and CC linguistics linguistics NNS concerned concern VBN with with IN the the DT interactions interaction NNS between between IN computers computer NNS and and CC human human JJ -LRB- -lrb- -LRB- natural natural JJ -RRB- -rrb- -RRB- languages language NNS . . .
Q53から出力部分を変えるのみです。
55. 固有表現抽出
入力文中の人名をすべて抜き出せ.
gist6ee9809052e2294a98ef9237316525c2
# go run q55.go Alan Turing Joseph Weizenbaum MARGIE Schank Wilensky Meehan Lehnert Carbonell Lehnert Racter Jabberwacky Moore
Stanford Core NLPで解析を行うと、人名がNER
にPERSON
として現れてくるのでそれを抜き出してあげるだけです。
56. 共参照解析
Stanford Core NLPの共参照解析の結果に基づき,文中の参照表現(mention)を代表参照表現(representative mention)に置換せよ.ただし,置換するときは,「代表参照表現(参照表現)」のように,元の参照表現が分かるように配慮せよ.
gistf36c33493e5d272f743916088a8ad6f5
// 最初の5文のみ抜粋 # go run q56.go Natural language processing From Wikipedia , the free encyclopedia Natural language processing -LRB- NLP -RRB- is [the free encyclopedia Natural language processing -LRB- NLP -RRB-] (a field of computer science) , artificial intelligence , and linguistics concerned with the interactions between computers and human -LRB- natural -RRB- languages . As such , NLP is related to the area of humani-computer interaction . Many challenges in NLP involve natural language understanding , that is , enabling [computers] (computers) to derive meaning from human or natural language input , and others involve natural language generation . History The history of NLP generally starts in the 1950s , although work can be found from earlier periods . In 1950 , Alan Turing published an article titled `` Computing Machinery and Intelligence '' which proposed what is now called the [Alan Turing] (Turing) test as a criterion of intelligence .
参照表現を()
で括り、もとの代表参照表現を[]
で括っています。
全文まとめてStanford Core NLPで解析したからか微妙な解析結果もちらほらあるようです。
しかし一文ずつ解析すると文をまたがった表現が拾えないので全文まとめた解析としました。
57. 係り受け解析
Stanford Core NLPの係り受け解析の結果(collapsed-dependencies)を有向グラフとして可視化せよ.可視化には,係り受け木をDOT言語に変換し,Graphvizを用いるとよい.また,Pythonから有向グラフを直接的に可視化するには,pydotを使うとよい.
gistea1dc7dec630b507a0d3ce336acda10f
# go run q57.go # dot -T png ../data/q57.dot -o ../data/q57.png # open ../data/q57.png
最初の一文をグラフにしました。 Goでの有向グラフの書き方は以前まとめたのでこちらをご覧ください。
58. タプルの抽出
Stanford Core NLPの係り受け解析の結果(collapsed-dependencies)に基づき,「主語 述語 目的語」の組をタブ区切り形式で出力せよ.ただし,主語,述語,目的語の定義は以下を参考にせよ.
- 述語: nsubj関係とdobj関係の子(dependant)を持つ単語
- 主語: 述語からnsubj関係にある子(dependent)
- 目的語: 述語からdobj関係にある子(dependent)
gist01e16fef3dd5e2f567fa7b63896e239d
# go run q58.go challenges involve generation others involve generation understanding enabling computers Turing published article experiment involved translation ELIZA provided interaction patient exceeded base ELIZA provide response which structured information underpinnings discouraged sort that underlies approach Some produced systems which make decisions systems rely which that contains errors implementations involved coding algorithms take set Some produced systems which make decisions models have advantage they express certainty Systems have advantages Automatic make use that make decisions
mapで実装しようとしたらcannot assign to struct field
のエラーが出てハマりました。
59. S式の解析
Stanford Core NLPの句構造解析の結果(S式)を読み込み,文中のすべての名詞句(NP)を表示せよ.入れ子になっている名詞句もすべて表示すること.
gist6f587f61adc2ca08abf5eda2201d2dcb
// 最初の1文のみ抜粋 # go run q59.go (NP (JJ Natural)(NN language)(NN processing)) (NP (NNP Wikipedia)) (NP (NP (DT the)(JJ free)(NN encyclopedia)(JJ Natural)(NN language)(NN processing))(PRN (-LRB- -LRB-)(NP (NN NLP))(-RRB- -RRB-))) (NP (DT the)(JJ free)(NN encyclopedia)(JJ Natural)(NN language)(NN processing)) (NP (NN NLP)) (NP (NP (NP (DT a)(NN field))(PP (IN of)(NP (NN computer)(NN science))))(, ,)(NP (JJ artificial)(NN intelligence))(, ,)(CC and)(NP (NP (NNS linguistics))(VP (VBN concerned)(PP (IN with)(NP (NP (DT the)(NNS interactions))(PP (IN between)(NP (NP (NNS computers))(CC and)(NP (JJ human)(-LRB- -LRB-)(JJ natural)(-RRB- -RRB-)(NNS languages))))))))) (NP (NP (DT a)(NN field))(PP (IN of)(NP (NN computer)(NN science)))) (NP (DT a)(NN field)) (NP (NN computer)(NN science)) (NP (JJ artificial)(NN intelligence)) (NP (NP (NNS linguistics))(VP (VBN concerned)(PP (IN with)(NP (NP (DT the)(NNS interactions))(PP (IN between)(NP (NP (NNS computers))(CC and)(NP (JJ human)(-LRB- -LRB-)(JJ natural)(-RRB- -RRB-)(NNS languages)))))))) (NP (NNS linguistics)) (NP (NP (DT the)(NNS interactions))(PP (IN between)(NP (NP (NNS computers))(CC and)(NP (JJ human)(-LRB- -LRB-)(JJ natural)(-RRB- -RRB-)(NNS languages))))) (NP (DT the)(NNS interactions)) (NP (NP (NNS computers))(CC and)(NP (JJ human)(-LRB- -LRB-)(JJ natural)(-RRB- -RRB-)(NNS languages))) (NP (NNS computers)) (NP (JJ human)(-LRB- -LRB-)(JJ natural)(-RRB- -RRB-)(NNS languages)) --------------
S式の簡易パーサを実装したのでそちらを使いました。 Treeは再帰的に処理させやすくてよいですね。
感想
Stanford Core NLPはもう少し丁寧に触るとかなりおもしろそうですね。 ステミングあたりなどは言葉から知らなかったり、パーサを初めて書いてみたり色々収穫の多い章でした。
いつも通りコードはGithubにも置いてあります。