python機械学習プログラミング(43ページ)

今回は少し進んで、43ページになります。

毎回プログラムのところでつまずいていますが、ちょっとずつでも進んでいきます。

さて、43ページの下の方で今回は詰まりました。というよりもまずここでつまずいて、他のところでもつまると思います。

つまずいた個所はここ

def _shuffle(self, X, y):
"""トレーニングデータをシャッフル"""
r = np.random.permutation(len(y))
return X[r], y[r]

トレーニングデータをシャッフルするというコメントがるのでとりあえずシャッフルするんだという理解まではしましたが具体的にどうなの??というところですね。

疑問になった点は、
permutation
というプログラムと引数に
len(y)
というプログラム
return X[r], y[r]
returnのあとが配列になっている。

プログラム初心者の僕はこの書き方がよくわかっていません。
returnもよく見るけど使い方もわかっていません。なので、確かめてみました。

実行プログラム
import numpy as np

def _shuffle(X,y):
    r = np.random.permutation(len(y))
    print("r")
    print(r)
    print("X[r]")
    print(X[r])
    print("y[r]")
    print(y[r])
    return X[r], y[r]
X = np.arange(40,60).reshape(4,5)
y = np.arange(8,12).reshape(4,1)
print("X")
print(X)
print("y")
print(y)
X, y = _shuffle(X, y)
print("shuffle X")
print(X)
print("shuffle y")
print(y)

<実行結果>


X
[[40 41 42 43 44]
 [45 46 47 48 49]
 [50 51 52 53 54]
 [55 56 57 58 59]]
y
[[ 8]
 [ 9]
 [10]
 [11]]
r
[2 1 3 0]
X[r]
[[50 51 52 53 54]
 [45 46 47 48 49]
 [55 56 57 58 59]
 [40 41 42 43 44]]
y[r]
[[10]
 [ 9]
 [11]
 [ 8]]
shuffle X
[[50 51 52 53 54]
 [45 46 47 48 49]
 [55 56 57 58 59]
 [40 41 42 43 44]]
shuffle y
[[10]
 [ 9]
 [11]
 [ 8]]

という感じです。
これでは説明しにくいのでもっとシンプルにします。

実行プログラム
import numpy as np   
def _shuffle(X,y):
    r = np.random.permutation(len(y))    ←len(y)は[0,1,2,3]なのでそれを並び替えてrに代入
    return X[r], y[r]            ←配列X[r]を返す。rがランダムなのでランダムなXが返される。
X = np.arange(40,60).reshape(4,5)
y = np.arange(8,12).reshape(4,1)
X, y = _shuffle(X, y)           ←XにシャッフルされたXを代入、yにシャッフルされたyを代入

なるほどぉ。

pythonでsum()の使い方や掛け算を確かめてみた

pythonでsum()の使い方を確かめてみました。

a = np.arange(10).reshape(5,2)
b = np.arange(10,20).reshape(2,5)
X = np.arange(20,30).reshape(5,2)
print("a  :  ")
print(a)
"""
a  :
[[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]
 """
print("b  :  ")
print(b)
"""
b  :
[[10 11 12 13 14]
 [15 16 17 18 19]]
"""
print("X   :   ")
print(X)
"""
X   :
[[20 21]
 [22 23]
 [24 25]
 [26 27]
 [28 29]]
"""

aa = a*a
print("aa : ")
print(aa)
"""
aa :
[[ 0  1]
 [ 4  9]
 [16 25]
 [36 49]
 [64 81]]
"""
a2 = a**2
print("a**2")
print(a2)
"""
a**2
[[ 0  1]
 [ 4  9]
 [16 25]
 [36 49]
 [64 81]]

"""

aTdota = a.T.dot(a)
print("a.T.dot(a)")
print(aTdota)
"""
a.T.dot(a)
[[120 140]
 [140 165]]

"""
asum = a.sum()
suma = sum(a)
print("a.sum()")
print(asum)
"""
a.sum()
45
"""
print("sum(a)")
print(suma)
"""
sum(a)
[20 25]
"""
aTsum = a.T.sum()
sumTa = sum(a.T)
print("a.T.sum()")
print(aTsum)
"""
a.T.sum()
45
"""

print("sum(a.T)")
print(sumTa)
"""
sum(a.T)
[ 1  5  9 13 17]
"""

大体は予想通りの動き方をしましたが、a*aの動作が要素ごとにかけたり、sum(a.T)の動作が列で足されるのかと初めて知りました。

python機械学習プログラミング(36ページ)

プログラムの中で、なんとなくわかったつもりでそのままにしているプログラムの表記を調べてみました。

36ページのプログラムの上部にある

self.w_[1:] += self.eta * X.T.dot(errors)

このプログラムのX.TはおそらくXの転置という事だと思います。

.dot(errors)についてもおそらく内積だと思います。

あと、少し下にある

cost = (errors**2).sum() / 2.0

についても、おそらくsum()は合計を意味しているのだと思うのですが、sum(a)とかカッコ内に何か入れて使うのでは?合計するなら

sum(errors**2)

とするのでは??みたいに思ったが、はっきりしないので、調べてみました。

【今のところの自分なりの理解】

自分でプログラムをうって確かめたところX.T.dot(errors)は

『Xの転置を行いerrorsとの内積を行っている』

という事で確認が取れました。

.dot()のカッコ内は(a,b)のように二つの変数じゃないと計算できないんじゃ?とか思ったのですが、errorsは配列でXも配列で問題ないので内積をとる時はこんな書き方もできるんだという事がわかりました。

あと、sumの使い方に関しては別の生地に確かめた内容などをまとめましたのでもしよろしければこちら↓までどうぞ。

deeplearning-benkyotyu.hatenablog.com

 

 

python機械学習プログラミング(19ページ)

21ページのずっと疑問に思っていた点を書いていきます。21ページ目に以下のようにあります。

 

 話を単純にするために、閾値θを左辺へ移動し、インデックス0の重みをおよびとして定義する。これにより、以下の簡潔な形式で総入力zを記述できるようになる。

 

 となっているのだが、25ページのプログラムを見るとθを定義する部分がないのだがどうなっているのだろうか??

【今のところの自分なりの理解】

ひょっとして、、、、

 

これがθの事なのか!? 

なんかそんな気がします。

 

 

 

python機械学習プログラミング(25ページ)

読み進めていくと結局このプログラムを理解しきれていないという事が問題で、後々で必ずここに戻ってくる。

そもそも、数式もわからないプログラムもわからないところから始めているのでつまずくのは当たり前なので地道にコツコツ頑張っていきます!!

では、プログラムの理解から始めますが、僕がつまずいているのはこの箇所!

  self.w_[1:] += update * xi

 25ページのプログラムの後半に出てくる箇所ですね。

【この部分についての自分なりの理解!!】

結論から言いますと21ページにある

\Delta w_{j} =\eta \left ( y^{(i)} - \hat{y}^{(i)} \right )x_{j}^{(i)}

 式(2.1.5)をプログラムにするとこうなるのかな??という理解をしました。

さて、なぜそうなるのか?というところですが、自分なりの理解を載せていきます。

self.w_[1:] += update * xi

を理解するためにプログラムの前後を見ていきます。

for _ in range(self.n_iter): 
    errors = 0
    for xi, target in zip(X, y):
       update = self.eta * (target - self.predict(xi))
       self.w_[1:] += update * xi
       self.w_[0] += update
       errors += int(update != 0.0)
       self.errors_.append(errors)
   return self

updateは

update = self.eta * (target - self.predict(xi))

となっています。山ほどわからないところがあるのでひとつづつ見ていきます。

update = self.eta * (target - self.predict(xi))

self.etaは最初の方に宣言されています。

def __init__(self, eta=0.01, n_iter=10):
    self.eta = eta
    self.n_iter = n_iter

なので、etaは0.01という事ですね。

targetは少し上の方にあります

for _ in range(self.n_iter): 
    errors = 0
    for xi, target in zip(X, y):
       update = self.eta * (target - self.predict(xi))

という事ですね。

あとはself.predict(xi)についてです。

これは下の方に

def net_input(self, X):
    return np.dot(X, self.w_[1:]) + self.w_[0]

def predict(self, X):
    return np.where(self.net_input(X) >= 0.0, 1, -1)

 という事で

self.predict(xi)は関数?メソッド?として宣言してあるので

np.where(self.net_input(X)>=0.0,1,-1)

となります。さらにself.net_input(X)はすぐ上にあるので、

np.dot(X,self.w_[1:])+self.w_[0]

となります。さてもう一度

self.w_[1:] += update * xi

を見ていきます。updateを分解します。

self.w_[1:] += self.eta * (target - self.predict(xi))*xi

次にself.predict(xi)を分解します。

self.w_[1:] += self.eta * (target - (np.where(self.net_input(X)>=0.0,1,-1)))*xi

さらにself.net_input(X)も分解します。

self.w_[1:] += self.eta * (target - (np.where((np.dot(X,self.w_[1:])+self.w_[0])>=0.0,1,-1)))*xi

さて、ここで21ページに戻ってみてみます。

\Delta w_{j} =\eta \left ( y^{(i)} - \hat{y}^{(i)} \right )x_{j}^{(i)}

 式(2.1.5)です。

僕なりの理解ではこの式をプログラムするとこうなるのだろうと思います。

 

python機械学習プログラミング(25ページ)

本当に何もできないなぁと自分の事が嫌になりますが、また分からないところが出てきました。

 

プログラム部分の

self.errors_.append(errors)

 についてです。

self.errors_

は配列で

append()

で要素を最後に追加するというプログラムのと思うのですが。

ただ、かっこの中身がerrorsというのは上でカウントされた数字だと思うのですが、数字を格納するという事でいいのだろうか?

 

とりあえず、このまま保留で先に進んでみようと思います。

 

また問題になって理解が出来たら報告します!

 

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

【自分なりにこう理解しました】

誤分類の個数を後で分析できるように格納すると26ページに書いてありました。。

失礼しました。

python機械学習プログラミング(25ページ)

さて、python機械学習プログラミングを読んでいて、わからないところが出てきました。

25ページのプログラムのところです。

errors += int(update != 0.0)

という部分ですね。

プログラムを走らせればうまく動くのかわかりませんが、とりあえず今わからなくなったのでご報告です。

 

 

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

とりあえず、解決?

【今のところの理解】

一行上の説明に以下のように書いてあります。

#重みの更新が0でない場合は誤分類としてカウント 

 つまりカウントする仕様のようです。

そこで、自分でプログラムを書いてみて少し確かめてみたところ。上の書き方しか利用できなさそうです。

つまり、

errors += int(update != 0.0)

変数 +=int(条件分)

という感じですかね。

これってなんて調べたら出てくるのかな???

 

誰か教えてください!!