hiramekunのブログ

プログラミングと読書と

Pythonのsetuptoolsで生じたAttributeErrorを解決(メモ)

setuptools周りを触り出したら、condaコマンドを打つたびに以下のようにエラーが出てきて実行ができなくなりました。f:id:thescript1210:20180808110606p:plain

AttributeError: '_NamespacePath' object has no attribute 'sort'
きちんとは理解していませんが、setuptoolsのgithubのissueをみると、最新のバージョンではこの問題は解決されているよ!というコメントを多数発見。

github.com

確かに以下によるとsetuptoolsが最新版ではないようです。

  File "/Users/takaakihirano/anaconda/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg/pkg_resources/__init__.py", line 2087, in _rebuild_mod_path
AttributeError: '_NamespacePath' object has no attribute 'sort'

なので、condaのdefault環境のsetuptoolsをupdateしたら無事に解決しました。

>> conda update setuptools

『「学力」の経済学』まとめ

出典はこちらの中室牧子先生の『「学力」の経済学』です。教育を経済的にエビデンスベースで解説してくれていて非常に興味深い本ですので、ぜひ本を読んでみてください。

「学力」の経済学

「学力」の経済学

教育経済学とは?

  • 教育経済学は教育を経済学の理論や手法を用いて分析することを目的としている応用経済学の一分野。大規模なデータを用いて教育を経済学的に分析する。
  • 所詮一つのものを表しているに過ぎないことを、あたかも全体を表しているかのようにすることを非常に危ぶんでおり、特に教育の分野ではそれが顕著に現れる。

    • しかしながら日本ではまだ、教育政策に科学的な根拠が必要だということが浸透していない。
  • 端的にいうと、科学的根拠に基づく教育政策とは、「どういう教育が成功する子を育てるのか」ということを科学的に明らかにしようとする試みである。

目先の利益と将来の利益

  • 遠い将来のことなら冷静に考えられても、近い将来のことだと、たとえ小さくてもすぐに得られるもので満足してしまう。
    • これを勉強に利用して、目先のご褒美で勉強させてはいけないのだろうか?
  • 「勉強したらご褒美」 VS 「いい成績とったらご褒美」で実験をしたところ、「勉強したらご褒美」の子供達の方が成績が上がった。→ outputではなくて、inputにご褒美を与えるべきである。

自尊心と学力の関係

  • 自尊心が高まれば、子供を反社会的なリスクから遠ざけることができるという科学的根拠はほとんど出なかった。
  • 自尊心が高いから学力が高まるのではなく、学力が高まったから自尊心が高くなっているだけ。
  • 宿題を行うときに自尊心を高めるメッセージを受け取ったグループの学生は、受け取らなかったグループの学生よりも、期末試験の成績が統計的に有意に低かった。
    •  しかし、褒め方が重要。子供の元々の能力を褒めると、子供たちは意欲を失い、成績が低下する。努力を褒められた生徒は成績を伸ばすことができた。

ゲームやテレビと学力

  • テレビの視聴時間と肥満・ゲームの使用時間と問題行動には正の相関がある。
  • テレビやゲームを1時間やめさせても男子については最大1.86分、女子については最大2.70分しか勉強時間が増えなかった。
  • テレビやゲームが一日2時間を超えると発達や学習時間への負の影響が飛躍的に大きくなる。

人間関係と学力

  • 父母ともに「勉強するようにいう」のはあまり効果がない。むしろ母親が娘に対して「勉強するようにいう」のは負の効果がある。
  • 女子が偶然多くなった学年では、女子が少ない学年と比べて、男女ともに成績が高くなった。→学力の高い女子の比率が高くなると、学年全体の平均的な学力に正の因果関係が確認される。
    • 多くの研究で男子よりも女子の方が成績が良いことが明らかになっているが理由ははっきりとはわかっていない。
  • 学力の高い学生と学力の低い学生が一緒のクラスにいる場合、学力の高い同級生の存在が学力の低い生徒の自信を喪失させ、大学進学の意欲を失わせた。
  • 問題児の存在が学級全体の学力に負の因果豪華を与える。
  • 習熟度別学級は、特定の学力層だけではなく、全体の学力を押し上げるのに有効な政策である。

幼児教育の大切さ

  • もっとも投資に対する収益率が高いのは、子供が小学校に入学する前の就学前教育。
  • 学力テストなどで測れる認知能力に関しては数年で、教育を受けていない子供たちとさはなくなる。それなのに年収や地位は異なっている。→大きな差は非認知能力に現れていた。
    • 自制心ややり抜く力という能力が高い人が成功している。
  • しつけは非認知能力の一つである勤勉性を養う重要なものである。

少人数学級に効果はあるか

  • 少人数学級は学力を向上させる因果効果はあるものの、他の政策と比較すると費用対効果は低い政策である。
  • 教育を受けることの経済的な価値に対する誤った思い込みを正すだけで、子供の学力を高めることができる。
  • 巨額の財政赤字を抱えている日本で、「少人数学級になるときめ細かい指導ができる」などという根拠のない期待や思い込みで、財政支出を行うのは極めて危険。

学力テストの罠

  • 学力テストの結果は、日本の公立小中学校に対して行われている。
  • 学力はどの学校に通うかだけではなく、どの家庭に生まれ育ったかも極めて重大な影響をあたえる。

学力格差の是正

  • ある世代の子供全員を対象にして平等に行われた政策は、親の学歴や所得に夜教育格差を拡大させてしまうことがある。
  • 子ども手当のような補助金は学力の向上には因果関係を持たなかった。
  • 世代内の平等を優先するあまり、世代間の平等が失われている現状がある。(たとえばゆとり世代

優秀な教員は生徒を変える

  • 教員の質が高いほど、テストの平均点は上がった。
  • 教員研修が教員の質に与える因果効果はない。
    • 元々能力の高い人を雇うのが大事。
  • 教員免許は必ずしも教員の質を担保できているわけではない。

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でガウス最尤推定(フィッシャーの線形判別分析)

全ての実装はこちらにあります。
7/5:リンク先更新しました。

github.com

ガウス最尤推定

流れ

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

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

定義

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

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

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

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

と言われても実感がわかないと思うので、実際に描画して感覚を掴んでいきたいと思います。
実装はこちらにあります。
7/5:リンク先更新しました。

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