デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理と英語を基礎からやり直す。https://qiita.com/yaju

2019年こそ英語を継続して勉強する

はじめに

今年になってサブタイトルにこっそり「英語」を追記しました。
毎年新年を迎えると今年こそ英語をと誓うものの、数ヶ月もすれば何もしないで終わってそのまま1年経ってしまう。
こんなことを25年ぐらいやっているわけで、溜まるのは本や教材ばかりです。
20年前のドリッピーもあるし、釈由美子さんやっていたNHK英語でしゃべらナイト」の本は全部揃ってます。

ネットで紹介されてた本も買うものの、買うだけで満足してしまったり、読み終えるだけで終わるって状態です。

習慣化

昨年、Twitterのツイートでコワーキングをしている「エニシア静岡」ってところを知りました。勉強会の会場とかになってたんですね。
www.enicia.net

静岡街中の丸井の最上階にあるんですが、今いる会社から近いので今年からAfter Time会員になって仕事帰りに静岡駅に行く前に寄るようにしています。
ここで今は平日は1時間勉強しています。慣れてくれば時間を徐々に増やして2時間ぐらいまでしていきたいところですが、家もそもそも遠いので限界があります。今なら観たいドラマもTverで時間ずらして見れますしね。

英語力

中学1年生レベルからはじめました。
本を購入したんですが、結局iPhoneアプリ版を使っています。

これと英語組み立てTOWNをやっています。自分は昔に購入したので有料版を使っていますが、今は広告有りの無料版が出ているようです。
これは英文法の整序問題で正しい順序にして英文法を作成するのですが、結構楽しいです。

最後に

TOEICを受けたことがないですが、現在のレベルからしたら300点以下だと思います。これをTOEIC600点以上にはしていきたいです。

「サザエさんのじゃんけん データ分析」の2018年の結果

はじめに

明けましておめでとうございます。

さてさて、2018年のサザエさんのじゃんけん結果はどうなったでしょう。
ちなみに、2017年のサザエさんのじゃんけん結果は、32勝9敗7分(勝率0.780)でした。

人工知能による予測化を断念

ごめんなさい、DeepLearningを使用して予想をする予定でしたが、まだ勉強中のままです。

r_stdさんが、機械学習を用いて検証してくれました。
この方は2016年に統計検定準1級に合格している方で幾つかの手法を使っています。
2017年の結果として、naive bayesで33勝9敗6分と好成績を残しています。
r-std.hatenablog.com

約一年越しに②の記事が追加されました。
2018年の結果としてランダムフォレストで32勝10敗7分と好成績を残しています。
r-std.hatenablog.com

次の手の予測アルゴリズム

2017年冬版 サザエさんじゃんけん白書によるとクール(四半期)の初回(1月、4月、7月、10月の初回)はチョキが出やすいとのことで、今回取り入れてみました。

  • チョキが多いので、グー > チョキ > パーの優先順位とする
  • 前回と違う手を出すので、上記の優先順位で勝手を選ぶ
  • 二手前と一手前が違う手なら、残りの手を出すので勝手を選ぶ
  • 三手の中に同手がある場合、 残りの手を出すので勝手を選ぶ
  • 二手前と一手前が同じ手なら、勝手を出すので負手を選ぶ
  • 1月、4月、7月、10月の第1週目はチョキが出やすいので、グーを選ぶ(追加)

qiita.com

2018年の勝敗結果

年月 サザエさんの手 予想の手 勝敗結果
01月07日 チョキ グー 勝ち
01月14日 グー グー 引き分け
01月21日 チョキ チョキ 引き分け
01月28日 グー チョキ 負け
02月04日 パー チョキ 勝ち
02月11日 グー グー 引き分け
02月18日 チョキ グー 勝ち
02月25日 チョキ チョキ 引き分け
03月04日 パー チョキ 勝ち
03月11日 グー パー 勝ち
03月18日 グー グー 引き分け
03月25日 チョキ グー 勝ち
04月01日 チョキ グー 勝ち
04月08日 グー チョキ 負け
04月15日 パー チョキ 勝ち
04月22日 パー グー 負け
04月29日 チョキ グー 勝ち
05月06日 グー パー 勝ち
05月13日 チョキ チョキ 引き分け
05月20日 パー チョキ 勝ち
05月27日 グー パー 勝ち
06月03日 チョキ グー 勝ち
06月10日 グー チョキ 負け
06月17日 パー チョキ 勝ち
06月24日 パー グー 負け
07月01日 チョキ グー 勝ち
07月08日 グー パー 勝ち
07月15日 パー チョキ 勝ち
07月22日 グー グー 引き分け
07月29日 チョキ グー 勝ち
08月05日 チョキ チョキ 引き分け
08月12日 パー チョキ 勝ち
08月19日 グー パー 勝ち
08月26日 グー グー 引き分け
09月02日 パー グー 負け
09月09日 チョキ グー 勝ち
09月16日 グー パー 勝ち
09月23日 チョキ チョキ 引き分け
09月30日 パー チョキ 勝ち
10月07日 チョキ グー 勝ち
10月14日 グー パー 勝ち
10月21日 パー チョキ 勝ち
11月04日 パー グー 負け
11月11日 チョキ グー 勝ち
11月18日 チョキ パー 負け
11月25日 グー パー 勝ち
12月02日 グー チョキ 負け
12月09日 パー チョキ 勝ち
12月16日 チョキ グー 勝ち

結果は、30勝9敗10分(勝率0.769)となりました。

ちなみに、サザエさんじゃんけん研究所 公式ウェブサイトサザエさんの手の予想と勝負結果(2018年)が29勝7敗13分(勝率0.805)でした。

今回は勝数では上回ったのですが、勝率では負けました。 勝率の計算は、「勝ち / (勝ち + 負け)」で行っているのですが、負けが響いたわけです。

データ分析(新)として「1月、4月、7月、10月の第1週目はチョキが出やすいのでグーを選ぶ」という機能を追加して過去の勝敗結果も出してみました。そうすると意外といい数字になるわけですね。

データ分析(新) データ分析 研究所公式 r_stdさん
2013 26勝11敗12分(勝率0.703) 24勝13敗12分(勝率0.649) 25勝9敗17分(勝率0.735) -
2014 32勝8敗11分(勝率0.800) 30勝10敗11分(勝率0.750) 30勝9敗12分(勝率0.769) -
2015 34勝8敗8分(勝率0.810) 32勝9敗9分(勝率0.780) 33勝9敗8分(勝率0.785) -
2016 26勝12敗12分(勝率0.684) 27勝11敗12分(勝率0.711) 22勝13敗15分(勝率0.628) -
2017 34勝8敗6分(勝率0.810) 32勝9敗7分(勝率0.780) 29勝8敗11分(勝率0.783) 33勝9敗6分(勝率0.785)
2018 30勝9敗10分(勝率0.769) - 29勝7敗13分(勝率0.805) 32勝10敗7分(勝率0.761)

勝率を計算する際には、引き分けを除いて考えることが多いです。プロ野球などの勝率は引き分けを除いて計算されています。 mathwords.net

スライド

2013年に静岡Developers勉強会で機械学習を学び、2014年1月にネタとしてSlideShareに公開しました。

サザエさんのじゃんけん データ分析 from yaju88

最後に

今年こそはTensorFlowを使って人工知能ディープラーニングで予測手を作りたいと思います。
r_stdさんのようにディープラーニングを使わない別の機械学習の方法でもいい結果が出ているので参考にさせて頂きます。

交差エントロピーを理解してみる

はじめに

ここ数ヶ月は別の件で忙しくて、機械学習に向き合えていませんでした。
仕事で調べたり学んだことはQiitaブログの方に書いていて結構すんなり書けるんですが、このブログは数学・物理・機械学習と特化するようにしているので、パワーがないと進まない。

ここ数ヶ月で頭の片隅にあったのは、損失関数の「交差エントロピー」です。今回はこれを理解していこうと思います。

何故、気になっていたのかというと、下記サイトの誤差関数(loss)のときのTensorflow関数「tf.nn.sigmoid_cross_entropy_with_logits」があり、シグモイド関数と交差エントロピーが一緒になっているからです。

yaju3d.hatenablog.jp

# 誤差関数(loss)
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=u, labels=y_)

損失関数

機械学習では学習時に、いかに答えに近い値になるように重みパラメータを調整(必要な補正量を定量的に示す)させます。その部分を担うのが損失関数となります。そして損失関数の最小値を探すことが学習のゴールとなる。 損失関数を設定する理由は、認識精度を指標するとパラメータの微分がほとんどの場所で 0 (動かなくなる)になるから。

簡単な説明では「値=損失」ということで、この損失をいかに少なくするのかということで「損失関数」となります。
ちなみに、損失関数と誤差関数の呼び方が違うだけで同義となります。
目的関数、コスト関数、誤差関数、損失関数いろいろあるけど、なにが違うのかを検討 - Qiita

損失関数は幾つか種類がありますが、機械学習では下記の2種類がよく使われます。
※理由として「誤差逆伝播」ができる関数であることのようです。

  • 二乗誤差(mean squared error)
  • 交差エントロピー誤差(cross entropy error)

交差エントロピー誤差(cross entropy error)

二乗誤差の方は比較的分かりやすいので、交差エントロピーを理解していきます。
分類問題(識別問題)になると交差エントロピーが出てきます。

f:id:Yaju3D:20160421012315p:plain

\displaystyle E=\sum_{k=1} -y_k\log{t_k}-(1-y_k)\log{(1-t_k)}

これがある条件(分類問題)になると簡単になります。
交差エントロピー誤差では、実質、正解データt = 1 の場合にしか計算は行われません(正解データt = 0 の時には、乗算結果は常に 0 に収束するから)

\displaystyle E=\sum_{k=1} - t_k \log y_k

エントロピー

エントロピーとは平均情報量のことです。

A国、B国に置けるその日の天気を表した表を以下に定義します。

晴れ(%) 曇り(%) 雨(%) 雪(%)
A国 25 25 25 25
B国 50 25 12.5 12.5

この時それぞれの天気のエンコード方法は以下のようにするとします。

天気 ビット
晴れ 00
曇り 01
10
11

この時、メモリの容量が1KB(8000bit)だとすると、4000(日)のデータを保存できる。
\displaystyle \frac{8000(bit)}{2(bit)}=4000(日)

しかし、このエンコード方法は無駄があることがわかるでしょうか?
なぜなら、B国では晴れの日が50%である為、以下の表のように、エンコードした際に使うbit数を1にすると、容量を節約することができ、同じ8000bitのメモリで4500日以上分のデータを保存できる。

天気 ビット
晴れ 0
曇り 10
110
111

\displaystyle H(P_b) = E_{P_b} \begin{bmatrix}log_{2}(\frac1{P_{b}(\omega)})\end{bmatrix} \displaystyle =0.5log_{2} \left(\frac1{0.5}\right)+0.25log_{2}\left (\frac1{0.25}\right) +0.125log_{2}\left (\frac1{0.125}\right)+0.125log_{2}\left (\frac1{0.125}\right) = 1.75

最適なコードの割り当て方法は数学的証明により、求められており

確率P(\omega) で起こる事象には長さ\displaystyle log_{2} \left(\frac{1}{P(\omega)}\right) のコードを割り当てるのが最適とされている。
また、期待値(1回の試行の結果を伝えるのに要する平均ビット数)をエントロピー(平均情報量)とよびます。

交差エントロピー

ここでそれぞれの国の最適エントロピーを上のような数学的方法によって求めてみましょう。
まずは、ある国の最適なエントロピーの求め方で、他の国のエントロピーを求めた場合を考える。

[例] B国の最適エントロピーの求め方で、A国のエントロピーを求める。

\displaystyle H(P_b) = E_{P_b} \begin{bmatrix}log_{2}(\frac1{P_{b}(\omega)})\end{bmatrix}
=\displaystyle  0.25log_{2} \left(\frac{1}{0.5}\right)+0.25log_{2} \left(\frac{1}{0.25}\right)+0.25log_{2} \left(\frac{1}{0.125}\right)+0.25log_{2} \left(\frac{1}{0.125}\right)=2.25

A国の最適エントロピーの求め方をしていないので、0.25[bit]分無駄が生じてしまっています。
このように、ある確率分布に最適化された方式で別の確率分布をエンコードした時の平均ビット長を「交差エントロピー」と呼びます。

交差エントロピーの「交差」とは何なのかを偶然知った。曰く、p×log(p)のようにlogの中身と外側に同じ変数が使われているのが普通のエントロピー。それに対して、t×log(y)のようにlogの中身と外側に異なる変数が使われているものを"交差"エントロピーと呼ぶらしい。 「ゼロから作るDeep Learning」を読んだ(後編) - 不確定な世界

損失関数・交差エントロピー誤差とは

交差エントロピー誤差では、 自然対数eを底とするモデル出力値のlog値と正解データ値を乗算したものの総和を、損失とします。
自然対数logは、logに渡される x の値が 0 に近い時には絶対数の大きな出力を返し、 x の値が 1 に近いほど、絶対数が 0 に近い出力を返します。 すなわち、正解データ t が 1 の時、それに対応するモデル出力 y が 1 に近い数値を出力できていれば、 t と x の乗算結果は小さくなり、 x が 0 に近い誤った数値を出力していれば、 t と x の乗算結果は大きくなる、という論理です。

wild-data-chase.com

qiita.com

なぜ分類問題では交差エントロピーが使われるのか

損失関数といえば二乗誤差が有名ですが、分類問題を扱う際には交差エントロピーが頻繁に使われます。
教師データと学習結果が大きく乖離している(損失関数の値が大きい)時、交差エントロピーを使った方が学習スピードが早い!!(1学習あたりの損失関数の減少幅が大きい)

出力結果(y)が0に近いところだと、交差エントロピーの微分値がとてつもなく大きなマイナスになっていることがわかります。微分値が大きなマイナスになっているということは、それだけ損失関数がマイナスに大きく変動しているということを意味しています。
なぜ交差(クロス)エントロピーが機械学習(ニューラルネットワーク)の損失関数に使われるのか? | まなれきドットコム

sigmoid_cross_entropy_with_logits

交差エントロピーは、ニューラルネットワークの誤差関数(損失関数)として使われることがあります。特に、シグモイド関数との相性がよい。
Tensorflowでは、「tf.nn.sigmoid_cross_entropy_with_logits - tensorflow」と一緒になっている。

交差エントロピーの式の中にシグモイド関数が入ったものである。
\displaystyle E=\sum_{k=1} -y_k\log{t_k}-(1-y_k)\log{(1-t_k)}

         ↓

\displaystyle E=\sum_{k=1} -z\log{(sigmoid(x))}-(1-z)\log{(1-sigmoid(x))}

         ↓ 符号が違うので、それぞれに -1 を掛ける \displaystyle E=\sum_{k=1} z-log{(sigmoid(x))}+(1-z)-\log{(1-sigmoid(x))}

 z * -log(sigmoid(x)) + (1 - z) * -log(1 - sigmoid(x))
= z * -log(1 / (1 + exp(-x))) + (1 - z) * -log(exp(-x) / (1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (-log(exp(-x)) + log(1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (x + log(1 + exp(-x))
= (1 - z) * x + log(1 + exp(-x))
= x - x * z + log(1 + exp(-x))

上記プログラムは、tf.nn.sigmoid_cross_entropy_with_logits のロジックのコメントにあったものである。
次の式の展開がどうしてそうなるのか分からない、数学が出来る人は過程を省略するんだよね。
そういうのは嫌い、自分が分かった限りで説明していきます。

= z * -log(1 / (1 + exp(-x))) + (1 - z) * -log(exp(-x) / (1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (-log(exp(-x)) + log(1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (x + log(1 + exp(-x))

この式で分かりにくい部分は、-log(1 / (1 + exp(-x))) → log(1 + exp(-x)) になることですね。
これは、対数の中身が分数の場合の展開が分かるといいです。log1=0
\displaystyle log\left(\frac{1}{8}\right) = log\left(\frac{1}{2^{3}}\right)  = log1-log(2^{3}) = 0-3log2 = -3log2

対数の分数は引き算に分けることができます。
\displaystyle -log\left(\frac{1}{1+exp(-x)}\right)
=-(log1-log(1+ exp(-x)))
=-(0-log(1 + exp(-x))
= log(1 + exp(-x))

同じ部分として -log(exp(-x) / (1 + exp(-x)) → (-log(exp(-x)) + log(1 + exp(-x))) があります。
これは先程と同じ展開で対数の分数は引き算になります。
-log(exp(-x) / (1 + exp(-x))
=-(log(exp(-x)) - log(1+ exp(-x)))
=(-log(exp(-x)) + log(1 + exp(-x))

3段目で分かりにくい部分は (-log(exp(-x)) → x ですかね。
これは自然対数の底の性質 (log(exp(x)) → x を使います。
今回は expの中の符号と外側の符号がマイナスになっていますので展開すると (-log(exp(-x)) =-(-x) = x となります。

= z * log(1 + exp(-x)) + (1 - z) * (x + log(1 + exp(-x))
= (1 - z) * x + log(1 + exp(-x))
= x - x * z + log(1 + exp(-x))

これは、 log(1 + exp(-x)) を 別の変数にすると分かりやすくなります。一旦 qにします。
=z * q + (1 - z) * (x + q)
=z * q + (1 - z) * x + (1 - z) * q
=zq + (1 - z) * x + q - zq
=(1 - z) * x + q - zq + zq
=(1 - z) * x + q
定義のqを元に戻す。
=(1 - z) * x + log(1 + exp(-x))
後は素直に展開すればいい。
=x - x * z + log(1 + exp(-x))

softmax_cross_entropy

qiita.com  

最後に

機械学習は一筋縄にはいかないので、皆さんがんばりましょう。

参照

シグモイド関数を理解してみる

はじめに

機械学習の学習すると必ず出てくる用語にシグモイド関数があります。
今回はこれを理解してみたいです。

シグモイド曲線

シグモイド曲線は入力した値を0から1の間に収めてくれる関数の1つです。
多くの自然界に存在する事柄は、このようなS字曲線を取ります。
欠点として1に近づくほど1そのものにならない性質があります。

使う理由

分類した場合に「1」と「-1」という2択ではなく、シグモイド関数は確率で分類すると考えます。
Aの確率が80%で、Bの確率が20%といった感じで分類していきます。
シグモイド曲線の値は 0 から 1 の間になるので確率として使用できます。

すべての関数は微分ができるわけではありません。
尖った点があったり、線が切れていると微分はできないのです。
※尖っていた場合、同じ点に対して二つの傾きが計算できてしまうので微分不可能になる。
どうしてシグモイド関数は滑らかな関数なのか - Qiita
自然科学のための数学2014年度第10講

例えば有名な例として絶対値の関数 y=|x| があります。この関数は x=0 で微分できません。
同様にステップ関数も x=0 で微分できません。
f:id:Yaju3D:20190331145627p:plain

シグモイド関数は下図グラフで示すようにステップ関数を滑らかにした形で線が切れてないので微分が可能になるのです。

数式

f(x) = \displaystyle  \frac{1}{1+e^{-ax}}

グラフ

f:id:Yaju3D:20170602002203p:plain

下図に示すステップ関数(step function)を滑らかにしたものであると見なすことができる。
f:id:Yaju3D:20170603024904p:plain

シグモイド関数の性質

いいサイトがあった。 risalc.info

単調増加性

数学での単調とは「上がったり下がったりがない」という意味です。
放物線は、単調減少と単調増加があります。
f:id:Yaju3D:20181104162349p:plain

シグモイド関数は、S字を描きますが徐々に上がり続けて下がりませんよね。

シグモイド関数の微分

前提

sigmoid(x) = \displaystyle \frac{1}{1 + e^{-x}}

結論

f(x)=sigmoid(x) とした時、
f(x)′=f(x)(1−f(x))

導出

逆数の微分

まず、逆数の微分公式を確認しておきます。
\displaystyle \left(\frac {1}{f}\right)^{\prime}=\frac{−f^{\prime}}{f^{2}} です。
逆数の微分公式の証明:「 商の微分公式の証明と例題
商の微分
\left(\dfrac{1}{f(x)}\right)^{\prime} = \displaystyle\lim_{h\to 0}\dfrac{\frac{1}{f(x+h)}-\frac{1}{f(x)}}{h}
=\displaystyle\lim_{h\to 0}\dfrac{\frac{f(x)}{f(x)f(x+h)}-\frac{f(x+h)}{f(x)f(x+h)}}{h}
=\displaystyle \lim_{h\to 0}\dfrac{f(x)-f(x+h)}{hf(x)f(x+h)}
=\displaystyle \lim_{h\to 0}-\dfrac{1}{f(x)f(x+h)}\cdot\dfrac{f(x+h)-f(x)}{h}
=-\dfrac{f'(x)}{{f(x)}^2}

シグモイド関数は 1+exp(−x) の逆数なので
f^{\prime}(x)=\left(\displaystyle \frac {1}{1+exp(−x)}\right)^{\prime}

=\displaystyle \frac{-(1+exp(-x))^{\prime}}{(1+exp(-x))^{2}}

=\displaystyle \frac {exp(−x)}{\left(1+exp(−x)\right)^{2}}

=\displaystyle \frac {1}{1+exp(−x)} \frac {exp(−x)}{1+exp(−x)}

=\displaystyle \frac {1}{1+exp(−x)} \left(\frac {1+exp(−x)}{1+exp(−x)}−\frac {1}{1+exp(−x)}\right)

=\displaystyle \frac {1}{1+exp(−x)} \left(1−\frac {1}{1+exp(−x)}\right)

ここで、
f(x)=\displaystyle \left(\frac {1}{1+exp(-x)}\right)
であるから、式を当てはめると

=f(x)\left(1−f(x)\right)

もう少し詳しい説明を書いてみました。
yaju3d.hatenablog.jp

グラフ

左図はシグモイド関数の微分したグラフ、右図は正規分布関数のグラフです。形が似ていますよね。
正規分布関数との類似性と計算のしやすさの2つが、機械学習でシグモイド関数がよく使われる理由なのです。 f:id:Yaju3D:20190523004451p:plain

使い道

シグモイド関数の微分(f(x)\left(1−f(x)\right) )はどこに使われるのか、最急降下法(勾配降下法)や 誤差逆伝播法(バックプロパゲーション)にてパラメーターの更新に使われます。
以前はシグモイド関数が主流でしたが、最近ではReLU関数などが使われています。これは勾配消失の問題です。
シグモイド関数の微分の最大値は0.25となるため、ディープラーニングで層を増やしていくと勾配が消失してしまうのです。その点、ReLU関数の場合は最大値が1.00で勾配消失がしにくくなる。

ロジスティック回帰との関係

ロジスティック回帰は、以下の数式で表現できます。

y=\displaystyle \frac {1} {1+exp(-(b_{1}X_{1}+b_{2}X_{2}+b_{3}X_{3}+ \cdots  + b_{i}X{i}+b_{0}))}

シグモイド関数と同じ形であり、数式の中の「b_{1}X_{1}+b_{2}X_{2}+b_{3}X_{3}+ \cdots  + b_{i}X{i}+b_{0}」という部分は重回帰分析と同じです。
よって、ロジスティック回帰のグラフを描くとシグモイド関数と同様になります。

ロジスティック回帰の最尤関数

統計学や機械学習をを勉強していると「尤度(ゆうど)」という概念に出会います。
尤もらしい(もっともらしい)ということで、最尤度は最高にもっともらしいってことですね。
尤度とはある事象が観測された時、それぞれの事象の確率の確率分布関数のパラメータがどれだけ尤もらしいかを測る量で、事象の同時確率として定義されます。
※同時確率とは、サイコロを2回投げた場合、1回目に1の目が出て、2回目に2が出る確率は?って聞かれたら、まず\frac {1}{6}で1が出て、次に\frac {1}{6}で2が出て、それが続けて起こる確率は掛け算を使って、\frac {1}{6}\cdot\frac {1}{6}=\frac {1}{36}

回帰の時の2乗誤差だった場合は最小化した値を求めるのが目的だったのに対し、今考えるのは同時確率で確率が高くなって欲しいので最大化するのが目的になります。

上記のロジスティック回帰をシグマに展開すると下記式になります。
PD_{i}=\displaystyle \frac{1}{1+exp(-(b_{0}+ \displaystyle \sum_{p=1}^{K}b_{p}X_{i,p}))}

同時確率を一般式すると下記式になります。
L=\displaystyle \prod_{i=1}^{N}PD_{i}^{Y_i} \left(1-PD_{i}\right)^{1-Y_{i}}

掛け算というのは計算が大変なので、掛け算を足し算にする「対数」を使って尤度関数を表すと下記式になります。
L=\displaystyle \log \left(\prod_{i=1}^{N}PD_{i}^{Y_i} \left(1-PD_{i}\right)^{1-Y_{i}}\right)

=\displaystyle \sum_{i=1}^{N}\left(Y_{i}\cdot\log\left(PD_{i}\right)+\left(1-Y_{i}\right)\cdot\log\left( 1-PD_{i}\right)\right)

活性化関数として

人間の脳は神経細胞(ニューロン)のネットワークで構成されています。この最小単位の神経細胞(ニューロン)を模倣したモデルがパーセプトロンとなります。このモデルは入力値が閾値を超えた場合に「1」を出力(この場合を「ニューロンが発火する」と表現)し、そうでない場合は「0」を出力します。このように入力値から出力値を生むまでの計算を活性化関数と呼びます。

パーセプトロンでは活性化関数に下図のステップ関数(入力に対してある閾値を境に階段(ステップ)のように出力が1か0か決まる)を使っていました。
f:id:Yaju3D:20170603024904p:plain

ニューラルネットワークは学習をする際に微分を含む計算を行うため、微分するとゼロになるステップ関数は都合が悪いことからステップ関数に似た形で微分してもゼロにならないシグモイド曲線(sigmoid)などが使用されるようになりました。
※微分するとゼロになると都合が悪いのは、値を微分値で更新しても同じ値のままになってしまうからです。

下図のExcelで、106行目の重みの値を更新する際に、前行(105行目)の重みと同行の赤枠「学習係数 x 勾配」の値を加算した値にします。
もし、勾配の値がゼロになってしまうと次の重みの値が更新されないため同じ値のままになり都合が悪くなります。
つまり、そこが正解値ならいいのですが、まだ途中段階で更新が止まってしまうのが良くないわけです。
f:id:Yaju3D:20181031012450p:plain

最後に

今回、シグモイド関数とロジスティック回帰の関係が分かりました。
自分がまだ微分の知識が足りてないってことが分かりました、数式はまだまだ苦手だな。

サポートベクターマシーン(SVM)を理解してみる

はじめに

ディープラーニング(深層学習)の理解もまだ進んでいないわけですが、今回は勝手に古い技術と思い込み何も理解しようとすらしていなかった サポートベクターマシン(Support Vector MachineSVM)に着目してみます。

サポートベクターマシンとは

サポートベクターマシン(Support Vector MachineSVM)は、1995年頃にAT&TV.Vapnik(ウラジミール・ヴァプニーク(Vladimir Vapnik;1936-))が発表したパターン識別用の教師あり機械学習方法であり、局所解収束の問題が無い長所がある。「マージン最大化」というアイデア等で汎化能力も高め、現在知られている方法としては、最も優秀なパターン識別能力を持つとされている。
参照:サポートベクターマシン(SVM)

機械学習には大きく分けて「識別関数」「識別モデル」「生成モデル」の3つの種類があります。このなかで識別関数が確率を使わないので初心者が入門するのに最適です。

識別問題には線形分離可能と線形分離不可能がある。
f:id:Yaju3D:20180901022342p:plain

パーセプトロンという基礎的な識別関数の学習手法は、誤差関数の勾配を利用してどんどん誤差関数を小さくしていくというものであるが、この手法には下記の2点の課題がある。

  • モデルの汎化能力が保証されない。
  • 線形分離可能な問題で利用できない。

SVMは2クラスの分類を行うための機械学習の手法で、大雑把に言うとパーセプトロンという基礎的な識別関数に「マージン最大化」と「カーネル関数」という考え方を導入して上記の課題に対応したものである。

マージン最大化

学習データの中で最も他クラス と近い位置にいるもの(サポー トベクタ)を基準として、その ユークリッド距離が最大になる ように識別面を決める。

汎化能力とは学習時に与えられた訓練データだけに対してだけでなく、未知の新たなデータに対するクラスラベルや関数値も正しく予測できる能力のことを指す。 そもそも、単純パーセプトロンのような機械学習を利用する目的は、スパムメールの例であれば、学習では使っていないメールでも上手くスパムかどうかを分類することである。 決して、以前にきたことのあるメールだけを分類すればいいというわけではない。

qiita.com

カーネルトリック

カーネルトリックとは、元々のデータ空間から高次元空間にデータを写像し、その高次元空間上で線形データ解析を行うことを指す。

ソフトマージンで線形分離不可能な場合でも、分離超平面を決定することができますが、 所詮線形分離なので、性能には限界があります。 カーネルトリックはその限界を取り払い、SVMが注目されるきっかけを作った手法です。

SVMの利点・欠点

参照:SVMってなに?

利点

  • データの特徴の次元が大きくなっても識別精度が良い
  • 最適化すべきパラメータが少ない
  • パラメータの算出が容易

欠点

  • 学習データが増えると計算量が膨大になる (「次元の呪い」の影響が顕著)
  • 基本的には2クラスの分類にしか使えない

線形SVN

線形SVNは「ハードマージン」と「ソフトマージン」に分けられます。

ハードマージン

SVMパターン認識手法の一種です。 ハードマージンSVMはその中でも一番基本となるものです。

shogo82148.github.io

ソフトマージン

線形分離不可能(直線では分けられない場合)にはうまく行きません。 それを解決するのがソフトマージンSVMです。
ソフトマージンSVMは、データにノイズが混じっている場合にもある程度強いという特徴があります。

shogo82148.github.io

参照

d.hatena.ne.jp d.hatena.ne.jp d.hatena.ne.jp

Google Colaboratory上でmatplotlibのアニメーションを再生する

はじめに

最近は、Anacodaを使わずにGoogle Colaboratoryを使用しています。
Google ChromでGoogle Colaboratory にアクセスすれば、すぐにPythonが使えますからね。

下記サイトでは勾配降下法 (Gradient Descent)のグラフをアニメーション化しており、かっこいいです。
sinhrks.hatenablog.com

Google Colaboratory でPython 3に変更して動かして見たのですが、アニメーションは動きませんでした。

アニメーション

下記サイトを参考に Jupyter notebookと同じようにmatplotlibのnbagg を有効にしてみたりしたのですが、駄目でした。 qiita.com

ネットの検索条件「Google Colaboratory animation」と英語化して、見つけたのが下記サイトとなります。 medium.com

技術的なことは、下記サイトが参考になります。
「JupiterにMatplotlibアニメーションをインタラクティブJavaScriptウィジェットとして埋め込む」
louistiao.me

下記プログラムをGoogle Colaboratoryに貼り付けると、アニメーションが表示されます。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from IPython.display import HTML
# animate over some set of x, y
x = np.linspace(-4, 4, 100)
y = np.sin(x)
# First set up the figure, the axes, and the plot element
fig, ax = plt.subplots()
plt.close()
ax.set_xlim(( -4, 4))
ax.set_ylim((-2, 2))
line1, = ax.plot([], [], lw=2)
line2, = ax.plot([], [], lw=2)
# initialization function: plot the background of each frame
def init():
    line1.set_data(x, y)      
    return (line1,)
# animation function: this is called sequentially
def animate(i):
  at_x = x[i]
  
  # gradient_line will have the form m*x + b
  m = np.cos(at_x)
  b = np.sin(at_x) - np.cos(at_x)*at_x
  gradient_line = m*x + b
  
  line2.set_data(x, gradient_line)
  return (line2,)
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=100, blit=True)
rc('animation', html='jshtml')
anim

f:id:Yaju3D:20180731234424g:plain

アニメーションの保存

下記サイトを見つけました。 qiita.com

Google Colaboratory上ではどうすれば出来るのかを検討したところ、mp4形式なら出来ることが分かりました。 参照:Sum approximation

準備として、ffmpeg をインストールする必要があります。

# To make an animation, we need ffmpeg
!apt-get update && apt-get install ffmpeg

先程のプログラムの下側にあるコードを変更します。

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=100, blit=True)

# add code
plt.rcParams['animation.ffmpeg_path'] = '/usr/bin/ffmpeg' # For google colab
HTML(ani.to_html5_video())

#rc('animation', html='jshtml')
#anim

表示された動画にある「︙」をクリックすれば、ダウンロード出来ます。
※下図はキャプチャした静止画です。
f:id:Yaju3D:20180812130117p:plain

Twitterは動画形式のmp4対応しているので、ツイートする分には問題ありません。
どうしてもgifにしたい場合には、オンライン上でmp4からgifに変換できます。
www.aconvert.com

gif保存には調査が必要

上記方法より先にgif形式を試したのですが、PillowWriterでインポートエラーになりました。
もしかしたら出来る方法があるかも知れませんが、追求はやめました。

from matplotlib.animation import PillowWriter

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=100, blit=True)
anim.save("gradientline.gif", writer=PillowWriter(fps=60))

#ImportError: cannot import name 'PillowWriter'

最後に

後で、勾配降下法 (Gradient Descent)のグラフをアニメーション化して公開する予定です。
今回は紹介まで。

【2018/05/01】アニメーション化しました。 qiita.com

Google ColaboratoryでGitHubのCSVデータをpandasに読み込む

はじめに

最近は、Anacodaを使わずにGoogle Colaboratoryを使用しています。
Google ChromでGoogle Colaboratory にアクセスすれば、すぐにPythonが使えますからね。

機械学習を学ぶ上では、サクッと使えるデータが必要です。

Google Colaboratoryでファイルの入出力

Google Colaboratoryでファイルの入出力については、ローカルファイルへアップロードしたり、google driveを使用する方法があります。
それらについては下記サイトを参考にするといいでしょう。 web.archive.org qiita.com

Web上からCSVデータの読み込み

ローカルファイルへアップロードしたり、google driveを使用することすら面倒くさいと思っていて、既にWeb上に置いてあるデータをそのまま使えれば楽ちんだよね。
下記サイトを参考にしたら、統計表一覧 政府統計の総合窓口 GL08020103 のcsvデータが読めました。 blog.neko-ni-naritai.com

import pandas as pd
import urllib.request
from io import StringIO

url = "http://www.e-stat.go.jp/SG1/estat/Csvdl.do?sinfid=000012460662"

#csvを読み込む関数
def read_csv(url):
    print(url)
    res = urllib.request.urlopen(url)
    res = res.read().decode('shift_jisx0213')
    df = pd.read_csv(StringIO( res) )
    return df

#実行
read_csv(url)

f:id:Yaju3D:20180630115212p:plain

では、誰かがあげてあるGitHubのデータも使えるんじゃないかと、機械学習の初心者が学ぶ際に使用する有名なデータのアヤメ(iris)を検索して一番最初に出てきたのを使用しました。
https://github.com/pandas-dev/pandas/blob/master/pandas/tests/data/iris.csv

先程のプログラムのURLを書き換えただけだと、「ParserError: Error tokenizing data. 」となりました。

url = "https://github.com/pandas-dev/pandas/blob/master/pandas/tests/data/iris.csv"

下記記事は、R言語ですがPyhtonでも似たようなものだろうと、Raw つまり データだけが表示されるページにアクセスすればいいようです。 web.archive.org

先程のgithubのサイトに「Raw」ボタンがあったので、そこをクリックした際のURLに書き換えます。また、デコードをSJISからUTF-8に変更します。

import pandas as pd
import urllib.request
from io import StringIO

url = "https://raw.githubusercontent.com/pandas-dev/pandas/master/pandas/tests/data/iris.csv"

#csvを読み込む関数
def read_csv(url):
    print(url)
    res = urllib.request.urlopen(url)
    res = res.read().decode("utf-8")
    df = pd.read_csv(StringIO( res) )
    return df

#実行
read_csv(url)

f:id:Yaju3D:20180630121137p:plain

最後に

自分は面倒くさがり屋です、この「面倒くさがり屋」とはプログラマの三大美徳である「怠惰」「短気」「傲慢」の「怠惰」に匹敵する言葉だったりします。
機械学習を学ぶ上で少しでも敷居を下げれればと思います。

スポンサーリンク