Re:ゼロから始めるML生活

機械学習ド素人が、流行に乗ってニューラルネットとか勉強してみるブログ

【写経】ニューラルネットワークについて勉強してみた

この前は、ニューラルネットワークのふわっとした概要だけ勉強しました。

tsunotsuno.hatenablog.com

勉強してた本はこちら。

bookmeter.com

正直、勉強している本の著者が書いたコードがgithubにあるのでやる気はなかったのですが、 最初のうちは馬鹿正直に見よう見まねで実装してみるのもありかと思ったのと、そもそもPython初心者なのでPythonの勉強も兼ねて、見よう見まねで実装(ほぼ写経)しました。

前回は理論について紹介したので、今回は実装について取り上げます。

※ちゃんとコード書いた証明にgithubにあげときます。あんまりきれいじゃないですが、気にしない気にしない。。。

github.com

実装の事始め

著者の方の実装を参考になんとなく実装しました。 特徴としては、関数ごとにPythonのクラスを作成しています。 順伝播と逆伝播のメソッドを備えたクラスを用意して、それを順番にガッチャンコしていって実装します。

まずイメージとしては、下の図のような2層ニューラルネットワークを作成します。

f:id:nogawanogawa:20171223163954j:plain:w400

これをクラスのつながりで表現するとこんな感じ。

なので、今回の簡単実装では出てクラスは主に下のような感じです。

  • Affine
  • Sigmoid
  • Softmax

3層以上のネットワークを作成しようと思っても、この実装だとガッチャンコするクラスの数を変えればいいだけなので、 使いたい分だけ勝手にカスタムできます。 あとで別の活性化関数を使用したかったりしたら、そこだけ置き換えれば動くはずです。

では、少しずつ中身を見ていきます。

MNIST

まず、今回使用するデータはニューラルネットで使用されるサンプルデータセットであるMNISTです。

f:id:nogawanogawa:20180108091704p:plain

上図のように、手書きの数字の図(28×28)とその正解の数字が格納されています。

読み込んで使用するときは意外と簡単で、下のような1行で読み込みができます。

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)

色々パラメータをしていますが、細かいことは本読んでみてください。←

簡単に使えるっていう雰囲気がわかったところで次に進みます。

Affine

前回さらっと言ってしまったのですが、ニューラルネットの計算のときに入力とリンクの重みを掛け合わせる行列積が出てきました。 幾何学的に言うとこれをAffine変換と言うそうです。

forward

前回は行列積しか紹介しませんでしたが、実際には特定の方向に強引に引き寄せるバイアスも入ってきます。 ですので、式としてはこんな感じになります。

{ \displaystyle
Y=A \cdot X + B
}

順伝播ではこれを計算します。

def forward(self, x):
    # 入力の形状を読み取って記録に残す
    self.original_x_shape = x.shape
    x = x.reshape(x.shape[0], -1)
    self.x = x

    #affine変換
    out = np.dot(self.x, self.W) + self.b

    return out

意外と簡単に書いていますね。最初の3行はbackwardで使うための準備で、 入力の値と行列の形状をオブジェクトに記録しています。 値を記録しているのは、逆伝播の際に順伝播の際の入力を使用するためです。 形状を記録するのは、backwardのときに行列を転置する必要があるためで、逆伝播の計算をした後行列を元の形状に戻すのに使用しています。

backward

Affine層では直前の層への入力と自分の層の重みの更新量を計算する必要があります。

Affine変換について逆伝播するときには、式としてはこんな感じになります。

{ \displaystyle
\frac{\partial L}{\partial W} = X^{T} \cdot \frac{\partial L}{\partial Y}
}

絵で書くとこんな感じです。

f:id:nogawanogawa:20180112221157j:plain

書いてみるとこんな感じです。

def backward(self, dout):
    dx = np.dot(dout, self.W.T)

    #更新する重みの差分量計算                                                                                                                     
    self.dW = np.dot(self.x.T, dout)
    self.db = np.sum(dout, axis=0)

    #直前の層への入力                                                                                                                             
    dx = dx.reshape(*self.original_x_shape)  # 入力データの形状に戻す(テンソル対応)                                                                         
    return dx

Affine層に直前の層がある場合には、そちらの層への左向きの入力が必要になるのでそちらも計算します。

Sigmoid

順伝播でAffine変換をしたあとは、活性化関数によって発火をします。 今回は活性化関数としてSigmoid関数を使用します。

forward

Sigmoid関数は式で書くと下のようになっていました。

{ \displaystyle
y=\frac{1}{1+e^{-x}}
}

図で書くとこんな感じです。

f:id:nogawanogawa:20171224091711p:plain

これを書いて見るとこんな感じになります。

def sigmoid(x):
    return 1 / (1 + np.exp(-x))
def forward(self, x):
    out = sigmoid(x)
    self.out = out
    return out
backward

Sigmoid関数自体は重みとか関係ないので、直前の層への入力の計算だけになります。 直前の層への入力は下のような感じになります。

{ \displaystyle
\frac{\partial L}{\partial y} y(1-y)
}

コードを書いてみるとこんな感じ。

    def backward(self, dout):
       return dout*(1.0 - self.out) * self.out

Softmax

分類問題の順伝播で出力層では、確率分布を算出するため、出力の総和を1になるように出力をならす必要があります。 今回は簡単な方法としてSoftmax関数をかませます。

forward

Softmax関数を式で表すとこんな感じです。

{ \displaystyle
y_k = \frac{e^{a_k}}{\sum_{i=1}^{n} e^{a_i}}
}

def softmax(x):
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0) # オーバーフロー対策①                                                                                                          
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T

    x = x - np.max(x) # オーバーフロー対策②                                                                                                                      

    return np.exp(x) / np.sum(np.exp(x))

ソフトマックス関数では、値がxの値が大きすぎるとべき乗計算をする関係で計算が簡単にオーバーフローします。 そのため、オーバーフローしないように、上の実装ではオーバーフローしないように工夫してあります。

次に、損失関数を計算しています。 損失関数としては、クロスエントロピー関数を使用しています。 (詳細は省略します)

def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)

    # 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換                                                                                            
    if t.size == y.size:
        t = t.argmax(axis=1)

    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size

上の2つの関数を使用すると、こんな感じのforwardになります。

def forward(self, x, t):
    self.t = t
    self.y = softmax(x)
    self.loss = cross_entropy_error(self.y, self.t)

    return self.loss
backward

Softmax関数でも、Sigmoid関数と同様に、直前の層に対する入力を計算するだけです。 計算する値は下のようになります。

{ \displaystyle
\frac{\partial L}{\partial y} y(1-y)
}

def backward(self, dout=1):
    batch_size = self.t.shape[0]

    if self.t.size == self.y.size :
        dx = (self.y - self.t) / batch_size
    else :
        dx = self.y.copy()
        dx[np.arange(batch_size), self.t] -= 1
        dx = dx / batch_size

    return dx

ちゃんと動けば、こんな感じの学習途中の検出精度のグラフが出ます。

f:id:nogawanogawa:20180113083857p:plain

感想

昔、C言語とかCUDAでで行列積とか書いてた事あったんですが、めちゃくちゃ苦労しました。 その点、Pythonはふわっと書けるのがいいですね。 性能最適化とか細かいところは、ライブラリ作成者にまるっとおまかせな感じがすごくラクです。

そろそろ難しいことやらないとなあ。。。

Rではじめる機械学習 第3章 クラスタリング分析の3つの手法でデータを分類

前回に引き続きRの勉強を進めていました。

tsunotsuno.hatenablog.com

今回は教師なし学習の「クラスタリング」について取り扱いました。クラスタリングとは、与えられたデータを特定のルールに基づいてグループ化していくことです。 使用したデータはこちら。

Webエクササイズ

階層化クラスタリング

階層化クラスタリングはざっくりいうと、 各データ(要素)を類似度をもとにかたまり(クラスタ)にしていき、最後に1つのクラスタに集める分類手法 です。

R言語を使えば、コマンド2、3個叩くだけでクラスタリングができるのですが、その裏でやっている処理はこんな感じです。

  1. 各要素-要素間のユークリッド距離を求める
  2. ユークリッド距離が最小のものを類似度が最大と判断して、クラスタにする
  3. 生成したクラスタを含む要素群に対し、全ての要素が一つのクラスタに集まるまで1. 2.を繰り返す

ユークリッド距離

各要素-要素間の類似度を求めるのに、本書ではユークリッド距離を使用しており、ユークリッド距離が最小のペアを類似度が最大と決めているようでした。

ユークリッド距離とは、下図のような要素間の距離です。

f:id:nogawanogawa:20171129140954j:plain:w350

nが3以下のときは、高校数学レベルで出てくる二点間の距離をご想像いただければ問題無いかと思います。実際にはnが4以上の時も、イメージしにくいですが、上の式に当てはめるだけで値を算出できます。

少し調べてみると類似度を測るためにはユークリッド距離以外にもシティブロック距離や、ミンコフスキー距離があるそうです。どの距離を使うかはケースバイケースですが、ユークリッド距離が最もメジャーに使用されているようでした。

手順の2でクラスタを形成します。そのため、2周目以降のユークリッド距離の算出には、クラスタ-要素、クラスタ-クラスタユークリッド距離を考慮する必要があります。

f:id:nogawanogawa:20171129141651j:plain

クラスタ距離の計算方法として、以下の6種類が紹介されていました。

手法
1 単連結法
2 完全連結法
3 群平均法
4 ウォード法
5 重心法
6 メディアン法

どの手法も一長一短なので、用途に応じて使い分ける必要があるようです。

試しにやってみた結果

f:id:nogawanogawa:20171129143101p:plain

試しに上で紹介したサンプルデータを使用して、階層化クラスタリングを実際にやってみました。 距離はユークリッド距離を使用して、各クラスタ距離に対して求めています。

図の出力方法がいまいちなのは置いておいて、それっぽい傾向は見えてきますね。拾ってきたサンプルデータなので、わかりやすいように加工されていますが、国産車輸入車がそれぞれグループ化されているように見えます。

非階層化クラスタリング

階層化クラスタリングとは別に、非階層化クラスタリングという分類手法もあります。一つずつ要素をクラスタに集めずに分類する方法になり、代表例としてk平均方(k-means)があります。

f:id:nogawanogawa:20171123205536j:plain

  1. 各要素をグループに分類
  2. グループ毎に中心点を求める
  3. 各要素を最も近い中心点に所属するようにグループを変更
  4. 2.および3. を、中心点の位置が変化しなくなるまで繰り返す

k-meansの注意点としては、外れ値に弱いという点だそうです。 要は中心点が外れ値によってずれていってしまうため、分類に影響を与えてしまうとのことでした。

おまけ

ソースコードはこちら:

https://github.com/nogawanogawa/R-Clustering.git

Rではじめる機械学習 第2章 回帰分析で目的変数の値や発生確率を予測

前回に引き続き、本日は2章をまとめます。

tsunotsuno.hatenablog.com

機会学習には大きく分けて教師あり学習/教師なし学習がありますが、 回帰分析は教師あり学習に該当します。

下図は最近の各日付の日経平均株価終値を示しています。

f:id:nogawanogawa:20171103090435p:plain

データはこちらから拝借しました。

日経平均株価 日足 時系列データ CSVダウンロード

図のように目的変数(縦軸)と説明変数(横軸)の分布が与えられた際に、 新しく与えられた説明変数に対応する目的変数を予想したいとします。

回帰分析では、目的変数と説明変数の関係を表現する関数(回帰曲線)を求めることで予測する手法です。 日系平均株価の終値が知りたいとした際に、回帰曲線を求め、説明変数を代入することで算出していきます。

単回帰分析

回帰分析では変数に関数に名前がついています。

知りたい変数 :目的変数(y) 与えられる変数:説明変数(x) 単回帰分析では、説明変数と目的関数が下の式に従うと仮定されています。

{ \displaystyle
y=ax+b
}

上のような近似直線を見つけ、xに値を代入することでyを予想します。

説明変数の候補がたくさんある場合にはどれを説明変数とするかを考えたりするみたいですが、今回はめんどくさいので省略。

今回はなんとなく始値終値相関係数を取ってみて、

cor = 0.9913799

だったので、かなり相関があると見えます。そのため、今回はその日の始値から終値を予想してみます。 (※始値から終値で大幅に変動するって、それこそリーマンショックとかで大暴落でもしない限りありえないですね。)

f:id:nogawanogawa:20171126201206p:plain

予測値と実測値の乖離(直線場に乗っているほど正確)を見てみてもなんとなく直線上に乗っているように見えます。

重回帰分析

単回帰分分析では説明変数は一つだけでした。 一方、説明変数を複数考慮したものを重回帰分析と呼ぶそうです。

説明変数が1つだったのが複数に増えただけなので、考え方は単回帰分析と変わりません。

ロジスティック回帰分析

単回帰分析や重回帰分析では、目的変数を推定していました。 ロジスティック回帰分析では、説明変数を代入したの特定の目的変数を発生する確率を求めます。

用途としては、yes/noなどの二値が目的変数の場合にその発生を予測する場合などがあります。

図で説明した方がわかりやすいと思いますので、やってみました。

f:id:nogawanogawa:20171126190023p:plain

上の関数はシグモイド関数と呼ばれており、式で表すとこんな感じになります。

{ \displaystyle
y=\frac{1}{1+e^{-x}}
}

シグモイド関数は、説明変数xを与えたときyは必ず0<y<1の範囲でとり、これが目的変数の発生確率を表しています。 シグモイド関数のxは別の関数で置き換えることで形状を変形させ、学習データに合うように変形させることがロジスティック回帰分析でやっている事になります。

ポアソン回帰分析

ポアソン回帰分析では、ある事象がx回発生する確率を求めます 式で表すとこんな感じです。

{ \displaystyle
P(x)=\frac{\lambda^{k}e^{-k}}{k!}
}

上式にkを代入すると確率Pが求まります。上のラムダを求めることがポアソン回帰のやっていることになります。

ニューラルネットワークについて勉強してみた

この前はTensorFlowをインストールして満足しました。

tsunotsuno.hatenablog.com

まずは基本的からニューラルネットワークをやってみることにします。

ニューラルネットワークの理論

ディープラーニングやってみたいとは言ったものの、ニューラルネットもさっぱりわかんないので、 はじめはニューラルネットワークの勉強から。

参考にしたのはこちらです。

bookmeter.com

こちらの本は理系出身の私には非常に分かりやすかったのです。 ただ数式がバンバン出て来るので簡単な線形代数線形代数ニューラルネットワークの関連がつかめないと難しいらしいです。

この記事では、難しい理論は最小限にして、ニューラルネットワークでなにをやっているのかを書きます。 細かい話は本を読んで下さいってことで。笑

全体像

まずよくあるニューラルネットワークの模式図がこちら。

f:id:nogawanogawa:20171223163954j:plain

見方としては、左から右に向かって電気信号が伝播することを意味しており、左から「入力層」「中間層」「出力層」といいます。 イメージとしてはこんな感じ。

f:id:nogawanogawa:20171223164247j:plain

基本的には、この「左から右」の方向に向かって機械学習したいことをモデル化していきます。 また、人間の脳は「学習」が可能であり、ニューラルネットワークでは、「学習」もモデル化しています。 そのため、処理の流れとしてはこんな感じです。

f:id:nogawanogawa:20171223164652j:plain

なので、全体のイメージはこんな感じ。

f:id:nogawanogawa:20171224090639j:plain

この動作がひたすらぐるぐる回るのがニューラルネットワークってやつです。

パーセプトロン

ちょっとずつ細かい部分について見ていきます。 注目する範囲はこちらです。

f:id:nogawanogawa:20171223165009j:plain

こちらを拡大すると、こんな感じになります。

f:id:nogawanogawa:20171223165057j:plain

こちらはパーセプトロンと呼ばれニューラルネットワークの一番小さい単位になっています。 こいつは、「左のノード(◯)の値をリンク(→)の重みをかけ合わせて足し合わせた値が右のノード(◯)の値になる」 という単純な仕組みになっています。

これくらい小さいスケールだと簡単なのですが、こんなサイズだとどうでしょう?

f:id:nogawanogawa:20171223165204j:plain

ちょっとコーディングするのが嫌になってきますね。 ここで、行列を使って簡単に表現します。 入力をベクトル、入力-出力のそれぞれのリンクの重みを行列にしたベクトルと行列の内積で表現するとこんな感じになります。

{ \displaystyle
{\bf Y} = {\bf X} \cdot {\bf W}
}

こんなにスッキリしちゃいます。実際にはもう少しごちゃごちゃするんですが、それでも一行で表現できます。 pythonをはじめ、そのへんのプログラミング言語には行列計算ライブラリが用意されているので、ベクトル/行列をセットするだけでスッキリ記述できますし、めっちゃ速く計算してくれます。

活性化関数

ニューラルネットワークでは入力の総和がそのまま出力されるわけではなく、「活性化関数」によって「発火」します。 これは、生物の神経細胞にも同じことが起こっているようで、どうでもいいような微弱な刺激は次の神経細胞に伝達しないようになっているようです。

f:id:nogawanogawa:20171223165325j:plain

活性化関数を表現するのに広く使用されるのが、シグモイド関数とReLU関数です。

シグモイド関数

f:id:nogawanogawa:20171224091711p:plain

ReLU関数

f:id:nogawanogawa:20171224094014p:plain

このような関数を噛ませることで、発火を表現しています。 とりあえずこんなのがワンクッション入っているんだーくらいで大丈夫です。 ここまでのパーセプトロンと活性化関数さえ分かれば、「右方向の伝達」は実装できます。

学習

パーセプトロンのところで出てきたリンクの重みですが、この値次第で出力層の結果が変化します。 そのため、このリンクの重みを適切な値に調整する作業をニューラルネットワークでは「学習」と呼びます。

下の図では、「ニューラルネットワークの出力」と「答え」を図示しています。

f:id:nogawanogawa:20171224111240j:plain

棒グラフが出力値、星が実際の答えを表しており、図のようにギャップが生じます。

学習では、推定した値と理想の解答との差分(損失関数)を求めます。 損失関数の値をもとに、リンクの重みを調整していきます。

f:id:nogawanogawa:20171224111257j:plain

算出された損失関数をもとに、「本来出力はどうなって欲しいのか」が分かるので、その方向に予想が近づくようにリンクの重みを調整します。 これをさまざまな入力(たくさんの画像、いろんなバリエーションの音声など)に対して行い、学習を繰り返すことで予想の精度を上げていきます。

誤差逆伝播法(Back propagation)

さて、学習では重みに関する微分Δwを計算する必要がありました。 高校レベルの

{ \displaystyle
f(x) = x^{2}
}

みたいな関数ならなんてことはないんですが、ニューラルネットワークだと、

  • 活性化関数が機能している
  • 層の数が多い(10層とかになる場合もある)

なんて理由から、微分求める事自体が簡単ではありません。 そのため、学習時の微分を効率的に実装することがニューラルネットワークの一つの鍵になってきます。

現在広く使用されている手法として、誤差逆伝播法(Back propagation)と呼ばれる方法があります。 イメージとしてはこちら。

f:id:nogawanogawa:20171230150434j:plain

上の図では、下のような式をグラフ構造で示しています。

{ \displaystyle
y = a*b+c
}

入力a,b,cがに対する出力yが分かった時、上の式を全微分すると

{ \displaystyle
dy = \frac{\partial y}{\partial a} da * \frac{\partial y}{\partial b} db+\frac{\partial y}{\partial c}dc
}

図で表すとこんな感じ。

f:id:nogawanogawa:20171230150450j:plain

損失関数が分かるとdyの値がわかるので、あとはリンクの重みが該当する変数の項の係数分だけ元の関数を修正すれば学習を表現できます。

ニューラルネットワークでは行列が使用されるので、行列で表現された形にするとこんな感じ。

f:id:nogawanogawa:20171230150508j:plain

上の図では、Wが学習で該当する変数(行列)なのでこれ以外の項は全てなくなります。 学習時の行列の微分や活性化関数の微分は、行列の内積なら微分はこれ、シグモイド関数を使った活性化関数は微分はこれ…みたいに、昔の偉い人が考えてくれた式があるので、そちらに代入していきます。 細かいところは本をご参照下さい。

層が多くなってもやることは一緒で、予測の時と逆の順番で微分を求めていき、各層のリンクの重みの修正値を求めていきます。

f:id:nogawanogawa:20171230155948j:plain

こんな感じのことをプログラムで実装すると、パラメータ調整を自動でやってくれるニューラルネットワークが出来上がりです。 勉強になります。。。

ニューラルネットワークの実装

自分で手書きで実装しようかと思ったのですが、著者の方が書いてくださったものがありますのでそちらをご参照下さい。

github.com

図をいっぱい作ってたら疲れちゃったので、実装は別の機会ということで。笑

TensorFlowの環境構築

色々ありまして、月に1回技術ブログを更新しないといけなくなりました。 資格試験とか興味ある本とかも読んだら更新しますが、そちらは趣味です。 IT関係の記事は半分お仕事なので、これから頑張って更新したいと思います。

やりたいこと

せっかく機械学習かじってみてるのでちょっとむずかしいことやってみたくなりました、はい。 やりたいこと決めないと実装できないので、先にやりたいことを考えてみました。

今のご時世、AI(あんまりこの呼び方好きじゃないので、以後「機械学習」を使います)を活用するって言うと食いつき良いし、 そもそも機械学習が盛り上がり始めたのがディープラーニングっていうこともあり、ディープラーニングをやってみようと思いました。

ちょうどこの間のGTC JAPANでもNVIDIAの人がプログレッシブGANっていうのを紹介していました。

news.mynavi.jp

プログレッシブGANについてはこちらが分かりやすかったです。

st-hakky.hatenablog.com

ここまで面白いことができるようになるかはわかりませんが、 なんか面白いことができるように頑張ります。 (ブログが書ける程度に死ぬ気で勉強します。笑)

環境構築

TensorFlow

ニューラルネットワークなんて学生だったころに後輩がやってて面白そうって思ってた程度で、やったことないです。 ちょっと調べたら機械学習ライブラリを使うってことだったので、メジャーなTensorFlowを使うことにしました。

www.tensorflow.org

Chainerにしようか一瞬悩んだんですが、「気に入らなかったら変えればいいや」くらいのノリでTensorFlowにしました。

導入手順(※本来ならこちら)

本家のインストール手順(英語)を見ていただければと思います。

Installing TensorFlow  |  TensorFlow

基本的にはインストール手順をなぞってもらえればできるはずです。 私の環境は下の通りでしたが問題なくインストールできました。

しかし、マニュアルどおりインストールしてみたら、「SSE命令が使えるよ」とワーニングが出ました。 せっかくなので、SSE命令も使えるようにしてやろうってことで、ちょっと特殊なインストールをすることに。

導入手順(特殊なインストール)

参考にしたのはこちら。

拡張命令セットでTensorFlowをコンパイルする方法 - Qiita

anaconda のインストール

とりあえずanacondaのインストール www.continuum.io

Bazelをインストール
brew install bazel
TensorFlowのソースコードをcloneする
git clone https://github.com/tensorflow/tensorflow
configurationをいじる
cd tensorflow
./configure

いろいろ聞かれますが、今回は全てデフォルト設定のため、Enterキー連打。

コンパイル
bazel build -c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-msse4.1 --copt=-msse4.2  -k //tensorflow/tools/pip_package:build_pip_package

ものすごーーーーーく時間かかるので、お茶でもしててください。環境次第だとは思いますが、寝てても平気かもしれないです。

このときは軽く1時間超えました。4時間くらいかかりました。

配布パッケージ作成

インストールするパッケージを作成します。

bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
仮装環境の作成

あまり良くわかってないのですが、仮想環境を作るそうです。

conda create -n tensorflow python=2.7 anaconda

最近は仮想環境を使うんですね、勉強になります。

仮想環境の起動

仮想環境を起動するとtensorflowが使えるようになります。

source activate tensorflow
仮想環境内でコンパイルしたパッケージをインストール
pip install /tmp/tensorflow_pkg/{パッケージ名}.whl

私の場合はこんなファイルになってます。

pip install /tmp/tensorflow_pkg/tensorflow-1.4.0-cp27-cp27m-macosx_10_7_x86_64.whl 
なにはともあれHello World

ここまででインストールできているはずなので、動作確認としてHello Wolrdのコードを実行。

$ python
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42

こんな感じで出てくればインストールされて、晴れてTensorFlowが使えるように。 意外と時間かかりましたが、ワーニングは無くなりましたし、動きそうです。

Rではじめる機械学習 第1章 Rと機会学習の基礎

ずっと気になっていたR言語について、こんな本買ってみました。

book.impress.co.jp

しばらくこの本使って使って勉強してみようかと思います。

環境構築

Rstudioをインストールして環境構築。

www.rstudio.com

ちなみに、日本語化はこちらを参考にしました。

kawamurakaeru.lolipop.jp

Rのインストールと簡単な使い方の解説

細かいコマンドの使い方は、本を見れば分かるので省略します。

平均

言わなくても分かりますが、分散と標準偏差と密接な関係があるという点で重要かなと思いました。

分散

各データから平均を引いたものを二乗した総和を「データの個数−1」で割ったもの。 個人的な解釈としては、「データの集合が平均からどれだけ外れているかを表現したもの」だと理解しました。

注意点としては、「データの個数」ではなく「データの個数−1」で割っていること。 どちらも値の表す意味としては大差ないと思われますが、何も知らないで手計算すると数字が変わって引っかかりそうです。

「データの個数」で割った場合 :標本分散

「データの個数−1」で割った場合 :不偏分散

Rやエクセルで分散を求める関数を使用すると、不偏分散が計算されるため、「分散」=「不偏分散」と考えるのが一般的のようです。

標準偏差

分散は、「平均からの距離の二乗」である一方、平均からの距離を平方根を取ったものを標準偏差と呼ぶらしいです。

計算するのは簡単ですが、中身の意味をきちんと理解するという意味では、勉強になりました。

正規分布

平均と標準偏差を決めれば、確率分布が求まるもの。データの集合が、正規分布に従うと分かれば、特定の値の出現率は関数に値を代入するだけで求まります。「ナンノコッチャイ」ってなりました。

イメージはこんな感じですね。

f:id:nogawanogawa:20171029215210p:plain

左右対称、総和は100%となるので確かにこれだけで分布は求まります。平均が変わると分布が左右にずれ、標準偏差が変わると上下に伸び縮みするイメージですかね。

t分布

正規分布は平均と標準偏差が分かることが前提なのですが、世の中そんなにうまくはいかない。サンプルデータがいくつかしかとれない、、、って状況は往々にしてあるので、サンプルデータから確率分布を推定しましょうってのがt分布。

求め方は本を参照するとして、イメージはサンプルデータが手元にあって、信頼区間をどの範囲するかを決めればそれっぽい分布が算出できて、なんとか使い物になるって代物ですね。

まとめ

1章はRのインストールと簡単な使い方の解説でした。