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

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

ただいまの
回答率

88.59%

[機械学習]パーセプトロンの分類直線について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 928

ebiebi5563

score 16

聞きたいこと

現在、機械学習の基礎を学んでいる最中なのですが、パーセプトロンの部分で詰まってしまいました...。以下の①不安な点と②理解できない点について、それぞれ回答いただきたいです。

不安な点

1.パーセプトロンは、重みベクトルを法線とする直線をもとに分類しているのか

2.重みを更新するか否かは、重みベクトルと各データの内積での正負、そして正解ラベルと照らし合わせることで決まる

理解できない点

1.「重みベクトルを法線とする直線の方程式は内積をとって0になるxの集まりで、式の形を整えると、
w*x = w1*x1 + w2*x2 = 0
x2 = -w1/w2*x1
となり、分類直線をプロットできる」
と書籍に書いてあったのですが、x1を変数とするx2の式にしなければいけないのでしょうか。
実際にプロットしてみたのですが、若干違いはあるものの、どちらも分類できているように思えます。

2.学習し終わったあとの重みをプロットしてみたのですが(★マーク)、これが重みベクトルなのでしょうか。

左画像(x2の式) 右画像(x1の式)

x(width)の方が大きい = More Width = 1(正解ラベル)
y(height)の方が大きい = More Height = -1(正解ラベル)
パーセプトロン

コード

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os
os.chdir("data")

data = pd.read_csv("images1.csv")

features = data.iloc[:, 0:2].copy()
target = data.iloc[:, 2].copy()

"""可視化
fig, axes = plt.subplots(figsize=(10, 10))
axes.scatter(features.ix[target == 1, 0], features.ix[target == 1, 1], label="More Width", marker="o", s=80, color="red", alpha=0.6)
axes.scatter(features.ix[target == -1, 0], features.ix[target == -1, 1], label="More Heght", marker="x", s=80, color="blue", alpha=0.6)
axes.set_title("Scatter of matplotlib")
axes.set_xlabel("x1")
axes.set_ylabel("x2")
axes.legend(loc="best")
#sns.lmplot(x="x1", y="x2", hue="y", data=data, fit_reg=False)
plt.show()
"""

print("説明変数")
print(features)
print("-"*77)
print("目的変数")
print(target)
print("-"*77)
print()

#重みの初期化
#2変数のため2つ生成
w = np.random.rand(2)

flag = False
#識別関数
def predict_f(x):
    if flag:
        print("w={}, x={}".format(w, x))
        result = np.dot(w, x)
        print(result)
    if np.dot(w, x) >= 0:
        return 1
    else:
        return -1

#繰り返し回数
epoch = 10

#更新回数
count = 0

#重みの更新式
for _ in range(epoch):
    for x, y in zip(features.values, target.values):
        if predict_f(x) != y:
            print("予測結果 = ", predict_f(x))
            print("正解データ = ", y)
            print("現在の重み = ", w)
            print("正解データ({}) × 各データ({}) = {}".format(y, x, (y * x)))
            print("現在の重みを更新\n{} + {} = {}".format(w, (y * x), (w + (y * x))))
            w = w + y * x
            count += 1
            print("{}回目: w = {}".format(count, w))
            print()

#どっち?
x_ = np.arange(0, 500)
y_1 = -w[0] / w[1] * x_
y_2 = -w[1] / w[0] * x_

#分類できるか確認
flag = True
t1 = [200, 100]
t2 = [100, 200]
p1 = predict_f(t1)
p2 = predict_f(t2)

fig, axes = plt.subplots(1, 2, figsize=(10, 10))
axes[0].scatter(features.ix[target == 1, 0], features.ix[target == 1, 1], label="More Width", marker="o", s=80, color="red", alpha=0.6)
axes[0].scatter(features.ix[target == -1, 0], features.ix[target == -1, 1], label="More Heght", marker="x", s=80, color="blue", alpha=0.6)
axes[0].scatter(t1[0], t1[1], label="Predict...{}".format(p1), color="red", s=150)
axes[0].scatter(t2[0], t2[1], label="Predict...{}".format(p2), color="blue", s=150, marker="x")
axes[0].scatter(w[0]/10, w[1]/10, color="gold", marker="*", edgecolor="k", s=150, label="Weight Vector?")
axes[0].plot(x_, y_1, linestyle="dashed", color="indianred")
axes[0].set_title("Perceptron Plot(x2 = -w[0] / w[1] * x1)")
axes[0].set_xlabel("x1")
axes[0].set_ylabel("x2")
axes[0].legend(loc="best")
#sns.lmplot(x="x1", y="x2", hue="y", data=data, fit_reg=False)

axes[1].scatter(features.ix[target == 1, 0], features.ix[target == 1, 1], label="More Width", marker="o", s=80, color="red", alpha=0.6)
axes[1].scatter(features.ix[target == -1, 0], features.ix[target == -1, 1], label="More Heght", marker="x", s=80, color="blue", alpha=0.6)
axes[1].scatter(t1[0], t1[1], label="Predict...{}".format(p1), color="red", s=150)
axes[1].scatter(t2[0], t2[1], label="Predict...{}".format(p2), color="blue", s=150, marker="x")
axes[1].scatter(w[0]/10, w[1]/10, color="gold", marker="*", edgecolor="k", s=150, label="Weight Vector?")
axes[1].plot(x_, y_2, linestyle="dashed", color="indianred")
axes[1].set_title("Perceptron Plot(x1 = -w[1] / w[0] * x2)")
axes[1].set_xlabel("x1")
axes[1].set_ylabel("x2")
axes[1].legend(loc="best")

plt.show()

何卒ご回答の程よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

式自体は式変形しているだけなので、どちらでも良いと言えます。

ただし、x1とx2の式なので、逆で求めたのならplotするときも逆転させてください。plotされているのはあくまでもx1とx2の空間なので、その点は注意する必要があります。

下のようにすれば同じ結果になると思います。

axes[1].plot(y_2, x_, linestyle="dashed", color="indianred")

どちらにせよ「同じ式」なので、分類境界は1つです。変化してはいけません。今回はx1とx2が同じようなスケールで、斜めの線を引くだけなので、変えてしまっても違和感のない結果になっていますが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/26 15:37

    ありがとうございます。
    参考になりました!

    キャンセル

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

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る