blog

単純パーセプトロン

Published:

By nob

Category: Posts

Tags: 機械学習 ニューラルネットワーク Python

モデル

import numpy as np


class SimplePerceptron:

    def __init__(self, epochs=20, learning_rate=0.1, persistence=2):
        self.epochs = epochs
        self.learning_rate = learning_rate
        self.persistence = persistence

    def step(self, z):
        return np.where(z >= 0, 1, 0)

    def activate(self, z):
        return self.step(z)

    def _predict(self, x, w):
        z = np.dot(x, w)
        return self.activate(z)

    def predict(self, X):
        if X.ndim == 1:
            X = np.array([X])
        elif X.ndim == 2:
            pass
        else:
            raise ValueError(
                "X should be 2 dimensional array, "
                + "e.g. [[0, 1, 2], [1, 2, 3]]"
            )
        x = np.c_[X, np.ones((X.shape[0], 1))]
        return self._predict(x, self.w)

    def _fit(self, x, y, w):
        o = self._predict(x, w)
        w = w + (y - o) * x * self.learning_rate
        return w

    def fit(self, X, y):
        if X.ndim != 2:
            raise ValueError(
                "X should be 2 dimensional array, "
                + "e.g. [[0, 1, 2], [1, 2, 3]]"
            )
        if y.ndim == 1:
            pass
        elif y.ndim == 2:
            if y.shape[0] == 1:
                y = y[0]
            elif y.shape[0] == X.shape[0] and y.shape[1] == 1:
                y = y.reshape(-1)
        else:
            raise ValueError(
                "y should be 1 or 2 dimensional array, "
                + "e.g. [0, 1, 2], [[0, 1, 2]]"
            )

        x = np.c_[X, np.ones((X.shape[0], 1))]
        w = np.zeros(x.shape[1])
        p = self.persistence
        for i, epoch in enumerate(range(self.epochs)):
            _w = w
            for j, (_x, _y) in enumerate(zip(x, y)):
                print(i, j, _x, _y, w)
                w = self._fit(_x, _y, w)
            if np.array_equal(w, _w):
                p -= 1
            if p <= 0:
                break

        self.w = w
        self.coef_ = self.w[:-1]
        self.intercept_ = self.w[-1]

テスト

AND

and_x = np.array(
    [
        [0, 0],
        [0, 1],
        [1, 0],
        [1, 1],
    ]
)
and_y = np.array([0, 0, 0, 1])

clf = SimplePerceptron(epochs=100)
clf.fit(and_x, and_y)
print(clf.predict(np.array([0, 0])))
0 0 [0. 0. 1.] 0 [0. 0. 0.]
0 1 [0. 1. 1.] 0 [ 0.   0.  -0.1]
0 2 [1. 0. 1.] 0 [ 0.   0.  -0.1]
0 3 [1. 1. 1.] 1 [ 0.   0.  -0.1]
1 0 [0. 0. 1.] 0 [0.1 0.1 0. ]
1 1 [0. 1. 1.] 0 [ 0.1  0.1 -0.1]
1 2 [1. 0. 1.] 0 [ 0.1  0.  -0.2]
1 3 [1. 1. 1.] 1 [ 0.1  0.  -0.2]
2 0 [0. 0. 1.] 0 [ 0.2  0.1 -0.1]
2 1 [0. 1. 1.] 0 [ 0.2  0.1 -0.1]
2 2 [1. 0. 1.] 0 [ 0.2  0.  -0.2]
2 3 [1. 1. 1.] 1 [ 0.1  0.  -0.3]
3 0 [0. 0. 1.] 0 [ 0.2  0.1 -0.2]
3 1 [0. 1. 1.] 0 [ 0.2  0.1 -0.2]
3 2 [1. 0. 1.] 0 [ 0.2  0.1 -0.2]
3 3 [1. 1. 1.] 1 [ 0.2  0.1 -0.2]
4 0 [0. 0. 1.] 0 [ 0.2  0.1 -0.2]
4 1 [0. 1. 1.] 0 [ 0.2  0.1 -0.2]
4 2 [1. 0. 1.] 0 [ 0.2  0.1 -0.2]
4 3 [1. 1. 1.] 1 [ 0.2  0.1 -0.2]
[0]

OR

or_x = np.array(
    [
        [0, 0],
        [0, 1],
        [1, 0],
        [1, 1],
    ]
)
or_y = np.array([0, 1, 1, 1])

clf = SimplePerceptron(epochs=100)
clf.fit(or_x, or_y)
0 0 [0. 0. 1.] 0 [0. 0. 0.]
0 1 [0. 1. 1.] 1 [ 0.   0.  -0.1]
0 2 [1. 0. 1.] 1 [0.  0.1 0. ]
0 3 [1. 1. 1.] 1 [0.  0.1 0. ]
1 0 [0. 0. 1.] 0 [0.  0.1 0. ]
1 1 [0. 1. 1.] 1 [ 0.   0.1 -0.1]
1 2 [1. 0. 1.] 1 [ 0.   0.1 -0.1]
1 3 [1. 1. 1.] 1 [0.1 0.1 0. ]
2 0 [0. 0. 1.] 0 [0.1 0.1 0. ]
2 1 [0. 1. 1.] 1 [ 0.1  0.1 -0.1]
2 2 [1. 0. 1.] 1 [ 0.1  0.1 -0.1]
2 3 [1. 1. 1.] 1 [ 0.1  0.1 -0.1]
3 0 [0. 0. 1.] 0 [ 0.1  0.1 -0.1]
3 1 [0. 1. 1.] 1 [ 0.1  0.1 -0.1]
3 2 [1. 0. 1.] 1 [ 0.1  0.1 -0.1]
3 3 [1. 1. 1.] 1 [ 0.1  0.1 -0.1]
4 0 [0. 0. 1.] 0 [ 0.1  0.1 -0.1]
4 1 [0. 1. 1.] 1 [ 0.1  0.1 -0.1]
4 2 [1. 0. 1.] 1 [ 0.1  0.1 -0.1]
4 3 [1. 1. 1.] 1 [ 0.1  0.1 -0.1]

XOR

xor_x = np.array(
    [
        [0, 0],
        [0, 1],
        [1, 0],
        [1, 1],
    ]
)
xor_y = np.array([0, 1, 1, 0])

clf = SimplePerceptron(epochs=100)
clf.fit(xor_x, xor_y)
0 0 [0. 0. 1.] 0 [0. 0. 0.]
0 1 [0. 1. 1.] 1 [ 0.   0.  -0.1]
0 2 [1. 0. 1.] 1 [0.  0.1 0. ]
0 3 [1. 1. 1.] 0 [0.  0.1 0. ]
1 0 [0. 0. 1.] 0 [-0.1  0.  -0.1]
1 1 [0. 1. 1.] 1 [-0.1  0.  -0.1]
1 2 [1. 0. 1.] 1 [-0.1  0.1  0. ]
1 3 [1. 1. 1.] 0 [0.  0.1 0.1]
2 0 [0. 0. 1.] 0 [-0.1  0.   0. ]
2 1 [0. 1. 1.] 1 [-0.1  0.  -0.1]
2 2 [1. 0. 1.] 1 [-0.1  0.1  0. ]
2 3 [1. 1. 1.] 0 [0.  0.1 0.1]
3 0 [0. 0. 1.] 0 [-0.1  0.   0. ]
3 1 [0. 1. 1.] 1 [-0.1  0.  -0.1]
3 2 [1. 0. 1.] 1 [-0.1  0.1  0. ]
3 3 [1. 1. 1.] 0 [0.  0.1 0.1]