본문 바로가기

2022.01./코딩 수업

01.25 퍼셉트론, 신경망

[0] 퍼셉트론
 (x1,x2)
 w1,w2,임계값 = 1,1,1
w1*x1+w2*x2>임계값 = 1반환
w1*x1+w2*x2<=임계값 = 0반환



1)CALL TEST 다른 파일에 만든 함수 호출하기
->에러난다.
1. 'module' object is not callable ->뒤에.py 붙여봄
2. No module named 'AND.py'; 'AND' is not a package -> 여전히 안됨

import numpy as np
import ANDArray
print(ANDArray.NAND(1,1))
->해결: 함수파일이름.쓰려는함수()

2)편향 더하기

import numpy as np
x = np.array([0,1])         #입력
w = np.array([0.5,0.5])     #가중치         
b = -0.7                    #편향
print(w*x)                  #원소별 곱
print(np.sum(w*x))          #원소별 곱의 합계
print(np.sum(w*x)+b)        #원소별 곱의 합계에 편향값 더하기 결과 출력

################################### globalfunc.py에 작성 ######################################## 
3) AND NAND OR 구현
NAND = AND 부호 반대화

import numpy as np
def AND(x1,x2):                     #둘 다 1이면 1 출력되게                 
    X = np.array([x1,x2])           #입력값을 리스트로
    W = np.array([0.5,0.5])         #가중치를 리스트로
    b = -0.7                        #편향값
    tmp = np.sum(X*W)+b             #array끼리의 합에 편향 값 더해주기
    if tmp>0:                       #둘 다 1이면 tmp=0.3 양수 -> 1반환
        return 1
    return 0

def NAND(x1,x2):                                
    X = np.array([x1,x2])           #입력값을 리스트로
    W = np.array([0.5,0.5])         #가중치를 리스트로
    b = -0.7                        #편향값
    tmp = np.sum(X*W)+b             #array끼리의 합에 편향 값 더해주기
    if tmp>0:                       #둘 다 1이면 tmp=0.3 ->0반환
        return 0
    return 1                        #하나라도 0이면 편향값 더해주면 음수나옴. -> 1 반환.


def OR(x1,x2):                      #둘 다 0이면 0출력되게                 
    X = np.array([x1,x2])           #입력값을 리스트로
    W = np.array([1,1])             #가중치를 리스트로
    b = -0.4                        #편향값
    tmp = np.sum(X*W)+b             #array끼리의 합에 편향 값 더해주기
    if tmp>0:                       #둘 다 0이면 temp가 -0.4
        return 1
    return 0

4) 위의 세개 엮어서 XOR 함수 
def XOR(x1,x2):
    orV=OR(x1,x2)                   #OR 함수의값
    nandV=NAND(x1,x2)               #NAND 함수의 값
    andV=AND(orV,nandV)             #AND 함수에 위의 값을 넣는다.
    return andV


print(XOR(0,0))
print(XOR(0,1))
print(XOR(1,0))
print(XOR(1,1))

***p121참고. 미분 적분 도함수 로그함수 복습할 필요성 느낌. 하... 고등수학 다시 할 때가 되다니ㅠ

[1] 신경망 (퍼셉트론 매개변수 컴퓨터가 자동학습)
 
1)활성화 함수(activation fuction)
입력 -> 출력으로 변환시켜주는 함수

(0)계단함수

def step_function(X):
    Y = X>0                  #Y는 참 거짓 나오는 bool배열.
    return Y.astype(np.int)  #int 형변환해주기. 거짓은 0, 참은 1. 이거 안해주면  [False/True]로 답 출력됨

x = np.arange(-5,5,0.1)      #x는 -5부터 5까지 0.1 간격으로
y = step_function(x)         #y는 스텝펑션. x가 0보다 커야 1이 출력되겠지. 0일때 갑자기 계단처럼 쑥 올라오겠네.
plt.plot(x,y)
plt.ylim(-0.1,1.1)           #y축 범위 설정          
plt.show()
print(step_function(np.array([-1,0,1])))   #참 거짓 판별 시험해보기 

error:  No module named 'matplotlib'
->다시 깔았다가 설치함.

(1) 시그모이드 함수 (s자 커브형태의 비선형 함수)
exp(-x)란, 자연상수 e를 활용(e=2.78.....)해 e^-x를 의미한다.
즉 h(x)= 1/(1+1/e^x)가 된다.
if x가 끝없이 증가 => h(x) =1에 수렴
if x가 0 => h(x) =1/2
if x가 끝없이 감소 => h(x) =0에 수렴

def sigmoid(x):
    return 1/(1+np.exp(-x)) # e^x로 나누어준 값

x = np.arange(-5,5,0.1)      #x는 -5부터 5까지 0.1 간격으로
y = sigmoid(x)         #y는 스텝펑션. x가 0보다 커야 1이 출력되겠지. 0일때 갑자기 계단처럼 쑥 올라오겠네.
plt.plot(x,y)
plt.ylim(-0.1,1.1)           #y축 범위 설정      
plt.show()

(2) 렐루 함수 (0보다 크면 그대로 출력, 0보다 같거나 작으면 0으로 출력하는 함수)

def relu(x):
    return np.maximum(0,x)   #0과 x중 더 큰 값 출력해주는 maximum함수

x = np.arange(-5,5,0.1)      #x는 -5부터 5까지 0.1 간격으로
y = relu(x)         #y는 스텝펑션. x가 0보다 커야 1이 출력되겠지. 0일때 갑자기 계단처럼 쑥 올라오겠네.
plt.plot(x,y)
plt.ylim(-0.1,6)           #y축 범위 설정 : x최대값이 5니까 비스무리하게.       
plt.show()

2)다차원 배열

import numpy as np

A = np.array([[[1,2,3],[-1,-2,-3]],[[5,4,7],[-5,-3,-2]],[[5,4,7],[-5,-3,-2]]])  #3차원[[[]]], 원하는 차원의 수만큼 대괄호 사용.
print(A)
print(np.ndim(A))                                                               #몇차원인가 
print(A.shape)                                                                  #3행 2열인데 그 안에 3개씩 값 있다. (3, 2, 3)    


(1)행렬의 곱(np.dot)
-a행렬과 단위행렬 곱하면 처음 값 그대로.
-단위 행렬에서 1행1열값만 숫자 n으로 바꾸고 a행렬과 곱해주면 1열만 n배로 변함.
-단위 행렬에서 2행2열값만 숫자 n으로 바꾸고 a행렬과 곱해주면 2열만 n배로 변함.
-단위행렬 음수화해서 a행렬과 곱해주면 전체 음수화. (원점 기준으로 대칭)
-a행렬과 (0,1 곱해주면 90도 회전함.
  1,0) 
.. 이런 내용들.

import numpy as np
A = np.array([[1,2,3],[4,5,6]])        #2*3 행렬
B = np.array([[1,2],[3,4],[5,6]])      #3*2 행렬
C = np.array([[1,2],[4,5]])            #2*2 행렬
Z=np.dot(A,B)                          #2*2 행렬
Y=np.dot(B,A)                          #3*3 행렬
K=np.dot(B,C)                          #3*2 행렬
#K=np.dot(Y,C)       #=>에러 발생. 3*3과 2*2 곱셈하기에는 형태가 안맞음
print(K)

error: shapes (3,3) and (2,2) not aligned: 3 (dim 1) != 2 (dim 0)
->!!!!!!!! 행렬 곱 할때는 앞의 열 숫자와 뒤의 행 숫자를 맞춰줘야 가능하다. !!!!!!!!!


(2) 각 층의 신호 전달 구현

import numpy as np

X = np.array([[1.0,0.5],[1.0,0.5]])                                 # 2*2 형태로 바꿔주면?
W1 = np.array([[0.1,0.2,0.3,0.4],[-0.1,0.2,-0.3,0.4]])              #가중치 2*4 형태 곱셈은 잘 되겠지.
B1 = np.array([3,4,2,8])                                            #X*W1에 더해줄 거니까 1*4 형태
H1 = np.dot(X,W1)
H2 = np.dot(X,W1) + B1                                              #더해질때 브로드캐스팅화 돼서 1행, 2행 다 잘 더해지네.
print(H1)
print(H2)

H1 이런상황
1     2     3    4
1 [[0.05 0.3  0.15 0.6 ]
2 [0.05 0.3  0.15 0.6 ]]


H2 이런상황
1     2     3     4
1 [[3.05 4.3  2.15 8.6 ]
 2 [3.05 4.3  2.15 8.6 ]]


globalfunc에 작성.
def identity_function(x):   #항등함수. 입력값 그대로 출력하는 함수.
    return x



-----------------------------------------------------------------------------------------------------------------------------

import numpy as np
import globalFunc as gf

# X = np.array([1.0,0.5])                                 # 1*2 형태
# W1 = np.array([[0.1,0.2,0.3,0.4],[-0.1,0.2,-0.3,0.4]])  #가중치 2*4 형태
# B1 = np.array([3,4,2,8])                                #X*W1에 더해줄 거니까 1*4 형태로
# H1 = np.dot(X,W1) + B1
# print(H1)

X = np.array([[-10000000.0,0-33333333.5],[1.0,0.5],[2,2]])                                 # 3*2 형태로 바꿔주면?
W1 = np.array([[0.1,0.2,0.3,0.4],[-0.1,0.2,-0.3,0.4]])              #가중치 2*4 형태 곱셈은 잘 되겠지.
B1 = np.array([3,4,2,8])                                            #X*W1에 더해줄 거니까 N*4 형태
H1 = np.dot(X,W1) + B1                                              #더해질때 브로드캐스팅화 돼서 1행, 2행 다 잘 더해지네.
Z1 = gf.sigmoid(H1)                                                 #sigmoid = (0 ~ 1 사이의 값으로 변환하는 함수)
#print(Z1)

W2 = np.array([[1,2],[-1,2],[2,3],[5,2]])                           #4*2 형태로 만들어야 Z1과 곱계산 가능. 그 결과는 3*2형태가 되겠지.
B2 = np.array([5,6])
H2 = np.dot(Z1,W2) + B2                                             #더해질때 브로드캐스팅화 돼서 1행, 2행 다 잘 더해지네.
Z2 = gf.sigmoid(H2)
# print(Z2.shape)

W3 = np.array([[1,1],[0.1,0.1]])
B3 = np.array([1,1])
H3 = np.dot(Z2,W3)+B3
Z3= gf.identity_function(H3)                                    #X 그대로 반환되는거를 Z3
print(Z3)


--------------------------------------------------------------------------------------------
같은 내용을 함수처럼 만들기.




import numpy as np
import globalFunc as gf

def init_network():
    network = {}
    network['W1'] = np.array([[0.1,0.2,0.3,0.4],[-0.1,0.2,-0.3,0.4]])              #가중치 2*4 형태 곱셈은 잘 되겠지.
    network['b1'] = np.array([3,4,2,8])
    network['W2'] = np.array([[1,2],[-1,2],[2,3],[5,2]])                           #4*2 형태로 만들어야 Z1과 곱계산 가능. 그 결과는 3*2형태가 되겠지.
    network['b2'] = np.array([5,6])
    network['W3'] = np.array([[1,1],[0.1,0.1]])
    network['b3'] = np.array([1,1])

    return network

def forward(net,x):
    W1,W2,W3=net['W1'],net['W2'],net['W3']
    b1,b2,b3=net['b1'],net['b2'],net['b3']
    H1 = np.dot(x,W1) + b1                                              #더해질때 브로드캐스팅화 돼서 1행, 2행 다 잘 더해지네.
    Z1 = gf.sigmoid(H1)
    H2 = np.dot(Z1,W2) + b2                                             #더해질때 브로드캐스팅화 돼서 1행, 2행 다 잘 더해지네.
    Z2 = gf.sigmoid(H2)
    H3 = np.dot(Z2,W3)+b3
    Z3= gf.identity_function(H3) 

    return Z3

X = np.array([[-10000000.0,0-33333333.5],[1.0,0.5],[2,2]])  
net = init_network()
z = forward(net,X)
print(z)                              
                                            













'2022.01. > 코딩 수업' 카테고리의 다른 글

01.28  (0) 2022.01.28
01.26 softmax(확률), 추론(배치처리), 손실함수  (0) 2022.01.26
01.14  (0) 2022.01.16
01.13  (0) 2022.01.13
01.12  (0) 2022.01.13