
# 조건문을 써야 할까?
# 퍼셉트론의 w와 theta는 지금으로썬 알 수가 없다.
# 따라서 임의로 설정하기로 한다.
def perceptron1(x1, x2):
	# 임의의 가중치인 w1, w2를 설정
    w1, w2 = 0.5, 0.5
    
    # 임의의 임계값인 theta를 설정
    theta = 2.0
    
    # 출력값 y 구하기
    y = (w1 * x1) + (w2 * x2)
    
    return y, y >= theta
    
# 시각화
# 입력 데이터 생성
x1 = np.linspace(-3, 7, 100)
x2 = np.linspace(-3, 7, 100)
# 퍼세브론의 결과물 구하기
y_value, y_result = perceptron1(x1, x2)
~~> (array([-3.        , -2.8989899 , -2.7979798 , -2.6969697 , -2.5959596 ,
        -2.49494949, -2.39393939, -2.29292929, -2.19191919, -2.09090909,
        -1.98989899, -1.88888889, -1.78787879, -1.68686869, -1.58585859,
        -1.48484848, -1.38383838, -1.28282828, -1.18181818, -1.08080808,
        -0.97979798, -0.87878788, -0.77777778, -0.67676768, -0.57575758,
        -0.47474747, -0.37373737, -0.27272727, -0.17171717, -0.07070707,
         0.03030303,  0.13131313,  0.23232323,  0.33333333,  0.43434343,
         0.53535354,  0.63636364,  0.73737374,  0.83838384,  0.93939394,
         1.04040404,  1.14141414,  1.24242424,  1.34343434,  1.44444444,
         1.54545455,  1.64646465,  1.74747475,  1.84848485,  1.94949495,
         2.05050505,  2.15151515,  2.25252525,  2.35353535,  2.45454545,
         2.55555556,  2.65656566,  2.75757576,  2.85858586,  2.95959596,
         3.06060606,  3.16161616,  3.26262626,  3.36363636,  3.46464646,
         3.56565657,  3.66666667,  3.76767677,  3.86868687,  3.96969697,
         4.07070707,  4.17171717,  4.27272727,  4.37373737,  4.47474747,
         4.57575758,  4.67676768,  4.77777778,  4.87878788,  4.97979798,
         5.08080808,  5.18181818,  5.28282828,  5.38383838,  5.48484848,
         5.58585859,  5.68686869,  5.78787879,  5.88888889,  5.98989899,
         6.09090909,  6.19191919,  6.29292929,  6.39393939,  6.49494949,
         6.5959596 ,  6.6969697 ,  6.7979798 ,  6.8989899 ,  7.        ]),
 array([False, False, False, False, False, False, False, False, False,
        False, False, False, False, False, False, False, False, False,
        False, False, False, False, False, False, False, False, False,
        False, False, False, False, False, False, False, False, False,
        False, False, False, False, False, False, False, False, False,
        False, False, False, False, False,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True]))
# 시각화
plt.plot(y_value, y_result)
plt.yticks([0, 1])
plt.xticks([-3, 2, 7], ['-∞', 'θ', '∞')])
plt.xlabel("w1x1+w2x2")
plt.ylabel("y", rotation=0)
plt.show()
~~> 
를 기준으로 의 결과가 0 또는 1로 결정지어진다. 이걸 함수로 일반화 시켜서 어떤 상황에서든 수식을 사용할 수 있도록 일반화 시켜보기
원래 수식
바뀐 수식
일반화된 함수 지정하기
 
 
함수 는 단위 계단 함수
z = np.linspace(-3, 3, 100)
plt.plot(z, z > 0)
plt.yticks([0, 1])
plt.xticks([-3, 0, 3], ['-∞', 'θ', '∞'])
plt.xlabel('z')
plt.ylabel('y=u(z)', rotation=0)
plt.show()~~> 

계단 함수 의 결과()에 따라서 항상 0 또는 1만 가지게 된다.

def AND(x1, x2):
	# x1, x2에 대해서 조건 검사(if)를 하는 것은 퍼셉트론이 아니다.
    # w1x1 + w2x2 - theta의 결과물만 검사
    
    w1, w2, theta = 0.5, 0.5, 0.7
    z = w1*x1 + w2*x2 - theta
    
    return int(z > 0) # 부등호를 쓴 것이 계단 함수 u를 사용한 것
    
AND(0, 0), AND(1, 0), AND(0, 1), AND(1, 1)
~~> (0, 0, 0, 1)# 입력이 몇개가 될지 모르기 때문에 numpy로 표현
x = np.array([0, 1])
w = np.array([0.5, 0.5]) # 항상 w의 개수는 x의 개수와 일치해야 한다.
b = -0.7 # theta가 0.7 이었으니깐 bias는 -0.7
print("행렬 곱 : {} " .format(w*x))
print('각 원소의 곱을 합한 결과 : {} ' .format(np.sum(w*x)))
print('편향 추가 계산 : {:.1f} ' .format(np.sum(w*x)+b)) # wx + b
~~> 행렬 곱 : [0.  0.5] 
각 원소의 곱을 합한 결과 : 0.5 
편향 추가 계산 : -0.2 AND 게이트를 numpy로 구현
def AND(x1, x2):
	x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.7
    
    z = np.sum(w*x) + b
    
    return int(z > 0)
AND(0, 0), AND(0, 1), AND(1, 0), AND(1, 1)
~~> (0, 0, 0, 1)가중치가 크다 : 입력값이 출력값에 영향을 많이 미친다.
가중치가 작다 : 입력값이 출력값에 영향을 많이 미치지 않는다.
def NAND(x1, x2):
	x = np.array([x1, x2])
    # 가중치와 편향의 부호를 AND 게이트의 반대로 설정
    w = np.array([-0.5, -0.5])
    b = 0.7
    
    z = np.sum(w * x) + b
    
    return int(z >0)
    
NAND(0, 0), NAND(0, 1), NAND(1, 0), NAND(1, 1)
~~> (1, 1, 1, 0)def OR(x1, x2):
	x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    
    # 편향만 조절해 준다.
    b = -0.2 # 얼만큼 조절해야하는지는 모른다. -> 찾아야함
    
    z = np.sum(w * x) + b
    
    return int(z > 0)
    
OR(0, 0), OR(0, 1), OR(1, 0), OR(1, 1)
~~> (0, 1, 1, 1)AND, NAND, OR는 각각 하나의 퍼셉트론으로써 각각의 연산을 충실히 수행
각각의 입력값을 받아서 각자의 역할을 수행하면, 한번에 입력에 대한 한번의 출력이 올바르게 이루어 진다. -> 단층 퍼셉트론
OR 퍼셉트론에 대한 시각화
plt.figure(figsize=(4,4))
plt.scatter([0],[0], marker='o')
plt.scatter([1,0,1],[0,1,1], marker='^')
plt.xticks([0, 0.5, 1])
plt.yticks([0, 0.5, 1])
plt.xlim((-0.2,1.2))
plt.ylim((-0.2,1.2))
plt.xlabel('x_1')
plt.ylabel('x_2', rotation=0)
plt.show()
~~>
XOR 게이트 시각화
plt.figure(figsize=(4,4))
plt.scatter([0,1],[0,1], marker='o')
plt.scatter([1,0],[0,1], marker='^')
plt.xticks([0, 0.5, 1])
plt.yticks([0, 0.5, 1])
plt.xlim((-0.2,1.2))
plt.ylim((-0.2,1.2))
plt.xlabel('x_1')
plt.ylabel('x_2', rotation=0)
plt.show()
~~>
단층 퍼셉트론을 여러 개 쌓아서 다층 퍼셉트론으로 만들어 주면 단층 퍼셉트론으로는 해결할 수 없던 일을 해결할 수 있다.
def XOR(x1, x2):
	s1 = NAND(x1, x2)
    s2 = OR(x1, x2)
    
    y = AND(s1, s2)
    
    return y
XOR(0, 0), XOR(0, 1), XOR(1, 0), XOR(1, 1)
~~> (0, 1, 1, 0)