ch0nny_log

[빅데이터분석] 딥러닝_5. 출력층 함수 소프트 맥스 함수 본문

빅데이터 분석(with 아이티윌)/deep learning

[빅데이터분석] 딥러닝_5. 출력층 함수 소프트 맥스 함수

chonny 2024. 10. 7. 15:08

▣ 3.10 출력층 함수 소프트 맥스 함수 구현하기

 

* 개와 고양이를 분류하는 신경망


   입력값 ---------->  신경망  -------->  출력층 함수 ------>  [ 0.8 , 0.2 ] 

 

                                                                                            확률값
   입력값 ---------->  신경망  -------->  출력층 함수 ------>  [ 0.8 , 0.2 ] 
                                                           소프트 맥스           개    고양이

 

 

예제1. 출력층 함수인 소프트 맥스 함수를 파이썬으로 구현하기.

1. 자연상수 e의 10승을 출력하시오
import numpy as np

print(np.exp(10)) # 22026.465794806718​

 

2. 자연상수 e 의 100승을 출력하시오 !
import  numpy  as  np

print( np.exp(100)  )  #  2.6881171418161356e+43​

3. 자연상수 e의 1000 승을 출력하시오 ! 
import  numpy  as  np

print( np.exp(1000)  )  # inf  <-- 무한대​


설명: p 94페이지 설명에 의하면 컴퓨터 메모리의 한계로 숫자를 전부 출력해주지 못하고 있습니다. 


4. 책 94 페이지에 맨 위에 나온대로 구현 해 봅니다.

import   numpy  as   np

a = np.array( [ 1010, 1000, 990 ] )
print( np.exp(a) )  # [inf inf inf]

 


이렇게는 수학적으로는 계산이 되는데 컴퓨터로는 계산이 안됩니다. 

5. 컴퓨터로 계산 될 수 있도록 다음과 같이 가지고 있는 숫자중에 가장 큰 값으로 각각 빼서 계산합니다.

a = np.array( [ 1010, 1000, 990 ] )
a = np.array( [ 1010, 1000, 990 ] )  

def  softmax(a):
    C = np.max(a)   #  a 리스트 요소중에서 가장 큰 요소를 C 에 할당
    minus =  a - C  #  a 리스트의 각 요소들을 C 로 차감함( 1010-C, 1000-C, 990-C ]
    np_exp  = np.exp(minus)
    return  np_exp

print ( softmax(a) ) 

분모까지 포함해서 구현하면 ?

a = np.array( [ 1010, 1000, 990 ] )  

def  softmax(a):
    C = np.max(a)   #  a 리스트 요소중에서 가장 큰 요소를 C 에 할당
    minus =  a - C  #  a 리스트의 각 요소들을 C 로 차감함( 1010-C, 1000-C, 990-C ]
    exp_a=np_exp  = np.exp(minus)    # 분자식 구현
    sum_exp_a = np.sum(exp_a) # 분모식 구현
    y = exp_a / sum_exp_a
    return  y

print ( softmax(a) )



6. 아래의 신경망에 출력층으로 softmax 함수의 결과를 출력하시오

#1. 입력층 구현(0층)
import  numpy  as  np

x = np.array([ 1, 2 ])

#2. 은닉층(1층)
w1 = np.array([ 1, 3, 5, 2, 4, 6 ]).reshape(2,3)
y = np.dot(x, w1)
y  # [ 5, 11, 17]

#3. y 값을 sigmoid 함수에 통과 시킵니다.

def  sigmoid(x):
    return  1  / ( 1 + np.exp(-x) ) 

y_hat = sigmoid(y)
print(y_hat)

#4. 은닉층(2층)

w2 = np.array([ 3, 4, 5, 6, 7, 8 ]).reshape(3,2)
z = np.dot( y_hat, w2 )
print(z)

#5. z 값을 시그모이드 함수에 통과 시키기

z_hat = sigmoid(z)
print(z_hat)

#6. 출력층 구현(소프트 맥스 함수로 구현)

def  softmax(a):
    C = np.max(a)   #  a 리스트 요소중에서 가장 큰 요소를 C 에 할당
    minus =  a - C  #  a 리스트의 각 요소들을 C 로 차감함( 1010-C, 1000-C, 990-C ]
    exp_a  = np.exp(minus)    # 분자식 구현
    sum_exp_a = np.sum(exp_a) # 분모식 구현
    y = exp_a / sum_exp_a  
    return  y

w3 = np.array([ 4, 2, 3, 2 ]).reshape(2,2)
k = np.dot( z_hat, w3 )
k_hat = softmax(k)
print( k_hat )   # [0.9525741 0.0474259]

 

문제1. 위에서 출력된 k_hat 의 요소들의 합을 출력하시오 ! 
import  numpy  as   np

np.sum( k_hat )   # 1.0​
문제2. 위에서 만든 3층 신경망을 텐썬 플로우로 구현하시오 !
# 1. 신경망에 필요한 모듈을 불러옵니다. 
import tensorflow as tf
import numpy as np
from tensorflow.keras.models import Sequential  # 신경망 모델 구현
from tensorflow.keras.layers import Dense        # 완전 연결 계층
from tensorflow.keras.optimizers import SGD      # 경사하강법
from tensorflow.keras.losses import MeanSquaredError  # 오차함수

# 2. 입력층 구현 (0층)
x = np.array([1, 2]).reshape(1, 2)
y = np.array([1, 0]).reshape(1, 2)  # 정답 데이터 [ 개, 고양이] 

# 3. 모델 생성 
model = Sequential()  

# 4. 신경망 층 구성 
model.add(Dense(3, input_shape=(2,), activation='sigmoid'))  # 은닉 1층
model.add(Dense(2, activation='sigmoid'))  # 은닉 2층
model.add(Dense(2, activation='softmax'))  # 출력층

# 5. 모델의 학습 방법 설정하기
model.compile(optimizer=SGD(),               # 경사하강법
              loss=MeanSquaredError(),      # 오차함수_예측값과 정답과의 차이 출력
              metrics=['accuracy'])         # 정확도 기준으로 학습시킴

# 6. 모델 학습 시키기
model.fit(x, y, epochs=500)  # ecochs -> epochs

# 7. 예측값 출력하기
result = model.predict(x)  # X -> x (입력 데이터 사용)
print(result)​

 

문제3. 아래의 그림 신경망을 텐써 플로우로 구현하시오.
# 1. 신경망에 필요한 모듈을 불러옵니다. 
import tensorflow as tf
import numpy as np
from tensorflow.keras.models import Sequential  # 신경망 모델 구현
from tensorflow.keras.layers import Dense        # 완전 연결 계층
from tensorflow.keras.optimizers import SGD      # 경사하강법
from tensorflow.keras.losses import CategoricalCrossentropy  # 분류 문제용 손실 함수

# 2. 입력층 구현 (0층)
x = np.array([1, 2]).reshape(1, 2)
y = np.array([1, 0, 0]).reshape(1, 3)  # 정답 데이터 [ 개, 고양이, 새] - 원핫 인코딩

# 3. 모델 생성 
model = Sequential()  

# 4. 신경망 층 구성 
model.add(Dense(5, input_shape=(2,), activation='sigmoid'))  # 은닉 1층
model.add(Dense(4, activation='sigmoid'))  # 은닉 2층
model.add(Dense(5, activation='sigmoid'))  # 은닉 3층
model.add(Dense(3, activation='softmax'))  # 출력층 (3개의 클래스를 예측)

# 5. 모델의 학습 방법 설정하기
model.compile(optimizer=SGD(),               # 경사하강법
              loss=CategoricalCrossentropy(), # 손실 함수 (분류 문제에 적합)
              metrics=['accuracy'])         # 정확도 기준으로 학습시킴

# 6. 모델 학습 시키기
model.fit(x, y, epochs=500)

# 7. 예측값 출력하기
result = model.predict(x)
print(result)​

 


▣ 3. 11.  손글씨 필기체 데이터 소개


데이터 설명:  mnist 데이터는 숫자 0~9까지의 숫자 이미지로 구성되어 있고 훈련 데이터가 6만장, 테스트 데이터가 1만장으로 구성되어 있습니다.  28x28 크기의 회색조 이미지(1채널) 이며 각 픽셀은 0~255 까지의  값을 취합니다. 

 

예제
1. 텐써 플로우를 이용해서 텐써 플로우에 내장된 mnist 데이터를 가져오시오
from tensorflow.keras.datasets import mnist

# MNIST 데이터셋 불러오기
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 데이터셋 크기 출력
print(x_train.shape)  # (60000, 28, 28)
print(x_test.shape)   # (10000, 28, 28)​

2. mnist 의 훈련 데이터 중에서 첫번째 사진을 시각화 하시오 !
import  matplotlib.pyplot  as  plt

img = x_train[0]
plt.figure()
plt.imshow( img, cmap='gray')​

 

3. 위의 사진의 정답을 확인하시오

print(y_train[0])

★ 4. 필기체 데이터를 학습시키는 3층 신경망을 텐써 플로우로 구현하시오. 

#1. mnist 필기체 데이터 불러오기

from  tensorflow.keras.datasets.mnist   import   load_data
(x_train, y_train), ( x_test, y_test ) = load_data('mnist.npz')

print(x_train.shape)  # (60000, 28, 28)

# 차원 축소하기
x_train = x_train.reshape((x_train.shape[0], -1))
x_test =  x_test.reshape((x_test.shape[0], -1) )  # 차원 축소 코드
print(x_train.shape)  # (60000, 784)

# 설명: 필기체 사진을 신경망에 넣으려면 다음과 같이 차원을 축소해야합니다.

# ( 60000, 28, 28 )  --------->  차원 축소 코드 ---------> ( 60000, 784 ) 
# -1 이라고 쓰면 28x28 을 알아서 계산해서 784로 해주는것입니다.

#2. 신경망 구성에 필요한 모듈 불러오기
import  tensorflow  as   tf
import  numpy  as  np
from  tensorflow.keras.models  import  Sequential   # 신경망 모델 구성
from  tensorflow.keras.layers  import  Dense  # 완전 연결계층 
from  tensorflow.keras.optimizers  import   SGD  # 경사감소법 
from  tensorflow.keras.losses   import   mse    #  오차함수 

#3. 모델 생성하기
model = Sequential()

#4. 층 구성하기 (3층 신경망)
model.add( Dense(  100,  input_shape=( 784,  ),  activation='sigmoid')  )  # 은닉1층
model.add( Dense(  50,  activation='sigmoid')  )  # 은닉 2층
model.add( Dense( 10, activation='softmax')   )  # 출력층 

#5. 모델 학습 방법 지정하기
model.compile( optimizer=SGD(),  # 경사하강법
                     loss= 'sparse_categorical_crossentropy',          # 오차함수
                     metrics=['acc']  )  # 정확도를 높이는 방법으로 학습 시키겠다.

#6. 학습 시키기
model.fit( x_train, y_train, epochs=100 )

# Epoch 500/500
# 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 642us/step - acc: 0.9831 - loss: 0.0531
# 설명: 훈련 데이터의 정확도가 0.98 이 출력되었습니다. 

#7. 테스트 데이터 예측하기 
y_pred = model.predict( x_test )
y_pred_classes = np.argmax( y_pred, axis=1)  #가장 높은 확률로 예측한 자리번호를 출력
y_pred_classes  # [7, 2, 1, ..., 4, 5, 6]  예측한 숫자들 출력됨 

#8. 정확도 확인하기
test_loss, test_acc = model.evaluate( x_test, y_test)
print( test_acc )  # 0.9692000150680542


6만장의 훈련 데이터를 학습해서 훈련 데이터의 정확도는 0.98 이 출력되었고
1만장의 테스트 데이터의 정확도는 0.96 이 나왔습니다. 

 

 

문제1. 훈련데이터 이미지 중에서 10번째 이미지와 10번재 정답을 확인하시오.
# 프레임만들기
from tensorflow.keras.datasets import mnist

# MNIST 데이터셋 불러오기
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 데이터셋 크기 출력
print(x_train.shape)  # (60000, 28, 28)
print(x_test.shape)   # (10000, 28, 28)

# 시각화
import  matplotlib.pyplot  as  plt

img = x_train[9]
plt.figure()
plt.imshow( img, cmap='gray')

# 정답
print(y_train[9])​

 

문제1. 그림판에 직접 필기체로 숫자를 하나 작성하고 28x28 로 저장합니다.
image_path='c:\\data\\7.png'

#1. 필요한 모듈을 불러옵니다.
from  PIL  import  Image
import  numpy  as  np
import  matplotlib.pyplot  as  plt

#2. 이미지를 전처리하는 함수를 생성합니다.
def  preprocess_image(image_path):
    img = Image.open(image_path).convert('L') # 흑백이미지 변환 
    img = img.resize((28, 28))  # mnist 형식에 맞게 28x28로 크기 변환
    img_array= np.array(img) / 255.0  # 0~255 범위를 0~1 사이로 스켈링 
    img_array= img_array.reshape(1, 784)  # 차원 축소
    return  img_array

image_path='c:\\data\\7.png'

result = preprocess_image(image_path)
plt.imshow( result.reshape(28, 28), cmap='gray')
plt.show()​

 

 

 


 

▣   배치처리     p115



 사진을 1장씩 신경망에 넣고 학습 시키는게 아니라 여러장씩 넣고 학습 시키는  방법이 배치처리입니다. 책에 미니배치라는 용어가 나오는데 이말의 의미는 사진을 신경망에 넣을때 100장씩 넣고 학습 시키겠다는것입니다.

 만약 1장씩 넣고 학습 시켜면 6만번을 학습해야하는데 100장씩 넣고 학습 시키면 600번만 학습하면 됩니다. 

 사람은 사진을 한번 1장씩만 공부할 수 있지만 컴퓨터는 한번에 여러장을 공부할 수 있습니다.   이렇게 하면 학습 속도가 아주 빨라집니다.

 

예제1.  100장씩 배치처리하는 방법은 무엇인가요 ?
# 앞에 학습 시킨 전체 코드들 ...

# 학습 시키기
model.fit ( x_train, y_train, epochs= 500, batch_size =100 )​

#1. mnist 필기체 데이터 불러오기

from  tensorflow.keras.datasets.mnist   import   load_data
(x_train, y_train), ( x_test, y_test ) = load_data('mnist.npz')

print(x_train.shape)  # (60000, 28, 28)

# 차원 축소하기
x_train = x_train.reshape((x_train.shape[0], -1))
x_test =  x_test.reshape((x_test.shape[0], -1) )  # 차원 축소 코드
print(x_train.shape)  # (60000, 784)

# 설명: 필기체 사진을 신경망에 넣으려면 다음과 같이 차원을 축소해야합니다.

# ( 60000, 28, 28 )  --------->  차원 축소 코드 ---------> ( 60000, 784 ) 
# -1 이라고 쓰면 28x28 을 알아서 계산해서 784로 해주는것입니다.

#2. 신경망 구성에 필요한 모듈 불러오기
import  tensorflow  as   tf
import  numpy  as  np
from  tensorflow.keras.models  import  Sequential   # 신경망 모델 구성
from  tensorflow.keras.layers  import  Dense  # 완전 연결계층 
from  tensorflow.keras.optimizers  import   SGD  # 경사감소법 
from  tensorflow.keras.losses   import   mse    #  오차함수 

#3. 모델 생성하기
model = Sequential()

#4. 층 구성하기 (3층 신경망)
model.add( Dense(  100,  input_shape=( 784,  ),  activation='sigmoid')  )  # 은닉1층
model.add( Dense(  50,  activation='sigmoid')  )  # 은닉 2층
model.add( Dense( 10, activation='softmax')   )  # 출력층 

#5. 모델 학습 방법 지정하기
model.compile( optimizer=SGD(),  # 경사하강법
                    loss= 'sparse_categorical_crossentropy',          # 오차함수
                     metrics=['acc']  )  # 정확도를 높이는 방법으로 학습 시키겠다.

#6. 학습 시키기
model.fit( x_train, y_train, batch_size=100,  epochs=500 )​


Epoch 500/500
600/600 ━━━━━━━━━━━━━━━━━━━━ 1s 926us/step - acc: 0.9983 - loss: 0.0092

배치 처리로 하니까 학습 속도도 빨라졌고 정확도도 더 좋아졌습니다.