Perceptrons as Logical Operator

가장 간단한 퍼셉트론은 (weight1, weight2)bias를 입력으로 받아 하나의 output 을 낸다. 우리는 퍼셉트론을 이용하여 연산자 (And, Or, Not)를 구현할 수 있다.

And

and-quiz

Or

or-quiz

AND to OR

and-to-or 같은 형태의 퍼셉트론이지만 단순히 weight를 증가시키거나 bias를 줄이는것 만으로도 AND 연산자에서 OR 연산자를 만들 수 있다.

### XOR

xor

XOR은 조금 어렵다. 실제로 XOR을 구현하는 것 때문에 인공지능 분야는 수년간 정체되었다. 정답은 아래와 같다.

xor (1)

Perceptron Algorithm

첫 과제는 가장 기본적인 perceptron algorithm에 대한 이론을 습득한 후, 간단한 linear regression을 실습해보는 과제였다.

points

Problem

Recall that the perceptron step works as follows. For a point with coordinates (p,q)(p,q), label yy, and prediction given by the equation $ \hat{y} = step(w_1x_1 + w_2x_2 + b) $

  • (case 0) If the point is correctly classified, do nothing.
  • (case 1) If the point is classified positive, but it has a negative label, subtract $αp,αq$, and $\alpha$ from $w_1, w_2$,and $b$ respectively.
  • (case 2) If the point is classified negative, but it has a positive label, add $\alpha p, \alpha q$, and $\alpha$ to $w_1, w_2$, and $b$ respectively.

Feel free to play with the parameters of the algorithm (number of epochs, learning rate, and even the randomizing of the initial parameters) to see how your initial conditions can affect the solution!

data.csv

0.78051,-0.063669,1
0.28774,0.29139,1
...
0.85275,0.85987,0
0.51912,0.62359,0

data.csv는 ($x_1,x_2,y$) 형태로 총 100개가 저장되어 있다.

X는 shape가 (2,100) 인 100개의 점들이고, y는 shape가 (1,100) 인 1-hot label들의 집합이며 W는 shape가 (2,1) 인 $(w_1, w_2)$ Weight이고 b는 0차원의 스칼라 값이다.

차원을 파악했으니, 위 조건에 맞는 함수를 구현하면 된다.

(case 0)은 따로 할 필요 없고, (case 1)과 (case 2)만 구현하자.

Let’s Code it !

perceptron.py

# 기본적인 스텝 함수
def stepFunction(t):
    if t >= 0:
        return 1
    return 0

# 예측 함수
def prediction(X, W, b):
    return stepFunction((np.matmul(X,W)+b)[0])

def perceptronStep(X, y, W, b, learn_rate = 0.01):

    for i in range(np.shape(X)[0]):

        if prediction(X[i], W, b) and not y[i] : # (case 1)

            W[0] -= X[i][0] * learn_rate
            W[1] -= X[i][1] * learn_rate
            b -= learn_rate

        elif not prediction(X[i], W, b) and y[i] : # (case 2)

            W[0] += X[i][0] * learn_rate
            W[1] += X[i][1] * learn_rate
            b += learn_rate

    return W, b

Result

learn_rate = 0.01, num_epochs = 25
learn_rate = 0.01, num_epochs = 25

성공! 처음에 임의로 그어졌던 직선이 학습이 진행됨에 따라 분류를 더 잘 하는 모습을 보여준다.

만약 learning_rate와 num_epoch를 바꾸면 어떻게 될까?

learn_rate = 0.01, num_epochs = 100
learn_rate = 0.01, num_epochs = 25

epochs를 4배로 증가시켰다. 어느정도 학습이 된 이후에는 변화하지 않는 것을 볼 수 있다.

learn_rate = 0.1, num_epochs = 25
learn_rate = 0.01, num_epochs = 25

learning rate를 10배로 증가시켰다. 학습이 너무 급격하게 진행되어 제대로 갈피를 못잡는 모습을 볼 수 있다.

첫 퍼셉트론 코딩의 결론

아주 간단한 단일 퍼셉트론 구현이었지만, 단순한 분류 정도에는 충분히 효과적이면서도 적절한 learning rate와 epochs등 변수의 세팅에 주의를 기울여야 한다. 그리고 각 변수를 변화시킬때 예상되는 결과에 대해 이해했다.

cleared Clear!

[첨부] Full-Code

perceptron.py

import numpy as np
# Setting the random seed, feel free to change it and see different solutions.
np.random.seed(42)

def stepFunction(t):
    if t >= 0:
        return 1
    return 0

def prediction(X, W, b):
    return stepFunction((np.matmul(X,W)+b)[0])

def perceptronStep(X, y, W, b, learn_rate = 0.01):

    for i in range(np.shape(X)[0]):

        if prediction(X[i], W, b) and not y[i] : # (case 1)

            W[0] -= X[i][0] * learn_rate
            W[1] -= X[i][1] * learn_rate
            b -= learn_rate

        elif not prediction(X[i], W, b) and y[i] : # (case 2)

            W[0] += X[i][0] * learn_rate
            W[1] += X[i][1] * learn_rate
            b += learn_rate

    return W, b

# This function runs the perceptron algorithm repeatedly on the dataset,
# and returns a few of the boundary lines obtained in the iterations,
# for plotting purposes.
# Feel free to play with the learning rate and the num_epochs,
# and see your results plotted below.
def trainPerceptronAlgorithm(X, y, learn_rate = 0.1, num_epochs = 25):
    x_min, x_max = min(X.T[0]), max(X.T[0])
    y_min, y_max = min(X.T[1]), max(X.T[1])
    W = np.array(np.random.rand(2,1))
    b = np.random.rand(1)[0] + x_max
    # These are the solution lines that get plotted below.
    boundary_lines = []
    for i in range(num_epochs):
        # In each epoch, we apply the perceptron step.
        W, b = perceptronStep(X, y, W, b, learn_rate)
        boundary_lines.append((-W[0]/W[1], -b/W[1]))
    return boundary_lines

Comments

Eungbean Lee's Picture

About Eungbean Lee

Lee is a Student, Programmer, Engineer, Designer and a DJ

Seoul, South Korea https://eungbean.github.io