$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

Coursera Machine Learning Week3の学習

に引き続き、Coursera Machine Learning Week3を受講した。

 Week3の講義を受けると次のことを学ぶことができた。

 以下講義を受けながら書いたメモを置いておく。

Classification and Representation

Classification

  • 線形回帰を分類問題に単純に適用してみるとうまく分類できない
  • ロジスティック回帰という手法を使うことで、分類問題を解くことができる

Hypothesis Representation

  • ロジスティック回帰で、あるxが与えられた時y=1となる確率を求める
  • ロジスティック回帰の予測関数は次のとおり

\begin{align*}& h_\theta (x) = g ( \theta^T x ) \newline \newline& z = \theta^T x \newline& g(z) = \dfrac{1}{1 + e^{-z}}\end{align*}

Decision Boundary

  • ロジスティック回帰によって、決定境界を見つけるというイメージ
  • 決定境界を決めるような \theta を得られたら、あとは\theta^Txを計算することで、yの値を決めることができる

\begin{align*}& \theta^T x \geq 0 \Rightarrow y = 1 \newline& \theta^T x < 0 \Rightarrow y = 0 \newline\end{align*}

Logistic Regression Model

Cost Function

  • 線形回帰と同一のcost functionを利用してしまうと、局所最適が多数できるような形になり、最急降下法が利用できない
  • 代わりに次のようなcost functionを利用する

\begin{align*}& J(\theta) = \dfrac{1}{m} \sum_{i=1}^m \mathrm{Cost}(h_\theta(x^{(i)}),y^{(i)}) \newline & \mathrm{Cost}(h_\theta(x),y) = -\log(h_\theta(x)) \; & \text{if y = 1} \newline & \mathrm{Cost}(h_\theta(x),y) = -\log(1-h_\theta(x)) \; & \text{if y = 0}\end{align*}

\begin{align*}& \mathrm{Cost}(h_\theta(x),y) = 0 \text{ if } h_\theta(x) = y \newline & \mathrm{Cost}(h_\theta(x),y) \rightarrow \infty \text{ if } y = 0 \; \mathrm{and} \; h_\theta(x) \rightarrow 1 \newline & \mathrm{Cost}(h_\theta(x),y) \rightarrow \infty \text{ if } y = 1 \; \mathrm{and} \; h_\theta(x) \rightarrow 0 \newline \end{align*}

Simplified Cost Function and Gradient Descent

ロジスティック回帰のcost functionを1行に圧縮すると
J(\theta) = - \frac{1}{m} \displaystyle \sum_{i=1}^m [y^{(i)}\log (h_\theta (x^{(i)})) + (1 - y^{(i)})\log (1 - h_\theta(x^{(i)}))]
となり、それをベクター化すると
\begin{align*} & h = g(X\theta)\newline & J(\theta) = \frac{1}{m} \cdot \left(-y^{T}\log(h)-(1-y)^{T}\log(1-h)\right) \end{align*}
となる。

最急降下法アルゴリズム
\begin{align*}& Repeat \; \lbrace \newline & \; \theta_j := \theta_j - \alpha \dfrac{\partial}{\partial \theta_j}J(\theta) \newline & \rbrace\end{align*}
となり、これもベクター化すると
\theta := \theta - \frac{\alpha}{m} X^{T} (g(X \theta ) - \vec{y})
となる。

Advanced Optimization

  • 正直あまり理解が進まなかったので、気が向いたらもう一回見る

Solving the Problem of Overfitting

The Problem of Overfitting

  • Modelのfeatureが少なすぎてうまく線形回帰問題や分類問題を解けない時、underfitting(high bias)と呼ぶ
  • 逆にfeatureが多すぎて、学習として与えたものにはフィットするが、予測に使えないModelになってしまったものをoverfitting(high variance)という
  • 対策としては
    • 1. featureを減らす
      • 手動で減らす <- 選択が難しいことが多い
      • model selection algorithmを利用する
    • 2. 正則化を行う
      • 特定のパラメータの重みを減らす(?)

Cost Function

  • 正則化を行う際、Cost Functionは以下のようになる。
    • \dfrac{1}{2m}\  \sum_{i=1}^m (h_\theta(x^{(i)}) - y^{(i)})^2 + \lambda\ \sum_{j=1}^n \theta_j^2
  • λは正則化パラメータと呼ぶ
  • これを使うことで不必要なfeatureの重みを減らすことができ、overfitting(過学習)を防げる

Regularized Linear Regression

線形回帰で正則化を行う際の最急降下法の公式。\theta_0は対象としないため、別の式となっている。

\begin{align*} & \text{Repeat}\ \lbrace \newline & \ \ \ \ \theta_0 := \theta_0 - \alpha\ \frac{1}{m}\ \sum_{i=1}^m (h_\theta(x^{(i)}) - y^{(i)})x_0^{(i)} \newline & \ \ \ \ \theta_j := \theta_j - \alpha\ \left[ \left( \frac{1}{m}\ \sum_{i=1}^m (h_\theta(x^{(i)}) - y^{(i)})x_j^{(i)} \right) + \frac{\lambda}{m}\theta_j \right] &\ \ \ \ \ \ \ \ \ \ j \in \lbrace 1,2...n\rbrace\newline & \rbrace \end{align*}

これを変形すると、

\theta_j := \theta_j(1 - \alpha\frac{\lambda}{m}) - \alpha\frac{1}{m}\sum_{i=1}^m(h_\theta(x^{(i)}) - y^{(i)})x_j^{(i)}

となり、\theta_j(1 - \alpha\frac{\lambda}{m})の項から、イテレーションごとに\theta_jを減らす処理を繰り返していることが分かる。


正規方程式で正則化を行う場合なら以下のとおり。

\begin{align*}& \theta = \left( X^TX + \lambda \cdot L \right)^{-1} X^Ty \newline& \text{where}\ \ L = \begin{bmatrix} 0 & & & & \newline & 1 & & & \newline & & 1 & & \newline & & & \ddots & \newline & & & & 1 \newline\end{bmatrix}\end{align*}

Regularized Logistic Regression

ロジスティック回帰にも同様に正則化を入れてみる。ロジスティック回帰のCost Functionに対して、正則化のための項を入れると以下のようになる。

J(\theta) = - \frac{1}{m} \sum_{i=1}^m [ y^{(i)}\ \log (h_\theta (x^{(i)})) + (1 - y^{(i)})\ \log (1 - h_\theta(x^{(i)})) ] + \frac{\lambda}{2m}\sum_{j=1}^n \theta_j^2

最急降下法のためのアルゴリズムは線形回帰のときとほぼおなじになるので割愛。

雑に書いたブログ記事が問題を起こさないようにする工夫

 ちょっとしたことでも雑にブログに書いておくと良いことが起こる - $shibayu36->blog; で、ちょっとしたことでも雑にブログに書いておくと良いことが起こるよということを書いた。さらに余談として最低限の雑さについても書いた。

 これをきっかけに、公開の場でアウトプットする時の最低限の雑さとはなんだろうという疑問が自分に生まれ、雑さによる問題や、それを引き起こさないようにするための自分の工夫について少し頭がまとまってきたので、自分の考えを書いておく。

過度な雑さから生じる最大の問題

 まずあまりにも雑に公開の場に書いてしまった場合の最大の問題について考える。この時、一番起こってほしくない問題は、「読み手が誤った情報を正しい情報と信じてしまう」ことだと考えた。

 あまりにも雑な文章は読み手の誤認を引き起こし、正しい情報ではないのに正しいと読み手が解釈してしまう問題がある。正しいと解釈してシェアなどを始めると、デマが流布されてしまう。さらにこれが発展すると、デマが流布されていると気づいた人によって叩かれるということが起こり、炎上などに繋がる。単にちょっとした自分の思いとかを書いておきたかっただけなのに、それが炎上してしまい、ボコボコにされると非常に辛い。

 また誤った情報を正しいと誤認させてしまうような記事がたくさんあると、徐々にインターネットでどの情報を信用すれば良いか分からなくなるという問題もある。公開の場に出す限りはある程度の配慮が必要であろう。

 では、雑に書いたとしても、「読み手が誤った情報を正しい情報と信じてしまう」問題を起こさないために、何に気をつけると良いだろうか。

上記の問題を起こさないための自分の工夫

 「読み手が誤った情報を正しい情報と信じてしまう」問題を起こさないために、自分は次のような工夫をしていると感じた。

  • 最低限自分が正しいと思っていることを書く
  • 事実なのか考えなのか分かる書き方をする
  • 最初に前提をはっきりさせる
  • 自分の中で曖昧な部分を書くときは、そのように明示する
  • 誤解を招くような表現がないかだけ最後にチェックする

最低限自分が正しいと思っていることを書く

 書く以上は最低限自分が正しいと思っていることを書くようにしている。やはり少なくとも正しいことを書くと心がけることは大事。もちろん書いた情報が時々間違っていることもあるけど、正しいことを書こうという思いだけは持っておく必要がある。

 また、自分が正しいと思えるくらいには調べておかないと、ちょっとしたことでも雑にブログに書いておくと良いことが起こる - $shibayu36->blog; で書いたような「知識が頭の中で言語化され、定着する」という効果も得られないだろう。

事実なのか考えなのか分かる書き方をする

 自分の考えを、読み手が事実として解釈し受け止められてしまった時、かつその考えが間違っていた時に、読み手が誤った情報を正しい情報と信じてしまうことが起こる。そのため、少なくとも自分の考えを事実として解釈できてしまうような書き方をしないよう心がけている。

 考えを明示するための書き方については「理科系の作文技術 (中公新書 (624))」という本に書かれていて、論理的な文章の技術を学ぶため「理科系の作文技術」を読んだ - $shibayu36->blog; にも書いたのだが、「私は〜と考える」という表現を使うのが最も簡単である。

最初に前提をはっきりさせる

 最初に記事の前提をはっきりさせることも心がけている。例えば今回だったら「雑さによる問題や、それを引き起こさないようにするための自分の工夫について少し頭がまとまってきたので、自分の考えを書いておく」がこの記事の前提だ。このように前提を書いておくことで、読者がこれは単なるこの人の考えなのだなと思いながら読むことができる。

 他にも自分の立場を明らかにするというのも有効だろう。例えばMySQLのfilesortは何ソートで行われているのか - $shibayu36->blog; の記事では、「MySQLのコードを読んだのも初めてで、しかもちゃんと読み解くことができなかった」という風に、MySQLという知識については初心者であるという立場をはっきりさせてから書いている。

自分の中で曖昧な部分を書くときは、そのように明示する

 また、雑に書こうとすると、自分の中でこれは本当に正しいか怪しいなと思う部分についても書くことがある。その部分は特に読者に誤認させたくない。

 そこで僕は自分の中でまだ曖昧な部分をメモしておくときは、きちんとその旨を明示するようにしている。例えば、「この部分はこのように解釈したが、正しいか自信がない」などの文言を追加したりする。

誤解を招くような表現がないかだけ最後にチェックする

 どれだけ書く時に気をつけても、誤解を招くような表現を無意識に使ってしまっていることがある。このような表現は書いている時には気づかないことが多い。

 そこで自分は書き終わった後に、最後に誤解を招く表現がないかだけはチェックするようにしている。誤解を招く表現というのは、自分の意見を事実のように捉えられる表現とかである。

まとめ

 今回はちょっとしたことでも雑にブログに書いておくと良いことが起こる - $shibayu36->blog; の余談である最低限の雑さから発展させ、雑に書いたブログ記事が問題を起こさないようにする自分なりの工夫について考えてみた。他にこういう問題があるのでは、こういう工夫があるのではという意見があったら知りたい。