Golangで主成分分析する

前回の記事では、 多次元正規分布から乱数を生成する方法を書きました。 今回は、このデータを使って主成分分析(PCA)を行っていきます。

PCAの詳細については、書籍や他の記事などで十分存在していると思うので、そちらを探してみてください。 分散を最大化する方向に軸を取るのか、射影誤差の最小化を行うのかなど複数の解釈が同じ数式に帰着するのも面白いですね。結局は、共分散行列の固有値問題に帰着するのですが。

まず、今回の対象データですが、  \Sigma = \begin{bmatrix}
3.0  \ \ 0.5 \\
0.5  \ \ 1.0
\end{bmatrix}
の共分散行列を用いて生成した擬似乱数(2次元×10000個)を使用します。 散布図を書くと以下のようになります。

f:id:cipepser:20171030224226p:plain

Golangstatパッケージでは、PCAを行ってくれるPrincipalComponentsメソッドがあるので、こちらを利用します。

コード

まず擬似乱数の生成です。のちほど使うPrincipalComponentsの引数がmat.Matrixなので、 mat.NewDenseで生成した*mat.Dense型のyに乱数を格納していきます。 ちなみに*mat.Dense型はmat.Matrix型のinterfaceを満たします。

y := mat.NewDense(N, d, nil)
for i := 0; i < N; i++ {
  rnd, _ := MultiNorm(mat.NewVecDense(d, []float64{0.0, 0.0}),
    mat.NewSymDense(d, []float64{3.0, 0.5, 0.5, 1.0}),
  )

  y.SetRow(i, mat.Col(nil, 0, rnd))
}

次にPCAの実行です。stat.PC型がPCA用の型となります。

var pc stat.PC
ok := pc.PrincipalComponents(y, nil)

PCAのあとはデータを射影していきます。次元削減を目的とする場合はkで残したい次元数を指定できます。

k := 2
var proj mat.Dense
proj.Mul(y, pc.VectorsTo(nil).Slice(0, d, 0, k))

以上をまとめたコード全体は次のようになります。

giste8f284fa0ed27fa4802ebe0867a795aa

PCA後の散布図は以下のようになりました。

f:id:cipepser:20171030224230p:plain

References

Golangで多次元正規分布を生成する

前回の記事も書きましたが、 Golangrandパッケージでは、 一次元正規分布の乱数生成が可能です。 今回は、多次元正規分布から乱数を生成する方法についてまとめます。

どうやって生成するか

まずPRMLから引用します。

平均 \boldsymbol{\mu} ,共分散 \boldsymbol{\Sigma} を持つ多変量ガウス分布に従うベクトル値の変数を生成するには,  \boldsymbol{\Sigma} = \boldsymbol{LL}^{T}の形を取るコレスキー分解(Cholesky decomposition)を用いればよい(Press et al., 1992). このとき, もし \boldsymbol{z}がベクトル値の確率変数であり, その各要素が独立で, 平均0, 分散1のガウス分布に従うとすれば,  \boldsymbol{y} = \boldsymbol{\mu} + \boldsymbol{Lz}は平均  \boldsymbol{\mu}, 共分散 \boldsymbol{\Sigma}ガウス分布に従う.

rand.NormFloat64()は、まさに平均0、分散1の一次元正規分布の乱数を生成してくれるので、 与えられた \boldsymbol{\Sigma}をコレスキー分解すれば多次元正規分布からの乱数生成ができます。

gonumのmatパッケージでは、Cholesky型のFactorizeメソッドでコレスキー分解ができるので、こちらを使って多次元正規分布からの乱数を生成します。

コード

実装は以下です。MultiNorm関数として実装しています。 散布図を描くコードも含んでいるので、少し長いです。。。

gist3609a47a7f572bd8e479ef120dae3f0e

実行結果

f:id:cipepser:20171029222325p:plain

References

Golangで正規乱数を生成する

意外と日本語記事がなかったので、あとで見返すメモとして。

gist0ede769769cc5831b540a5896bf6e868

ヒストグラムにすると以下です。

f:id:cipepser:20171029040935p:plain

References

インフラ/ネットワークエンジニアのためのネットワーク・デザインパターン 実務で使えるネットワーク構成の最適解27を読んだ

前作であるインフラ/ネットワークエンジニアのためのネットワーク技術&設計入門を読んでから、少し間が空いてしまいましたが、続編となるインフラ/ネットワークエンジニアのためのネットワーク・デザインパターン 実務で使えるネットワーク構成の最適解27 - みやた ひろしを読みました。

感想

まず、読んでいて一番の感想は、本自体の構成も設計されている ということです。 ネットワークを設計するにあたって、ネットワークを以下の4つに分類し、それぞれについて述べる形で整理された構成となっています。

  • Trustゾーン
  • Untrustゾーン
  • DMZゾーン1
  • WANゾーン

さらに各ゾーンを大中小の3規模にわけ、それぞれ2つずつデザインパターンを述べる構成となってています。 各ゾーンの説明が小さい順に記載されており、設計の考え方自体は一貫しているので、大規模ネットワークになっても理解しやすかったです。

さらに各節の中でも項目が一貫しており、以下のようになっています。

  • 物理構成、論理構成
  • 機器構成設計、物理構成設計、VLAN設計、IPアドレス設計、ルーティング設計
  • 障害設計
  • 運用設計

これに加えて各構成で独自に必要な設計(負荷分散設計やSTP設計など)は個別に述べられています。

各構成で考え方が一貫している一方で、同じ話が何度か登場します。 内容が重複してしまうのは一長一短ですが、個人的には、何回も同じトピックが出るので理解が染み込んでくる点、あとで読み返す際にその節だけ読めばいい点で、丁度よいと感じました。

個人的にヒットしたところ

LAGを使ってSTP構成を組む場合に、物理ポート障害が発生するとSTPの再計算となる話が載っています。
STPの仕組みとしてコストがあり、このコストに応じてL2ループが発生しないようになっていることはわかっていたのですが、障害時に余計な再計算をさせないように値を設定する、といった意識できていなかった話が載っており、学びが多かったです。

こういう人におすすめ

ネットワーク設計に多少の経験があるので、デザインパターンを体系的に整理したいという方におすすめです。

一方で、OSPFやBGP、IPsecなど各種の設定で注意すべき設定などは書かれているものの基本的な仕組みなどの記載は少ないので、ネットワーク技術の知識に不安がある場合は、本書の前に前作のインフラ/ネットワークエンジニアのためのネットワーク技術&設計入門を読むのがいいと思います。

どちらも構成がわかりやすいのと簡潔にまとめられているので数日あれば十分読めると思います。 本書に関しては、ページを捲る手が止まらず実質2日くらいで読み切ってしまいました。

インフラ/ネットワークエンジニアのためのネットワーク・デザインパターン 実務で使えるネットワーク構成の最適解27 - みやた ひろし

いつもはkindle派な自分ですが、データフローを正常時と障害時で見比べたりしながら読むと理解が深まるので紙の書籍がおすすめです。


  1. 余談ですが、よくDMZゾーンって言葉を耳にするときに、頭痛が痛いになってるなぁと思っていたのですが、本書ではわかりやすさを優先し、DMZゾーンと記載すると書いてあり、すっきりしました。

Golangで言語処理100本ノック2015 第8章: 機械学習

言語処理100本ノック 2015の第8章: 機械学習の10問です。

本章では,Bo Pang氏とLillian Lee氏が公開しているMovie Review Dataのsentence polarity dataset v1.0を用い,文を肯定的(ポジティブ)もしくは否定的(ネガティブ)に分類するタスク(極性分析)に取り組む.

70. データの入手・整形

文に関する極性分析の正解データを用い,以下の要領で正解データ(sentiment.txt)を作成せよ.

  1. rt-polarity.posの各行の先頭に"+1 "という文字列を追加する(極性ラベル"+1"とスペースに続けて肯定的な文の内容が続く)
  2. rt-polarity.negの各行の先頭に"-1 "という文字列を追加する(極性ラベル"-1"とスペースに続けて否定的な文の内容が続く)
  3. 上述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

f:id:cipepser:20171015142932p:plain

f:id:cipepser:20171015142939p:plain

感想

機械学習の流れ自体は、学生時代に触っていたので頭に入っているものの素性など、NLP特有の用語で少し戸惑いました。あと2値分類といえば、SVMばかりだったのでロジスティック回帰も改めて勉強して整理できたのでよかったです。

いつも通りコードはGithubにも置いてあります。

Reference

はてなブログでベクトルをbold表記したい[markdown]

TeXでいうところの\boldmath{x}をやりたいもののはてなでは表示されないので、以下の書式をメモ代わりに残しておきます。 はてなでベクトルのbold表記は以下でできます。


 \boldsymbol{x}

\boldsymbol{x} 

ちなみに検索すると以下がよく見つかるのですが、斜体でないのでやりたいこととは違いました。

 \textbf{x}

\textbf{x}

Reference

zplugのautosuggestionsのカラー設定方法

fishコマンドとbash/zshコマンドの微妙な差異で時間を浪費するのをやめるべく、zshに戻る決心をしました。 一方でzshでも、AutoSuggestionを使いたく、 zsh-autosuggestions を導入したものの、デフォルトの色が見えないほど薄かったので変える方法をまとめます。

変え方

READMEZSH_AUTOSUGGEST_HIGHLIGHT_STYLEを設定すればよいとあります。

今回はzplugzplug "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