일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- sqld
- %in%
- 총과 카드만들기
- 회귀분석 알고리즘
- 상관관계
- 단순회귀 분석
- 그래프 생성 문법
- 데이터분석
- 여러 데이터 검색
- difftime
- max
- 그래프시각화
- Dense_Rank
- 정보획득량
- 불순도제거
- merge
- 회귀분석
- 막대그래프
- 히스토그램 그리기
- loop 문
- 빅데이터
- Intersect
- 팀스파르타
- 순위출력
- 데이터분석가
- if문 작성법
- Sum
- sql
- count
- 빅데이터분석
- Today
- Total
ch0nny_log
[빅데이터분석] 딥러닝_8. 2층 신경망 구현하기(오차 역전파로 2층 신경망 학습시키기) 본문
[빅데이터분석] 딥러닝_8. 2층 신경망 구현하기(오차 역전파로 2층 신경망 학습시키기)
chonny 2024. 10. 10. 16:21■ 2층 신경망 구현하기(오차 역전파로 2층 신경망 학습시키기)
1. 오차 역전파로 기울기를 구하는 함수 소개
기존에 배웠던 신경망이 학습되는 원리 ?
오차가 가장 작아지는 지점의 가중치를 알아내겠금 학습이 되는 원리입니다.
그래서 기울기를 구하기 위해서 4장에서 아래의 미분 함수를 만들었습니다.
def numerical_diff( f, x ):
h = 0.0001
return ( f(x+h) - f(x-h) ) / (2*h)
이 미분함수를 이용해서 신경망 학습을 시키게 되면 문제가 하나 있습니다.
그 문제가 뭐냐면 ?
기울기 구해야하는 가중치가 너무 많습니다.
너무 많아서 위의 함수로는 기울기를 구하는 작업 속도가 너무 느립니다.
뭔가 다른 방법을 컴퓨터 과학자들이 생각을 해야했습니다.
미분을 하지 말고 도함수를 이용해서 미분계수를 구하자로 아이디어를 냈습니다.
[ 정리 ]
1. 기존 numerial_diff를 이용해서 오차함수를 미분하여 기울기를 구했더니 학습시간이 몇주일 몇달이 지속되었습니다.
2. 컴퓨터 과학자들이 도함수를 이용해서 미분하자는 아이디어를 냈고 이 방법으로 신경망을 학습시켰더니 몇시간 또는 몇분에 신걍망이 학습이 완료 되었습니다.
실습1. 미분함수를 이용해서 미분계수(기울기)를 구하는 실습
# f(x) 함수 정의 def f(x): return 2*x**2 + 3*x + 7 # 연산 기호 추가: 2*x**2 + 3*x # 수치 미분 함수 정의 def numerical_diff(f, x): h = 0.0001 # 아주 작은 값 h return (f(x + h) - f(x - h)) / (2 * h) # x가 3인 지점의 미분계수 구하기 result = numerical_diff(f, 3) # 결과 출력 print(f"x = 3에서의 미분계수: {result}")
실습2. 도함수를 이용하여 미분계수(기울기)를 구하는 실습
아래의 함수의 x=3 인 지점의 기울기(미분계수)를 구하시오 !
f(x) = 2x^2 + 3x + 7
# 도함수를 파이썬으로 생성 def f_prime(x): return 4*x + 3 # 위의 도함수에 3을 입력해서 x가 3일때 미분계수(기울기)구하기 f_prime(3) #15
문제1. 아래의 오차함수의 x가 7인 지점의 미분계수(기울기)를 구하시오! (도함수를 이용하세요)
def f_prime(x): return 12*x**2 + 4*x + 3 f_prime(7) #619
설명: 도함수를 이용해서 신경망을 구성하면 빠르게 학습 시킬 수 있습니다. 구글에서 만든 텐써 플로우 함수 내에도 모두 도함수로 코딩되어져 있습니다. 그래서 속도가 빠른겁니다.
문제2. 아래의 오차함수의 도함수를 구해서 x가 4인 지점의 미분계수(기울기)를 구하시오
def f_prime(x): return 45*x**4 + 6*x**2 + 3 f_prime(4) # 11619
2. 계산 그래프를 이용해서 신경망 순전파 구현하기
미국 스탠포드 대학교에서 신경망을 학생들에게 수업하는데 너무 어려워해서 어떻게 하면 쉽게 신경망을 설명해줄 수 있을까 생각하다가 알아낸 수업방법이 계산 그래프를 이용해서 신경망을 설명하는것 입니다.
이 그림에 빈 박스를 채워넣을 수 만 있으면 5장(오차 역전파로 신경망 학습)을 이해한것입니다.
예제1. 사과 가격을 계산하는 신경망
사과 1개에 100원이고 2개를 구입했을 때 가격은 220원입니다. 세금 10%포함가격
예제2. 동그라미는 곱셈 뉴런(노드)
사과 가격을 계산할 때 뉴런이 2개가 사용되고 있습니다.
예제3. 사과와 귤을 같이 구입했을 때의 그래프첫번째 노드(뉴런) 에서는 사과 가격을 계산하고 있습니다. 두번째 노드(뉴런) 에서는 귤가격을 계산하고 있습니다. 세번째 노드(뉴런) 에서는 사과 가격과 귤가격을 더하고 있습니다. 네번째 노드(뉴런)은 소비세를 계산하고 있습니다. 각각의 뉴런이 자기가 해야할 일에만 집중을 하고 있다는 것을 봐주세요.
예제4. 전체가 아무리 복잡해도 각 노드에서 수행되는 자기가 해야할 일에 해당하는 단순계산에만 집중하여 문제를 풀면 복잡한 문제도 쉽게 풀 수 있다는 것입니다.위의 그림이 컴퓨터 프로그램 알고리즘 중에 아주 유명한 '동적 프로그래밍 알고리즘' 이라고 합니다.
동적 프로그래밍이란 큰 문제를 해결하는 방법은 큰 문제를 작은 문제로 나눠서 작은 문제를 하나식 해결하다 보면 큰 문제를 해결 할 수 있다는 것 입니다.
신경망의 원리에서도 똑같이 각각의 뉴런(노드) 에서 수행되는 단순한 계산에만 집중하여 문제를 단순화 시킬 수 있다는 것입니다.
큰 문제를 작은 문제로 나눠서 문제를 해결하는 방법이 바로 "계산 그래프를 이용한 방법" 입니다.
큰문제 ---------> 신경망 -----------> 해결된 결과
3. 왜 계산 그래프로 신경망의 구현 문제를 푸는가?
신경망 전체가 아무리 복잡해도 각 노드에서 수행되는 단순한 계산에만 집중하여 문제를 단순화 시킬 수 있기 때문
예제1. 사과 가격이 조금 올랐을때 전체 지불 금액이 얼마나 증가하는지 알고 싶다
순전파 : 100 -------> 200 -------> 220 으로 전파 되었습니다.
역전파 : 1 --------> 1.1 -------> 2.2 순으로 미분값(기울기) 이 역전파 되었습니다.
Q. 사과 가격이 1원이 오르면 최종 금액은 얼마가 오를까 ?
A. 2.2 원
2.2 를 어떻게 해야 빨리 알아낼 수 있는가 ?
사과쪽으로 전파를 역전파 시키면 알 수 있습니다.
순전파는 숫자행렬이 흘러가는것이고 역전파는 기울기가 흘러오는것입니다.
위의 계산 그래프 처럼 신경망에도 역전파가 일어나는데 역전파 될때 기울기가 흘러옵니다. 그리고 이 기울기는 각각의 신경망 층에서 가중치를 갱신할 때 사용이 됩니다. 순전파와 역전파가 계속 반복되면서 가중치가 계속 갱신되는 것입니다.
4. 계산 그래프의 역전파
예제1. 곱셈노드를 파이썬으로 생성하시오 (곱셈 노드 순전파)
class MulLayer: def __init__(self): self.x = None # x를 저장 self.y = None # y를 저장 def forward(self, x, y): self.x = x # 입력받은 x를 저장 self.y = y # 입력받은 y를 저장 out = x * y # 곱셈 연산 return out # 뉴런 객체를 만들어 사과 가격을 계산 mul_apple_layer = MulLayer() apple_price = mul_apple_layer.forward(100, 2) # 사과 한 개당 100원, 2개의 사과 print(apple_price) # 200 출력
예제2. 아래의 크래스(설계도)를 가지고 뉴런 객체는 만들어서 사과의 가격을 계산하시오mul_apple_layer = MulLayer() apple_price = mul_apple_layer.forward(100,2) print( apple_price )
예제3. 그 다음에 소비세를 계산해서 220원이 출력되게 소비세를 계산하는 노드를 생서하고 220원이 출력되게 파이썬 코드를 작성하시오.mul_apple_layer = MulLayer() # 사과 가격 계산 노드 mul_tax_layer = MulLayer() # 세금을 계산하는 노드 apple_price = mul_apple_layer.forward(100,2) price = mul_tax_layer.forward( apple_price, 1.1 ) price
5. 덧셈 계산 그래프의 순전파
예제1. 뎃셈 노드를 구현하시오
class AddLayer: def __init__(self): pass def forward( self, x, y ): out = x + y return out
예제2. 덧셈 클래스를 객체화 시키시오 (덧셈노드 순전파)
add_layer = AddLayer() add_layer.forward( 10, 5 )
문제1. 계산그래프를 생성하는데 곱셈클래스와 덧셈 클래스를 이용해서 만드시오.
# 1. 뉴런 4개 만들기 apple_price_layer= MulLayer() orange_price_layer = MulLayer() add_apple_orange_layer = AddLayer() mul_tax_layer = MulLayer() # 2. 순전파 구현하기 apple_price = apple_price_layer.forward( 100, 2 ) orange_price = orange_price_layer.forward(150, 3) # 사과 가격과 오렌지 가격을 더하는 코드 total_fruit_price = add_apple_orange_layer.forward(apple_price, orange_price) # 더한 가격에 세금 계산하는 코드 final_price = mul_tax_layer.forward(total_fruit_price, 1.1) # 결과 출력 코드 print(f"최종 가격 (세금 포함): {final_price}")
6. 덧셈노드의 역전파
신경망을 순전파일때는 입력된 값이 흘러가지만 역전파일때는 기울기가 흘러옵니다. 이 기울기는 가중치를 갱신할 때 사용됩니다.
실습1. 앞에서 만들었떤 덧셈노드 클래스에 역전파 함수도 추가하시오.
class AddLayer: def __init__(self): print('덧셈 노드가 생성되었습니다.') def forward( self, x, y ): out = x + y return out def backward( self, dout): # dout 는 상류에서 흘러온 기울기 dx = dout * 1 dy = douy * 1 return dx, dy
실습2. 위에서 만든 덧셈 노드를 객체화 시켜서 그림 5-11처럼 구현하시오add_layer = AddLayer() # 덧셈 클래스를 객체화 시킵니다. result1 = add_layer.forward(10, 5) # 순전파 result2 = add_layer.backward(1.3); print(result2)
7. 곱셈노드의 역전파
곱셈노드의 역전파는 상류에서 흘려왔던 값에 순정파 때 보냈던 상대편쪽 값을 곱해주는 것 입니다.
실습1. 순전파만 있는 곱셈 노드 클래스에 역전파 함수도 추가하시오 !
class MulLayer: def __init__(self): self.x = None self.y = None def forward( self, x, y ): self.x = x self.y = y out = x * y return out def backward( self, dout ): dx = dout * self.y dy = dout * self.x return dx, dy
실습2. 그림5-13에 나온 곱셈 노드의 순전파와 역전파를 실습1에서 만들었던 곱셈노드 클래스를 가지고 계산하시오 !mul_layer = MulLayer() mul_layer.forward( 10, 5 ) result2 = mul_layer.backward(1.3) print(result2)
곱셈노드의 역전파 때 순전파 때 보냈던 입력 데이터가 사용되고 있습니다.
문제1. 그림5-15에 나오는 네모의 값을 채워 넣으시오 !
곱셈 뉴런은 3개가 필요하고 뎃셈 뉴런은 1개가 필요합니다.
문제2. 그림 5-15의 총계산된 값이 715가 출력되도록 뉴런을 만들어 계산하시오 !
class MulLayer: def __init__(self): self.x = None self.y = None def forward(self, x, y): self.x = x self.y = y out = x * y return out def backward(self, dout): dx = dout * self.y dy = dout * self.x return dx, dy class AddLayer: def __init__(self): print('덧셈 노드가 생성되었습니다.') def forward(self, x, y): out = x + y return out def backward(self, dout): dx = dout * 1 dy = dout * 1 return dx, dy # 1. 뉴런 4개를 만듭니다. apple_price_layer = MulLayer() orange_price_layer = MulLayer() add_apple_orange_layer = AddLayer() mul_tax_layer = MulLayer() # 2. 순전파를 구현합니다. apple_price = apple_price_layer.forward(100, 2) # 사과 가격: 100원 * 2개 orange_price = orange_price_layer.forward(150, 3) # 오렌지 가격: 150원 * 3개 all_price = add_apple_orange_layer.forward(apple_price, orange_price) # 총 과일 가격 # 세율을 조정하여 최종 가격을 715로 만듭니다. tax = 1.1 # 세율 10% final_price = mul_tax_layer.forward(all_price, tax) # 총 가격에 세금 적용 print(f"최종 가격: {final_price}") # 715가 나오는지 확인 # 결과: 세금 적용 후 최종 가격이 715
8. 신경망 활용을 쉽게 할 수 있는 사용자 인터페이스 만들기
# 1. 코드의 큰 플로우 차트
1. 필요한 모듈 불러오기
↓
2. 신경망 모델 불러오기
↓
3. 타겟 딕셔너리( 신경망이 출력한 숫자와 라벨을 매핑)
↓
4. 이미지 전처리 함수 (이미지 색상반전, 28x28 로 리시이즈, 흑백처리, 0~1로 정규화)
↓
5. 사진을 선택하게 하는 파일 박스 함수 + 사진 시각화
↓
6. 사진이 물체가 뭔지 예측하는 함수
↓
7. tkinter GUI 설정 코드들 (버튼 위치, 인터페이스 색깔, 출력 글씨 크기등)
전체 코드:
# 1. 필요한 모듈 불러오기
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import numpy as np
import tensorflow as tf
import cv2 # 이미지를 전문으로 전처리하는 모듈
# 2. 신경망 모델 로드 (미리 학습된 모델을 가정)
model = tf.keras.models.load_model('c:\\data\\fashion_model.h5')
# 3. 타겟 딕셔너리 (번호에 해당하는 레이블)
target_dict = {
0: 'T-shirt/top',
1: 'Trouser',
2: 'Pullover',
3: 'Dress',
4: 'Coat',
5: 'Sandal',
6: 'Shirt',
7: 'Sneaker',
8: 'Bag',
9: 'Ankle boot',
}
# 4. 이미지 전처리 함수
def preprocess_image(image_path):
# 이미지 불러오기
img = cv2.imread(image_path) # 이미지를 숫자로 변환
# 이미지 색상 반전 (흰색을 검정색으로)
img = cv2.bitwise_not(img)
# 이미지 크기를 28x28로 조정
resized_img = tf.image.resize(img, (28, 28))
# RGB 이미지를 그레이스케일로 변환
grayscale_img = tf.image.rgb_to_grayscale(resized_img)
# 이미지를 1D 벡터로 변환
img_array = np.array(grayscale_img) / 255.0 # 정규화
img_array = img_array.reshape(1, 28 * 28) # 1D 벡터로 변환
return img_array
# 5. 이미지 선택 및 표시
def select_image():
global file_path
file_path = filedialog.askopenfilename() # 선택한 이미지 경로 저장
if not file_path:
return
# 선택한 이미지 표시
img_display = cv2.imread(file_path)
img_display = cv2.resize(img_display, (400, 400)) # 화면에 출력할 크기로 조정
img_display = cv2.cvtColor(img_display, cv2.COLOR_BGR2RGB) # OpenCV는 BGR, tkinter는 RGB를 사용함
img_tk = ImageTk.PhotoImage(Image.fromarray(img_display))
# 이미지 위젯 업데이트
label_image.config(image=img_tk)
label_image.image = img_tk
# 6. 예측 및 결과 표시
def predict_image():
if not file_path:
label_prediction.config(text="No image selected")
return
# 이미지를 전처리하여 예측
img = preprocess_image(file_path)
prediction = model.predict(img)
predicted_label = np.argmax(prediction)
# 라벨 번호에 해당하는 타겟 텍스트
predicted_text = target_dict.get(predicted_label, "Unknown")
# 예측 결과 업데이트
label_prediction.config(text=f"Prediction: {predicted_text}")
#7. TKinter GUI 설정
# tkinter 윈도우 설정
root = tk.Tk()
root.title("Image Classifier")
root.geometry("600x700") # 기본 창 크기 설정
# 이미지 선택 버튼 (위쪽에 배치)
button_select = tk.Button(root, text="Select Image", command=select_image)
button_select.pack(pady=10) # 위쪽에 공간을 추가
# 이미지 출력할 라벨 (이미지 박스)
label_image = tk.Label(root)
label_image.pack(pady=10)
# 예측 버튼 (이미지 아래에 배치)
button_predict = tk.Button(root, text="Predict", command=predict_image)
button_predict.pack(pady=10)
# 예측 결과 출력할 라벨 (예측 버튼 아래에 배치)
label_prediction = tk.Label(root, text="", font=("Helvetica", 16))
label_prediction.pack(pady=20)
# tkinter 실행
root.mainloop()
'빅데이터 분석(with 아이티윌) > deep learning' 카테고리의 다른 글
[빅데이터분석] 딥러닝_11. CNN 층 (1) | 2024.10.15 |
---|---|
[빅데이터분석] 딥러닝_9. 2층 신경망 구현하기2 (오차 역전파로 2층 신경망 학습시키기) (2) | 2024.10.11 |
[빅데이터분석] 딥러닝_7. 미니배치/수치미분/사진인식(mnist) (0) | 2024.10.10 |
[빅데이터분석] 딥러닝_6. 2층 신경망 구현하기 (1) | 2024.10.07 |
[빅데이터분석] 딥러닝_5. 출력층 함수 소프트 맥스 함수 (0) | 2024.10.07 |