hiramekunのブログ

プログラミングと読書と

Macのストレージ不足を解決

まずはこちらのサイトを参考にしました。 qiita.com

調べる

以下のコマンドで5GB以上のファイル・ディレクトリを出力します。

$ sudo du -g -x -d 5 / | awk '$1 >= 5{print}'
...
5   /usr/local/texlive/2017/texmf-dist
5   /usr/local/texlive/2017
6   /usr/local/texlive
...

Tex環境削除

どうやらtexの環境が容量を食っているようなので、texの開発環境を削除します。
最近ではoverleafを使っているので、ローカルでのtex環境はいらない状態になったためです。

自分はこれで5GB程度空きました。 qiita.com

Homebrewキャッシュ削除

次にhomebrewのキャッシュを削除します。
Homebrew でキャッシュを cleanup する方法 | gotohayato

まずはbrewで管理しているライブラリのうちで、異なるversionのものが入っている可能性があります。自分はgccのversionが3つほど入っていたのでそれを削除しました。
cleanupコマンドで、指定したライブラリに対して最新版以外のversionを削除を実行します。自分はこれで1GB程度空きました。

よくcleanup -sで全て重複しているものを削除する方法を見かけますが、pythonなどは異なるversionのものが必要でインストールしているので、自分は実行しませんでした。

$ brew list --versions
$ brew cleanup gcc

次にbrewがキャッシュしているdisk imageへのpathを調べ、そのpathのディレクトリを削除します。
自分はこれで1GB程度空きました。

$ brew --cache
~/Library/Caches/Homebrew
$ rm -rf ~/Library/Caches/Homebrew

Anaconda関連

こちらのサイトを参考にしました。 weblabo.oscasierra.net 自分は不要な環境がpy2.7という名前で存在していたので、その環境を削除します。

$ conda remove -n py2.7 --all

次に、不要になったパッケージやキャッシュを削除します。

$ conda clean --all

以上二つ合計で2GB程度空きました。

AndroidStudio関連

こちらのサイトを参考にしました。
https://tm23forest.com/contents/androidstudio-diskspace-reduction

特に3つめのエミュレータとシステムイメージは容量がでかいので一つ削除するだけで5GB程度確保することができます。

  • gradleファイルのキャッシュ削除
  • 古いSDK Toolsの削除
  • 使用していないエミュレータとシステムイメージの削除

UDPについて簡単にまとめる(TCPとの違い等)

UDPの機能

以下の二つの機能のみを持ちます。

  1. IPの層にもう一つ別のアドレッシングの層を追加する
  2. 転送中に発生し得るデータの破損を検出し、破損したデータグラムを破棄する

TCPとの違い

接続を確立しなくても使用することができる
受診時には、UDPソケットはどんなアドレスのホストからでも、複数のホストとの間でメッセージを送受信することができます。TCPでは1対1で接続を確立した後に送受信を行います。

ベストエフォート型の伝送
確実に宛先に届く保証はなく、メッセージが送信時と異なる順序で相手に届くこともあります。メッセージの欠落への対応と、並べ替えの仕組みが必要です。

UDPが使われる理由

効率が良い
わずかなデータ量しかやり取りをしないアプリケーションの場合、TCPでは接続確立段階で通信に必要なメッセージの数が少なくとも倍になります。

柔軟性を重視した時
参考した本によると、TCPによる信頼性の高いストリーム型のサービスが必要ない時に使えば、オーバーヘッドを非常に小さく抑えることができます。しかし、具体例が思い浮かばないので理解できていません。

参考

下記の本を参考にしました。

TCP/IPソケットプログラミング Java編

TCP/IPソケットプログラミング Java編

dotfilesの管理/運用方法をまとめる

目標

様々な設定ファイルをgithubで管理運用するのは、以下のような目標があります。

  1. 他のpcに乗り換えた時に環境構築を簡単に行いたい
  2. 設定ファイルのバックアップを取っておきたい
  3. 他の人に自分の設定ファイルを共有したい

しかし、普通に管理しようとすると、github上に設定ファイル分のレポジトリを作成することになります。そこで、今回はdotfilesというレポジトリ一個で全ての設定ファイルを管理する方法をまとめておきます。

dotfilesをレポジトリ管理

管理用ディレクトリ作成

ルートディレクトリに、管理したいファイルをまとめておくディレクトリを作成します。

$ mkdir dotfiles

そこに、管理したいファイルを全て入れます。私の場合は、zsh/bash/fish, vim, karabiner, bettertouchtool, ide用のideavimrcなどを管理しています。

$ mv ~/.config/fish ~/dotfiles/fish
$ mv ~/.bashrc ~/dotfiles/.bashrc
$ mv ~/.zshrc ~/dotfiles/.zshrc
etc...

シンボリックリンクを貼る

このままでは、本来ファイルがあるべき場所に設定ファイルがないので、mvしたファイルの設定が読み込まれないことになります。
なので、シンボリックリンクを貼って、本来ファイルがあるべき場所にaliasを設定します。

$ ln -sf ~/dotfiles/fish ~/.config/fish
$ ln -sf ~/dotfiles/.bashrc ~/.bashrc
$ ln -sf ~/dotfiles/.zshrc ~/.zshrc

githubにpush

こちらの記事などを参考にして、githubにdotfilesという名前のレポジトリを作成→commit→pushという流れでgithubに登録します。
qiita.com

自分のdotfilesはこちらにあります。

github.com

Rでガウス最尤推定(フィッシャーの線形判別分析)

ガウス最尤推定

流れ

ガウスモデルに標本が従っていると仮定します。  

そのガウスモデルから計算した対数事後確率が最も高いクラスに、標本を振り分けると考えます。
そのために、ガウスモデルのパラメータ推定→事後確率計算という流れを経ることになります。

定義

ガウスモデルとは正規分布のことです。
こちらの記事でも紹介していますが、定義は以下のようになっています。

hiramekun.hatenablog.com

{ \displaystyle
f(x) = \frac{1}{(2\pi)^{\frac{D}{2}}|\Sigma|^{\frac{1}{2}}}\exp(-\frac{1}{2}(x-\mu)^{T}\Sigma^{-1}(x-\mu))
}

{D}:次元
{x}:D次元ベクトル
{\Sigma}:xの分散共分散行列
{\mu}:D次元の分散ベクトル

最尤推定

最尤推定自体に関する説明は省きます。
各カテゴリごとに異なるガウスモデルを仮定した場合(つまり、 {y_i} ごとに異なる平均や分散の値を持っているということです)、上記のガウスモデルの最尤推定量は次のように計算されます。
 {\displaystyle
\hat{\mu_y} = \frac{1}{n_y}\sum_{i:y_i = y}x_i
}

 {\displaystyle
\hat{\Sigma_y} = \frac{1}{n_y}\sum_{i:y_i = y}(x_i - \hat{\mu_y})(x_i - \hat{\mu_y})^{T}
}

{\sum_{i:y_i = y}}{y_i = y} を満たす  {i} に関する和

対数事後確率

ベイズの定理と事後確率自体に関する説明は省きます。
対数事後確率は、計算すると以下のようになります。
 {\displaystyle
\log{\hat{p}(y|x)} = -\frac{1}{2}(x-\hat{\mu_y})^{T}{\hat{\Sigma_y}}^{-1}(x-\hat{\mu_y}) - \frac{1}{2}\log{|\hat{\Sigma_y}|} + \log{n_y} + C
}

やや複雑な形になるので、今回は各カテゴリの分散共分散行列が等しい時を考えます(つまり、 {y_i} の分散は等しく、同じ散らばりを持った分布であるとします)。

その時、対数事後確率は以下のように簡略化できます。
 {\displaystyle
\log{\hat{p}(y|x)} = \hat{\mu_y}^{T}{\hat{\Sigma_y}}^{-1}x - \frac{1}{2}\hat{\mu_y}^{T}{\hat{\Sigma_y}}^{-1}\hat{\mu_y} + \log{n_y} + C^{'}
}

フィッシャーの線形判別分析

この、分散共分散行列が共通の時、決定境界は超平面になります。
この場合をフィッシャーの線形判別分析と呼びます。

Rで手書き文字を分類する

事後確率計算

trainデータの分散共分散行列と平均を受け取って、testデータに対する事後確率を計算します。

calc_possibility = function(mean, invs, test_label) {
  mean %*% invs %*% test_label - (mean %*% invs %*% t(mean) / 2)[1][1]
}

結果

2クラス分類

まずは1と2を分類するタスクを実装しました。

正確には、2のtestデータセットを与え、1と判別するか2と判別するかを測定しました。
すると、testデータセット200に対して精度が99%と出ました。

[1] 0.99

そこで間違えて分類している2枚の画像はこんな感じ。
f:id:thescript1210:20180506051123p:plain

多クラス分類

今度は0~9までの数字全てに対して一度に分類を行ってみました。

それぞれの数字に対する精度を出力しました。

[1] "Accuracy of 1: 0.995000"
[1] "Accuracy of 2: 0.845000"
[1] "Accuracy of 3: 0.905000"
[1] "Accuracy of 4: 0.910000"
[1] "Accuracy of 5: 0.815000"
[1] "Accuracy of 6: 0.925000"
[1] "Accuracy of 7: 0.905000"
[1] "Accuracy of 8: 0.825000"
[1] "Accuracy of 9: 0.910000"
[1] "Accuracy of 0: 0.960000"

平均は約89%で、もちろんdeepには及ばないものの、簡単な実装でそこそこの精度が出ることがわかりました。

[1] 0.8995

全ての実装はこちらにあります。

github.com

RでKLダイバージェンスを描画する

今回はRでKLダイバージェンスを描画します。
KLダイバージェンスとは、カルバック・ライブラー情報量の略称。2つの確率分布の差異を測る距離的尺度として捉えることができます。

と言われても実感がわかないと思うので、実際に描画して感覚を掴んでいきたいと思います。
実装はこちらにあります。   github.com

定義

まずはエントロピーの説明をし、その上にあるKLダイバージェンスの定義を述べます。

エントロピー

連続関数のエントロピーは、情報量の期待値という定義なので次のように表せます。

\displaystyle
H(X) = -\int_{-\infty}^{\infty}p(x)\ln{p(x)} dx
直感的には、次に得られる情報量がどれだけの価値がある可能性があるかを示している数値になります。
(情報量とは、確率的に低いものを得た時に情報量を多く得たと判断するものです。)

KLダイバージェンス

今、正しい確率分布  p(x) と、その確率分布を近似したモデルである  q(x) があるとします。
この時に、 q(x) によって真の値を推測するために追加で必要な情報量の平均として定義されます。
具体的には、次のように表されます。「 q(x)エントロピー-  p(x)エントロピー」と捉えるとわかりやすいかもしれません。
{\displaystyle
KL(p||q) = -\int_{-\infty}^{\infty}p(x)\ln{\frac{q(x)}{p(x)}}dx
}

描画してみる

対象とするモデル

以下のように、平均mean2=2, 標準偏差sd2=2の正規分布を対象とします。

X = seq(-10, 10, length = n)
Y4 = dnorm(X, mean = mean2, sd = sd2)
plot(X,
Y4,
type = "l",
col = "blue")

f:id:thescript1210:20180501005147p:plain

KLダイバージェンスの図示

左の図は平均値を変化させた時のKLダイバージェンスの値。平均値が対象モデルと同じ2の時にKLダイバージェンスは最小値を取ることがわかります。
右の図は標準偏差を変化させた時のKLダイバージェンスの値。標準偏差が対象モデルと同じ2の時にKLダイバージェンスは最小値を取ることがわかります。

これらのことから、KLダイバージェンスは、モデル間のパラメータを用いて、モデル間の距離を表していると捉えることができますね。

f_kl_divergence = function(m1, m2, sd1, sd2) {
  log(sd1 / sd2) + (sd2 ^ 2 + (m1 - m2) ^ 2) / (2 * sd1 ^ 2) - 1 / 2
}
y_mean = c()
x = seq(-4, 4, length = 100)
for (i in x) {
y_mean = append(y_mean, f_kl_divergence(i, mean2, sd2, sd2))
}

y_sd = c()
x2 = seq(1, 3, length = 100)
for (i in x2) {
   y_sd = append(y_sd, f_kl_divergence(mean2, mean2, i, sd2))
}

layout(matrix(1:2, ncol=2))
plot(x, y_mean, type="l")
plot(x2, y_sd, type="l")

f:id:thescript1210:20180501005336p:plain

(番外編)Rのライブラリを用いてみる

Rには、KLダイバージェンスにしたがって乱数を生成し、元モデルのパラメータを推定する関数があります。
その関数であるKL.divergence()を用いて乱数を発生させ、それをプロットしました。

するとその結果は先ほどplotした理論値に近いグラフを描画することができました。

library(FNN)
set.seed(100)

kl_mean = c()
Y1 =  rnorm(n * 10, mean = mean2, sd = sd2)
for (i in seq(-4, 4, length = 100)) {
  Y2 = rnorm(n * 10, mean = i, sd = sd2)
  divs = KL.divergence(Y1, Y2, k = 2)
  kl_mean = append(kl_mean, mean(divs))
}

kl_sd = c()
for (i in seq(1, 3, length = 100)) {
  Y3 = rnorm(n * 10, mean = mean2, sd = i)
  divs2 = KL.divergence(Y1, Y3, k = 2)
  kl_sd = append(kl_sd, mean(divs2))
}

layout(matrix(1:2, ncol=2))
plot(seq(-4, 4, length = 100), kl_mean, type="l")
plot(seq(1, 3, length = 100), kl_sd, type="l")

f:id:thescript1210:20180501005418p:plain

Rで2次元正規分布を描画する

D次元正規分布

1次元正規分布はよく統計学とかでも出て来ますが、今回は2次元正規分布確率密度関数を描画したいと思います。

定義

{ \displaystyle
f(x) = \frac{1}{(2\pi)^{\frac{D}{2}}|\Sigma|^{\frac{1}{2}}}\exp(-\frac{1}{2}(x-\mu)^{T}\Sigma^{-1}(x-\mu))
}

{D}:次元
{x}:D次元ベクトル
{\Sigma}:xの分散共分散行列
{\mu}:D次元の分散ベクトル

以後D=2の場合を扱っていきます。

散布図

とりあえず確率密度関数を描画する前に、2次元正規分布に従う散布図をプロットしてみます。

library(mvtnorm)
sigma = matrix(c(2, 0.8, 0.8, 2), ncol = 2)
rand = rmvnorm(n = 1000, mean = c(0, 0), sigma)
x1 = rand[, 1]
x2 = rand[, 2]
plot(x1, x2)

mvtnormが多次元正規分布を描画するときには必要になります。
流れとしては、

  1. sigmaという分散共分散行列の定義
  2. rmvnormの引数に、平均と分散共分散行列を渡す
  3. rmvnormは渡された次元数を元に、多次元正規分布に従った乱数を生成

f:id:thescript1210:20180425000159p:plain

確率密度関数

それでは、確率密度関数{f(x)}を描画していきます。

x1 = seq(-3, 3, length = 50)
x2 = x1
f = function(x1, x2) {
  dmvnorm(matrix(c(x1, x2), ncol = 2), mean = c(0, 0), sigma = sigma)
}
z = outer(x1, x2, f)
z[is.na(z)] = 1
op = par(bg = "white")
persp(x1, x2, z, theta = 30, phi = 30, expand = 0.5, col = "orange")  

今回は、dmvnormという関数を用います。

  1. x1, x2に軸用の値を代入
  2. dmvnormの第一引数に軸ラベル、そして平均と分散共分散行列を渡す
  3. dmvnormは渡された次元数を元に、多次元正規分布を生成
  4. 多次元正規分布の出力をzに代入しperspでグラフ描画

こんな感じになります。
f:id:thescript1210:20180425000954p:plain

参考

こちらのサイトなどを参考にさせていただきました。
http://cse.naro.affrc.go.jp/minaka/R/R-binormal.html

また、自分の実装はgithubにあります。
github.com

Shift-JISのエクセルファイルの文字化けを直す

何回も同じことを調べていて覚えないので備忘録的に残します。
ファイルの文字コードを調べる

>> nkf -g hoge.csv
Shift-JIS

ファイルの文字コードをUTF-BOMに変更する
UTFの文字コードにすると、エクセルは適切に読み込んでくれないので、UTF-BOMに変換する必要があるようです。

>> nkf --overwrite --oc=UTF-8-BOM hoge.csv
>> nkf -g hoge.csv
UTF-8