質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2771閲覧

Perceptronの重み更新

MycoChild

総合スコア36

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/06/10 13:22

Python機械学習プログラミング 達人データサイエンティストによる~
の第2章のパーセプトロンのプログラム中のPerceptronのクラスのdef fitの重み更新のところで、以下のようにi番目のΔw(update * xi)を、w[1:]のように1番目からすべての重みに対して加算しているのはなぜですか???w[i]+=update * xiではないのですか?

python

1import numpy as np 2 3class Perceptron(object): 4 def __init__(self, eta, n_iter, random_state = 1): 5 self.eta = eta 6 self.n_iter = n_iter 7 self.random_state = 1 8 9 def fit(self, X, y): 10 rgen = np.random.RandomState(self.random_state) 11 self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1]) 12 self.errors_ = [] 13 14 for _ in range(self.n_iter): 15 errors = 0 16 for xi, target in zip(X, y): 17 update = self.eta * (target - self.predict(xi)) 18 print(self.w_[1:]) 19 self.w_[1:] += update * xi 20 self.w_[0] += update 21 22 errors += int(update != 0.0) 23 self.errors_.append(errors) 24 return self 25 26 def net_input(self, X): 27 return np.dot(X, self.w_[1:]) + self.w_[0] 28 29 def predict(self, X): 30 return np.where(self.net_input(X) >= 0.0, 1, -1) 31

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

1番目からすべての重みに対して加算しているのはなぜですか???w[i]+=update * xiではないのですか?

self.w_[1:] += update * xi であっています。
パーセプトロンの学習規則は間違えて判別したサンプルが見つかったら、そのサンプルを正しく判別できるように分類超平面を回転させて、調整するということをやっています。

パーセプトロンの学習でやっていること

簡略化のために2次元で学習率やバイアスは考えないものとし、以下の分類超平面があったとします。

イメージ説明

正解ラベルが t=-1 である点 x_err = (12, 4) が今の重みの超平面では、y=1と誤識別されてしまったとします。

イメージ説明

ここで、w_{i + 1} = w_i + t * x_err で重みを更新します。

イメージ説明

すると、超平面が以下のように変化し、x_err は y=-1 と正しく認識できるようになります。

イメージ説明

これを間違えたサンプルが見つかるたびに繰り返して、学習するというのがパーセプトロンの学習規則です。


これで1つのサンプルを正しく識別できるように分類超平面を調整したら、今まで正しく識別できていた他のサンプルが逆に誤識別するようになり、全部のサンプルを正しく識別できる重みが見つからないのではないかと心配になるかもしれませんが、線形識別可能 (超平面で2つのクラスのサンプルが完全に分離可能) なデータの場合、有限回の反復で収束する (すべてのサンプルを正しく識別できるようになる) ことが数学的に証明できます。

追記

質問のように、本のコードはself.w_[1:] += update * xiとなっています。(誤植ではないと思います)

これでよい理由についてわかりませんか?

回答では簡略化のために、学習率 self.eta = 1、バイアス self.w_[0] = 0 としましたが、「質問のコードの重み更新でやっていること」と、「上記回答のパーセプトロンの重みの更新」はやっていることは同じですよ。
2次元データだとすると、重みは self.w_ = [b, w0, w1] とバイアス b と重み w0, w1 になりますよね。self.w_[1:] = [w0, w1] なので、

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

ここで、self.eta * (target - self.predict(xi)) について考えると、ラベルが-1, 1 の2クラスなら
target = -1, self.predict(xi) = 1 なら self.eta * (-1 - 1) = -2 self.eta
target = 1, self.predict(xi) = -1 なら self.eta * (1 - (-1)) = 2 self.eta
target == self.predict(xi) なら0
となります。なので、

正解が-1なのに予測が1と誤識別したら
→ self.w_[1:] = self.w_[1:] - self.eta * 2 * xi と更新
正解が1なのに予測が-1と誤識別したら
→ self.w_[1:] = self.w_[1:] + self.eta * 2 * xi
正解と予測が一致したら
→ self.w_[1:] = self.w_[1:] + 0 * xi = self.w_[1:] (つまり、更新しないのと同じ)

となっています。

投稿2020/06/10 15:37

編集2020/06/11 09:05
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MycoChild

2020/06/11 08:37

回答ありがとうございます。図までつけてくださり、非常に分かりやすかったのですが、質問のように、本のコードは```self.w_[1:] += update * xi```となっています。(誤植ではないと思います) これでよい理由についてわかりませんか?
tiitoi

2020/06/11 08:54 編集

追記しましたが、本のコードの self.w_[1:] += update * xi と回答記載のパーセプトロンの学習規則 w_{i + 1} = w_i + t * x_err がやっていることは同じです。
tiitoi

2020/06/11 08:59

self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1]) なので、特徴量の次元数が n (サンプルの数ではない) としたとき、重みは self.w_ = [b, w0, w1, ..., w_n] という1次元配列で表されているという点は大丈夫ですよね?
MycoChild

2020/06/11 09:04

なんか勘違いしていました。。。 大丈夫です。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問