{% endif %}
diff --git a/_includes/nav_list_bak b/_includes/nav_list_bak
new file mode 100644
index 000000000000..a035a5bd7b15
--- /dev/null
+++ b/_includes/nav_list_bak
@@ -0,0 +1,26 @@
+{% assign navigation = site.data.navigation[include.nav] %}
+
+
diff --git a/_includes/page__meta.html b/_includes/page__meta.html
index 3d228c921205..575542ef23eb 100644
--- a/_includes/page__meta.html
+++ b/_includes/page__meta.html
@@ -9,14 +9,14 @@
{% endif %}
-
- {% if document.read_time and document.show_date %}{% endif %}
+
+ {% if document.read_time and document.show_date %}{% endif %}
{% if document.read_time %}
{% assign words_per_minute = document.words_per_minute | default: site.words_per_minute | default: 200 %}
{% assign words = document.content | strip_html | number_of_words %}
-
+
{% endif %}
{% endif %}
diff --git a/_includes/sidebar.html b/_includes/sidebar.html
index a4ca1ca78151..4c25cc498ab8 100644
--- a/_includes/sidebar.html
+++ b/_includes/sidebar.html
@@ -5,7 +5,7 @@
{% for s in page.sidebar %}
{% if s.image %}
+ alt="{% if s.image_alt %}{{ s.image_alt }}{% endif %}">
{% endif %}
{% if s.title %}
{{ s.title }}
{% endif %}
{% if s.text %}{{ s.text | markdownify }}{% endif %}
diff --git a/_pages/category-archive.md b/_pages/category-archive.md
new file mode 100644
index 000000000000..3cd6f6e06761
--- /dev/null
+++ b/_pages/category-archive.md
@@ -0,0 +1,7 @@
+---
+title: "Category"
+layout: categories
+permalink: /categories/
+author_profile: true
+sidebar_main: true
+---
\ No newline at end of file
diff --git a/_pages/tag-archive.md b/_pages/tag-archive.md
new file mode 100644
index 000000000000..58ae8e76afc6
--- /dev/null
+++ b/_pages/tag-archive.md
@@ -0,0 +1,7 @@
+---
+title: "Tag"
+layout: tags
+permalink: /tags/
+author_profile: true
+sidebar_main: true
+---
\ No newline at end of file
diff --git a/_posts/2022-01-05-Numpy.md b/_posts/2022-01-05-Numpy.md
new file mode 100644
index 000000000000..b2cda2142eb9
--- /dev/null
+++ b/_posts/2022-01-05-Numpy.md
@@ -0,0 +1,687 @@
+---
+layout: single
+title: "[Python] Numpy 개인 정리"
+categories: Python
+tag: [python, Numpy, 파이썬]
+toc: true
+toc_sticky: true
+---
+
+
+
+
+
+
+```python
+import numpy as np
+```
+
+
+```python
+# numpy의 배열 생성
+list1 = [1,2,3,4,5]
+list2 = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
+
+arr1 = np.array(list1) # 1차원 배열
+arr1
+```
+
+
+
+
+ array([1, 2, 3, 4, 5])
+
+
+
+
+```python
+arr2 = np.array(list2) # 2차원 배열
+arr2
+```
+
+
+
+
+ array([[ 1, 2, 3, 4],
+ [ 5, 6, 7, 8],
+ [ 9, 10, 11, 12]])
+
+
+
+
+```python
+# 배열의 크기 확인
+print(arr1.shape)
+print(arr2.shape)
+```
+
+ (5,)
+ (3, 4)
+
+
+
+```python
+# size는 배열 내의 요소 개수
+print(arr1.size)
+print(arr2.size)
+```
+
+ 5
+ 12
+
+
+
+```python
+# 배열의 데이터 타입 확인
+print(arr1.dtype)
+print(arr2.dtype)
+```
+
+ int64
+ int64
+
+
+
+```python
+# 배열의 차원 확인
+print(arr1.ndim)
+print(arr2.ndim)
+```
+
+ 1
+ 2
+
+
+
+```python
+# 배열 초기화
+arr_zero = np.zeros((3,3))
+print(arr_zero)
+print(arr_zero.dtype)
+
+arr_one = np.ones((2,3))
+print(arr_one)
+```
+
+ [[0. 0. 0.]
+ [0. 0. 0.]
+ [0. 0. 0.]]
+ float64
+ [[1. 1. 1.]
+ [1. 1. 1.]]
+
+
+
+```python
+# 특정 값으로 배열 초기화
+# np.full(차원, 데이터)
+
+arr_full = np.full((4,3), 'z')
+print(arr_full)
+```
+
+ [['z' 'z' 'z']
+ ['z' 'z' 'z']
+ ['z' 'z' 'z']
+ ['z' 'z' 'z']]
+
+
+
+```python
+# 범위를 지정해서 배열 생성
+# arange(시작점, 끝점+1, 데이터 폭)
+arr = np.arange(1,51,5)
+print(arr)
+print(arr.shape)
+print(arr.size)
+```
+
+ [ 1 6 11 16 21 26 31 36 41 46]
+ (10,)
+ 10
+
+
+
+```python
+# 배열 생성 시 타입 지정
+arr_type = np.array([1,2,2,5,3,4], dtype=np.str0)
+
+print(arr_type)
+
+# 타입 변경
+arr_type = arr_type.astype('int64')
+print(arr_type)
+```
+
+ ['1' '2' '2' '5' '3' '4']
+ [1 2 2 5 3 4]
+
+
+
+```python
+# 랜덤 값으로 배열 생성
+# np.random.rand(차원 수) : 랜덤 실수값
+arr_random = np.random.rand(2,3)
+print(arr_random)
+```
+
+ [[0.069824 0.56538797 0.08239869]
+ [0.05746204 0.47192185 0.65286904]]
+
+
+
+```python
+# np.random.randint(시작점, 끝점, size=(차원 수)) : 시작점부터 끝점-1 까지의 랜덤 정수 값
+arr_random2 = np.random.randint(1,11, size=(3,3))
+arr_random2
+```
+
+
+
+
+ array([[ 3, 10, 5],
+ [ 1, 3, 8],
+ [ 9, 9, 8]])
+
+
+
+
+```python
+# array 연산
+array1 = np.array([1,2,3])
+array2 = np.array([4,5,6])
+
+print(array1+array2)
+print(array1 / array2)
+print(array1 // array2)
+print(array1 % array2)
+```
+
+ [5 7 9]
+ [0.25 0.4 0.5 ]
+ [0 0 0]
+ [1 2 3]
+
+
+- BMI 지수 구하기
+
+
+```python
+# txt파일 불러오기
+data = np.loadtxt('/Users/min-yungi/Desktop/20210905pr/data/height_weight.txt', delimiter = ',')
+print(data)
+print(data.shape)
+print(data[1,0])
+```
+
+ [[175.2 180.3 175. 169.2 185.2 188. 177.6 178.2 177. 179. ]
+ [ 65.6 88. 79.2 69.3 55. 71.2 73. 68.9 74. 82. ]]
+ (2, 10)
+ 65.6
+
+
+
+```python
+height = data[0] * 0.01
+print(height)
+```
+
+ [1.752 1.803 1.75 1.692 1.852 1.88 1.776 1.782 1.77 1.79 ]
+
+
+
+```python
+weight = data[1]
+print(weight)
+```
+
+ [65.6 88. 79.2 69.3 55. 71.2 73. 68.9 74. 82. ]
+
+
+
+```python
+bmi = weight/(height**2)
+print(bmi)
+```
+
+ [21.37153104 27.07018468 25.86122449 24.20652885 16.03543423 20.14486193
+ 23.14392095 21.69720651 23.62028791 25.59220998]
+
+
+ - Indexing & Slicing
+
+
+```python
+array7 = np.arange(10)
+print(array7)
+
+print(array7[3:8])
+
+array7[3:8] = 10
+print(array7)
+```
+
+ [0 1 2 3 4 5 6 7 8 9]
+ [3 4 5 6 7]
+ [ 0 1 2 10 10 10 10 10 8 9]
+
+
+
+```python
+# 2차원 배열 생성
+array8 = np.arange(50).reshape(5,10)
+print(array8)
+print(array8.shape)
+
+# 2차원 배열 슬라이싱
+print(array8[1:4,4:9])
+```
+
+ [[ 0 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 32 33 34 35 36 37 38 39]
+ [40 41 42 43 44 45 46 47 48 49]]
+ (5, 10)
+ [[14 15 16 17 18]
+ [24 25 26 27 28]
+ [34 35 36 37 38]]
+
+
+- Boolean 색인
+
+
+```python
+name = np.array(['윤기','석준','원빈','은수','태헌'])
+name
+```
+
+
+
+
+ array(['윤기', '석준', '원빈', '은수', '태헌'], dtype='=4.5,0].astype('int')
+over4
+```
+
+
+
+
+ array([ 91, 101, 215, 233, 266, 283, 288, 307, 372, 446, 447,
+ 451, 567, 661, 682, 761, 764, 951, 953, 989, 1021, 1131,
+ 1315, 1349, 1378, 1437, 1569, 1670, 1702, 1856, 1863, 1940, 1959,
+ 1986, 2118, 2155, 2243, 2339, 2363, 2497, 2510, 2574, 2593, 2694,
+ 2726, 2791, 2838, 2849, 2922, 2964, 3036, 3073, 3210, 3282, 3287,
+ 3306, 3324, 3437, 3461, 3596, 3604, 3699, 3738, 3864, 3902, 4136,
+ 4176, 4187, 4189, 4273, 4518, 4584, 4589, 4595, 4634, 4649, 4755,
+ 4801, 4904, 4925, 4982, 5003, 5069, 5073, 5102, 5165, 5212, 5255,
+ 5343, 5427, 5499, 5542, 5582, 5609, 5696, 5768, 5839, 5862, 5936,
+ 5984])
+
+
+
+
+```python
+# 최고 평균 평점 구하기
+max_mean = arr_means[:,1].max()
+max_mean
+```
+
+
+
+
+ 4.962962962962963
+
+
+
+
+```python
+# 최고 평점 구하기
+data[:,2].max()
+```
+
+
+
+
+ 5
+
+
diff --git a/_posts/2022-01-07-Queue.md b/_posts/2022-01-07-Queue.md
new file mode 100644
index 000000000000..345a273c3e48
--- /dev/null
+++ b/_posts/2022-01-07-Queue.md
@@ -0,0 +1,383 @@
+---
+layout: single
+title: "[자료구조/알고리즘] 큐(Queue)와 덱(Deque)"
+categories: 자료구조/알고리즘
+tag: [python, 파이썬, Queue, Deque, 큐, 덱, SinglyLinkedList, 자료구조, 알고리즘]
+toc: true
+toc_sticky: true
+---
+
+
+
+
+
+### 큐(Queue)
+
+
+
++ FIFO(선입선출) 형식의 자료구조
++ 먼저 들어온 데이터가 순서대로 먼저 나가는 구조입니다.
+스택과 다르게 한쪽에서 데이터가 추가되고, 다른 한쪽에서 데이터가 삭제되는 구조입니다.
+
+#### 리스트를 이용한 큐 구현
+
+
+
++ enqueue : 큐의 맨 뒤쪽에 항목 삽입
++ dequeue : 큐 맨 앞쪽의 항목을 반환하고 제거
++ peek/front : 큐의 맨 앞쪽 항목을 조회
++ empty : 큐가 비었는지 확인
++ size : 큐의 크기를 확인
+
+
+```python
+# 리스트를 이용한 Queue 구현
+class Queue(object):
+ def __init__(self):
+ self.items = [] # 값을 담아줄 큐 배열
+
+ # 큐가 비었는지 확인하는 함수(Empty : True / Not Empty : false)
+ def isEmpty(self):
+ return not self.items
+
+ def dequeue(self):
+ # 큐가 비어있다면
+ if self.isEmpty():
+ print("Queue is Empty!")
+
+ # 그렇지 않으면
+ else:
+ value = self.items.pop(0) # 큐 배열의 0번째 값을 반환
+ return value
+
+
+ def enqueue(self, item):
+ self.items.append(item) # 큐 배열의 맨 뒤에 값을 삽입
+
+ def size(self):
+ return len(self.items) # 큐 배열의 크기를 반환
+
+ def peek(self):
+ if self.isEmpty():
+ print("Queue is Empty!")
+
+ else:
+ return self.items[0]
+
+ def __repr__(self):
+ return repr(self.items)
+```
+
+```python
+if __name__ == "__main__":
+ queue = Queue()
+ print("큐가 비었습니까? {}".format(queue.isEmpty()))
+ print("큐에 값을 추가합니다.")
+ for i in range(10):
+ queue.enqueue(i)
+ print("Queue : {}".format(queue))
+ print("큐의 크기 : {}".format(queue.size()))
+ print("peek : {}".format(queue.peek()))
+ print("dequeue : {}".format(queue.dequeue()))
+ print("peek : {}".format(queue.peek()))
+ print("Queue : {}".format(queue))
+```
+
+ 큐가 비었습니까? True
+ 큐에 값을 추가합니다.
+ Queue : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ 큐의 크기 : 10
+ peek : 0
+ dequeue : 0
+ peek : 1
+ Queue : [1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+
+#### 노드를 이용한 큐(Queue) 구현
++ 노드를 이용해서 SingleLinkedList로 구현합니다.
+
+
+```python
+# Node를 이용해 큐 구현
+
+class Node(object):
+ def __init__(self, value = None, pointer = None):
+ self.value = value
+ self.pointer = pointer
+
+class LinkedQueue(object):
+ def __init__(self):
+ self.head = None # 큐의 맨 앞
+ self.tail = None # 큐의 맨 뒤
+ self.count = 0
+
+ def isEmpty(self):
+ return not bool(self.head)
+
+ def dequeue(self):
+ if self.isEmpty():
+ print("Queue is Empty!")
+
+ else:
+ node = self.head
+ self.head = self.head.pointer
+ self.count -= 1
+
+ if self.head is None: # 데이터를 삭제함으로써 큐가 빌 경우
+ # head와 tail은 같은 노드를 바라보고 있었으므로
+ self.tail = None # tail값도 비워주기
+
+ return node.value
+
+ def enqueue(self, value):
+ node = Node(value)
+ if not self.head: # head가 비어있다면
+ self.head = node
+ self.tail = node
+ else:
+ self.tail.pointer = node # 현재 tail의 포인터를 node와 연결
+ self.tail = node # 연결된 node를 tail로 지정
+ self.count += 1
+
+ def size(self):
+ return self.count
+
+ def peek(self):
+ if self.head:
+ return self.head.value
+ else:
+ print("Queue is Empty!")
+
+ def printQueue(self):
+ node = self.head
+ while node:
+ print(node.value, end = " ")
+ node = node.pointer
+ print()
+```
+
+```python
+if __name__ == "__main__":
+ queue = LinkedQueue()
+ print("스택이 비었습니까? {0}".format(queue.isEmpty()))
+ print("스택에 값을 추가합니다.")
+
+ for i in range(10):
+ queue.enqueue(i)
+ queue.printQueue()
+ print("큐의 크기는? {0}".format(queue.size()))
+ print("peek : {}".format(queue.peek()))
+ print("pop : {}".format(queue.dequeue()))
+ print("peek : {}".format(queue.peek()))
+ queue.printQueue()
+
+# for i in range(9):
+# queue.dequeue()
+# print(queue.tail)
+
+```
+
+ 스택이 비었습니까? True
+ 스택에 값을 추가합니다.
+ 0 1 2 3 4 5 6 7 8 9
+ 큐의 크기는? 10
+ peek : 0
+ pop : 0
+ peek : 1
+ 1 2 3 4 5 6 7 8 9
+
+
+LinkedQueue의 head는 큐의 맨 앞, tail은 맨 뒤를 의미합니다.
+
+
+
+Enqueue(데이터 추가)할 때는 데이터 값을 노드 형식(value, pointer)으로 변수 node에 대입한 후
+head가 비어있다면 > 큐에서 유일한 값이 되므로 head와 tail이 모두 추가된 node를 가리키게 됩니다.
+
+
+
+head가 비어있지 않을땐 > 들어오는 값을 큐에 우선 연결해준 후, tail의 위치를 마지막으로 변경해주면 됩니다.
+tail의 다음값으로 지정하기 위해 우선 기존의 tail.pointer에 변수 node를 넣어주고, 추가된 노드를 tail로 지정해줍니다.
+
+
+
+Dequeue(데이터 삭제)할 때는 큐의 맨 앞, head를 반환해주기 위해 임시 node변수에 대입합니다.
+그 후, head에 head.pointer(즉, 기존 head에서 가리키는 다음 노드)를 넣어줍니다.
+
+
+
+마지막으로 임시 node에 저장된 기존 head값을 return해주기 전에\!
+큐의 유일한 노드가 삭제 될 경우는 head와 tail이 그 노드를 동시에 바라보고 있었기 때문에
+tail도 None으로 초기화 해주어야 합니다.
+
+### 덱(Deque)
+
+
+
++ 덱(Double Ended Queue)은 큐와 다르게 양쪽 끝에서 항목을 조회, 삽입, 삭제가 가능합니다.
+(스택과 큐의 융합)
++ 위에서 구현했던 큐 리스트를 그대로 상속해서 덱을 구현해보겠습니다.
+
+
+```python
+# 리스트를 활용한 덱 구현
+class Deque(Queue): # 큐 리스트를 상속
+ # enqueue 반대로 하기
+ def enqueue_front(self, item):
+ self.items.insert(0, item) # 리스트 0번째에 값 추가
+
+ # dequeue 반대로 하기
+ def dequeue_back(self):
+ if self.isEmpty():
+ print("Queue is Empty!")
+ else:
+ value = self.items.pop() # 리스트 가장 뒤에 있는 값을 삭제, 반환
+ return value
+```
+
+```python
+if __name__ == "__main__":
+ deque = Deque()
+ print("덱이 비었습니까? {}".format(deque.isEmpty()))
+ print("덱에 값을 추가합니다.")
+ for i in range(1,20,2):
+ deque.enqueue(i)
+ print("덱 : {}".format(deque))
+ print("peek : {0}".format(deque.peek()))
+ print("dequeue : {0}".format(deque.dequeue()))
+ print("덱 : {0}".format(deque))
+ deque.enqueue_front(50)
+ print("덱 : {0}".format(deque))
+ print("dequeue_back : {}".format(deque.dequeue_back()))
+ print("덱 : {0}".format(deque))
+```
+
+ 덱이 비었습니까? True
+ 덱에 값을 추가합니다.
+ 덱 : [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
+ peek : 1
+ dequeue : 1
+ 덱 : [3, 5, 7, 9, 11, 13, 15, 17, 19]
+ 덱 : [50, 3, 5, 7, 9, 11, 13, 15, 17, 19]
+ dequeue_back : 19
+ 덱 : [50, 3, 5, 7, 9, 11, 13, 15, 17]
+
+
+#### 덱 모듈 사용하기
++ Python의 Collections 모듈 안에 Deque라는 클래스가 이미 구현되어 있습니다.
++ Deque 클래스는 이중 연결 리스트(Double Linked List)로 구성되어서 여러 기능을 효율적으로 사용이 가능합니다.
+
+
+```python
+# 덱 모듈 사용하기
+
+from collections import deque
+
+# deque() : 덱 생성
+q = deque(["Apple", "Banana", "Peach"])
+print(q)
+
+# 오른쪽에 값을 추가
+q.append("Strawberry")
+print(q)
+
+# 왼쪽에 값을 추가
+q.appendleft("Mango")
+print(q)
+
+# 왼쪽의 값을 반환
+q.popleft()
+print(q)
+
+# 오른쪽의 값을 반환
+q.pop()
+print(q)
+
+# rotate(n) : n의 길이만큼 양수면 오른쪽, 음수면 왼쪽으로 값들이 이동
+q = deque(['Mango', 'Apple', 'Banana', 'Peach', 'Strawberry'])
+q.rotate(2)
+print(q)
+
+q.rotate(-1)
+print(q)
+
+# collections안의 Deque은 이중 연결 리스트 형식으로 되어져있기 때문에
+# 이러한 기능이 가능합니다.
+```
+
+ deque(['Apple', 'Banana', 'Peach'])
+ deque(['Apple', 'Banana', 'Peach', 'Strawberry'])
+ deque(['Mango', 'Apple', 'Banana', 'Peach', 'Strawberry'])
+ deque(['Apple', 'Banana', 'Peach', 'Strawberry'])
+ deque(['Apple', 'Banana', 'Peach'])
+ deque(['Peach', 'Strawberry', 'Mango', 'Apple', 'Banana'])
+ deque(['Strawberry', 'Mango', 'Apple', 'Banana', 'Peach'])
+
+
diff --git a/_posts/2022-01-07-Stack.md b/_posts/2022-01-07-Stack.md
new file mode 100644
index 000000000000..841c9d5d731f
--- /dev/null
+++ b/_posts/2022-01-07-Stack.md
@@ -0,0 +1,256 @@
+---
+layout: single
+title: "[자료구조/알고리즘] 스택(Stack)"
+categories: 자료구조/알고리즘
+tag: [python, 파이썬, Stack, 스택, 자료구조, 알고리즘]
+toc: true
+toc_sticky: true
+---
+
+
+
+
+
+### 스택(Stack)
+
+
+
+
++ LIFO(후입선출)구조
++ 배열의 끝에서만 데이터를 접근할 수 있는 선형 자료구조입니다.
+데이터의 삽입과 삭제가 한쪽에서만 수행되는 구조입니다.
+
+#### 리스트를 이용한 Stack
+
+
+
++ push : 스택의 맨 위에 항목 삽입
++ pop : 스택의 맨 위 항목을 반환,삭제
++ top/peek :스택 맨 끝의 항목을 조회
++ empty : 스택이 비어있는지 확인
++ size : 스택의 크기를 확인
+
+
+```python
+class Stack(object):
+ # 생성자
+ def __init__(self):
+ self.items = [] # 값을 담아줄 스택 형태의 리스트
+
+ # 스택이 비었는지 확인하는 함수(Empty : True / Not Empty : false)
+ def isEmpty(self):
+ return not self.items
+
+ # pop : 스택의 맨 끝의 요소 반환, 삭제
+ def pop(self):
+ # 스택이 비어있다면
+ if self.isEmpty():
+ print("Stack is Empty!")
+ else:
+ value = self.items.pop() # 리스트의 가장 마지막 요소 반환, 삭제 후 value에 저장
+ return value
+
+ # push : 스택의 맨 끝에 요소 삽입
+ def push(self, value):
+ self.items.append(value)
+
+ # size : 스택의 크기 조회
+ def size(self):
+ return len(self.items)
+
+ # peek / top : 스택의 맨 위의 항목 조회
+ def peek(self):
+ if self.isEmpty():
+ print("Stack is Empty!")
+ else:
+ return self.items[-1] # 리스트의 마지막 값
+
+ def __repr__(self):
+ return repr(self.items)
+```
+
+```python
+if __name__ == "__main__":
+ stack = Stack()
+ print("스택이 비었습니까 ? {}".format(stack.isEmpty()))
+ print("스택에 값을 추가합니다.")
+ for i in range(10):
+ stack.push(i)
+ print("Stack : {}".format(stack))
+ print("스택의 크기 : {}".format(stack.size()))
+ print("peek : {}".format(stack.peek()))
+ print("pop : {}".format(stack.pop()))
+ print("peek : {}".format(stack.peek()))
+ print("Stack : {}".format(stack))
+```
+
+ 스택이 비었습니까 ? True
+ 스택에 값을 추가합니다.
+ Stack : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ 스택의 크기 : 10
+ peek : 9
+ pop : 9
+ peek : 8
+ Stack : [0, 1, 2, 3, 4, 5, 6, 7, 8]
+
+
+ + 객체에 대한 정보를 프린트 구문으로 출력하게 만들어주는 메소드
+ (당연히 print구문으로 객체들을 호출하면 객체의 주소값이 출력됨 -> __repr__, __str__ 메소드 활용)
+
+
+
+ + __repr__ : 객체의 official(공식적인) 정보를 출력
+ -> 시스템이 인식하는 대로, 객체의 모습 그대로를 호출하는 "딱딱한" 호출
+ + __str__ : 객체의 informal(비공식적인) 정보를 출력
+ -> 사용자 입장에서 보기 쉬운, 조금은 "느슨한" 호출
+
+#### 노드를 이용한 Stack 구현
+
+
+
++ 노드의 기본 모양을 먼저 정의합니다.
+
+
+```python
+# 노드의 기본 모양
+class Node(object):
+ def __init__(self, value = None, pointer = None): # value와 pointer 초기화
+ self.value = value
+ self.pointer = pointer
+```
+
++ 정의된 노드를 활용하여 스택을 구현합니다.
+
+
+```python
+# 스택 구현
+class Stack(object):
+ def __init__(self):
+ self.top = None # 초기에 스택은 비어있으므로 top, count 초기화
+ self.count = 0
+
+ def isEmpty(self):
+ return not bool(self.top) # 스택의 Top이 비어있으면 Empty
+
+ def pop(self):
+ # 스택이 비어있다면
+ if self.isEmpty():
+ print("Stack is Empty!")
+ else:
+ node = self.top # 임시 node에 스택의 Top부터 담는다
+ self.top = self.top.pointer # node의 다음 가리키는 곳을 Top으로 지정
+ self.count -= 1 # count 감소
+
+ return node.value # node의 값 반환(기존의 top의 값)
+
+ def push(self, item):
+ self.top = Node(item, self.top) # 새로운 값과 기존의 Top을 포인터로 Node형식(값, 포인터)
+ self.count += 1 # count 증가
+
+ def size(self):
+ return self.count
+
+ def peek(self):
+ if self.isEmpty():
+ print("Stack is Empty!")
+ else:
+ return self.top.value
+
+ def printStack(self):
+ node = self.top
+ while node:
+ print(node.value, end=" ")
+ node = node.pointer
+ print()
+```
+```python
+if __name__ == "__main__":
+ stack = Stack()
+ print("스택이 비었습니까? {}".format(stack.isEmpty()))
+ print("스택에 값을 추가합니다.")
+ for i in range(10):
+ stack.push(i)
+ stack.printStack()
+ print("스택의 크기 : {}".format(stack.size()))
+ print("peek : {}".format(stack.peek()))
+ print("pop {}".format(stack.pop()))
+ print("peek : {}".format(stack.peek()))
+ stack.printStack()
+```
+
+ 스택이 비었습니까? True
+ 스택에 값을 추가합니다.
+ 9 8 7 6 5 4 3 2 1 0
+ 스택의 크기 : 10
+ peek : 9
+ pop 9
+ peek : 8
+ 8 7 6 5 4 3 2 1 0
+
diff --git "a/_posts/2022-01-13-1.\354\204\240\355\230\225\355\232\214\352\267\200\354\231\200 \352\262\275\354\202\254\355\225\230\352\260\225\353\262\225.md" "b/_posts/2022-01-13-1.\354\204\240\355\230\225\355\232\214\352\267\200\354\231\200 \352\262\275\354\202\254\355\225\230\352\260\225\353\262\225.md"
new file mode 100644
index 000000000000..8d385654e41b
--- /dev/null
+++ "b/_posts/2022-01-13-1.\354\204\240\355\230\225\355\232\214\352\267\200\354\231\200 \352\262\275\354\202\254\355\225\230\352\260\225\353\262\225.md"
@@ -0,0 +1,647 @@
+---
+layout: single
+title: "선형 회귀와 경사 하강법 정리"
+categories: 딥러닝
+tag: [python, Numpy, 파이썬, 머신러닝, 딥러닝, 기초통계, 선형회귀, 경사하강법]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+저는 이 책을 참고하여 개념을 정리했습니다.
+
+
+
+
+
+
+
+![image](/assets/images/모두의딥러닝.png)
+
+
+### 선형 회귀와 로지스틱 회귀
+
+
+
+ 선형 회귀는 (x, y) 점들의 특징을 가장 잘 나타내는 선을 그리는 과정입니다.
+
+
+
+- 독립변수 x 하나의 값만으로 y값을 설명할 수 있다면 단순 선형 회귀
+
+
+
+
+
+
+
+- 여러개의 x값이 필요할 땐 다중 선형 회귀
+
+
+#### 최소 제곱법
+
+ 최소 제곱법은 주어진 x의 값이 하나일 때 적용이 가능합니다. (단순 선형 회귀일 때)
+
+ 여러개의 x가 주어지는 경우(다중 선형 회귀) 경사하강법을 적용합니다.
+
+
+
+
+
+![Alt text](/assets/images/공식_최소제곱법.png)
+
+
+
+
+
+
+
+##### 최소제곱법을 이용하여 a, b 구하기
+
+ 구하려는 직선이 y = ax + b라고 가정한다면,
+
+
+
+ a = (x - x평균) * (y - y평균)의 합 / (x - x평균)^2의 합
+
+
+
+ b = y - ax이므로
+
+ = (y의 평균) - (a * x의 평균)
+
+
+
+```python
+import numpy as np
+
+x = [2, 4, 6, 8]
+y = [81, 93, 91, 97]
+
+mx = np.mean(x) # x의 평균
+my = np.mean(y) # y의 평균
+
+# 기울기 공식의 분모
+divisor = sum([(i - mx)**2 for i in x])
+
+# 기울기 공식의 분자
+def top(x, y, mx, my):
+ d = 0
+
+ for i in range(len(x)):
+ d += (x[i] - mx) * (y[i] - my)
+
+ return d
+divided = top(x, y, mx, my)
+
+a = divided / divisor
+b = my - mx * a
+
+print(f"기울기 : {a}")
+print(f"y절편 : {b}")
+```
+
+
+기울기 : 2.3
+y절편 : 79.0
+
+ 하지만, 모든 딥러닝 프로젝트는 여러개의 입력변수를 다룹니다.
+
+
+
+ 따라서 최소제곱법이 아닌 다른 방법이 필요한데, 가장 많이 사용하는 방법은
+
+ '일단 그리고 조금씩 수정해 나가기' 방식입니다.
+
+
+
+ 즉, 나중에 그린선이 먼저 그린 선보다 더 좋은지 나쁜지를 판단해야 하는데,
+
+ 각 선의 오차를 계산하여 오차가 작은 쪽으로 바꾸는 알고리즘이 필요합니다.
+
+
+#### 평균 제곱 오차(MSE)
+
+ 여러개의 x에 대해 오차가 존재하므로 모든 x에 대한 평균 오차를 평균 제곱 오차라고 합니다.
+
+
+
+
+
+
+
+![Alt text](/assets/images/공식_MSE.png)
+
+
+
+
+
+
+
+ 따라서, 선형 회귀란 임의의 직선을 그어 이에 대한 평균 제곱 오차(MSE)를 구하고,
+
+ 이 값을 가장 작게 만들어 주는 a와 b 값을 찾아가는 작업입니다.
+
+
+
+```python
+# 위의 y = ax + b 활용
+
+fake_a_b = [a, b]
+
+# 위에서 구한 직선으로 y값 예측
+def predict(x):
+ return fake_a_b[0] * x + fake_a_b[1]
+
+# MSE 함수
+def mse(y, y_hat): # y_hat: y의 평균
+ return ((y - y_hat)**2).mean()
+
+# MSE 함수를 각 y값에 대입하여 최종 값을 구하는 함수
+def mse_val(y, predict_result):
+
+ # 리스트의 각 원소끼리 -연산을 하기 위해 np.array형태
+ return mse(np.array(y), np.array(predict_result))
+
+# 예측값이 들어갈 리스트
+predict_result = []
+
+# 예측값 구하기
+for i in range(len(x)):
+ predict_result.append(predict(x[i]))
+ print(f"x값 : {x[i]}, 실제 y값 : {y[i]}, 예측 y값 : {predict_result[i]}")
+
+# 최종 MSE 출력
+print(f"MSE : {mse_val(predict_result, y)}")
+```
+
+
+#### 오차 수정하기
+
+ 기울기 a를 너무 크게 잡거나 너무 작게 잡으면 오차가 커집니다.
+
+ 이러한 기울기 a와 오차의 관계는 이차 함수 그래프로 표현할 수 있습니다.
+
+
+
+
+
+
+
+![Alt text](/assets/images/경사하강법.png)
+
+
+
+
+
+
+
+ 오차가 가장 작을 때는 아래쪽의 볼록한 부분 m일때 입니다.
+
+
+
+ 컴퓨터를 이용해 m의 값을 구하려면 임의의 한점(a1)을 찍고,
+
+ 이점을 m에 가까운 쪽으로 점점 이동(a1 -> a2)시키는 과정이 필요합니다.
+
+
+
+ 이러한 방법을 미분 기울기를 이용하는 경사 하강법이라고 합니다.
+
+
+
+##### 경사 하강법
+
+ 최솟값 m에서의 순간 기울기는 0입니다.
+
+ 즉, 경사 하강법에서는 미분값이 0인 지점을 찾는 것이 됩니다.
+
+
+
++ 경사 하강법의 과정
+
+ 1. a1에서 미분을 구합니다.
+
+ 2. 구해진 기울기의 반대 방향(기울기가 +면 음의 방향, -면 양의 방향)으로
+
+ 이동시킨 a2에서 미분을 구합니다.
+
+ 3. 구한 미분 값이 0이 될때까지 반복합니다.
+
+
+
+
+
+
+
+![Alt text](/assets/images/경사하강법_과정.png)
+
+
+
+##### 학습률
+
+ 기울기의 부호를 바꿔 이동시킬 때 적절한 거리를 찾지 못해 너무 멀리 이동시키면
+
+ a 값이 한점으로 모이지 않고 위로 치솟아 버립니다.
+
+
+
+ 따라서 어느 만큼 이동시킬지를 신중히 결정해야 하는데, 이때 이동 거리를 정해주는 것이 바로 학습률입니다.
+
+
+
+ 딥러닝에서 학습률의 값을 적절히 바꾸면서 최적의 학습률을 찾는 것은 중요한 최적화 과정 중 하나입니다.
+
+
+
+
+
+
+
++ 따라서, 경사하강법은 오차의 변화에 따라 이차 함수 그래프를 만들고 적절한 학습률을 설정해
+
+미분 값이 0인 지점을 구하는 것입니다.
+
+
+
+
+
+
+
++ y절편 b값(편향)도 이와 같은 성질을 가지고 있기 때문에 최적의 b값을 구할 때 역시 경사하강법을 사용합니다.
+
+
+##### 경사 하강법 실습
+
+
+
+```python
+import pandas as pd
+import matplotlib.pyplot as plt
+
+# 그래프로 나타내기
+plt.figure(figsize=(8, 5))
+plt.scatter(x, y)
+plt.show()
+
+x_data = np.array(x)
+y_data = np.array(y)
+
+# 기울기 a와 절편 b의 값 초기화
+a, b = 0, 0
+
+lr = 0.03 # 적절한 학습률 정하기
+epochs = 2001 # 몇 번 반복할지 설정
+
+# 경사 하강법 시작
+for i in range(epochs):
+ y_pred = a * x_data + b # y예측값 구하기
+ error = y_data - y_pred
+
+ # 오차 함수를 a로 미분한 값
+ a_diff = -(2 / len(x_data)) * sum(x_data * error)
+
+ # 오차 함수를 b로 미분한 값
+ b_diff = -(2 / len(x_data)) * sum(error)
+
+ a = a - lr * a_diff
+ b = b - lr * b_diff
+
+ if i % 100 == 0: # 100번째 반복때마다 출력
+ print(f"epochs = {i}, 기울기 = {a}, 절편 = {b}")
+
+# 그래프 다시 그리기
+y_pred = a * x_data + b
+plt.scatter(x, y)
+plt.plot([min(x_data), max(x_data)], [min(y_pred), max(y_pred)])
+plt.show()
+```
+
+
+
+
++ 퍼셉트론 하나로 해결되지 않던 문제를 은닉층을 만들어 해결했습니다.
+
++ 은닉층을 여러개 쌓아올려 복잡한 문제를 해결하는 과정을 '신경망'이라고 부릅니다.
+
+
+#### 오차 역전파
+
++ 다층 퍼셉트론에서 결과값을 얻으면 오차를 구해 이를 토대로 앞선 가중치를 차례로 거슬러 올라가며 조정하는 작업
+
+
+
+
+
+
+
+#### 오차 역전파 과정
+
+![image](/assets/images/오차역전파1.png)
+
++ 1. 결과 값과 실제 값을 비교하여 오차를 구합니다.
+
++ 2. 경사 하강법을 이용해 바로 앞 가중치를 오차가 작아지는 방향으로 업데이트 합니다.
+
++ 3. 위 과정을 더이상 오차가 줄어들지 않을 때까지 반복합니다.
+
+
+
+
+
+
+
+'오차가 작아지는 방향으로 업데이트한다'는 의미는 미분 값이 0에 가까워지는 방향으로 나아간다는 말입니다.
+
+가중치 수정 작업은 현 가중치에서 가중치에 대한 기울기를 뺀 값(즉, 미분 값)을 빼서 새 가중치로 조정합니다.
+
+
+
+![image](/assets/images/오차역전파2.png)
+
+
+
+
+
+
+
+오차 역전파 과정에서 '체인룰'을 활용하여 미분 값을 얻어낼 수 있습니다.
+
+
+
+![image](/assets/images/체인룰.png)
+
+
+
+
+
+
+
+
+
+
+
+#### 기울기 소실 문제
+
+
+
+
+
+
+
+은닉층이 늘어나면서 역전파를 통해 전달되는 기울기의 값이 점점 작아져
+
+맨 처음 층까지 전달되지 않는 문제입니다.
+
+이는 활성화 함수로 사용된 시그모이드 함수의 특성이 원인입니다.
+
+
+
+
+
+
+
+![image](/assets/images/시그모이드미분.png)
+
+
+
+위 그림과 같이 시그모이드를 미분하면 최대값이 약 0.3이 됩니다.
+
+1보다 작으므로 계속 곱하다 보면 0에 가까워지게 됩니다.
+
+따라서, 여러 층을 거칠수록 기울기가 사라져 가중치를 수정하기가 어려워집니다.
+
+이를 해결하고자 여러 활성화 함수로 대체합니다.
+
+
+#### 고급 경사 하강법
+
+
+
+가중치를 업데이트하는 방법으로 경사 하강법이 존재합니다.
+
+그런데 경사 하강법은 정확하게 가중치를 찾아가지만, 한 번 업데이트할 때마다 전체 데이터를
+
+미분해야 하므로 계산량이 많아 속도가 느리고 최적해를 찾기 전에 멈출수 있다는 단점이 있습니다.
+
+이러한 점을 보완하기 위해 고급 경사 하강법이 등장합니다.
+
+
+
+
+
+
+
+##### 확률적 경사 하강법(SGD)
+
+확률적 경사 하강법은 전체 데이터를 사용하는 것이 아니라, 랜덤하게 추출한 일부 데이터를 사용합니다.
+
+그러므로 더 빨리, 더 자주 업데이트를 하는 것이 가능합니다.
+
+
+
+![image](/assets/images/확률적_경사_하강법.png)
+
+
+
+그림을 참고한다면, 랜덤한 일부 데이터를 사용하는 만큼 확률적 경사 하강법은
+
+중간 결과의 진폭이 크고 불안정해 보일 수 있습니다.
+
+하지만 속도가 확연히 빠르면서도 최적 해에 근사한 값을 찾아낼 수 있어 경사 하강법의 대안으로 사용되고 있습니다.
+
+
+
+
+
+
+
+##### 모멘텀(momentum)
+
+momentum이란 '관성, 탄력, 가속도'라는 뜻입니다. 모멘텀 SGD란 말 그대로 경사 하강법에 탄력을 더한 것입니다.
+
+경사 하강법과 마찬가지로 매번 기울기를 구하지만, 이를 통해 오차를 수정하기 전 바로 앞 수정값과
+
+방향(+ / -)을 참고하여 같은 방향으로 일정한 비율만 수정되게 하는 방법입니다.
+
+따라서 지그재그로 일어나느 현상이 줄어들고, 이전 이동 값을 고려해 일정 비율만큼만 다시 값을 결정하므로
+
+관성 효과를 낼 수 있습니다.
+
+
+
+![image](/assets/images/모멘텀.png)
+
+
+
+
+
+
+
+##### 고급 경사 하강법 활용법
+
+
+
+![image](/assets/images/활성화함수_테이블.png)
+
+
+
+아담(Adam)은 현재 가장 많이 사용되는 고급 경사 하강법입니다.
+
diff --git "a/_posts/2022-01-25-CNN(Convolution\354\270\265 + Pooling\354\270\265).md" "b/_posts/2022-01-25-CNN(Convolution\354\270\265 + Pooling\354\270\265).md"
new file mode 100644
index 000000000000..6ef7bc508bc5
--- /dev/null
+++ "b/_posts/2022-01-25-CNN(Convolution\354\270\265 + Pooling\354\270\265).md"
@@ -0,0 +1,420 @@
+---
+layout: single
+title: "CNN 정리(컨볼루션 층, 풀링 층)"
+categories: 딥러닝
+tag: [python, keras, CNN, 컨볼루션, 풀링, Convolution, Pooling, 인공지능, 딥러닝, 머신러닝]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+#### 합성곱 신경망
+
+합성곱 신경망(Convolutional Neural Network)은 이미지 처리에 탁월한 성능을 보이는 신경망입니다.
+
+합성곱 신경망은 크게 합성곱층(Convolution layer)과 풀링층(Pooling layer)으로 구성됩니다.
+
+
+
+
+
+
+
+이미지 처리를 하기 위해 앞서 배운 다층 퍼셉트론을 사용할 수는 있지만 한계가 있습니다.
+
+다층 퍼셉트론을 사용한다면 이미지를 1차원 벡터로 변환하고 입력층으로 사용해야 합니다.
+
+하지만, 몇가지 픽셀값만 달라져도 예측에 적지 않은 영향을 받게 되고,
+
+1차원 벡터로 변환하면서 공간적인 구조 정보가 유실되므로 좀 더 정확한 예측을 위해 합성곱 신경망을 사용합니다.
+
+
+
+
+
+
+
+##### 채널
+
+이미지는 (높이, 너비, 채널)이라는 3차원 텐서입니다.
+
+높이는 이미지의 세로 방향 픽셀 수, 너비는 이미지의 가로 방향 픽셀 수, 채널은 색 성분을 의미합니다.
+
+여기서 흑백 이미지는 채널 수가 1이고,
+
+컬러 이미지는 적색(Red), 녹색(Green), 청색(Blue) 세가지 색깔의 조합으로 이루어지므로 채널수가 3입니다.
+
+
+
+
+
+
+
+##### 필터(=커널 =가중치)
+
+합성곱층은 합성곱 연산을 통해 이미지의 특징을 추출하는 역할을 합니다.
+
+이때, 필터(커널)라는 N x M 크기의 행렬로 이미지를 처음부터 끝까지(가장 왼쪽 위부터 가장 오른쪽 아래까지)
+
+순차적으로 훑으면서 필터와 겹쳐지는 부분의 각 이미지와 필터의 원소(가중치) 값을 곱해서 모두 더한 값을 출력합니다.
+
+
+
+
+
+
+
+
+
+아래의 그림은 채널이 1인(흑백 이미지) 2차원 합성곱일 경우 입력층에 필터를 지나쳐 출력이 되는 예시입니다.
+
+4x4 크기의 입력층과 2x2 크기의 필터를 합성곱 연산할 경우 3x3형태의 출력이 나옵니다.
+
+물론 필터에는 각 가중치가 존재하면서 편향도 존재합니다.
+
+예를 들어, 편향이 +1이라면 아래의 그림에 나오는 출력의 각 원소들은 +1이되어 출력이 됩니다.
+
+이때, 만들어지는 출력을 특성맵(feature map)이라고 합니다.
+
+입력층이 필터와 합성곱 연산이 되고 특성맵으로 출력이 될때, 활성화 함수가 사용되는 보통 relu함수를 사용합니다.
+
+
+
+![Image](/assets/images/합성곱신경망_커널.png)
+
+
+
+
+
+
+
+##### 여러개의 필터(커널)
+
+Dense층을 여러개를 사용하는 것처럼 여러개의 필터를 사용할 수 있습니다.
+
+당연히 필터가 여러개면 필터의 가중치는 서로 다릅니다.
+
+아래의 그림처럼 4x4크기의 입력에 3개의 필터와 합성곱 연산 결과 3개의 출력 즉, 3x3x3크기의 특성맵이 됩니다.
+
+그림에서는 필터의 크기가 3x3이었지만, 커널의 크기를 사용자가 정할 수 있습니다.
+
+다만, 그림에선 커널의 크기가 2x2이지만, 커널의 크기가 크면 특징을 감지하는데 효과가 떨어진다고 하여 보통 3x3 또는 5x5를 사용합니다.
+
+
+
+
+
+
+
++ 커널의 깊이(채널) = 입력 데이터의 깊이(채널)
+
++ 합성곱 연산 결과 : 특성 맵은 입력 데이터의 깊이와 상관없이 (높이, 너비)의 특성 맵을 얻습니다.
+
+(특성 맵의 채널은 1)
+
++ 다만, 합성곱 연산에서 다수의 커널을 사용할 경우 : 특성 맵은 (높이, 너비, 커널의 수) 크기가 됩니다.
+
+(특성 맵의 채널은 합성곱 연산에 사용된 커널의 수)
+
+
+
+![Image](/assets/images/합성곱신경망_여러개의필터.png)
+
+
+
+
+
+
+
+##### 스트라이드(stride)
+
+그림에서는 커널이 입력층 위에 한 칸씩 이동(슬라이딩)하면서 합성곱 연산을 수행합니다.
+
+하지만, 커널의 슬라이딩 범위 또한 사용자가 정할 수 있습니다.
+
+이러한 이동 범위를 스트라이드(stride)라고 합니다.
+
+스트라이드가 2일 경우에 4x4 이미지에 2x2의 필터가 두 칸씩 이동하면서 합성곱 연산을 수행하게 됩니다.
+
+그렇다면, 최종적으로 2x2x3 크기의 특성 맵을 얻게 됩니다.
+
+
+
+
+
+
+
+##### 케라스의 합성곱 층
+
+```python
+
+from tensorflow import keras
+
+keras.layers.Conv2D(10, kernel_size=(3, 3), activation='relu')
+
+```
+
+
+
++ 첫번재 인자 10은 필터의 개수를 뜻합니다.
+
++ kernel_size는 커널(필터)의 크기를 지정하는 인자입니다.
+
++ 역시 activation으로 활성화 함수를 지정합니다.
+
+
+
+
+
+
+
+##### 패딩(padding)
+
++ 패딩의 목적
+
+위 그림에서 4x4 이미지에 2x2 필터로 합성곱 연산을 했을 때, 스트라이드가 1일 경우엔 3x3의 특성 맵을 얻었습니다.
+
+이처럼 합성곱 연산의 결과로 얻은 특성 맵은 입력보다 크기가 작아진다는 특성이 있습니다.
+
+그렇다면 합성곱 층을 여러개 쌓은다면 최종적으로 얻는 특성 맵의 크기는 처음 입력보다 매우 작아집니다.
+
+여러개의 합성곱 연산 이후에도 특성 맵의 크기를 동일하게 유지되도록 하는 작업을 패딩(padding)이라고 합니다.
+
+
+
+
+
+
+
+패딩은 입력 이미지의 가장자리에 지정된 개수의 폭만큼 가상의 픽셀로 테두리를 추가합니다.
+
+주로 값을 0으로 채우는 제로 패딩(zero padding)을 사용합니다.
+
+그렇다면 필터의 슬라이딩 범위가 늘어나게 되고 최종적으로 얻는 특성 맵의 크기는 패딩하기 전보다 커지게 됩니다.
+
+아래는 4x4 크기의 이미지를 1폭 만큼 제로 패딩을 사용했을 때 모습입니다.
+
+![Image](/assets/images/제로패딩.png)
+
+
+
+
+
+
+
+##### 케라스의 패딩과 스트라이드 설정
+
+```python
+
+from tensorflow import keras
+
+keras.layers.Conv2D(10, kernel_size=(3, 3), activation='relu', padding='same', strides=1)
+
+```
+
+
+
++ padding='same' : (same 패딩) 입력값과 특성맵 크기를 동일하게 해주는 패딩입니다.
+
+커널을 사용하여 합성곱 연산을 했을 때, 특성맵의 사이즈가 얼마나 될지 쉽게 알 수 있습니다.
+
++ padding='valid' : (valid 패딩) 패딩을 사용하지 않는 옵션입니다.
+
++ stride는 특수한 상황이 아닌 이상, 보통 1로 설정합니다.
+
+
+##### 풀링
+
+일반적으로 합성곱 층(합성곱 연산 + 활성화 함수) 다음에는 풀링 층을 추가합니다.
+
+합성곱 층(컨볼루션 층)을 통해 나온 특성 맵이 크고 복잡하다면 이를 축소(다운샘플링)해야 합니다.
+
+이 과정을 풀링 연산(서브샘플링)이라 하며, 이러한 연산을 하는 층을 풀링 층이라고 합니다.
+
+
+
+
+
+
+
+일반적으로 최대 풀링(max pooling)과 평균 풀링(average pooling)이 사용됩니다.
+
+최대 풀링은 정해진 구역 안에서 최댓값을 뽑아내는 방법이고,
+
+평균 풀링은 평균값을 뽑아내는 방법입니다.
+
+
+
+
+
+
+
+아래의 그림은 4x4크기의 특성 맵을 스트라이드가 2일때, 2x2 커널로 맥스 풀링하는 모습입니다.
+
+![Image](/assets/images/맥스풀링.png)
+
+
+
+
+
+
+
+위의 그림에서 특성 맵을 맥스풀링하게 된다면 2x2의 크기, 절반으로 특성 맵이 작아지는 걸 확인할 수 있습니다.
+
+만약 채널이 추가된다면 즉, 컨볼루션 층이 3개가 사용되어 특성 맵이 4x4x3 크기였다면 맥스 풀링 결과는 2x2x3이 됩니다.
+
+차원이 여러개 있는 특성 맵에서 풀링은 각 차원마다 수행되므로 채널 차원은 변하지 않습니다.
+
+
+
+
+
+
+
++ 풀링과 합성곱의 차이
+
+풀링도 합성곱 연산과 유사하게 커널을 슬라이딩시켜 특성 맵을 얻으므로 유사하다고 느낄 수 있지만,
+
+풀링은 합성곱 연산과 달리 곱하기나(가중치) 더하는(편향) 연산이 없는 걸 확인할 수 있습니다.
+
+또한, 풀링 과정에서 커널이 슬라이딩할 때 서로 겹치지 않습니다.
+
+즉, 위의 사진에서 커널이 2x2라면 스트라이드는 2로 설정되고 겹치지 않게 이동합니다.
+
+커널이 3x3이면 스트라이드는 3, 커널이 4x4이면 스트라이드는 4가 됩니다.
+
+하지만, 통상적으로 풀링은 2x2 커널을 사용합니다.
+
+
+
+
+
+
+
+##### 케라스의 풀링 층
+
+```python
+
+keras.layers.MaxPooling2D(2, strides=2, padding='valid')
+
+```
+
++ 첫번째 인자 2는 2x2의 커널로 풀링하겠다는 뜻입니다.
+
++ strides는 따로 지정하지 않아도 자동으로 풀링의 크기에 맞춰서 셋팅되기 때문에 굳이 지정하지 않아도 됩니다.
+
++ 풀링은 패딩을 하지않고(valid패딩), 입력 크기를 줄이는게 목적이기 때문에 굳이 지정하지 않아도 됩니다.
+
+
+
+
+
+
+
+##### 컨볼루션 층 + 풀링 층 사용
+
+앞서 확인한 내용들을 바탕으로 컨볼루션 층과 풀링 층은 쌍으로 보통 사용합니다.
+
+(컨볼루션 층 + 풀링 층) 또는 (컨볼루션 층 + 컨볼루션 층 + 풀링 층) 이런 식으로 사용하게 되는데,
+
+2차원 이상의 크기로 출력이 됩니다.
+
+그 후에 밀집층(은닉층+출력층 또는 출력층)을 사용하여 원하는 결과값을 얻기 위해 1차원 배열로 풀어서 펼쳐야 합니다.
+
+따라서 Flatten()함수를 사용하여 1차원 크기로 바꾸어 사용합니다.
+
+
+#### 3차원 합성곱
+
+
+
+보통 컬러 이미지를 입력 데이터로 사용한다면 3차원 배열(높이, 너비, 깊이(채널)) 크기가 됩니다.
+
+이러한 경우엔 커널도 동일하게 3차원으로 만들면 됩니다.
+
+3차원 합성곱에서 커널의 설명은 위에서 설명한 내용과 같습니다.
+
+
+
++ 커널의 깊이(채널) = 입력 데이터의 깊이(채널)
+
++ 합성곱 연산 결과 : 특성 맵은 입력 데이터의 깊이와 상관없이 (높이, 너비)의 특성 맵을 얻습니다.
+
+(특성 맵의 채널은 1)
+
++ 다만, 합성곱 연산에서 다수의 커널을 사용할 경우 : 특성 맵은 (높이, 너비, 커널의 수) 크기가 됩니다.
+
+(특성 맵의 채널은 합성곱 연산에 사용된 커널의 수)
+
diff --git a/_posts/2022-01-25-Fashion_mnist.md b/_posts/2022-01-25-Fashion_mnist.md
new file mode 100644
index 000000000000..4e29023bbe3b
--- /dev/null
+++ b/_posts/2022-01-25-Fashion_mnist.md
@@ -0,0 +1,901 @@
+---
+layout: single
+title: "인공신경망 정리, fashion mnist"
+categories: 딥러닝
+tag: [python, keras, 파이썬, 딥러닝, fashion mnist, 인공신경망, 다중 분류, 예측]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+### Fashion MNIST 실습
+
+
+
+
+
+
+
+케라스의 fashion_mnist 데이터의 카테고리를 인공신경망을 활용해 분류해보려 합니다.
+
+처음으로 scikit-leran의 로지스틱 회귀를 통해 간단하게 분류 정확도를 체크하고,
+
+간단한 인공신경망 구축, 은닉층 추가, 옵티마이저 설정과 과적합을 피하기 위한 방법을 추가하며 결과를 확인해보겠습니다.
+
+
+
+
+
+
+
+Keras의 fashion_mnist데이터
+
+ + 10개의 패션 아이템 클래스를 가지고 있습니다.
+
+ + 28 x 28 픽셀의 흑백 이미지로 이루어져 있습니다.
+
+
+##### keras의 fashion mnist 데이터 가져오기
+
+
+
+```python
+from tensorflow.keras.datasets import fashion_mnist
+
+(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
+
+X_train.shape, y_train.shape
+```
+
+
+((60000, 28, 28), (60000,))
+
+##### 데이터 확인해보기
+
+
+
+```python
+import matplotlib.pyplot as plt
+import numpy as np
+
+# 0 ~ 9번째 X데이터 출력
+fig, axs = plt.subplots(1, 10, figsize=(10, 10))
+
+for i in range(10):
+ axs[i].imshow(X_train[i], cmap='gray_r')
+ axs[i].axis('off')
+plt.show()
+
+# 0 ~ 9번째 Y데이터 출력
+print([y_train[i] for i in range(10)])
+
+# 카테고리 번호를 출력해보기(return_counts : 각 카테고리당 몇개씩 들어있는지 확인)
+print(np.unique(y_train, return_counts=True))
+```
+
+
+
+
++ 로지스틱 회귀를 적용하기 위해 loss 매개변수에 손실 함수로 'log'를 지정합니다.
+
++ max_iter 매개변수에 반복횟수로 5를 지정합니다.
+
++ 반복 실행시 결과가 동일하게 나오기 위해 난수 초기값을 random_state 매개변수로 지정합니다.
+
+
+
+```python
+# scikit_learn의 SGDClassifier 클래스를 활용하여 경사하강법을 이용한 로지스틱 회귀를 사용
+from sklearn.linear_model import SGDClassifier
+from sklearn.model_selection import cross_validate
+
+sc = SGDClassifier(loss='log', max_iter=5, random_state=42)
+
+scores = cross_validate(sc, X_train_scaled, y_train, n_jobs=-1)
+print(np.mean(scores['test_score'])) # 훈련데이터에 있어서 약 82프로의 정확도를 얻음
+```
+
+
+0.8192833333333333
+
+10개의 클래스를 분류해야하는데 손실함수를 'log'로 사용하는 이유
+
++ SGD는 cross_entropy를 지정하는 곳이 따로 없기 때문에 10개의 클래스를 분류하기 위해 10개의
+
++ 예를 들어, 부츠를 양성, 나머지 9개를 음성으로 분류하여 1개의 모델을 훈련
+
++ 티셔츠를 양성, 나머지 9개를 음성으로 분류하여 1개의 모델을 훈련 -> 이런식으로 10개의 모델을 훈련
+
++ 10개의 계산값이 나오면 softmax함수(이진 분류일땐 sigmoid함수)를 사용하여 확률로 바꿔줍니다.
+
++ 이런식으로 이진분류를 다중분류처럼 사용하는 방법을 OVR(One verses Rest)라고 합니다.
+
+
+#### 인공 신경망으로 구현
+
++ 로지스틱 회귀 경우 : 픽셀1 x w1 + 픽셀2 x w2 + ... + 픽셀784 x w784 + b => 10개의 모델
+
++ 이를 인공 신경망으로 구현해봅니다.
+
+
+
+```python
+# 검증 데이터 0.2 비율로 분리
+from sklearn.model_selection import train_test_split
+X_train_scaled, X_val_scaled, y_train, y_val = train_test_split(
+ X_train_scaled, y_train, test_size=0.2, random_state=42)
+
+X_train_scaled.shape, y_train.shape, X_val_scaled.shape, y_val.shape
+```
+
+
+##### 모델 정의
+
++ Dense 레이어를 사용하여 은닉층과 출력층을 생성합니다.
+
++ 은닉층의 활성화 함수에는 자주 쓰이는 'relu'를 사용합니다.
+
++ 출력층의 활성화 함수에는 다중분류이므로 'softmax'(이진분류일때는 'sigmoid')를 사용합니다.
+
+
+
+##### 모델 컴파일
+
++ 손실 함수
+
+ + 이진 분류 : binary_crossentropy
+
+ + 다중 분류 : categorical_crossentropy
+
++ sparse_categorical_crossentropy란?
+
+ + y데이터의 값은 0 ~ 9 까지의 정수인것을 확인했습니다.
+
+ 이 정수값을 그대로 사용할 순 없고, 출력층에는 10개의 유닛에서 softmax함수값을 거쳐 10개의 확률값이 나옵니다.
+
+ + crossentropy의 공식에 따라 10개의 확률값에 각각 로그를 취하고 타깃값과 곱하게 됩니다.
+
+ (샘플이 티셔츠일 확률 : a1 => -log(a1) x target값, -log(a2) x target값, ...)
+
+ + 여기서, 티셔츠는 첫번째 원소가 1이고 나머지 0(\[1, 0, 0, ... , 0\])인 원 핫 인코딩이 되어있어야지만
+
+ 첫번째 unit을 제외한 나머지 unit에서의 출력값이 모두 0이 곱해져 상쇄되어 티셔츠에 해당되는 뉴런의 출력값만 손실에 반영됩니다.
+
+ + 하지만 원 핫 인코딩을 사용하지 않고, Y데이터의 정수값 그대로를 사용하려면 sparse_categorical_crossentropy를 사용합니다.
+
+
+
+
+
+```python
+from tensorflow.keras.models import Sequential
+from tensorflow.keras.layers import Dense
+
+model = Sequential()
+
+# 다중분류이므로 softmax 사용
+model.add(Dense(10, activation='softmax', input_shape=(784, )))
+
+model.compile(loss='sparse_categorical_crossentropy',
+ optimizer='adam',
+ metrics=['acc'])
+```
+
+
+```python
+# 모델 학습
+history = model.fit(X_train_scaled, y_train, epochs=15, batch_size=100,
+ validation_data=(X_val_scaled, y_val))
+```
+
+
+#### 옵티마이저
+
++ 학습률 : 경사하강법을 비유하자면, 산을 내려가면서 최적값을 찾아갈때 이동하는 거리.
+
+학습률을 너무 높게 잡는다면 최적값을 지나칠 수도 있기 때문에 적절한 학습률 조정이 필요합니다.
+
+
+
+기본 경사 하강법 옵티마이저
+
++ SGD
+
+ + 기본 학습률은 0.01입니다.
+
+ model.compile(optimizer='sgd')
+
+ + 학습률 조정도 가능합니다. (0.1로 변경)
+
+ sgd = tensorflow.keras.optimizers.SGD(learning_rate=0.1)
+
++ 모멘텀
+
+ + SGD에서 momentum > 0
+
+ sgd = tensorflow.keras.optimizers.SGD(momentum=0.9)
+
++ 네스테로프 모멘텀
+
+ + SGD의 설정에서 nesterov = True를 주어 사용합니다.
+
+
+
+
+
+
+
+경사하강법에서 학습률에 따라 최적값을 찾아갈때, 최적값과 멀리 있을 땐 높은 이동 거리로 빠르게 접근하고,
+
+최적값과 가까워질 땐 좁은 거리로 이동하며 최대한 최적값에 수렴해가는게 좋습니다.
+
+이렇게 변화할 수 있는 학습률을 가지고 있는 것이 적응적 학습률 옵티마이저입니다.
+
+
+
+
+
+
+
+적응적 학습률 옵티마이저
+
++ RMSProp
+
++ Adam
+
++ Adagrad
+
+
+#### 정확도와 손실 시각화해보기
+
+model.fit()의 history는 훈련 과정 중 epoch별로 loss와 acc의 결과를 담고 있습니다.
+
+이를 활용해 모델의 정확도와 손실을 시각화 해볼 수 있습니다.
+
+
+
+
+
+
+
+시각화를 한 결과, epoch가 증가할 수록 훈련 데이터와 검증 데이터의 loss가 같이 줄어들고,
+
+정확도는 동시에 증가하는 것을 볼 수 있습니다.
+
+즉, 과적합이 많이 나타나지 않는 괜찮은 성능의 모델이라 확인할 수 있습니다.
+
+
+
+```python
+loss = history.history['loss']
+val_loss = history.history['val_loss']
+acc = history.history['acc']
+val_acc = history.history['val_acc']
+
+epochs = range(1, len(loss) + 1)
+fig = plt.figure(figsize=(10, 5))
+
+ax1 = fig.add_subplot(1, 2, 1)
+ax1.plot(epochs, loss, color='blue', label='train_loss')
+ax1.plot(epochs, val_loss, color='orange', label='val_loss')
+ax1.set_title('train and val loss')
+ax1.set_xlabel('epochs')
+ax1.set_ylabel('loss')
+ax1.legend()
+
+ax2 = fig.add_subplot(1, 2, 2)
+ax2.plot(epochs, acc, color='green', label='train_acc')
+ax2.plot(epochs, val_acc, color='red', label='val_acc')
+ax2.set_title('train and val acc')
+ax2.set_xlabel('epochs')
+ax2.set_ylabel('acc')
+ax2.legend()
+```
+
+
+
+
+
+
+#### 드롭아웃
+
++ 가장 많이 사용하는 과적합을 피하는 방법 중 하나입니다.
+
++ 모델을 훈련할 때, 0 ~ 1사이의 확률로 랜덤적으로 뉴런의 계산을 끄고 학습을 진행합니다.
+
++ 제외하지 않은 나머지 뉴런에서만 훈련이 이루어집니다.
+
++ 특정 뉴런의 의존하게 되는 계산을 막을 수 있습니다.
+
++ 모델을 평가할때는 모든 뉴런을 사용합니다.
+
+
+
+```python
+from tensorflow.keras.layers import Dropout
+
+model = Sequential()
+
+model.add(Flatten(input_shape=(28, 28)))
+model.add(Dense(100, activation='relu'))
+model.add(Dropout(0.3)) # 0.3비율로 Dropout
+model.add(Dense(10, activation='softmax'))
+
+model.compile(loss='sparse_categorical_crossentropy',
+ optimizer='adam',
+ metrics=['acc'])
+
+model.summary()
+```
+
+
+시각화를 해보면, Dropout을 사용했을 때 train_loss와 val_loss의 폭이 좀 더 줄어들고,
+
+val_loss의 증가율이 좀 더 낮아졌음을 볼 수 있습니다.
+
+
+
+```python
+loss = history.history['loss']
+val_loss = history.history['val_loss']
+acc = history.history['acc']
+val_acc = history.history['val_acc']
+
+epochs = range(1, len(loss) + 1)
+fig = plt.figure(figsize=(10, 5))
+
+ax1 = fig.add_subplot(1, 2, 1)
+ax1.plot(epochs, loss, color='blue', label='train_loss')
+ax1.plot(epochs, val_loss, color='orange', label='val_loss')
+ax1.set_title('train and val loss')
+ax1.set_xlabel('epochs')
+ax1.set_ylabel('loss')
+ax1.legend()
+
+ax2 = fig.add_subplot(1, 2, 2)
+ax2.plot(epochs, acc, color='green', label='train_acc')
+ax2.plot(epochs, val_acc, color='red', label='val_acc')
+ax2.set_title('train and val acc')
+ax2.set_xlabel('epochs')
+ax2.set_ylabel('acc')
+ax2.legend()
+```
+
+
+
+
+
+
+#### 모델 저장 및 복원
+
++ model.save_weights() : 모델의 구조는 저장하지않고, 파라미터만 저장합니다. (가중치, 편향)
+
++ model.load_weights() : 저장된 모델 객체를 불러옵니다.
+
+
+
+
+
+
+
++ model.save() : 모델 구조 자체를 모두 저장합니다.
+
++ model.load_model() : 저장된 모델을 불러옵니다.
+
+
+
+```python
+# 모델 저장
+model.save('./fashion_mnist_model-whole.h5')
+```
+
+model.predict() : 10개의 클래스가 존재하므로 각 샘플마다 10개의 확률을 출력해줍니다.
+
+10개의 확률 중 np.argmax()를 통해 가장 높은 값을 찾아서 그 인덱스를 예측값으로 사용합니다.
+
+얻은 예측값과 실제 테스트 데이터를 비교하여 평균을 내어 정확도를 내줍니다.
+
+아래에서 예측을 수행한 결과 약 88%의 정확도를 확인할 수 있습니다.
+
+
+
+```python
+# model.predict() : 각 샘플마다 10개의 확률을 출력해주는 메서드
+# 10개의 확률 중 가장 높은 값을 찾아서 그 인덱스를 예측 값으로 사용합니다.
+
+predictions = model.predict(X_test)
+val_labels = np.argmax(predictions, axis=1) # axis=1 : 행 기준으로 연산 수행(<-> axis=0 : 열 기준)
+print(np.mean(val_labels == y_test)) # True : 1, False : 0
+```
+
+
+0.8728
+
+#### 조기종료
+
+학습이 진행될수록 학습셋의 정확도는 올라가지만 과적합으로 인해 테스트셋의 실험 결과가 점점 나빠질 수 있습니다.
+
+이렇게 학습이 진행되어도 텟트셋 오차가 줄지 않을 경우 학습을 멈추게 하는 함수입니다.
+
+
+
+
+
+
+
++ patience = 2 : 검증셋의 손실이 2번 증가하면 중지
+
++ restore_best_weights=True : 가장 손실이 낮았던 곳으로 되돌리기
+
+
+
+```python
+import keras
+
+checkpoint_cb = keras.callbacks.ModelCheckpoint('fashion_mnist_model-whole.h5')
+early_stopping_cb = keras.callbacks.EarlyStopping(patience=2,
+ restore_best_weights=True)
+
+history = model.fit(X_train, y_train, epochs=50, verbose=0,
+ validation_split=0.2, callbacks=[checkpoint_cb, early_stopping_cb])
+
+print(f"종료될 떄의 epoch : {early_stopping_cb.stopped_epoch}")
+
+loss = history.history['loss']
+val_loss = history.history['val_loss']
+
+plt.plot(loss)
+plt.plot(val_loss)
+plt.xlabel('epoch')
+plt.ylabel('loss')
+plt.legend(['train', 'val'])
+plt.show()
+```
+
+
+종료될 떄의 epoch : 11
+
+
diff --git "a/_posts/2022-02-04-\354\210\234\354\260\250 \353\215\260\354\235\264\355\204\260\354\231\200 \354\210\234\355\231\230 \354\213\240\352\262\275\353\247\235.md" "b/_posts/2022-02-04-\354\210\234\354\260\250 \353\215\260\354\235\264\355\204\260\354\231\200 \354\210\234\355\231\230 \354\213\240\352\262\275\353\247\235.md"
new file mode 100644
index 000000000000..51ce65377c98
--- /dev/null
+++ "b/_posts/2022-02-04-\354\210\234\354\260\250 \353\215\260\354\235\264\355\204\260\354\231\200 \354\210\234\355\231\230 \354\213\240\352\262\275\353\247\235.md"
@@ -0,0 +1,382 @@
+---
+layout: single
+title: "순환신경망(RNN) 정리"
+categories: 딥러닝
+tag: [python, keras, 순환신경망, 순차데이터, RNN, 딥러닝]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+다음의 출처를 참고했습니다.
+
+
+
+
+### 순차 데이터
+
+순차 데이터는 순서에 의미가 있으며, 순서가 달라질 경우 의미가 손상되는 데이터입니다.
+
+시간적 의미가 있는 경우 Temporal Sequence라고 하며, 일정한 시간차라면 Time Series라고 합니다.
+
+
+### 순환 신경망(RNN)
+
+순환 신경망은 순차 데이터와 같이 시간의 흐름에 따라 변화하는 데이터를 학습하기 위한 인공신경망입니다.
+
+따라서, 과거의 출력 데이터를 재귀적으로 참조합니다.
+
+순환되는 고리가 있는 신경망입니다.
+
+
+
+
+
+
+
+![RNN](/assets/images/RNN.png)
+
+
+위의 그림을 보면 은닉층의 노드에서 나온 결과값이 출력층 방향으로도 보내지고,
+
+다시 은닉층 노드의 다음 계산을 위한 입력으로도 보내지는 특징이 있습니다.
+
+그러므로, 결과값 O(t)는 결과값 O(t-1)에 대한 정보가 어느정도 포함(기억)되고,
+
+O(t+1)은 O(t)와 O(t-1)의 정보가 어느정도 포함(기억)된다고 할 수 있습니다.
+
+이렇게 이전의 계산에서 나온 출력값을 다시 다음 단계 계산에서 사용하는 하나의 사이클을 Time Step이라고 합니다.
+
+
+
+
+
+
+
++ 셀 : 은닉층에서 결과를 두 뱡향(출력층과 다음 연산)으로 내보내는 노드를 메모리 셀 혹은 셀이라고 합니다.
+
+
+
+
+
+
+
+완전 연결층에서 출력되는 값은 활성화 출력, 합성곱 층에서 출력되는 값은 특성 맵이라고 하듯이,
+
+셀에서 출력하는 값은 은닉 상태(Hidden State)라고 합니다.
+
+또한, RNN에서는 입력층/출력층을 입력벡터/출력벡터 라고 합니다.
+
+
+
+
+
+
+
+##### RNN 수식 이해하기
+
+
+
+![RNN 수식](/assets/images/RNN수식.PNG)
+
+
+
++ ht : 현재 타임 스텝 t에서의 은닉 상태값
+
++ wx : 입력 벡터의 입력값과 곱해질 가중치
+
++ wh : 이전 타임 스텝 t-1에서의 은닉 상태값 ht-1과 곱해질 가중치
+
+
+
+따라서 ht를 계산하는 수식은 다음과 같습니다.
+
++ ht = activation_function((wh * ht-1) + (wx * xt) + b)
+
++ yt = activation_function((wy * ht) + b)
+
+
+
+RNN에서도 역시 활성화 함수를 사용하는데, 보통 tanh함수를 많이 사용합니다.(relu를 사용하기도)
+
+(tanh도 역시 S자 모양으로 -1 ~ 1값을 가지기 때문에 시그모이드라고 불리기도 합니다.)
+
+
+
+RNN은 이렇게 각 타임 스텝마다 wx와 wh를 동일하게 사용합니다.
+
+이런 부분을 보았을 때, RNN은 타임 스텝에 따라서 가중치를 공유하며 모델의 파라미터를 효율적으로 사용할 수 있습니다.
+
+
+##### 순환 신경망의 입력과 출력
+
+RNN층은 (batch_size, timesteps, input_dim) 형태의 3D 텐서를 입력받습니다.
+
++ batch_size는 한번에 RNN이 학습하는 데이터의 양을 의미합니다.
+
++ timesteps는 입력 시퀀스의 크기입니다. input_length와 동일합니다.
+
++ input_dim은 입력의 크기입니다.
+
+
+
+```python
+from tensorflow.keras.models import Sequential
+from tensorflow.keras.layers import SimpleRNN
+
+model = Sequential()
+model.add(SimpleRNN(3, input_shape=(2, 10)))
+# batch_size=8, timesteps=2, input_dim=10
+
+model.summary()
+```
+
+
+return_sequences=True를 설정하면 출력값으로 (batch_size, timesteps, output_dim) 크기의
+
+3D 텐서가 출력되는 것을 확인할 수 있습니다.
+
+
+##### RNN의 활용
+
+RNN은 입력과 출력의 길이가 고정되어 있지 않습니다. 그러므로, 설계에 따라 다양한 용도로 신경망을 사용할 수 있습니다.
+
+
+
+![RNN활용](/assets/images/RNN활용.PNG)
+
+
+
+일대다 모델
+
++ 하나의 이미지 입력에 대해서 사진의 제목을 출력하는 이미지 캡셔닝(Image Captioning)작업에 사용할 수 있습니다.
+
+사진의 제목은 단어들의 나열이므로 시퀀스 출력입니다.
+
+
+
+다대일 모델
+
++ 입력 문서가 긍정적인지 부정적인지 판별하는 감성 분류(sentiment classification)
+
++ 메일이 정상 메일인지 스팸 메일인지 판별하는 스팸 메일 분류(spam detection)등에 사용할 수 있습니다.
+
+
+
+다대다 모델
+
++ 사용자가 문장을 입력하면 대답 문장을 출력하는 챗봇
+
++ 입력 문장으로부터 번역된 문장을 출력하는 번역기 등이 있습니다.
+
+
+#### 양방향 순환 신경망
+
+
+
+양방향 RNN은 이전과 이후의 시점 모두를 고려해서 현재 시점의 예측을 더욱 정확하게 할 수 있도록 고안된 방법입니다.
+
+기본적으로 두 개의 메모리 셀을 사용합니다.
+
+첫번째 셀은 기존과 동일하게 앞 시점의 은닉 상태를 전달받아 현재의 은닉 상태를 계산합니다.
+
+두번째 셀은 뒤 시점의 은닉상태를 전달 받아 현재의 은닉 상태를 계산합니다.(입력 시퀀스를 반대 방향으로 읽습니다.)
+
+이처럼 앞, 뒤 2개의 시점을 이용하여 현재 시점의 은닉 상태를 출력합니다.
+
+
+
+
+```python
+from tensorflow.keras.layers import Bidirectional
+
+model = Sequential()
+model.add(Bidirectional(SimpleRNN(3, return_sequences=True), input_shape=(2, 10)))
+
+model.summary()
+```
+
+
+#### 모델 구성
+
+
+
+```python
+from tensorflow.keras.models import Sequential
+from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
+
+model = Sequential()
+
+# 첫번째 합성곱 층
+model.add(Conv2D(32, kernel_size=3, activation='relu', padding='same', input_shape=(28,28,1)))
+model.add(MaxPooling2D(2))
+
+# 두번째 합성곱 층
+model.add(Conv2D(64, kernel_size=3, activation='relu', padding='same'))
+model.add(MaxPooling2D(2))
+
+# 완전 연결층
+model.add(Flatten())
+model.add(Dense(100, activation='relu'))
+model.add(Dropout(0.4))
+model.add(Dense(10, activation='softmax')) # 10개의 클래스 중 택1, 10개의 확률을 얻기위해 softmax 사용
+```
+
+첫번째 컨볼루션 층에서는 32개의 커널을 사용, 커널의 사이즈는 (3,3,1)이며, 활성화 함수는 relu를 사용하겠습니다.
+
+(입력 데이터의 채널이 1이므로 커널의 채널도 1이 됩니다. 만약 입력 데이터가 컬러이면 채널은 3이 되겠습니다.).
+
+same 패딩을 사용할 것이고, 입력 사이즈는 배치 차원없이 (28, 28, 1)이 됩니다.
+
+그럼 출력되는 특성 맵은 (28, 28, 32) 크기가 됩니다.
+
+
+
+
+
+
+
+특성 맵을 맥스 풀링을 해줍니다. 이때 풀링에 사용되는 커널은 2x2사이즈로 해서 절반으로 줄여줍니다.
+
+최종적으로 첫번째 (컨볼루션 + 풀링)층에서 나오는 특성 맵의 크기는 (14, 14, 32)가 됩니다.
+
+
+
+
+
+
+
+두 번째 합성곱 층에선 64개의 필터를 사용했습니다.
+
+동일한 커널 사이즈와 활성화 함수 패딩을 사용했으므로 나오는 특성 맵의 크기는 (14, 14, 64)가 됩니다.
+
+동일하게 맥스 풀링을 통과하면 특성 맵의 크기는 최종적으로 (7, 7, 64)가 됩니다.
+
+
+
+
+
+
+
+그 다음엔 Dense층을 놓고 클래스 개수에 맞는 10개의 확률값을 얻어야하기 때문에 Flatten()을 사용하여
+
+(7, 7, 64) 특성 맵을 1차원 배열로 만들어줍니다.
+
+
+
+
+
+
+
+첫 번째 Dense층에서 활성화 함수 relu를 사용하는 뉴런 100개를 은닉층으로 두었습니다.
+
+3136개의 입력이 100개의 뉴런에 완전 연결이 되었으므로 굉장히 많은 가중치가 생성될 거 같네요.
+
+그래서 과적합을 피해보기 위해 은닉층 뒤에 Dropout을 사용해서 훈련 시에 40%의 뉴런을 끄도록 지정해 보았습니다.
+
+최종 출력층에는 10개의 출력을 가지고 softmax를 사용해야 10개의 확률을 얻을 수 있습니다.
+
+
+#### 모델 summary
+
+각 층마다 출력되는 특성 맵과 출력 데이터의 크기와 파라미터 개수는 summary()함수를 통해 다시 한 번 확인해봅니다.
+
+
+
+```python
+model.summary()
+```
+
+
+summary 내용을 확인해 보았을 때, 첫번째 Dense층의 100개의 뉴런이 Flatten 층에서 나온 3136개의 입력 배열과
+
+완전 연결이 되었으므로 굉장히 많은 가중치가 생긴 걸 확인할 수 있네요.
+
+그 위에 있는 합성곱층 2개의 가중치를 모두 더한것보다 훨씬 많은 것을 확인할 수 있는데요.
+
+이 점을 보았을 때 완전 연결층은 과적합이 쉽게 나타날 수 있고
+
+반대로, 합성곱 층은 적은 개수의 파라미터로 효과적으로 이미지의 특징을 잘 잡아낼 수 있는 거 같습니다.
+
+
+#### plot_model
+
+keras에는 plot_model()이라는 라이브러리가 있습니다.
+
+모델 구성 정보에 대한, summary()함수로 확인할 수 있는 정보들을 시각화해주는 라이브러리입니다.
+
+show_shapes=True로 주면 각 층의 input shape과 output shape을 나타내줍니다.
+
+
+
+```python
+from tensorflow.keras.utils import plot_model
+
+plot_model(model, show_shapes=True)
+```
+
+
+
+#### 모델 컴파일 및 훈련
+
+옵티마이저는 'adam'을 사용했고, y데이터를 원 핫 인코딩 하지않고 그대로 사용하기 위해
+
+손실 함수를 'sparse_categorical_crossentropy'로 지정했습니다.
+
+
+
+```python
+# 모델 컴파일
+model.compile(optimizer='adam',
+ loss='sparse_categorical_crossentropy',
+ metrics=['acc'])
+```
+
+체크 포인트를 models 폴더 안에 'fashion_mnist_cnn_model.h5'로 지정하고
+
+검증 셋의 점수가 2회 이상 증가했을 때 조기종료를 하고, 가장 손실이 낮았던 곳으로 되돌리기 위해 콜백을 지정했습니다.
+
+
+
+```python
+# 모델 훈련
+from tensorflow.keras import callbacks
+import os
+
+# models라는 폴더에 모델(h5파일)을 저장하려는데 해당 폴더가 없으면 만들어주기
+if not os.path.exists('./models/'):
+ os.mkdir('./models/')
+
+checkpoint_ch = callbacks.ModelCheckpoint('./models/fasion_mnist_cnn_model.h5')
+
+early_stopping_cb = callbacks.EarlyStopping(patience=2, restore_best_weights=True)
+
+history = model.fit(X_train, y_train, verbose=0,
+ epochs=20, validation_data=(X_val, y_val),
+ callbacks=[checkpoint_ch, early_stopping_cb])
+```
+
+#### 훈련 시각화
+
+훈련 셋과 검증 셋의 정확도와 손실을 시각화 해보겠습니다.
+
+아래와 같이 8번째 epoch(0부터)에서 훈련이 멈췄고 patience를 2로 주었기 때문에
+
+6번째 에포크에서 가장 낮은 검증 손실을 얻을 수 있다고 확인할 수 있습니다.
+
+이 이후에는 검증 셋의 손실이 올라가기 때문에 과적합이 존재한다고 볼 수 있습니다.
+
+
+
+```python
+import matplotlib.pyplot as plt
+
+loss = history.history['loss']
+val_loss = history.history['val_loss']
+acc = history.history['acc']
+val_acc = history.history['val_acc']
+
+epochs = range(1, len(loss) + 1)
+fig = plt.figure(figsize=(10, 5))
+
+ax1 = fig.add_subplot(1, 2, 1)
+ax1.plot(epochs, loss, color='blue', label='train_loss')
+ax1.plot(epochs, val_loss, color='orange', label='val_loss')
+ax1.set_title('train and val loss')
+ax1.set_xlabel('epochs')
+ax1.set_ylabel('loss')
+ax1.legend()
+
+ax2 = fig.add_subplot(1, 2, 2)
+ax2.plot(epochs, acc, color='green', label='train_acc')
+ax2.plot(epochs, val_acc, color='red', label='val_acc')
+ax2.set_title('train and val acc')
+ax2.set_xlabel('epochs')
+ax2.set_ylabel('acc')
+ax2.legend()
+```
+
+
+evaluate 메소드를 사용해서 이 모델을 검증 데이터로 평가해보면
+
+손실값은 약 0.22 정도 나오고, 정확도는 0.92정도가 나옵니다.
+
+
+
+
+
+
+
+이미지 하나를 28x28로 reshape 해서 이미지를 출력해보면 아래와 같은 가방 이미지가 출력됩니다.
+
+그리고 predict 메소드를 사용해서 각 10개의 카테고리에 포함될 10개의 확률을 확인 할 수 있습니다.
+
+9번째 확률값이 제일 높은 1이므로, 이 이미지는 카테고리 9에 해당하는 데이터라고 예측 됨을 확인 할 수 있습니다.
+
+
+
+```python
+plt.imshow(X_val[0].reshape(28, 28), cmap='gray')
+plt.show()
+
+preds = model.predict(X_val[0:1])
+print(preds)
+```
+
+
+
+
+이번에는 테스트 데이터를 evaluate 메소드를 통해 예측을 해보면 결과는 검증 셋보다
+
+약간 더 높은 0.25 정도의 손실값과 약 0.91의 정확도가 나오는 것을 확인 할 수 있습니다.
+
+
+
+```python
+model.evaluate(X_test, y_test)
+```
+
+
\ No newline at end of file
diff --git "a/_posts/2022-02-07-IMDB \352\270\215\354\240\225 \354\227\254\353\266\200 \354\230\210\354\270\241(RNN, Embedding).md" "b/_posts/2022-02-07-IMDB \352\270\215\354\240\225 \354\227\254\353\266\200 \354\230\210\354\270\241(RNN, Embedding).md"
new file mode 100644
index 000000000000..4b019e78d05d
--- /dev/null
+++ "b/_posts/2022-02-07-IMDB \352\270\215\354\240\225 \354\227\254\353\266\200 \354\230\210\354\270\241(RNN, Embedding).md"
@@ -0,0 +1,627 @@
+---
+layout: single
+title: "IMDB 긍정 여부 분류 (RNN, Embedding)"
+categories: 딥러닝
+tag: [python, 파이썬, keras, 딥러닝, imdb, RNN, 시퀀스 패딩, Embedding, 예측]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+#### IMDB 영화 리뷰 긍정 여부 예측 모델 학습
+
+총 25000개의 샘플이 존재하며, 각 샘플은 영화 리뷰 한 건을 의미합니다.
+
+데이터셋은 이미 정수로 인코딩되어 있고, 정수값은 단어의 빈도수를 나타냅니다.
+
+
+
+
+
+
+
++ imdb.load_data()의 인자로 num_words : 단어의 등장 빈도 순위로 몇 등까지 사용할 것인지를 의미합니다.
+
+ num_words를 10000으로 설정하여 단어의 등장 빈도 순위가 10000을 넘는 단어는 보이지 않게 해서 데이터셋을
+
+ 좀 더 간단하게 표현하기 위해 사용합니다.
+
+ 즉, 이 데이터에 사용할 단어 사전에 10000개의 단어를 사용합니다.
+
+
+
+```python
+from tensorflow.keras.datasets import imdb
+import matplotlib.pyplot as plt
+import numpy as np
+
+num_word = 500
+
+(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=num_word)
+
+X_train.shape, y_train.shape
+```
+
+
+((25000,), (25000,))
+
+X_train의 샘플을 확인해보면 각 단어의 빈도 순위가 정수형으로 나타나 있는걸 확인할 수 있습니다.
+
+
+
+```python
+print(X_train[0])
+```
+
+
+이 데이터 셋은 리뷰의 긍정여부를 나타내기 때문에 y값은 0과 1 두개의 값만 가지는 것을 확인할 수 있습니다.
+
+
+
+```python
+print(np.unique(y_train))
+```
+
+
+[0 1]
+
+이 데이터는 토큰화와 정수 인코딩이라는 텍스트 전처리가 완료된 상태입니다.
+
+다음에 시퀀스 패딩을 사용하기 위해 적절한 리뷰의 길이 즉, 토큰의 길이와 그에 따른 빈도 수를 확인해봅니다.
+
+
+
+
+
+
+
+대체적으로 1000이하의 길이를 가지며, 100 ~ 500정도의 길이를 가진 데이터가 많은 것을 확인할 수 있습니다.
+
+
+
+```python
+from sklearn.model_selection import train_test_split
+
+X_train, X_val, y_train, y_val = train_test_split(X_train, y_train,
+ test_size=0.2, random_state=42)
+
+length = np.array([len(x) for x in X_train])
+print(f"X_train의 평균 : {np.mean(length)}\nX_train의 중간값 : {np.median(length)}")
+
+plt.hist(length)
+plt.xlabel('length')
+plt.ylabel('frequency')
+plt.show()
+```
+
+
+X_train의 평균 : 239.00925
+X_train의 중간값 : 178.0
+
+
+
+#### 시퀀스 패딩
+
++ 서로 다른 개수의 단어로 이루어진 문장을 같은 길이로 만들어주기 위해 패딩을 사용합니다.
+
++ 패딩을 사용하기 위해서 tensorflow.keras.preprocessing.sequence 모듈의 pad_sequences함수를 사용합니다.
+
++ pad_sequences 함수는 숫자 0을 이용해서 같은 길이의 시퀀스로 변환합니다.
+
+
+
+
+
+
+
+###### padding 파라미터
+
++ 'post' : 시퀀스의 뒤에 패딩이 채워집니다. 디폴트는 'pre'입니다.
+
++ maxlen 파라미터
+
+ + 시퀀스의 최대 길이를 제한합니다.
+
++ truncating 파라미터
+
+ + 최대 길이를 넘는 시퀀스를 잘라낼 위치를 지정합니다.
+
+ + 'post'로 지정하면 뒷부분을 잘라냅니다.
+
+
+
+
+
+
+
+pad_sequences()의 인자 maxlen을 통해 패딩할 길이를 설정합니다.
+
+위에서 데이터의 토큰 길이를 시각화해보고 100이 적절하다고 생각하여 maxlen을 100으로 설정합니다.
+
+
+
+```python
+from tensorflow.keras.preprocessing.sequence import pad_sequences
+
+max_len = 100
+
+X_train_seq = pad_sequences(X_train, maxlen=max_len)
+X_val_seq = pad_sequences(X_val, maxlen=max_len)
+
+X_train_seq.shape, X_val_seq.shape
+```
+
+
+((20000, 100), (5000, 100))
+
+#### 원 핫 인코딩
+
+단어 집합의 크길르 벡터 차원으로 만들어줍니다.
+
+표현하고 싶은 단어의 인덱스에 1의 값을 부여하고, 나머지는 0을 부여하는 벡터 표현 방식입니다.
+
+
+
+```python
+from tensorflow import keras
+
+X_train_seq = keras.utils.to_categorical(X_train_seq)
+X_val_seq = keras.utils.to_categorical(X_val_seq)
+
+X_train_seq.shape, X_val_seq.shape
+```
+
+
+((20000, 100, 500), (5000, 100, 500))
+
+#### 순환 신경망 모델 만들기
+
+
+
+```python
+model = keras.Sequential()
+
+model.add(keras.layers.SimpleRNN(8, input_shape=(100, 500)))
+model.add(keras.layers.Dense(1, activation='sigmoid'))
+```
+
+단순 순환 신경망 하나로 이루어진 간단한 모델입니다.
+
+은닉층 크기는 8, 입력 크기는 원 핫 인코딩을 끝낸 벡터의 차원을 입력해서 SimpleRNN을 사용합니다.
+
+RNN층 다음에 Dense층을 사용할 때는 합성곱층과 달리 Flatten층을 사용할 필요가 없습니다.
+
+Dense층은 긍정/부정 두가지 레이블을 판별하므로 sigmoid를 사용했습니다.
+
+
+
+```python
+model.summary()
+```
+
+
+
+
+단순히 SimpleRNN 하나의 층만을 사용해서 약 0.78 정도의 정확도를 얻을 수 있었습니다.
+
+결과를 시각화해보면 40번째 epoch에서 과적합이 심해져 조기 종료되었음을 확인 할 수 있습니다.
+
+
+
+
+
+
+
+원 핫 인코딩을 사용해서 입력 데이터를 준비한다면, 단어 사전을 유연하게 늘리기가 어렵습니다.
+
+단어 사전이 증가할수록 또는 토큰의 개수가 늘어날수록 벡터 차원의 개수가 매우 많이 늘어나기 때문입니다.
+
+또한, 원 핫 인코딩은 하나의 벡터 원소만 1이고 나머진 0으로 채워지기 때문에 각 토큰 사이의 관련성을 알기 어렵습니다.
+
+이에 대비해서 임베딩 방법이 존재합니다.
+
+임베딩은 토큰들을 지정된 갯수의 실수 벡터 즉, 밀집 벡터로 변환해줍니다.
+
+원 핫 인코딩에 비해 단어 사이에 의미 있는 정보를 얻을 수 있는 방법입니다.
+
+임베딩을 사용하여 두번째 모델을 만들어 보겠습니다.
+
+
+
+
+
+
+
+Embedding()
+
++ 단어를 밀집 벡터로 만드는 작업을 워드 임베딩(word embedding)이라고 합니다.
+
++ 원-핫 인코딩과 상대적으로 저차원을 가지며 모든 원소의 값이 실수입니다.
+
+ + 첫번째 인자 : 단어 사전의 크기(총 단어의 개수)
+
+ + 두번째 인자 : 임베딩 벡터의 출력 차원(결과로 나오는 임베딩 벡터의 크기)
+
+ 만약, embedding층과 연결된 층이 순환신경망이면 사용하지 않습니다.
+
+ + input_length : time step의 길이(입력 시퀀스의 길이)
+
+ 만약, 다음에 Flatten층이 오게 되면 반드시 input_length를 명시해주어야 합니다.
+
+
+
+```python
+model2 = keras.Sequential()
+
+model2.add(keras.layers.Embedding(500, 16, input_length=100))
+model2.add(keras.layers.SimpleRNN(8))
+model2.add(keras.layers.Dense(1, activation='sigmoid'))
+
+model2.summary()
+```
+
+
+모델 학습 과정에서 손실과 정확도를 시각화해보면 검증 셋에서 약 0.84정도의 정확도를 얻었습니다.
+
+epoch가 약 30에서 과적합이 심해져 조기 종료 되었음을 확인 할 수 있습니다.
+
+테스트 데이터에 모델을 적용한 결과 약 0.84의 정확도의 나쁘지 않은 결과를 얻을 수 있었습니다.
+
diff --git "a/_posts/2022-02-12-LSTM, GRU(imdb \354\230\210\354\270\241).md" "b/_posts/2022-02-12-LSTM, GRU(imdb \354\230\210\354\270\241).md"
new file mode 100644
index 000000000000..48f6ebdf29b3
--- /dev/null
+++ "b/_posts/2022-02-12-LSTM, GRU(imdb \354\230\210\354\270\241).md"
@@ -0,0 +1,625 @@
+---
+layout: single
+title: "LSTM과 GRU를 사용한 IMDB 분류"
+categories: 딥러닝
+tag: [python, 파이썬, 딥러닝, 순환신경망, LSTM, GRU, IMDB]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+#### LSTM
+
+
+
+RNN은 관련 정보와 그 정보를 사용하는 지점 사이 거리가 멀 경우 역전파시 그래디언트가 점차 줄어 학습능력이 떨어진다고 알려져 있습니다. (vanishing gradient problem)
+
+이 문제를 보완하기 위해 LSTM이 등장합니다.
+
+
+
+LSTM(Long Short Term Memory)는 기존의 RNN이 출력과 먼 위치에 있는 정보를 기억할 수 없다는 단점을 보완한 방법입니다.
+
+장기 / 단기 기억을 가능하게 설계한 신경망의 구조입니다.
+
+주로 시계열, 자연어 처리에 사용됩니다.
+
+
+
+
+
+
+
+#### LSTM의 구조
+
+
+
+LSTM은 RNN과 다르게 한 개의 tanh layer가 아닌 4개의 layer로 구성되어 서로 정보를 주고 받는 방식입니다.
+
+또한, LSTM 셀에서는 상태가 크게 두 가지의 상태가 순환합니다.
+
+RNN의 은닉 상태(hidden state)에 셀 상태(cell state)가 추가됩니다.
+
+LSTM의 출력으로 사용되는 것은 은닉 상태, 셀 상태는 셀 안에서 순환하는 상태입니다.
+
+
+
+![LSTM구조](/assets/images/LSTM구조.png)
+
+<이미지 출처 : https://imgur.com/jKodJ1u>
+
+
+
+여기서 LSTM 모듈에는 4개의 layer가 존재하는 것을 알 수 있습니다.
+
+
+
+
+
+
+
+#### LSTM 과정
+
+
+
+![LSTM순전파](/assets/images/LSTM기호.png)
+
+노란색 박스는 학습된 neural network layer이고, 분홍색 동그라미는 vector 연산과 같은 pointwise operation을 나타냅니다.
+
+합쳐지는 선은 concatenateion을 의미하고, 갈라지는 선은 정보를 복사해서 다른쪽으로 보내는 fork입니다.
+
+
+
+
+
+
+
+![LSTM순전파](/assets/images/LSTM_cell상태.png)
+
+
+
+Cell state는 모듈 상단에 수평으로 그어진 윗 선에 해당됩니다.
+
+Cell state는 컨베이어 벨트와 같이, 정보가 전혀 바뀌지 않고 그대로 흐르게만 하는 역할을 합니다.
+
+LSTM은 Cell state에 뭔가를 더하거나 없애는 과정을 반복합니다. 이 과정에서 3가지의 gate를 사용합니다.
+
+
+
+
+
+
+
+![LSTM순전파](/assets/images/LSTM_forget게이트.png)
+
+
+
+LSTM의 첫 단계로 Cell state로부터 어떤 정보를 버릴 것인지 정하는 forget gate 입니다.
+
+ht-1과 xt를 받아 시그모이드를 취해(0 ~ 1값) ct-1에 보내줍니다.
+
+이 값이 1이면 "모든 정보 전달", "0이면 모두 버리기"가 됩니다.
+
+
+
+
+
+
+
+![LSTM순전파](/assets/images/LSTM_input게이트.png)
+
+
+
+다음 단계는 입력되는 새로운 정보 중 어떤 것을 Cell state에 저장할 것인지 정하는 input gate 입니다.
+
+먼저 sigmoid layer가 어떤 값을 업데이트할 지 정하고, 그 다음에 tanh layer가 새로운 후보 값 c~t라는 vector를 만들고 Cell state에 더할 준비를 합니다.
+
+이렇게 두 단계에서 나온 정보를 합쳐서 state에 업데이트할 준비를 합니다.
+
+
+
+
+
+
+
+![LSTM순전파](/assets/images/LSTM_cell_update.png)
+
+
+
+이전 state인 ct-1에 ft를 곱해서 forget gate에서 잊어버리기로 정했던 정보들을 모두 잊어버립니다.
+
+그리고나서 it x c~t를 더해줍니다. 이 더한 값은 두번째 단계에서 업데이트하기로 한 값을 얼마나 업데이트할 지 정한 만큼 scale한 값이 됩니다.
+
+
+
+
+
+
+
+![LSTM순전파](/assets/images/LSTM_output게이트.png)
+
+
+
+마지막으로 출력으로 내보내는 output gate 입니다.
+
+먼저, sigmoid layer에 input 데이터를 넣어서 Cell state의 어느 부분을 ouput으로 보낼지 정합니다.
+
+그리고 Cell state를 tanh layer에 전달해서 -1과 1사이의 값을 받은 뒤에 방금 전의 sigmoid layer의 output과 곱합니다.
+
+그 후, ouput으로 보내게 됩니다.
+
+
+#### GRU 셀
+
+GRU 셀은 LSTM 셀에서 좀 더 간소화된 구조라고 말할 수 있습니다.
+
+LSTM에 비해 Gate가 2개이며 reset gate(r)와 update gate(z)로 이루어집니다.
+
++ reset gate는 이전 상태를 얼마나 잊어버릴지를 결정합니다.
+
++ update gate는 이전 상태와 현재 상태를 얼마만큼의 비율로 반영할지를 결정합니다.
+
+
+
+LSTM 셀에 존재하는 cell state와 hidden state가 하나로 합쳐집니다.
+
+
+
+![GRU](/assets/images/GRU셀.png)
+
+
+
+Input
+
+이전 시점의 셀에서 전달된 hidden state(h(t-1))와 새로운 input값인 x(t)가 합쳐지고 두 방향으로 나뉘어 전달됩니다.
+
+하나는 게이트에 전달될 정보가 되고, 다른 하나는 LSTM의 Candidate state의 역할을 합니다.
+
+
+
+reset gate
+
+이전 상태의 은닉 상태와 현재 상태의 x를 받아 sigmoid처리를 합니다.
+
+candidate state(h_hat(t))에 전달되는 데이터에 어떤 정보를 지우고, 어떤 정보를 전달할지 결정합니다.
+
+
+
+update gate
+
+이전 상태의 은닉 상태와 현재 상태의 x를 받아 sigmoid처리를 합니다.
+
+LSTM 셀의 forget과 input 게이트와 비슷한 역할을 하지만, Update 되는 정보의 양에 1이라는 제한이 있습니다.
+
+이전 정보인 h(t-1)과 reset gate를 지나온 candidate state(h_hat(t))에 동시에 전달되는데,
+
+이때 한쪽에 x의 크기가 전달되면, 반대쪽은 1-x만큼 전달됩니다.
+
+즉, 정보를 지운만큼만 새로운 정보를 입력하고, 새로운 정보를 입력한 만큼 정보를 지울 수 있습니다.
+
+
+
+candidate state
+
+현재 셀에 입력된 정보 중에서 Output과 다음 셀로 전달할 중요한 후보 정보를 담고 있는 state입니다.
+
+reset gate를 거친 정보들은 tanh함수를 취해 update gate까지 지나며 h(t-1)과 합쳐집니다.
+
+
+
+hidden state
+
+LSTM의 cell state의 역할까지 동시에 합니다.
+
+update gate를 통과하면서 의미 없는 데이터를 삭제하고 현재 셀의 중요한 정보를 담고 있는 candidate state와
+
+합쳐져 output이 되고, 동시에 다음 시점의 셀로 정보를 전달합니다.
+
+
+#### LSTM 신경망으로 IMDB 예측
+
+
+
+이전에 SimpleRNN과 Embedding을 사용하여 예측했던 IMDB 데이터 분류를 LSTM을 사용하여 다시 분류해보겠습니다.
+
+데이터 처리 과정은 이전과 동일하게 수행하겠습니다.
+
+
+
+```python
+from tensorflow import keras
+import numpy as np
+import matplotlib.pyplot as plt
+from sklearn.model_selection import train_test_split
+from tensorflow.keras.preprocessing.sequence import pad_sequences
+
+(X_train, y_train), (X_test, y_test) = keras.datasets.imdb.load_data(num_words=10000)
+
+X_train_seq = pad_sequences(X_train, maxlen=500)
+X_test_seq = pad_sequences(X_test, maxlen=500)
+
+X_train_seq, X_val_seq, y_train, y_val = train_test_split(X_train_seq, y_train)
+
+X_train_seq.shape, X_val_seq.shape
+```
+
+
+
+
+
+
+#### Dropout 추가
+
+
+
+이전에 구성했던 모델을 좀 더 정확한 예측을 위해 신경망을 좀 더 깊게 수정하고 Dropout을 추가해보았습니다.
+
+LSTM층에서 다음 LSTM층을 쌓아 연결할때는, 각 타임 스텝의 은닉상태를 모두 출력해주어야 마지막에 있는 순환 셀이 제대로 동작할 것입니다.
+
+기본적으로 keras의 순환층은 마지막 타임 스텝의 은닉상태만 출력하기 때문에 모든 타임 스텝마다 은닉상태를 출력해주기 위해 return_sequences=True를 설정해주어야 합니다.
+
+LSTM에서 Dropout을 사용할 땐 따로 층을 추가하지 않고 매개변수로서 추가를 해줘야 합니다.
+
+
+
+```python
+from tensorflow import keras
+import numpy as np
+import matplotlib.pyplot as plt
+from sklearn.model_selection import train_test_split
+from tensorflow.keras.preprocessing.sequence import pad_sequences
+
+(X_train, y_train), (X_test, y_test) = keras.datasets.imdb.load_data(num_words=10000)
+
+X_train_seq = pad_sequences(X_train, maxlen=500)
+X_test_seq = pad_sequences(X_test, maxlen=500)
+
+X_train_seq, X_val_seq, y_train, y_val = train_test_split(X_train_seq, y_train)
+
+X_train_seq.shape, X_val_seq.shape
+```
+
+
+Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/imdb.npz
+17465344/17464789 [==============================] - 0s 0us/step
+17473536/17464789 [==============================] - 0s 0us/step
+
+
+
+드롭아웃을 적용한 모델에서 훈련 데이터와 검증 데이터의 손실값 차이가 좀 더 적게 나타난 것을 확인할 수 있습니다.
+
+다음은 GRU셀을 이용해서 동일한 방법으로 모델을 구성해보았습니다.
+
+
+
+```python
+model3 = keras.Sequential()
+
+model3.add(keras.layers.Embedding(10000, 16, input_length=500))
+model3.add(keras.layers.GRU(8, dropout=0.3, return_sequences=True))
+model3.add(keras.layers.GRU(8, dropout=0.3))
+model3.add(keras.layers.Dense(1, activation='sigmoid'))
+
+model3.summary()
+```
+
+
+
+
+IMDB 데이터셋을 분류할 때, LSTM 셀을 사용한 방법과 GRU 셀을 사용한 방법이 비슷한 정확도를 가질 수 있는 것을 확인했습니다.
+
+실제로 GRU 셀을 사용했을 때 학습시간이 덜 걸린 것을 확인할 수 있었습니다.
\ No newline at end of file
diff --git a/_posts/2022-09-10-ml01_K-Nearest Neighbors(KNN).md b/_posts/2022-09-10-ml01_K-Nearest Neighbors(KNN).md
new file mode 100644
index 000000000000..452125d12ad1
--- /dev/null
+++ b/_posts/2022-09-10-ml01_K-Nearest Neighbors(KNN).md
@@ -0,0 +1,253 @@
+---
+layout: single
+title: "K-Nearest Neighbors(KNN)"
+categories: 머신러닝
+tag: [KNN, 머신러닝, python]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+## k-최근접 이웃 알고리즘이란?
+
+- 새로운 데이터 포인트와 가장 가까운 훈련 데이터셋의 데이터 포인트를 찾아 예측
+- **k 값에 따라 가까운 이웃의 수가 결정**
+- **분류**와 **회귀**에 모두 사용 가능
+
+![01](/assets/images/ml01/01.png)
+
+## 특징
+
+- **k 값이 작을 수록** 모델의 **복잡도가 상대적으로 증가**.(noise 값에 민감)
+- 반대로 **k 값이 커질수록** 모델의 **복잡도가 낮아진다.**
+- 100개의 데이터를 학습하고 k를 100개로 설정하여 예측하면 **빈도가 가장 많은 클래스** 레이블로 분류
+- 이해하기 매우 쉬운 모델
+- 훈련 데이터 세트가 크면(특성,샘플의 수) 예측이 느려진다
+- 수백 개 이상의 많은 특성을 가진 데이터 세트와 특성 값 대부분이 0인 희소(sparse)한 데이터 세트에는 잘 동작하지 않는다
+- 거리를 측정하기 때문에 같은 scale을 같도록 **정규화** 필요
+
+## 데이터 포인트(sample) 사이 거리 값 측정 방법
+
+- 유클리디언 거리공식 (Euclidean Distance)
+
+![02](/assets/images/ml01/02.png)
+
+## scikit-learn 주요 매개변수
+
+- metric : 유클리디언 거리 방식
+- n_neighbors : 이웃의 수
+- weight : 가중치 함수
+ - uniform : 가중치를 동등하게 설정.
+ - distance : 가중치를 거리에 반비례하도록 설정
+
+## KNN 알고리즘 직접 구현
+
+### 과제
+
+- 예측 데이터와 모든 학습 데이터(500개)와의 거리 계산 -> 유클리드 거리 계산
+- 계산된 모든 거리값 중 설정된 k값(k=5)만큼 가장 가까운 데이터 추출
+- 추출된 데이터의 비율 확인 후 예측
+
+### 데이터 로딩 및 가공
+
+```python
+import pandas as pd
+
+data = pd.read_csv("./data/bmi_lbs.csv")
+data['Weight(kg)'] = data['Weight(lbs)'] * 0.453592 # kg 단위로 변환
+```
+
+### 학습 데이터
+
+```python
+X = data[['Height','Weight(kg)']]
+y = data['Label']
+```
+
+### 예측할 샘플 데이터
+
+```python
+sample_data = data.iloc[[30,110,150,433,498],[2,4]]
+ground_truth = data.iloc[[30,110,150,433,498],0]
+```
+
+### KNN 함수
+
+```python
+# my_KNN
+# 입력 변수 (예측할 데이터 샘플, k값)
+def my_KNN(input_data, k):
+ # 카운터 딕셔너리
+ from collections import Counter
+
+ # 1. 모든 데이터와 input데이터 사이의 거리계산
+ distance_list = []
+
+ for i in range(len(input_data)):
+ temp = (X - input_data.iloc[i]) ** 2 # X데이터 전체[키, 몸무게] - i번째 인풋[키, 몸무게] -> 결과 : [a제곱, b제곱]
+ distance = (temp.iloc[:, 0] + temp.iloc[:, 1])**0.5 # (키 + 몸무게) 의 제곱근
+
+ distance_list.append(distance)
+ distance_list = pd.Series(distance_list, index=input_data.index) # list -> series 변환, 크기 : 샘플데이터 갯수 X 500
+ #print(distance_list)
+
+ # 2. k값만큼 가장 가까운 거리의 데이터 추출
+ k_neighbors = []
+
+ for i in range(len(input_data)):
+ input_i = distance_list.iloc[i]
+ temp = []
+ for j in range(k):
+ # k개만큼 최솟값들 뽑기
+ #idx = input_i[input_i == input_i.min()].index[0]
+ idx = input_i.idxmin() # 구한 최솟값의 인덱스 구하기
+ temp.append(y.loc[idx])
+ input_i.drop([idx], inplace=True) # 최솟값 중복 없애게 이번에 뽑은 최솟값은 제거해주기
+ k_neighbors.append(temp) # k_neighbors -> 크기 : (샘플데이터 갯수 X k개의 최소거리 인덱스)
+
+ #print(k_neighbor)
+
+ # 3. 추출된 데이터의 비율 확인 후 예측
+ output = []
+ for nb in k_neighbors:
+ count = Counter(nb) # key : 결과, value: key값이 나온 갯수
+ output.append(max(count,key=count.get))
+
+ output = pd.Series(output, index=input_data.index) # input값의 인덱스 유지하기 위해 series화
+ return output
+```
+
+### 테스트
+
+- 예측
+
+```python
+sample2 = data.iloc[[0,1,2,3,4],[2,4]]
+my_KNN(sample2, 5)
+```
+
+```
+0 Obesity
+1 Normal
+2 Obesity
+3 Overweight
+4 Overweight
+dtype: object
+```
+
+- 실제 정답
+
+```python
+y.iloc[[0,1,2,3,4]]
+```
+
+```
+0 Obesity
+1 Normal
+2 Obesity
+3 Overweight
+4 Overweight
+Name: Label, dtype: object
+```
+
+- 예측
+
+```python
+sample3 = data.iloc[[12,16,19,21,31],[2,4]]
+my_KNN(sample3, 5)
+```
+
+```
+12 Overweight
+16 Extreme Obesity
+19 Extreme Obesity
+21 Extreme Obesity
+31 Weak
+dtype: object
+```
+
+- 실제 정답
+
+```python
+y.iloc[[12,16,19,21,31]]
+```
+
+```
+12 Overweight
+16 Extreme Obesity
+19 Extreme Obesity
+21 Extreme Obesity
+31 Weak
+Name: Label, dtype: object
+```
\ No newline at end of file
diff --git "a/_posts/2022-09-15-ml02_\353\215\260\354\235\264\355\204\260 \354\212\244\354\274\200\354\235\274\353\247\201.md" "b/_posts/2022-09-15-ml02_\353\215\260\354\235\264\355\204\260 \354\212\244\354\274\200\354\235\274\353\247\201.md"
new file mode 100644
index 000000000000..c98bc02266b3
--- /dev/null
+++ "b/_posts/2022-09-15-ml02_\353\215\260\354\235\264\355\204\260 \354\212\244\354\274\200\354\235\274\353\247\201.md"
@@ -0,0 +1,121 @@
+---
+layout: single
+title: "데이터 스케일링(Data Scaling)"
+categories: 머신러닝
+tag: [KNN, 머신러닝, python, 스케일링, Scaling]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+## 2. 데이터 스케일링이란?
+
+- **특성(Feature)들의 범위(range)를 정규화** 해주는 작업
+- 특성마다 다른 범위를 가지는 경우 머신러닝 모델들이 제대로 학습되지 않을 가능성이 있다.
+(KNN, SVM, Neural network 모델, Clustering 모델 등)
+
+![01.png](/assets/images/ml02/01.png)
+
+- 시력과 키를 함께 학습시킬 경우 키의 범위가 크기때문에 거리 값을 기반으로 학습 할 때 영향을 많이 준다.
+
+## 장점
+
+- 특성들을 비교 분석하기 쉽게 만들어 준다.
+- **Linear Model, Neural network Model** 등에서 학습의 안정성과 속도를 개선시킨다.
+- 하지만 특성에 따라 원래 범위를 유지하는게 좋을 경우는 scaling을 하지 않아도 된다.
+
+## 종류
+
+![02.png](/assets/images/ml02/02.png)
+
+### StandardScaler
+
+- 변수의 **평균,표준편차를 이용**해 **정규분포 형태**로 변환 (평균 0, 분산 1)
+- **이상치(Outlier)에 민감**하게 영향을 받는다
+
+### RobustScaler
+
+- 변수의 **사분위수**를 이용해 변환
+- **이상치가 있는 데이터 변환**시 사용 할 수 있다.
+
+### MinMaxScaler
+
+- 변수의 **Max 값, Min 값을 이용**해 변환 (0 ~ 1 사이 값으로 변환)
+- **이상치에 민감**하게 영향을 받는다.
+
+### Normalizer
+
+- **특성 벡터의 길이가 1**이 되도록 조정 (**행마다 정규화** 진행)
+- 특성 벡터의 길이는 상관 없고 **데이터의 방향(각도)만 중요할 때** 사용.
\ No newline at end of file
diff --git "a/_posts/2022-09-20-ml03_Decision Tree(\352\262\260\354\240\225\355\212\270\353\246\254).md" "b/_posts/2022-09-20-ml03_Decision Tree(\352\262\260\354\240\225\355\212\270\353\246\254).md"
new file mode 100644
index 000000000000..f055434083f5
--- /dev/null
+++ "b/_posts/2022-09-20-ml03_Decision Tree(\352\262\260\354\240\225\355\212\270\353\246\254).md"
@@ -0,0 +1,290 @@
+---
+layout: single
+title: "Decision Tree 결정트리"
+categories: 머신러닝
+tag: [머신러닝, python, Decision Tree, 결정트리, 분류]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+## Decision Tree란?
+
+- Tree를 만들기 위해 예/아니오 질문을 반복하며 학습한다.
+- 다양한 **앙상블**(ensemble) 모델이 존재한다 (RandomForest, GradientBoosting, XGBoost, LightGBM)
+- **분류**와 **회귀**에 모두 사용 가능
+
+![01.png](/assets/images/ml03/01.png)
+
+- 타깃 값이 한 개인 리프 노드를 순수 노드라고 한다.
+- 모든 노드가 **순수 노드**가 될 때 까지 학습하면 **복잡해지고 과대적합**이 된다.
+
+## 결정 트리 과대적합 제어
+
+- 노드 생성을 미리 중단하는 **사전 가지치기(pre-pruning)**와 트리를 만든후에 크기가 작은 노드를 삭제하는 **사후 가지치기(pruning)**가 있다 (sklearn은 사전 가지치기만 지원)
+- 트리의 최대 깊이(**max_depth, 값이 클수록 모델의 복잡도가 올라간다**)나 리프 노드의 최대 개수(**max_leaf_nodes**)를 제어
+- 노드가 분할하기 위한 데이터 포인트의 최소 개수(**min_samples_leaf**)를 지정
+
+## 지니 불순도
+
+![02.png](/assets/images/ml03/02.png)
+
+- 지니지수는 얼마나 불확실한가? (=**얼마나 많은 것들이 섞여있는가**?)를 보여준다.
+- 지니 지수가 0이라는 것은 불확실성이 0이라는 것으로 **같은 특성을 가진 객체들끼리** 잘 모여있다는 의미이다.
+- 지니 지수가 **0.5**(최대)라는 것은 **반반** 섞여 있다는 의미
+
+# Decision Tree 실습
+
+## 목표
+
+- 독버섯과 식용버섯을 분리하는 tree 모델 만들기
+- tree 모델 시각화
+- tree 모델의 특성 중요도 확인
+
+```python
+import pandas as pd
+import numpy as np
+import matplotlib.pyplot as plt
+import seaborn as sns
+from sklearn.metrics import accuracy_score
+from sklearn.model_selection import train_test_split
+```
+
+- 데이터 불러오기
+
+```python
+data = pd.read_csv('./data/mushroom/mushroom.csv')
+display(data.shape)
+display(data.head())
+```
+
+```
+(8124, 23)
+```
+
+| | poisonous | cap-shape | cap-surface | cap-color | bruises | odor | gill-attachment | gill-spacing | gill-size | gill-color | … | stalk-surface-below-ring | stalk-color-above-ring | stalk-color-below-ring | veil-type | veil-color | ring-number | ring-type | spore-print-color | population | habitat |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | p | x | s | n | t | p | f | c | n | k | … | s | w | w | p | w | o | p | k | s | u |
+| 1 | e | x | s | y | t | a | f | c | b | k | … | s | w | w | p | w | o | p | n | n | g |
+| 2 | e | b | s | w | t | l | f | c | b | n | … | s | w | w | p | w | o | p | n | n | m |
+| 3 | p | x | y | w | t | p | f | c | n | n | … | s | w | w | p | w | o | p | k | s | u |
+| 4 | e | x | s | g | f | n | f | w | b | k | … | s | w | w | p | w | o | e | n | a | g |
+
+5 rows × 23 columns
+
+```python
+data.info()
+```
+
+```
+
+RangeIndex: 8124 entries, 0 to 8123
+Data columns (total 23 columns):
+ # Column Non-Null Count Dtype
+--- ------ -------------- -----
+ 0 poisonous 8124 non-null object
+ 1 cap-shape 8124 non-null object
+ 2 cap-surface 8124 non-null object
+ 3 cap-color 8124 non-null object
+ 4 bruises 8124 non-null object
+ 5 odor 8124 non-null object
+ 6 gill-attachment 8124 non-null object
+ 7 gill-spacing 8124 non-null object
+ 8 gill-size 8124 non-null object
+ 9 gill-color 8124 non-null object
+ 10 stalk-shape 8124 non-null object
+ 11 stalk-root 8124 non-null object
+ 12 stalk-surface-above-ring 8124 non-null object
+ 13 stalk-surface-below-ring 8124 non-null object
+ 14 stalk-color-above-ring 8124 non-null object
+ 15 stalk-color-below-ring 8124 non-null object
+ 16 veil-type 8124 non-null object
+ 17 veil-color 8124 non-null object
+ 18 ring-number 8124 non-null object
+ 19 ring-type 8124 non-null object
+ 20 spore-print-color 8124 non-null object
+ 21 population 8124 non-null object
+ 22 habitat 8124 non-null object
+dtypes: object(23)
+memory usage: 1.4+ MB
+```
+
+```python
+X = data.iloc[:, 1:]
+y = data['poisonous']
+
+X.shape, y.shape
+```
+
+((8124, 22), (8124,))
+
+- 데이터 전체를 원핫인코딩
+
+```python
+X_onehot = pd.get_dummies(X)X_onehot.head()
+```
+
+| | cap-shape_b | cap-shape_c | cap-shape_f | cap-shape_k | cap-shape_s | cap-shape_x | cap-surface_f | cap-surface_g | cap-surface_s | cap-surface_y | … | population_s | population_v | population_y | habitat_d | habitat_g | habitat_l | habitat_m | habitat_p | habitat_u | habitat_w |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | … | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
+| 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | … | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
+| 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | … | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
+| 3 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | … | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
+| 4 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | … | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
+
+5 rows × 117 columns
+
+```python
+X_train, X_test, y_train, y_test = train_test_split(X_onehot, y, test_size=0.3, random_state=926)
+
+X_train.shape, X_test.shape, y_train.shape, y_test.shape
+```
+
+((5686, 117), (2438, 117), (5686,), (2438,))
+
+- 모델 생성 및 학습
+
+```python
+from sklearn.tree import DecisionTreeClassifier
+
+tree_model = DecisionTreeClassifier()
+tree_model.fit(X_train, y_train)
+
+pred = tree_model.predict(X_test)
+```
+
+- 모델 평가
+
+```python
+accuracy_score(pred, y_test)
+```
+
+1.0
+
+- 트리의 특성 중요도 확인
+ - 트리 모델은 각 특성의 중요도를 확인 할 수 있음
+ - **tree_model.feature_importances_**
+
+```python
+# 데이터프레임화 하기, 중요도 기준으로 내림차순 정렬
+df = pd.DataFrame([X_train.columns, tree_model.feature_importances_]).T
+df.sort_values(by=1, ascending=False)
+```
+
+| | 0 | 1 |
+| --- | --- | --- |
+| 27 | odor_n | 0.615161 |
+| 53 | stalk-root_c | 0.16913 |
+| 55 | stalk-root_r | 0.093209 |
+| 100 | spore-print-color_r | 0.034151 |
+| 33 | gill-spacing_c | 0.024172 |
+| … | … | … |
+| 39 | gill-color_g | 0.0 |
+| 38 | gill-color_e | 0.0 |
+| 37 | gill-color_b | 0.0 |
+| 34 | gill-spacing_w | 0.0 |
+| 116 | habitat_w | 0.0 |
+
+117 rows × 2 columns
+
+### Graphviz 시각화
+
+- tree 모델 시각화
+- **Gini Impurity(지니 불순도)** 확인해보기
+
+```python
+from sklearn.tree import export_graphvizimport graphviz
+```
+
+```python
+export_graphviz(tree_model, # 저장할 트리 모델 객체
+ out_file='tree.dot', # 결과로 저장할 파일
+ class_names=['독', '식용'], # 클래스 이름 설정
+ feature_names=X_train.columns, # 컬럼 이름 넣어주기
+ impurity=True, # 불순도 표기 여부
+ filled=True, # 색상 채우기 여부
+ rounded=True # 수치값 반올림 여부
+ )
+```
+
+```python
+# 저장한 시각화 파일 불러오기
+with open('./tree.dot', encoding='utf-8') as f:
+ dot_graph = f.read()
+
+display(graphviz.Source(dot_graph))
+```
+
+![output_20_0.svg](/assets/images/ml03/output_20_0.svg)
\ No newline at end of file
diff --git "a/_posts/2022-09-24-ml04_\354\247\221\352\260\222 \354\230\210\354\270\241 DecisionTree(\355\232\214\352\267\200).md" "b/_posts/2022-09-24-ml04_\354\247\221\352\260\222 \354\230\210\354\270\241 DecisionTree(\355\232\214\352\267\200).md"
new file mode 100644
index 000000000000..1a7319e99c34
--- /dev/null
+++ "b/_posts/2022-09-24-ml04_\354\247\221\352\260\222 \354\230\210\354\270\241 DecisionTree(\355\232\214\352\267\200).md"
@@ -0,0 +1,708 @@
+---
+layout: single
+title: "Decision Tree 집값 예측(회귀)"
+categories: 머신러닝
+tag: [머신러닝, python, Decision Tree, 결정트리, 회귀]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+## 목표
+
+- Decision Tree 모델 사용하기
+- 모델 최적화하기
+
+```python
+# 예측하기 좋은 최적의 질문을 만들어 학습하는 모델
+from sklearn.tree import DecisionTreeRegressor
+
+house_model = DecisionTreeRegressor()
+```
+
+### 2. 모델 학습
+
+- 데이터 로딩 후 탐색
+
+```python
+import pandas as pd
+
+# 데이터 로딩
+train = pd.read_csv('./data/house/train.csv')
+test = pd.read_csv('./data/house/test.csv')
+train.head()
+```
+
+| | Id | Suburb | Address | Rooms | Type | Method | SellerG | Date | Distance | Postcode | … | Car | Landsize | BuildingArea | YearBuilt | CouncilArea | Lattitude | Longtitude | Regionname | Propertycount | Price |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 5467 | Rosanna | 22 Douglas St | 2 | h | S | Miles | 19/11/2016 | 11.4 | 3084 | … | 1.0 | 757 | NaN | NaN | Banyule | -37.74280 | 145.07000 | Eastern Metropolitan | 3540 | 1200000 |
+| 1 | 4365 | North Melbourne | 103/25 Byron St | 1 | u | SP | Jellis | 16/07/2016 | 2.3 | 3051 | … | 1.0 | 0 | 60.0 | 2012.0 | Melbourne | -37.80200 | 144.95160 | Northern Metropolitan | 6821 | 450000 |
+| 2 | 9741 | Surrey Hills | 4/40 Durham Rd | 3 | u | SP | Noel | 17/06/2017 | 10.2 | 3127 | … | 1.0 | 149 | NaN | NaN | Boroondara | -37.82971 | 145.09007 | Southern Metropolitan | 5457 | 780000 |
+| 3 | 11945 | Cheltenham | 3/33 Sunray Av | 2 | t | S | Buxton | 29/07/2017 | 17.9 | 3192 | … | 1.0 | 171 | NaN | NaN | Kingston | -37.96304 | 145.06421 | Southern Metropolitan | 9758 | 751000 |
+| 4 | 4038 | Mont Albert | 7/27 High St | 3 | t | S | Fletchers | 15/10/2016 | 11.8 | 3127 | … | 2.0 | 330 | 148.0 | 2001.0 | Whitehorse | -37.81670 | 145.10700 | Eastern Metropolitan | 2079 | 1310000 |
+
+5 rows × 22 columns
+
+```python
+# 전체 데이터 갯수 파악
+train.shape, test.shape
+```
+
+((10185, 22), (3395, 21))
+
+```python
+# 컬럼 확인
+train.info()
+```
+
+```
+
+RangeIndex: 10185 entries, 0 to 10184
+Data columns (total 22 columns):
+ # Column Non-Null Count Dtype
+--- ------ -------------- -----
+ 0 Id 10185 non-null int64
+ 1 Suburb 10185 non-null object
+ 2 Address 10185 non-null object
+ 3 Rooms 10185 non-null int64
+ 4 Type 10185 non-null object
+ 5 Method 10185 non-null object
+ 6 SellerG 10185 non-null object
+ 7 Date 10185 non-null object
+ 8 Distance 10185 non-null float64
+ 9 Postcode 10185 non-null int64
+ 10 Bedroom2 10185 non-null int64
+ 11 Bathroom 10185 non-null int64
+ 12 Car 10142 non-null float64
+ 13 Landsize 10185 non-null int64
+ 14 BuildingArea 5367 non-null float64
+ 15 YearBuilt 6153 non-null float64
+ 16 CouncilArea 9174 non-null object
+ 17 Lattitude 10185 non-null float64
+ 18 Longtitude 10185 non-null float64
+ 19 Regionname 10185 non-null object
+ 20 Propertycount 10185 non-null int64
+ 21 Price 10185 non-null int64
+dtypes: float64(6), int64(8), object(8)
+memory usage: 1.7+ MB
+```
+
+```python
+# 기술 통계, include='all' 범주형 통계 값 포함(고유값, 최빈값, ...)
+train.describe(include='all')
+```
+
+| | Id | Suburb | Address | Rooms | Type | Method | SellerG | Date | Distance | Postcode | … | Car | Landsize | BuildingArea | YearBuilt | CouncilArea | Lattitude | Longtitude | Regionname | Propertycount | Price |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| count | 10185.000000 | 10185 | 10185 | 10185.000000 | 10185 | 10185 | 10185 | 10185 | 10185.000000 | 10185.000000 | … | 10142.000000 | 10185.000000 | 5367.000000 | 6153.000000 | 9174 | 10185.000000 | 10185.000000 | 10185 | 10185.000000 | 1.018500e+04 |
+| unique | NaN | 310 | 10066 | NaN | 3 | 5 | 243 | 58 | NaN | NaN | … | NaN | NaN | NaN | NaN | 33 | NaN | NaN | 8 | NaN | NaN |
+| top | NaN | Reservoir | 2 Bruce St | NaN | h | S | Nelson | 27/05/2017 | NaN | NaN | … | NaN | NaN | NaN | NaN | Moreland | NaN | NaN | Southern Metropolitan | NaN | NaN |
+| freq | NaN | 261 | 3 | NaN | 7106 | 6753 | 1156 | 364 | NaN | NaN | … | NaN | NaN | NaN | NaN | 887 | NaN | NaN | 3525 | NaN | NaN |
+| mean | 6802.613942 | NaN | NaN | 2.943250 | NaN | NaN | NaN | NaN | 10.198213 | 3105.172607 | … | 1.613883 | 573.426411 | 154.137372 | 1964.904599 | NaN | -37.809763 | 144.995347 | NaN | 7447.172018 | 1.077961e+06 |
+| std | 3926.702100 | NaN | NaN | 0.952794 | NaN | NaN | NaN | NaN | 5.866640 | 90.198740 | … | 0.959076 | 4550.757180 | 614.711880 | 37.603561 | NaN | 0.079922 | 0.104255 | NaN | 4354.473015 | 6.364301e+05 |
+| min | 3.000000 | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | 0.000000 | 3000.000000 | … | 0.000000 | 0.000000 | 0.000000 | 1196.000000 | NaN | -38.182550 | 144.431810 | NaN | 249.000000 | 1.310000e+05 |
+| 25% | 3384.000000 | NaN | NaN | 2.000000 | NaN | NaN | NaN | NaN | 6.200000 | 3044.000000 | … | 1.000000 | 178.000000 | 93.920000 | 1940.000000 | NaN | -37.857700 | 144.929500 | NaN | 4380.000000 | 6.500000e+05 |
+| 50% | 6838.000000 | NaN | NaN | 3.000000 | NaN | NaN | NaN | NaN | 9.300000 | 3084.000000 | … | 2.000000 | 448.000000 | 127.000000 | 1970.000000 | NaN | -37.802900 | 145.000130 | NaN | 6543.000000 | 9.050000e+05 |
+| 75% | 10223.000000 | NaN | NaN | 4.000000 | NaN | NaN | NaN | NaN | 13.000000 | 3149.000000 | … | 2.000000 | 652.000000 | 175.000000 | 2000.000000 | NaN | -37.756710 | 145.059280 | NaN | 10331.000000 | 1.330000e+06 |
+| max | 13577.000000 | NaN | NaN | 8.000000 | NaN | NaN | NaN | NaN | 48.100000 | 3977.000000 | … | 10.000000 | 433014.000000 | 44515.000000 | 2018.000000 | NaN | -37.408530 | 145.526350 | NaN | 21650.000000 | 7.650000e+06 |
+
+11 rows × 22 columns
+
+- 문제와 정답 추출
+- 일단은 결측치가 존재하는 컬럼과 문자형태의 컬럼은 배제
+
+```python
+X_train = train[['Propertycount', 'Rooms', 'Bedroom2']]
+y_train = train['Price']
+```
+
+```python
+# train -> 7.5 : 2.5비율로 train2, validation 데이터로 나누기
+from sklearn.model_selection import train_test_split
+
+X_train2, X_val, y_train2, y_val = train_test_split(X_train, y_train, random_state=3)
+X_train2.shape, X_val.shape, y_train2.shape, y_val.shape
+```
+
+((7638, 3), (2547, 3), (7638,), (2547,))
+
+```python
+house_model.fit(X_train2, y_train2)
+```
+
+DecisionTreeRegressor()
+
+### 3. 모델 예측
+
+```python
+pred = house_model.predict(X_val)
+pred
+```
+
+array([ 451840. , 1344925. , 684462.5, …, 1843500. , 1300000. , 2272500. ])
+
+### 4. 모델 평가
+
+- MAE(Mean Absolute Error, 평균 절대값 오차) 활용한 평가
+
+```python
+from sklearn.metrics import mean_absolute_error
+error = mean_absolute_error(y_val, pred)
+error
+```
+
+255227.3455560717
+
+### 캐글에 업로드 하기
+
+```python
+X_test = test[['Propertycount', 'Rooms', 'Bedroom2']]
+X_test.shape
+```
+
+(3395, 3)
+
+```python
+test_pre = house_model.predict(X_test)
+test_pre
+```
+
+array([ 382333.33333333, 522500. , 700000. , …, 710500. , 651357.14285714, 1042205.88235294])
+
+```python
+# 정답지 파일 로딩
+submission = pd.read_csv("./data/house/sample_submission.csv")
+submission
+```
+
+| | Id | Price |
+| --- | --- | --- |
+| 0 | 3189 | 0 |
+| 1 | 2539 | 0 |
+| 2 | 9171 | 0 |
+| 3 | 4741 | 0 |
+| 4 | 12455 | 0 |
+| … | … | … |
+| 3390 | 12276 | 0 |
+| 3391 | 4618 | 0 |
+| 3392 | 12913 | 0 |
+| 3393 | 11741 | 0 |
+| 3394 | 1072 | 0 |
+
+3395 rows × 2 columns
+
+```python
+test.head()
+```
+
+| | Id | Suburb | Address | Rooms | Type | Method | SellerG | Date | Distance | Postcode | … | Bathroom | Car | Landsize | BuildingArea | YearBuilt | CouncilArea | Lattitude | Longtitude | Regionname | Propertycount |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 3189 | Hawthorn | 22/9 Lisson Gr | 1 | u | S | Biggin | 19/11/2016 | 4.6 | 3122 | … | 1 | 1.0 | 0 | 52.0 | 1970.0 | Boroondara | -37.82610 | 145.02690 | Southern Metropolitan | 11308 |
+| 1 | 2539 | Fitzroy | 113/300 Young St | 1 | u | SP | Jellis | 19/11/2016 | 1.6 | 3065 | … | 1 | 1.0 | 0 | 52.0 | 2011.0 | Yarra | -37.79740 | 144.97990 | Northern Metropolitan | 5825 |
+| 2 | 9171 | Greenvale | 7 Murray Ct | 5 | h | S | Barry | 3/06/2017 | 20.4 | 3059 | … | 3 | 5.0 | 1750 | 310.0 | 1990.0 | Hume | -37.65439 | 144.89113 | Northern Metropolitan | 4864 |
+| 3 | 4741 | Port Melbourne | 172 Albert St | 2 | h | S | hockingstuart | 10/12/2016 | 3.8 | 3207 | … | 1 | 0.0 | 106 | 70.0 | 1910.0 | Port Phillip | -37.83460 | 144.93730 | Southern Metropolitan | 8648 |
+| 4 | 12455 | Brunswick West | 47 Everett St | 4 | h | VB | Nelson | 9/09/2017 | 5.2 | 3055 | … | 2 | 2.0 | 600 | 180.0 | 2004.0 | NaN | -37.75465 | 144.94144 | Northern Metropolitan | 7082 |
+
+5 rows × 21 columns
+
+```python
+submission['Price'] = test_pre
+submission.head()
+```
+
+| | Id | Price |
+| --- | --- | --- |
+| 0 | 3189 | 3.823333e+05 |
+| 1 | 2539 | 5.225000e+05 |
+| 2 | 9171 | 7.000000e+05 |
+| 3 | 4741 | 9.572778e+05 |
+| 4 | 12455 | 1.294818e+06 |
+
+```python
+# csv파일로 저장
+submission.to_csv("./data/house/myPrediction.csv",
+ index=False)
+```
+
+## 다른 컬럼을 이용해보자.
+
+1. 결측치가 있는 컬럼
+ - 데이터를 버린다. -> drop, dropna
+ - 데이터를 채운다. -> fillna
+ - 기술통계 활용
+ - 모델 활용 -> 결측치를 정답, 주변컬럼을 문제로 설정
+2. 문자형태의 컬럼
+ - 문자타입 -> 숫자타입 변경(인코딩)
+ - 라벨 인코딩 -> 임의의 숫자를 글자에 부여
+ - 원핫 인코딩 -> 0과1을 이용해서 변환
+
+```python
+test.columns
+```
+
+Index([‘Id’, ‘Suburb’, ‘Address’, ‘Rooms’, ‘Type’, ‘Method’, ‘SellerG’, ‘Date’, ‘Distance’, ‘Postcode’, ‘Bedroom2’, ‘Bathroom’, ‘Car’, ‘Landsize’, ‘BuildingArea’, ‘YearBuilt’, ‘CouncilArea’, ‘Lattitude’, ‘Longtitude’, ‘Regionname’, ‘Propertycount’], dtype=‘object’)
+
+```python
+train.corr()
+```
+
+| | Id | Rooms | Distance | Postcode | Bedroom2 | Bathroom | Car | Landsize | BuildingArea | YearBuilt | Lattitude | Longtitude | Propertycount | Price | h | t | u | Method_label | Regionname_label |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| Id | 1.000000 | 0.100741 | 0.293943 | 0.092843 | 0.116731 | 0.040834 | 0.099056 | 0.026959 | 0.024208 | 0.104456 | 0.040772 | 0.056133 | 0.008075 | -0.051498 | 0.114506 | -0.041921 | -0.099133 | 0.011529 | 0.267904 |
+| Rooms | 0.100741 | 1.000000 | 0.294621 | 0.053791 | 0.937357 | 0.588991 | 0.406340 | 0.024508 | 0.115067 | -0.059154 | 0.012710 | 0.104277 | -0.081669 | 0.497539 | 0.507407 | -0.028028 | -0.543692 | 0.003428 | 0.166209 |
+| Distance | 0.293943 | 0.294621 | 1.000000 | 0.430208 | 0.294438 | 0.120574 | 0.268467 | 0.024602 | 0.108834 | 0.245371 | -0.134113 | 0.239075 | -0.052206 | -0.164388 | 0.213490 | -0.012074 | -0.228571 | -0.093669 | 0.510509 |
+| Postcode | 0.092843 | 0.053791 | 0.430208 | 1.000000 | 0.059840 | 0.108927 | 0.052475 | 0.027304 | 0.061235 | 0.021593 | -0.408562 | 0.450340 | 0.057250 | 0.111511 | -0.024155 | -0.008960 | 0.032696 | 0.016300 | -0.055349 |
+| Bedroom2 | 0.116731 | 0.937357 | 0.294438 | 0.059840 | 1.000000 | 0.579122 | 0.402223 | 0.024382 | 0.112563 | -0.045148 | 0.012189 | 0.105248 | -0.080096 | 0.473742 | 0.485838 | -0.027327 | -0.520256 | 0.005557 | 0.165695 |
+| Bathroom | 0.040834 | 0.588991 | 0.120574 | 0.108927 | 0.579122 | 1.000000 | 0.319449 | 0.038824 | 0.106673 | 0.154065 | -0.072667 | 0.116156 | -0.050214 | 0.464396 | 0.169435 | 0.119998 | -0.267174 | 0.084622 | 0.015280 |
+| Car | 0.099056 | 0.406340 | 0.268467 | 0.052475 | 0.402223 | 0.319449 | 1.000000 | 0.023537 | 0.096233 | 0.113786 | -0.003670 | 0.067147 | -0.024338 | 0.235853 | 0.253054 | -0.014562 | -0.270764 | 0.012097 | 0.112987 |
+| Landsize | 0.026959 | 0.024508 | 0.024602 | 0.027304 | 0.024382 | 0.038824 | 0.023537 | 1.000000 | 0.546089 | 0.040293 | 0.010407 | 0.010326 | -0.009704 | 0.040665 | 0.022618 | -0.018688 | -0.012693 | 0.029722 | 0.022445 |
+| BuildingArea | 0.024208 | 0.115067 | 0.108834 | 0.061235 | 0.112563 | 0.106673 | 0.096233 | 0.546089 | 1.000000 | 0.021732 | 0.052281 | -0.033764 | -0.029216 | 0.082028 | 0.060088 | -0.004645 | -0.064177 | -0.001155 | 0.060186 |
+| YearBuilt | 0.104456 | -0.059154 | 0.245371 | 0.021593 | -0.045148 | 0.154065 | 0.113786 | 0.040293 | 0.021732 | 1.000000 | 0.060937 | -0.017734 | 0.006838 | -0.324162 | -0.393885 | 0.298914 | 0.230626 | 0.027549 | 0.130729 |
+| Lattitude | 0.040772 | 0.012710 | -0.134113 | -0.408562 | 0.012189 | -0.072667 | -0.003670 | 0.010407 | 0.052281 | 0.060937 | 1.000000 | -0.359648 | 0.060830 | -0.210428 | 0.108648 | -0.035545 | -0.096862 | -0.027790 | 0.141548 |
+| Longtitude | 0.056133 | 0.104277 | 0.239075 | 0.450340 | 0.105248 | 0.116156 | 0.067147 | 0.010326 | -0.033764 | -0.017734 | -0.359648 | 1.000000 | 0.056610 | 0.206866 | -0.008365 | 0.006092 | 0.005237 | 0.022174 | -0.006846 |
+| Propertycount | 0.008075 | -0.081669 | -0.052206 | 0.057250 | -0.080096 | -0.050214 | -0.024338 | -0.009704 | -0.029216 | 0.006838 | 0.060830 | 0.056610 | 1.000000 | -0.046582 | -0.065180 | -0.020591 | 0.085853 | -0.005943 | -0.184688 |
+| Price | -0.051498 | 0.497539 | -0.164388 | 0.111511 | 0.473742 | 0.464396 | 0.235853 | 0.040665 | 0.082028 | -0.324162 | -0.210428 | 0.206866 | -0.046582 | 1.000000 | 0.391641 | -0.061995 | -0.392931 | 0.029182 | -0.237278 |
+| h | 0.114506 | 0.507407 | 0.213490 | -0.024155 | 0.485838 | 0.169435 | 0.253054 | 0.022618 | 0.060088 | -0.393885 | 0.108648 | -0.008365 | -0.065180 | 0.391641 | 1.000000 | -0.453989 | -0.807573 | -0.065250 | 0.191063 |
+| t | -0.041921 | -0.028028 | -0.012074 | -0.008960 | -0.027327 | 0.119998 | -0.014562 | -0.018688 | -0.004645 | 0.298914 | -0.035545 | 0.006092 | -0.020591 | -0.061995 | -0.453989 | 1.000000 | -0.158859 | 0.008709 | -0.037968 |
+| u | -0.099133 | -0.543692 | -0.228571 | 0.032696 | -0.520256 | -0.267174 | -0.270764 | -0.012693 | -0.064177 | 0.230626 | -0.096862 | 0.005237 | 0.085853 | -0.392931 | -0.807573 | -0.158859 | 1.000000 | 0.066537 | -0.186580 |
+| Method_label | 0.011529 | 0.003428 | -0.093669 | 0.016300 | 0.005557 | 0.084622 | 0.012097 | 0.029722 | -0.001155 | 0.027549 | -0.027790 | 0.022174 | -0.005943 | 0.029182 | -0.065250 | 0.008709 | 0.066537 | 1.000000 | -0.070270 |
+| Regionname_label | 0.267904 | 0.166209 | 0.510509 | -0.055349 | 0.165695 | 0.015280 | 0.112987 | 0.022445 | 0.060186 | 0.130729 | 0.141548 | -0.006846 | -0.184688 | -0.237278 | 0.191063 | -0.037968 | -0.186580 | -0.070270 | 1.000000 |
+- Type 컬럼 전처리
+
+```python
+# 원한인코딩 함수
+type_onehot = pd.get_dummies(train['Type'])
+type_onehot
+```
+
+| | h | t | u |
+| --- | --- | --- | --- |
+| 0 | 1 | 0 | 0 |
+| 1 | 0 | 0 | 1 |
+| 2 | 0 | 0 | 1 |
+| 3 | 0 | 1 | 0 |
+| 4 | 0 | 1 | 0 |
+| … | … | … | … |
+| 10180 | 1 | 0 | 0 |
+| 10181 | 1 | 0 | 0 |
+| 10182 | 1 | 0 | 0 |
+| 10183 | 1 | 0 | 0 |
+| 10184 | 0 | 1 | 0 |
+
+10185 rows × 3 columns
+
+```python
+type_onehot_test = pd.get_dummies(test['Type'])
+type_onehot_test
+```
+
+| | h | t | u |
+| --- | --- | --- | --- |
+| 0 | 0 | 0 | 1 |
+| 1 | 0 | 0 | 1 |
+| 2 | 1 | 0 | 0 |
+| 3 | 1 | 0 | 0 |
+| 4 | 1 | 0 | 0 |
+| … | … | … | … |
+| 3390 | 1 | 0 | 0 |
+| 3391 | 1 | 0 | 0 |
+| 3392 | 0 | 1 | 0 |
+| 3393 | 1 | 0 | 0 |
+| 3394 | 0 | 0 | 1 |
+
+3395 rows × 3 columns
+
+```python
+train = pd.concat([train, type_onehot], axis=1)
+train.head()
+```
+
+| | Id | Suburb | Address | Rooms | Type | Method | SellerG | Date | Distance | Postcode | … | YearBuilt | CouncilArea | Lattitude | Longtitude | Regionname | Propertycount | Price | h | t | u |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 5467 | Rosanna | 22 Douglas St | 2 | h | S | Miles | 19/11/2016 | 11.4 | 3084 | … | NaN | Banyule | -37.74280 | 145.07000 | Eastern Metropolitan | 3540 | 1200000 | 1 | 0 | 0 |
+| 1 | 4365 | North Melbourne | 103/25 Byron St | 1 | u | SP | Jellis | 16/07/2016 | 2.3 | 3051 | … | 2012.0 | Melbourne | -37.80200 | 144.95160 | Northern Metropolitan | 6821 | 450000 | 0 | 0 | 1 |
+| 2 | 9741 | Surrey Hills | 4/40 Durham Rd | 3 | u | SP | Noel | 17/06/2017 | 10.2 | 3127 | … | NaN | Boroondara | -37.82971 | 145.09007 | Southern Metropolitan | 5457 | 780000 | 0 | 0 | 1 |
+| 3 | 11945 | Cheltenham | 3/33 Sunray Av | 2 | t | S | Buxton | 29/07/2017 | 17.9 | 3192 | … | NaN | Kingston | -37.96304 | 145.06421 | Southern Metropolitan | 9758 | 751000 | 0 | 1 | 0 |
+| 4 | 4038 | Mont Albert | 7/27 High St | 3 | t | S | Fletchers | 15/10/2016 | 11.8 | 3127 | … | 2001.0 | Whitehorse | -37.81670 | 145.10700 | Eastern Metropolitan | 2079 | 1310000 | 0 | 1 | 0 |
+
+5 rows × 25 columns
+
+```python
+test = pd.concat([test, type_onehot_test], axis=1)
+test.head()
+```
+
+| | Id | Suburb | Address | Rooms | Type | Method | SellerG | Date | Distance | Postcode | … | BuildingArea | YearBuilt | CouncilArea | Lattitude | Longtitude | Regionname | Propertycount | h | t | u |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 3189 | Hawthorn | 22/9 Lisson Gr | 1 | u | S | Biggin | 19/11/2016 | 4.6 | 3122 | … | 52.0 | 1970.0 | Boroondara | -37.82610 | 145.02690 | Southern Metropolitan | 11308 | 0 | 0 | 1 |
+| 1 | 2539 | Fitzroy | 113/300 Young St | 1 | u | SP | Jellis | 19/11/2016 | 1.6 | 3065 | … | 52.0 | 2011.0 | Yarra | -37.79740 | 144.97990 | Northern Metropolitan | 5825 | 0 | 0 | 1 |
+| 2 | 9171 | Greenvale | 7 Murray Ct | 5 | h | S | Barry | 3/06/2017 | 20.4 | 3059 | … | 310.0 | 1990.0 | Hume | -37.65439 | 144.89113 | Northern Metropolitan | 4864 | 1 | 0 | 0 |
+| 3 | 4741 | Port Melbourne | 172 Albert St | 2 | h | S | hockingstuart | 10/12/2016 | 3.8 | 3207 | … | 70.0 | 1910.0 | Port Phillip | -37.83460 | 144.93730 | Southern Metropolitan | 8648 | 1 | 0 | 0 |
+| 4 | 12455 | Brunswick West | 47 Everett St | 4 | h | VB | Nelson | 9/09/2017 | 5.2 | 3055 | … | 180.0 | 2004.0 | NaN | -37.75465 | 144.94144 | Northern Metropolitan | 7082 | 1 | 0 | 0 |
+
+5 rows × 24 columns
+
+- Method 컬럼 전처리
+
+```python
+# 라벨인코딩
+# 캐글의 metadata 정보 참고
+method_dict = {
+ 'S' : 0,
+ 'SP' : 1,
+ 'PI' : 2,
+ 'PN' : 3,
+ 'SN' : 4,
+ 'NB' : 5,
+ 'VB' : 6,
+ 'W' : 7,
+ 'SA' : 8,
+ 'SS' : 9
+}
+method_label = train['Method'].map(method_dict)
+method_label_test = test['Method'].map(method_dict)
+method_label
+```
+
+```
+0 0
+1 1
+2 1
+3 0
+4 0
+ ..
+10180 0
+10181 2
+10182 0
+10183 2
+10184 0
+Name: Method, Length: 10185, dtype: int64
+```
+
+```python
+train['Method_label'] = method_label
+test['Method_label'] = method_label_test
+train.head()
+```
+
+| | Id | Suburb | Address | Rooms | Type | Method | SellerG | Date | Distance | Postcode | … | CouncilArea | Lattitude | Longtitude | Regionname | Propertycount | Price | h | t | u | Method_label |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 5467 | Rosanna | 22 Douglas St | 2 | h | S | Miles | 19/11/2016 | 11.4 | 3084 | … | Banyule | -37.74280 | 145.07000 | Eastern Metropolitan | 3540 | 1200000 | 1 | 0 | 0 | 0 |
+| 1 | 4365 | North Melbourne | 103/25 Byron St | 1 | u | SP | Jellis | 16/07/2016 | 2.3 | 3051 | … | Melbourne | -37.80200 | 144.95160 | Northern Metropolitan | 6821 | 450000 | 0 | 0 | 1 | 1 |
+| 2 | 9741 | Surrey Hills | 4/40 Durham Rd | 3 | u | SP | Noel | 17/06/2017 | 10.2 | 3127 | … | Boroondara | -37.82971 | 145.09007 | Southern Metropolitan | 5457 | 780000 | 0 | 0 | 1 | 1 |
+| 3 | 11945 | Cheltenham | 3/33 Sunray Av | 2 | t | S | Buxton | 29/07/2017 | 17.9 | 3192 | … | Kingston | -37.96304 | 145.06421 | Southern Metropolitan | 9758 | 751000 | 0 | 1 | 0 | 0 |
+| 4 | 4038 | Mont Albert | 7/27 High St | 3 | t | S | Fletchers | 15/10/2016 | 11.8 | 3127 | … | Whitehorse | -37.81670 | 145.10700 | Eastern Metropolitan | 2079 | 1310000 | 0 | 1 | 0 | 0 |
+
+5 rows × 26 columns
+
+### 결측치와 문자형태를 처리해서 다양한 컬럼으로 학습해보자.
+
+1. train, test 데이터에 원하는 결측치,인코딩 처리 실시
+2. 원하는 컬럼 선택
+3. train을 train2와 val로 분리
+4. 모델 학습 후 평가
+5. test 데이터를 예측해 kaggle에 업로드
+
+- Car 컬럼 전처리
+
+```python
+# Car 컬럼의 결측치 채우기
+train['Car'].describe()
+```
+
+```
+count 10142.000000
+mean 1.613883
+std 0.959076
+min 0.000000
+25% 1.000000
+50% 2.000000
+75% 2.000000
+max 10.000000
+Name: Car, dtype: float64
+```
+
+```python
+# 중앙값으로 채우기
+train['Car'] = train['Car'].fillna(train['Car'].median())
+test['Car'] = test['Car'].fillna(train['Car'].median())
+```
+
+- Regionname 컬럼 전처리
+
+```python
+train['Regionname'].value_counts()
+```
+
+```
+Southern Metropolitan 3525
+Northern Metropolitan 2912
+Western Metropolitan 2219
+Eastern Metropolitan 1096
+South-Eastern Metropolitan 348
+Eastern Victoria 37
+Northern Victoria 30
+Western Victoria 18
+Name: Regionname, dtype: int64
+```
+
+```python
+regionname_dict = {
+ 'Southern Metropolitan' : 0,
+ 'Northern Metropolitan' : 1,
+ 'Western Metropolitan' : 2,
+ 'Eastern Metropolitan' : 3,
+ 'South-Eastern Metropolitan' : 4,
+ 'Eastern Victoria' : 5,
+ 'Northern Victoria' : 6,
+ 'Western Victoria' : 7
+}
+
+regionname_label = train['Regionname'].map(regionname_dict)
+regionname_label_test = test['Regionname'].map(regionname_dict)
+regionname_label
+```
+
+```python
+train['Regionname_label'] = regionname_label
+test['Regionname_label'] = regionname_label_test
+train.head()
+```
+
+| | Id | Suburb | Address | Rooms | Type | Method | SellerG | Date | Distance | Postcode | … | Lattitude | Longtitude | Regionname | Propertycount | Price | h | t | u | Method_label | Regionname_label |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 5467 | Rosanna | 22 Douglas St | 2 | h | S | Miles | 19/11/2016 | 11.4 | 3084 | … | -37.74280 | 145.07000 | Eastern Metropolitan | 3540 | 1200000 | 1 | 0 | 0 | 0 | 3 |
+| 1 | 4365 | North Melbourne | 103/25 Byron St | 1 | u | SP | Jellis | 16/07/2016 | 2.3 | 3051 | … | -37.80200 | 144.95160 | Northern Metropolitan | 6821 | 450000 | 0 | 0 | 1 | 1 | 1 |
+| 2 | 9741 | Surrey Hills | 4/40 Durham Rd | 3 | u | SP | Noel | 17/06/2017 | 10.2 | 3127 | … | -37.82971 | 145.09007 | Southern Metropolitan | 5457 | 780000 | 0 | 0 | 1 | 1 | 0 |
+| 3 | 11945 | Cheltenham | 3/33 Sunray Av | 2 | t | S | Buxton | 29/07/2017 | 17.9 | 3192 | … | -37.96304 | 145.06421 | Southern Metropolitan | 9758 | 751000 | 0 | 1 | 0 | 0 | 0 |
+| 4 | 4038 | Mont Albert | 7/27 High St | 3 | t | S | Fletchers | 15/10/2016 | 11.8 | 3127 | … | -37.81670 | 145.10700 | Eastern Metropolitan | 2079 | 1310000 | 0 | 1 | 0 | 0 | 3 |
+
+5 rows × 27 columns
+
+- CouncilArea 전처리
+
+```python
+X_train = train[['Rooms', 'Distance', 'Bedroom2', 'Bathroom', 'Car', 'Landsize', 'Propertycount', 'h', 't', 'u', 'Method_label', 'Regionname_label', 'Lattitude', 'Longtitude']]
+y_train = train['Price']
+
+X_test = test[['Rooms', 'Distance', 'Bedroom2', 'Bathroom', 'Car', 'Landsize', 'Propertycount', 'h', 't', 'u', 'Method_label', 'Regionname_label', 'Lattitude', 'Longtitude']]
+X_train.head()
+```
+
+| | Rooms | Distance | Bedroom2 | Bathroom | Car | Landsize | Propertycount | h | t | u | Method_label | Regionname_label | Lattitude | Longtitude |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 2 | 11.4 | 2 | 1 | 1.0 | 757 | 3540 | 1 | 0 | 0 | 0 | 3 | -37.74280 | 145.07000 |
+| 1 | 1 | 2.3 | 1 | 1 | 1.0 | 0 | 6821 | 0 | 0 | 1 | 1 | 1 | -37.80200 | 144.95160 |
+| 2 | 3 | 10.2 | 2 | 1 | 1.0 | 149 | 5457 | 0 | 0 | 1 | 1 | 0 | -37.82971 | 145.09007 |
+| 3 | 2 | 17.9 | 2 | 1 | 1.0 | 171 | 9758 | 0 | 1 | 0 | 0 | 0 | -37.96304 | 145.06421 |
+| 4 | 3 | 11.8 | 3 | 2 | 2.0 | 330 | 2079 | 0 | 1 | 0 | 0 | 3 | -37.81670 | 145.10700 |
+
+```python
+X_test.head()
+```
+
+| | Rooms | Distance | Bedroom2 | Bathroom | Car | Landsize | Propertycount | h | t | u | Method_label | Regionname_label | Lattitude | Longtitude |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| 0 | 1 | 4.6 | 1 | 1 | 1.0 | 0 | 11308 | 0 | 0 | 1 | 0 | 0 | -37.82610 | 145.02690 |
+| 1 | 1 | 1.6 | 1 | 1 | 1.0 | 0 | 5825 | 0 | 0 | 1 | 1 | 1 | -37.79740 | 144.97990 |
+| 2 | 5 | 20.4 | 5 | 3 | 5.0 | 1750 | 4864 | 1 | 0 | 0 | 0 | 1 | -37.65439 | 144.89113 |
+| 3 | 2 | 3.8 | 2 | 1 | 0.0 | 106 | 8648 | 1 | 0 | 0 | 0 | 0 | -37.83460 | 144.93730 |
+| 4 | 4 | 5.2 | 4 | 2 | 2.0 | 600 | 7082 | 1 | 0 | 0 | 6 | 1 | -37.75465 | 144.94144 |
+- 검증데이터 분리
+
+```python
+X_train3, X_val3, y_train3, y_val3 = train_test_split(X_train, y_train, test_size=0.2, random_state=916)
+```
+
+- 모델 정의
+
+```python
+house_model2 = DecisionTreeRegressor()
+```
+
+- 모델 학습
+
+```python
+house_model2.fit(X_train3, y_train3)
+```
+
+DecisionTreeRegressor()
+
+- 모델 예측
+
+```python
+pred = house_model2.predict(X_val3)
+```
+
+- 모델 평가
+
+```python
+mean_absolute_error(y_val3, pred)
+```
+
+245946.3264604811
+
+- 캐글 제출
+
+```python
+submission['Price'] = house_model2.predict(X_test)
+submission.head()
+```
+
+| | Id | Price |
+| --- | --- | --- |
+| 0 | 3189 | 348000.0 |
+| 1 | 2539 | 597000.0 |
+| 2 | 9171 | 725500.0 |
+| 3 | 4741 | 1000000.0 |
+| 4 | 12455 | 1610000.0 |
+
+```python
+submission.to_csv("./data/house/myPrediction.csv",
+ index=False)
+```
+
+### 모델 최적화
+
+- 모델복잡도 제어하기
+- KNN은 이웃의 숫자로 모델의 복잡도 제어
+ - 이웃의 숫자가 커질수록 단순,
+ - 숫자가 적어질수록 복잡해진다.
+- DecisionTree는 질문의 깊이로 모델의 복잡도를 제어(max_depth)
+ - 깊이가 얕으면 단순,
+ - 깊이가 깊으면 복잡해진다.
+
+```python
+train_score_list = []
+val_score_list = []
+
+for d in range(1, 30):
+ m = DecisionTreeRegressor(max_depth=d)
+ m.fit(X_train3, y_train3)
+ pred_train = m.predict(X_train3)
+ pred_val = m.predict(X_val3)
+
+ score_train = mean_absolute_error(y_train3, pred_train)
+ score_val = mean_absolute_error(y_val3, pred_val)
+ train_score_list.append(score_train)
+ val_score_list.append(score_val)
+ print(d, ":", score_val)
+```
+
+```
+1 : 417733.49974970485
+2 : 343806.0797298899
+3 : 296665.1121222014
+4 : 266627.09369623766
+5 : 250658.9323204579
+6 : 240011.4545997507
+7 : 228006.44228511458
+8 : 225544.86401968033
+9 : 223158.24205112088
+10 : 222866.61170201903
+11 : 222247.53782971326
+12 : 226750.59009251397
+13 : 232785.61967598234
+14 : 236449.60651906623
+15 : 238339.72952208374
+16 : 235256.46193522654
+17 : 239032.74728354442
+18 : 246129.8931403534
+19 : 245102.87083875437
+20 : 248124.2068576584
+21 : 248081.48209490062
+22 : 247554.49879324844
+23 : 247564.5162821142
+24 : 243753.52724594992
+25 : 248604.58184694266
+26 : 244163.59204712813
+27 : 244919.02258222876
+28 : 245388.98429062346
+29 : 248771.09327442318
+```
+
+```python
+# 시각화
+import matplotlib.pyplot as plt
+
+plt.figure(figsize=(10, 5))
+plt.plot(range(1, 30), train_score_list)
+plt.plot(range(1, 30), val_score_list)
+plt.show()
+```
+
+![output_61_0.png](/assets/images/ml04/output_61_0.png)
+
+- max_depth가 11일때 가장 낮은 MAE값을 얻을 수 있다.
\ No newline at end of file
diff --git "a/_posts/2022-09-29-ml05_Ensemble(\354\225\231\354\203\201\353\270\224).md" "b/_posts/2022-09-29-ml05_Ensemble(\354\225\231\354\203\201\353\270\224).md"
new file mode 100644
index 000000000000..b80eab6e9071
--- /dev/null
+++ "b/_posts/2022-09-29-ml05_Ensemble(\354\225\231\354\203\201\353\270\224).md"
@@ -0,0 +1,155 @@
+---
+layout: single
+title: "Ensemble(앙상블)"
+categories: 머신러닝
+tag: [머신러닝, python, Ensemble, 결정트리, 앙상블]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+## Decision Tree Ensemble(결정트리 앙상블)
+
+- 앙상블(ensemble)은 **여러 머신러닝 모델을 연결**하여 더 강력한 모델을 만드는 기법
+- 결정트리의 가지치기 후 **과대적합되는 단점을 보완**하는 모델
+- **RandomForest, GradientBoosting, XGBoost, LightGBM, CatBoost** 등
+- 회귀와 분류에 모두 사용 가능
+
+## 앙상블 기법
+
+1. **보팅(Voting)**
+ - 서로 다른 모델을 학습시켜 예측 결과를 **다수의 결과로 투표**하는 방법
+ - 앙상블의 가장 기본 원리
+ - **하드 보팅**(최종 예측 결과로만 보팅), **소프트 보팅**(모델들의 예측 확률로 보팅)으로 나뉜다.
+2. **배깅(Bagging)**
+ - 같은 알고리즘을 가진 모델들을 학습시켜 예측 결과를 투표하는 방법
+ - 학습 데이터(행)를 모델마다 다르게 샘플링(Bootstraping), 병렬 학습
+ - 학습에 사용되는 컬럼(열)을 다르게 랜덤 선택
+ - 배깅이 적용된 Decision Tree가 **RandomForest**
+3. **부스팅**
+ - 같은 알고리즘을 가진 모델을 학습시켜 예측결과를 투표하는 방법
+ - **이전 모델이 잘못 예측한 부분을 다음 모델이 강조해서 학습**하는 방법
+ - 순차적 학습 -> 학습 속도가 비교적 느림
+
+## RandomForest (배깅 모델)
+
+- 서로 다른 방향으로 **과대적합된 트리를 많이 만들고 평균을 내어 일반화** 시키는 모델
+- 다양한 트리를 만드는 방법 두 가지
+ - 트리를 만들 때 사용하는 데이터 포인트 샘플을 무작위로 선택한다.
+ - 노드 구성시 기준이 되는 특성을 무작위로 선택하게 한다.
+- **결정트리의 단점을 보완**하고 **장점은 그대로** 가지고 있는 모델이어서 별다른 조정 없이도 괜찮을 결과를 만들어낸다.
+- 트리가 여러 개 만들어지기 때문에 비전문가에게 예측과정을 보여주기는 어렵다.
+- 랜덤하게 만들어지기 때문에 random_state를 고정해야 같은 결과를 볼 수 있다.
+
+### 주요 매개변수
+
+- n_estimators : 생성할 트리의 갯수
+- n개의 데이터 부트스트랩 샘플 구성 (n개의 데이터 포인트 중 무작위로 n 횟수만큼 반복 추출, 중복된 데이터가 들어 있을 수 있다.)
+- max_features : 무작위로 선택될 후보 특성의 개수 (각 노드 별로 max_features 개수 만큼 무작위로 특성을 고른 뒤 최선의 특성을 찾는다.)
+- max_features를 높이면 트리들이 비슷해진다.
+
+```python
+from sklearn.ensemble import RandomForestClassifier
+
+rf_model = RandomForestClassifier(random_state=923,
+ n_estimators=1000, # 앙상블할 모델(tree)의 갯수
+ max_features=0.6, # 학습에 사용할 특성(컬럼) 수 (설정된 값은 60%)
+ max_depth=15 # 트리의 깊이 설정
+ )
+```
+
+## GradientBoosting (부스팅 모델)
+
+- 정확도가 낮더라도 얕은 깊이의 모델을 만든 뒤, 나타난 예측 오류를 두 번째 모델이 보완한다.
+- **이전 트리의 예측 오류를 보완하여 다음 트리를 만드는 작업을 반복**한다.
+- 마지막까지 **성능을 쥐어짜고 싶은 경우** 사용한다, 주로 경진 대회에서 많이 활용.
+(GradientBoosting을 더 발전시킨 **XGBoost**도 있음)
+- 보통 트리의 깊이를 깊게하지 않기 때문에 **예측 속도는 비교적 빠르다**. 하지만 이전 트리의 오차를 반영해서 새로운 트리를 만들기 때문에 **학습속도가 느리다**.
+- 특성의 **스케일을 조정하지 않아도 된다.**
+
+### 주요 매개변수
+
+- n_estimators : 생성할 트리의 개수 (트리가 많아질수록 과대적합이 될 수 있다.)
+- learning_rate : 오차를 보정하는 정도 (값이 높을수록 오차를 많이 보정하려고 한다.)
+- max_depth : 트리의 깊이 (일반적으로 **트리의 깊이를 깊게 설정하지 않는다.**)
+
+```python
+from sklearn.ensemble import GradientBoostingClassifier
+
+gbtree = GradientBoostingClassifier(n_estimators=100, # 트리의 갯수(순차적으로 생성되고, 이전 트리의 오류에 가중치가 더해짐)
+ learning_rate=0.1, # 이전트리의 오류를 다음트리에 얼마나 반영할지
+ max_depth=5, # 트리의 깊이
+ subsample=1 # 1: 전체데이터 사용, 과적합이 우려된다면 값을 줄여도 됨
+ )
+```
\ No newline at end of file
diff --git "a/_posts/2022-10-01-DL01_\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225,\354\230\244\354\260\250\354\227\255\354\240\204\355\214\214,\355\231\234\354\204\261\355\231\224\355\225\250\354\210\230 \354\240\225\353\246\254.md" "b/_posts/2022-10-01-DL01_\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225,\354\230\244\354\260\250\354\227\255\354\240\204\355\214\214,\355\231\234\354\204\261\355\231\224\355\225\250\354\210\230 \354\240\225\353\246\254.md"
new file mode 100644
index 000000000000..b31027c1f61e
--- /dev/null
+++ "b/_posts/2022-10-01-DL01_\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225,\354\230\244\354\260\250\354\227\255\354\240\204\355\214\214,\355\231\234\354\204\261\355\231\224\355\225\250\354\210\230 \354\240\225\353\246\254.md"
@@ -0,0 +1,163 @@
+---
+layout: single
+title: "경사하강법,오차역전파,활성화함수 정리"
+categories: 딥러닝
+tag: [딥러닝, python, 경사하강법, 오차역전파, 활성화함수, 신경망]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+## 오차 역전파
+
+- 순전파 : 입력 데이터를 입력층에서부터 출력층까지 정방향으로 이동시키며 출력 값을 예측해 나가는 과정
+- 역전파 : 출력층에서 발생한 오차를 입력층 쪽으로 전파시키면서 최적의 결과를 학습해 나가는 과정
+
+![img2.png](/assets/images/DL01/img2.png)
+
+## 경사하강법
+
+- 그 자리에서 loss가 작아지는 방향으로 이동하는 방법
+- 즉, 비용함수(loss)의 기울기를 구하여 기울기가 낮은 쪽으로 계속 이동하여 값을 최적화 시키는 방법이다.
+
+![img1.png](/assets/images/DL01/img1.png)
+
+- 비용함수의 기울기 = loss 변화량 / w 변화량
+ - w값의 변화량에 따라 loss가 변화하는 정도
+ - 즉, 모델은 학습할 때, loss가 감소하는 w로 최적화한다.
+ - 최적화 함수(optimizer)가 경사하강법을 수행하면서 모델을 최적화한다.
+
+## 기울기 소실(Vanishing Gradient)
+
+![img3.png](/assets/images/DL01/img3.png)
+
+- 깊은 층을 만들어 보니 출력층에서 시작된 가중치의 업데이트(역전파)가 처음 층까지 잘 전달되지 않는 현상 발생
+- 이를 기울기 소실이라고 함
+- 시그모이드 함수의 특성 때문
+
+### sigmoid의 문제점
+
+- 시그모이드 함수를 미분하면 최대치는 약 0.3임
+- 1보다 작기때문에 계속 곱하다 보면 0에 가까워져 가중치를 수정하기 어려워짐
+
+![img4.png](/assets/images/DL01/img4.png)
+
+## 활성화 함수 종류
+
+- sigmoid의 문제점을 해결하기 위해 다양한 활성화 함수가 존재
+
+![img5.png](/assets/images/DL01/img5.png)
+
+## 최적화 함수(Optimizer)의 종류
+
+### SGD(확률적 경사 하강법)
+
+- 경사하강법은 전체 데이터를 이용해 업데이트 하는 방법이다
+- 하지만, 실제로는 전체 데이터를 모두 활용하여 모델을 학습하기는 불가능(경사하강법은 이론상으로만 존재)
+- SGD, 확률적 경사 하강법 : 확률적으로 선택된 일부 데이터를 이용해 업데이트
+- SGD를 수행할 때 확률적으로 선택할 데이터 갯수 : batch_size로 결정한다
+
+![img6.png](/assets/images/DL01/img6.png)
+
+### batch size
+
+- 일반적으로 PC 메모리의 한계 및 속도 저하 때문에 대부분의 경우 한번의 epoch에 모든 데이터를 집어넣기 힘듦
+- batch_size를 줄임
+ - 메모리 소모가 적음
+ - 학습 속도가 느림, 정확도는 높아짐
+- batch_size를 높임
+ - 메모리 소모가 큼
+ - 학습 속도가 빠름, 정확도는 낮아짐
+- batch_size의 디폴트 값은 32이며 일반적으로 32, 64가 많이 사용됨
+
+### 모멘텀
+
+- 경사 하강법에 관성을 적용해 업데이트함
+- 현재 batch 뿐만 아니라 이전 batch 데이터의 학습결과도 반영하는 방법
+- 개선된 모멘텀 방식으로는 네스테로프 모멘텀이 있다.
+
+### Adagrad(에이다그래드)
+
+![img9.png](/assets/images/DL01/img9.png)
+
+- 학습을 진행하면서 학습률을 점차 줄여가는 방법
+- 처음에는 크게 학습하다가 조금씩 작게 학습함
+- 학습을 빠르고 정확하게 할 수 있는 장점이 있다.
+
+### 최적화 함수(Optimizer) 종류 한눈에 보기
+
+![img10.png](/assets/images/DL01/img10.png)
+
+- 방향(스텝 방향)과 학습률(스텝 사이즈)을 모두 고려하는게 Adam
+- Adam을 사용하면 기본은 간다
\ No newline at end of file
diff --git "a/_posts/2022-10-05-DL02_CNN \355\225\251\354\204\261\352\263\261 \354\213\240\352\262\275\353\247\235 \354\240\225\353\246\254.md" "b/_posts/2022-10-05-DL02_CNN \355\225\251\354\204\261\352\263\261 \354\213\240\352\262\275\353\247\235 \354\240\225\353\246\254.md"
new file mode 100644
index 000000000000..98d519bd5821
--- /dev/null
+++ "b/_posts/2022-10-05-DL02_CNN \355\225\251\354\204\261\352\263\261 \354\213\240\352\262\275\353\247\235 \354\240\225\353\246\254.md"
@@ -0,0 +1,319 @@
+---
+layout: single
+title: "Tensorflow:: CNN 합성곱 신경망 정리"
+categories: 딥러닝
+tag: [딥러닝, python, 컨볼루젼, 합성곱, 신경망, 2D, 이미지 처리, tensorflow, CNN]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+## MLP에서의 이미지 분석
+
+- MLP 신경망을 이미지 처리에 사용하면 이미지의 위치에 민감하게 동작하여 **위치에 종속**적인 결과를 얻게 됨
+- 이는 모든 픽셀을 연산하기 때문
+- MLP로 이미지 처리를 하기 위해서는 이미지를 1차원 벡터로 변환하고 입력층으로 사용해야 하는데, 이러면 공간적인 구조 정보가 유실되므로 좀 더 정확한 예측이 힘들다.
+
+# CNN (Convolution Neural Network)
+
+- MLP에서는 크기가 바뀌거나 이미지 데이터의 위치, 회전 정도가 다를 경우 특징 추출이 굉장히 힘들다.
+- 이러한 문제를 **CNN**으로 해결할 수 있다.
+
+합성곱 신경망은 이미지 처리에 탁월한 성능을 보이는 신경망이고, 특성추출부와 MLP로 이루어져 있다.
+
+![01_1.png](/assets/images/DL02/01_1.png)
+
+## 특성추출부
+
+- Convolution Layer(합성곱층)
+
+ 특징들을 부각해주는 역할을 함
+
+- Pooling Layer(풀링층)
+
+ 특징이 약한 부분을 없애주는 역할
+
+
+**Conv Layer**는 특정 연산을 수행하기 때문에 뒤에 활성화 함수가 붙지만, **Pooling Layer**는 필요 없는 픽셀을 제거하는 역할만 수행하기 때문에 뒤에 활성화 함수가 오지 않는다.
+
+### 채널
+
+- 합성곱 계층에서 이미지의 색상 정보를 채널이라고 부름
+- 이미지는 (높이, 너비, 채널)형태의 3차원 텐서
+- 흑백 이미지는 채널이 1, 컬러 이미지는(RGB) 3이다.
+
+## 필터(=커널 = 가중치)
+
+합성곱층은 합성곱 연산을 통해 이미지의 특징을 추출한다.
+
+이때, **필터**라는 N * M 크기의 행렬로 이미지를 처음부터 끝까지(가장 왼쪽 위 > 오른쪽 아래) 순차적으로 훑으면서(**슬라이딩**) 필터와 겹쳐지는 부분의 각 이미지와 필터의 원소(**가중치**) 값을 곱해서 모두 더한 값을 출력한다. 필터를 걸쳐 출력되는 데이터를 **특성맵**(feature map)이라고 한다.
+
+![01_2.png](/assets/images/DL02/01_2.png)
+
+- 그림 설명
+
+ 채널이 1인 (흑백 이미지) 2차원 합성곱일 경우 입력층에 필터를 지나쳐 출력 되는 예시이다.
+
+ **4x4**크기 Input 이미지와 **2x2**크기 kernel을 합성곱 연산할 경우 **3x3**형태의 특성맵이 출력됨.
+
+ 물론, 필터에는 각 가중치가 존재하면서 **편향**도 존재한다.
+
+ 예를 들어, 편향이 +1 이라면 출력되는 특성맵의 각 원소들은 +1이 되어 출력된다.
+
+
+### 여러개의 필터
+
+Dense 층을 여러개를 사용하는 것처럼 여러개의 필터를 사용할 수 있고, 각 필터의 가중치도 서로 다르다.
+
+여러개의 필터를 사용하면 특징 추출을 더 세밀하게 할 수 있다.
+
+- 채널 C개 입력 * 채널 C인 **필터가 FN개** = **채널 FN개 출력**
+- 즉, **출력 데이터의 채널 수 = 필터의 개수**
+
+![01_3.png](/assets/images/DL02/01_3.png)
+
+- 우선 Input 이미지는 크기가 4X4인 상태이다.
+
+ 채널 1인 Input 이미지에 채널 1인 2X2 kernel 3개를 사용하면 3개의 3X3 크기의 특성맵을 얻을 수 있다.
+
+ 즉, 한 이미지의 특징을 추출한 부분을 3개로 세분화 시켰고, 이미지의 크기는 줄어들었다.
+
+
+### 3차원 합성곱 정리
+
+보통 컬러 이미지를 입력 데이터로 사용한다면 3차원 배열(높이, 너비, 채널(깊이)) 형태이다.
+
+이러한 경우엔 커널도 동일한 채널을 갖게 된다.
+
+(**입력의 채널 수와 필터의 채널 수가 같아야함**)
+
+- **kernel의 채널(깊이)의 수 = Input 데이터의 채널(깊이)의 수**
+- **합성곱 연산 결과** : Input 데이터는 **채널 수와 상관없이 kernel 별로 1개의 특성맵**이 만들어진다.즉, **입력 데이터의 깊이와 상관없이 (높이, 너비, 1)**의 특성 맵을 얻음
+- 다만, 합성곱 연산에서 다수의 커널을 사용할 경우 : 특성 맵은 **(높이, 너비, 커널의 수)** 크기
+
+ (특성 맵의 채널은 합성곱 연산에 사용된 커널의 수)
+
+
+![01_6.png](/assets/images/DL02/01_6.png)
+
+## 패딩(padding)
+
+합성곱 연산을 수행하며 kernel을 통과할때마다 특성맵의 크기는 점점 **줄어든다**. 하지만, 복잡한 학습을 위해 깊은 층을 쌓아야 한다면 크기가 점점 줄어드는 탓에 더 이상 연산이 힘들어지게 된다.
+
+그러므로, 여러 합성곱 연산 이후에도 특성맵의 크기를 비슷하게 유지되도록 **패딩**을 수행할 수 있다.
+
+![01_4.png](/assets/images/DL02/01_4.png)
+
+- 입력 이미지의 가장 자리에 지정된 폭만큼 가상의 픽셀로 **테두리를 추가**한다.
+- 그렇다면 필터의 **슬라이딩 범위가 늘어나게** 되고 kernel에서 출력되는 특성맵의 크기는 패딩하기 전보다 커지게 된다.
+- 주로 0으로 채우기 대문에 제로 패딩(zero padding)이라고도 함
+
+## 축소 샘플링
+
+합성곱 수행 후 다음 계층으로 전달할 때, 모든 정보를 전달하지 않고 일부만 샘플링하여 넘겨주는 작업을 말한다. 크게 **스트라이드(stride)**와 **풀링(pooling)**이 있다.
+
+## 스트라이드(stride)
+
+그림에서는 kernel이 Input 이미지에 한 칸씩 이동(슬라이딩)하면서 합성곱 연산을 수행한다.
+
+하지만, 커널의 슬리이딩 범위 또한 사용자가 정할 수 있다.
+
+이러한 이동 범위를 **스트라이드(stride)**라고 한다.
+
+- kernel이 2픽셀. 3픽셀씩 건너 뛰면서 합성곱 연산을 수행하는 방법
+- stride2 또는 stride3이라고 하는데, 이렇게 하면 **ouput 특성맵의 크기를 더 줄일 수 있다.**
+
+## 풀링(pooling)
+
+일반적으로 합성곱 층(합성곱 연산 + 활성화 함수) 다음에는 풀링 층을 추가한다.
+
+합성곱 층 ouput인 특성맵이 크고 복잡하다면 이를 **축소(다운 샘플링)**해야 한다. 이 과정을 풀링 연산이라 하며, 이러한 연산을 하는 층이 **풀링 층**이다.
+
+- 일반적으로 **최대 풀링(max pooling)**과 **평균 풀링(average pooling)**이 사용된다.
+- **최대 풀링**은 지역 내 최대 값을 뽑아내는 방법이다.
+- 최대 풀링을 하면 지역 내의 대표 정보만 남기고 나머지 신호들을 제거하는 효과가 있음
+- **평균 풀링**은 지역 내 평균 값을 뽑아내는 방법이다.
+
+![01_5.png](/assets/images/DL02/01_5.png)
+
+- 2X2 Max Pooling 수행
+
+ 4X4 특성맵을 2X2 맥스 풀링하면 절반으로 특성맵이 작아지는 것을 확인할 수 있다.
+
+ 풀링은 통상적으로 2X2 풀링을 사용한다.
+
+
+## 합성곱과 풀링의 차이
+
+풀링도 합성곱 연산과 유사하게 커널을 슬라이딩 시켜 특성 맵을 얻으므로 유사한 느낌을 가질 수 있다.
+
+하지만, 풀링은 합성곱 연산과 달리 **곱하기나(가중치)** **더하는(편향)** 연산이 없고, 풀링 과정에서 커널이 슬라이딩할 때 서로 겹치지 않는다.
+
+## 합성곱층 + 풀링층 사용
+
+앞서 확인한 내용들을 바탕으로 컨볼루션 층과 풀링 층은 쌍으로 보통 사용한다.
+
+(컨볼루션 층 + 풀링 층) 또는 (컨볼루션 층 + 컨볼루션 층 + 풀링 층) 이런 식으로 사용하게 되는데,
+
+2차원 이상의 크기로 출력됨
+
+그 후에 밀집층(은닉층+출력층 또는 출력층)을 사용하여 원하는 결과값을 얻기 위해 1차원 배열로 풀어서 펼치는 작업 수행, 따라서 Flatten을 사용하여 1차원 크기로 바꾸어 사용한다.
+
+## CNN 모델 만들기
+
+```python
+from tensorflow.keras.layers import Conv2D, MaxPool2D, Flatten
+import numpy as np
+import pandas as pd
+import matplotlib.pyplot as plt
+```
+
+- Conv2D : 2D 이미지 데이터에 대해 특징이 되는 부분들을 부각시켜줌
+ - input_shape : Input 데이터 크기(height, width, channel)
+ - filters : 필터의 갯수
+ - kernel_size : 필터의 크기
+ - padding=‘same’ : 원본 데이터의 크기에 맞게 알아서 패딩 적용(valid : 적용X)
+- MaxPool2D : 2D 이미지 데이터에 대해 필요 없는 정보를 삭제(축소 샘플링)
+ - pool_size : 디폴트 값은 2(2 X 2)
+
+```python
+# 모델 설계
+cnn_model = Sequential()
+
+# 특성 추출부(Conv층)
+cnn_model.add(Conv2D(input_shape=(224, 224, 3), filters=128, kernel_size=(3, 3), padding='same', activation='relu'))
+
+# 특성 추출부(Pooling층)
+cnn_model.add(MaxPool2D())
+cnn_model.add(Conv2D(filters=256, kernel_size=(3, 3), padding='same', activation='relu'))
+cnn_model.add(MaxPool2D())
+cnn_model.add(Conv2D(filters=128, kernel_size=(3, 3), padding='same', activation='relu'))
+cnn_model.add(MaxPool2D())
+cnn_model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu'))cnn_model.add(MaxPool2D())
+
+# 분류기(MLP)
+cnn_model.add(Flatten())
+cnn_model.add(Dense(128, activation='relu'))
+cnn_model.add(Dense(64, activation='relu'))
+cnn_model.add(Dense(32, activation='relu'))
+cnn_model.add(Dense(3, activation='softmax'))
+```
+
+- 생성한 CNN 모델 정보 확인하기
+
+```python
+cnn_model.summary()
+```
+
+```
+Model: "sequential_1"
+_________________________________________________________________
+ Layer (type) Output Shape Param #
+=================================================================
+ conv2d (Conv2D) (None, 224, 224, 128) 3584
+
+ max_pooling2d (MaxPooling2D (None, 112, 112, 128) 0
+ )
+
+ conv2d_1 (Conv2D) (None, 112, 112, 256) 295168
+
+ max_pooling2d_1 (MaxPooling (None, 56, 56, 256) 0
+ 2D)
+
+ conv2d_2 (Conv2D) (None, 56, 56, 128) 295040
+
+ max_pooling2d_2 (MaxPooling (None, 28, 28, 128) 0
+ 2D)
+
+ conv2d_3 (Conv2D) (None, 28, 28, 64) 73792
+
+ max_pooling2d_3 (MaxPooling (None, 14, 14, 64) 0
+ 2D)
+
+ flatten_1 (Flatten) (None, 12544) 0
+
+ dense_5 (Dense) (None, 128) 1605760
+
+ dense_6 (Dense) (None, 64) 8256
+
+ dense_7 (Dense) (None, 32) 2080
+
+ dense_8 (Dense) (None, 3) 99
+
+=================================================================
+Total params: 2,283,779
+Trainable params: 2,283,779
+Non-trainable params: 0
+_________________________________________________________________
+```
\ No newline at end of file
diff --git "a/_posts/2022-10-09-springboot01_Spring Boot \355\224\204\353\241\234\354\240\235\355\212\270 \354\213\234\354\236\221.md" "b/_posts/2022-10-09-springboot01_Spring Boot \355\224\204\353\241\234\354\240\235\355\212\270 \354\213\234\354\236\221.md"
new file mode 100644
index 000000000000..a42d2f4f0c85
--- /dev/null
+++ "b/_posts/2022-10-09-springboot01_Spring Boot \355\224\204\353\241\234\354\240\235\355\212\270 \354\213\234\354\236\221.md"
@@ -0,0 +1,282 @@
+---
+layout: single
+title: "Spring Boot 프로젝트 시작"
+categories: SpringBoot
+tag: [Java, Spring, Spring Boot, STS, Eclipse]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+## STS로 스프링 부트 시작하기
+
+- Java Development Kit(JDK): 8이상 (11이상 권장)
+- STS 다운로드 : [https://spring.io/tools](https://spring.io/tools)
+
+## 프로젝트 생성하기
+
+Spring Initializer로 프로젝트 세팅 후 STS에서 프로젝트를 시작하는 방법이다.
+
+[https://start.spring.io/](https://start.spring.io/)
+
+![00_1.png](/assets/images/springboot01/00_1.png)
+
+- 프로젝트 환경
+ - Tool : STS
+ - build : Maven
+ - Language : Java
+ - Spring Boot Version : 2.7.4
+ - Packageing : Jar
+ - JAVA Version : 8
+
+이니셜라이저를 사용하게 되면 프로젝트를 좀 더 간편하게 생성할 수 있다.
+
+필요한 기능을 사용하기 위해 우측의 Dependencies에서 선택하여 프로젝트를 생성할 수 있기 때문에 초반 세팅에 귀찮은 작업에 낭비되는 시간을 절약할 수 있다.
+
+프로젝트 셋팅 완료 후 다운로드 받은 후, 해당 파일을 STS의 workspace로 이동시킨다.
+
+## Spring Boot 프로젝트 설정
+
+## 1. porm.xml 설정
+
+### **POM(프로젝트 객체 모델(Project Object Model))**
+
+- Maven의 기능을 이용하기 위해서 POM이 사용된다.
+- POM은 pom.xml파일을 말하며 pom.xml은 Maven을 이용하는 프로젝트의 root에 존재하는 xml 파일이다.
+
+ (하나의 자바 프로젝트에 빌드 툴을 Maven으로 설정하면, 프로젝트 최상위 디렉토리에 "pom.xml"이라는 파일이 생성된다.)
+
+- 파일은 프로젝트마다 1개이며, pom.xml만 보면 프로젝트의 모든 설정, 의존성 등을 알 수 있다.
+- 다른 파일이름으로 지정할 수도 있다. (mvn -f 파일명.xml test). 하지만 pom.xml으로 사용하기를 권장
+
+**ex) pom.xml 예시**
+
+```xml
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.4
+
+
+ com.example
+ demo
+ 0.0.1-SNAPSHOT
+ demo
+ Demo project for Spring Boot
+
+ 1.8
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.2.2
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
+```
+
+### 엘리먼트
+
+- modelVersion : POM model의 버전
+- parent : 프로젝트의 계층 정보
+- groupId : 프로젝트를 생성하는 조직의 고유 아이디를 결정한다. 일반적으로 도메인 이름을 거꾸로 적는다.
+- artifactId : 프로젝트 빌드시 파일 대표이름 이다. groupId 내에서 유일해야 한다. Maven을 이용하여 빌드시 다음과 같은 규칙으로 파일이 생성 된다.
+
+ artifactid-version.packaging. 위 예의 경우 빌드할 경우 bo-0.0.1-SNAPSHOT.war 파일이 생성된다. (하단 예시 파일 참고)
+
+- version : 프로젝트의 현재 버전, 프로젝트 개발 중일 때는 SNAPSHOT을 접미사로 사용.
+- packaging : 패키징 유형(jar, war, ear 등)
+- name : 프로젝트, 프로젝트 이름
+- description : 프로젝트에 대한 간략한 설명
+- url : 프로젝트에 대한 참고 Reference 사이트
+- properties : 버전관리시 용이 하다. ex) 하당 자바 버전을 선언 하고 dependencies에서 다음과 같이 활용 가능 하다.
+
+ ${java.version}
+
+- dependencies : dependencies태그 안에는 프로젝트와 의존 관계에 있는 라이브러리들을 관리 한다.
+- build : 빌드에 사용할 플러그인 목록
+
+### 라이브러리
+
+Spring부트는 spring-boot-starter로 시작하는 라이브러리를 제공한다. starter-parent에 지정된 라이브러리 버전을 따른다.
+
+- spring-boot-starter-web
+
+ : Spring MVC를 사용한 RESTful서비스를 개발하는데 사용.
+
+- spring-boot-starter-test
+
+ : Junit, Hamcrest, Mockito를 포함하는 스프링 어플리케이션을 테스트 가능하도록 한다.
+
+- spring-boot-devtools
+
+ : devtools는 Spring boot에서 제공하는 개발 편의를 위한 모듈이다. 쉽게 말하면 브라우저로 전송되는 내용들에 대한 코드가 변경되면, **자동으로 어플리케이션을 재시작**하여 브라우저에도 업데이트를 해주는 역할을 한다.
+
+- mybatis-spring-boot-starter
+
+ : 스프링부트 위에 MyBatis 애플리케이션을 빠르게 빌드 할 수 있다.
+
+ - DataSource 를 자동 감지합니다.
+ - SqlSessionFactory 를 전달 하는 인스턴스를 자동 생성하고 등록합니다
+ - DataSource.SqlSessionFactoryBean 의 인스턴스를 만들고 등록합니다.
+ - @Mapper주석이 표시된 매퍼를 자동 스캔하고에 연결합니다.
+ - SqlSessionTemplateSpring 컨텍스트에 등록하여 Bean에 주입 할 수 있도록합니다.
+- mysql-connector-java
+
+ : 스프링부트에서 MySQL을 사용하기 위한 라이브러리
+
+- lombok
+
+ : Java 라이브러리로 반복되는 getter, setter, toString 등의 메서드 작성 코드를 줄여주는 코드 다이어트 라이브러리
+
+- spring-boot-starter-thymeleaf
+
+ : ThymeLeaf 템플릿을 사용하기 위한 라이브러리
+
+
+## 2. application.properties 설정
+
+이 파일은 스프링부트가 애플리케이션을 구동할 때 자동으로 로딩하는 파일이다.
+
+key - value 형식으로 값을 정의하면 애플리케이션에서 참조하여 사용할 수 있다.
+
+![01_1.png](/assets/images/springboot01/01_1.png)
+
+- url을 호출할 때 필요한 context-path
+- Server 포트 설정
+
+ 기본 포트는 8080
+
+- JSP View Resolver(JSP 사용할 때)
+- MySQL 접속 정보
+- mapper.xml 경로 설정(별도의 경로를 사용할 때 설정)
+- ThymeLeaf 설정
+
+ 기본 경로는 classpath:/templates/
\ No newline at end of file
diff --git "a/_posts/2022-10-10-DL03_\354\240\204\354\235\264\355\225\231\354\212\265 fine_tuning.md" "b/_posts/2022-10-10-DL03_\354\240\204\354\235\264\355\225\231\354\212\265 fine_tuning.md"
new file mode 100644
index 000000000000..c3e891687584
--- /dev/null
+++ "b/_posts/2022-10-10-DL03_\354\240\204\354\235\264\355\225\231\354\212\265 fine_tuning.md"
@@ -0,0 +1,106 @@
+---
+layout: single
+title: "Tensorflow:: 전이학습, Fine tuning"
+categories: 딥러닝
+tag: [딥러닝, python, 전이학습, 사전학습, Fine tuning, tensorflow]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+전이학습이란 다른 데이터 셋으로 이미 학습한 모델을 유사한 다른 데이터를 인식하는데 사용하는 기법
+
+- 이 방법은 특히 새로 훈련시킬 데이터가 충분히 확보되지 못한 경우에 높은 학습 효율을 높여줌
+- 전이학습 모델을 적절히 이용하는 방법은 특성 추출(feature extraction) 방식과 미세 조정(fine-tuning) 방식이 있다.
+
+### 전이학습 - 특성 추출 방식(feature extraction)
+
+![02_1.png](/assets/images/DL03/02_1.png)
+
+CNN 층에서 특성추출부만 가져와서 사용하는 방식이다.
+
+- 특성추출부 부분만 사용하는 이유는 분류기(MLP)의 경우 우리가 해결 하고자 하는 문제에 맞게 새로 설정해줘야 하기 때문
+- 단, 새롭게 분류할 클래스의 종류가 사전 학습에 사용된 데이터와 특징이 매우 다르면, 특성추출부 전체를 재사용해서는 안되고 앞 단의 일부 계층만을 재사용해야 함(심플한 특징들만 추출해내기 위해)
+
+### 전이학습 - 미세 조정 방식(fine-tuning)
+
+![02_2.png](/assets/images/DL03/02_2.png)
+
+'사전 학습된 모델의 가중치’ 를 목적에 맞게 전체 또는 일부를 재학습시키는 방식이다.
+
+특성 추출부의 층들 중 하단부 몇 개의 계층을 전결합층 분류기(MLP)와 함께 새로 학습시킨다.
+
+- 처음부터 특성추출부 계층들과 분류기(MLP)를 같이 훈련시키면 새롭게 만든 분류기에서 발생하는 큰 에러 값으로 인해, 특성추출부에서 사전 학습된 가중치가 많이 손실될 수 있음
+- 처음에는 분류기(MLP)의 파라미터가 랜덤하게 초기화 되어 있으므로 컨볼루션 베이스 중 앞 단 계층들을 고정(동결)하고 뒷 단의 일부 계층만 학습이 가능하게 설정한 후, MLP와 같이 학습시켜
+파라미터(w, b) 들을 적당하게 잡아 준다.
\ No newline at end of file
diff --git "a/_posts/2022-10-14-DL04_\353\213\244\354\244\221\353\266\204\353\245\230_\353\252\250\353\215\270_\353\247\214\353\223\244\352\270\260(3\354\242\205\353\245\230_\353\217\231\353\254\274).md" "b/_posts/2022-10-14-DL04_\353\213\244\354\244\221\353\266\204\353\245\230_\353\252\250\353\215\270_\353\247\214\353\223\244\352\270\260(3\354\242\205\353\245\230_\353\217\231\353\254\274).md"
new file mode 100644
index 000000000000..c344d3387c1b
--- /dev/null
+++ "b/_posts/2022-10-14-DL04_\353\213\244\354\244\221\353\266\204\353\245\230_\353\252\250\353\215\270_\353\247\214\353\223\244\352\270\260(3\354\242\205\353\245\230_\353\217\231\353\254\274).md"
@@ -0,0 +1,688 @@
+---
+layout: single
+title: "Tensorflow:: 다중분류_모델_만들기(3종류_동물)"
+categories: 딥러닝
+tag: [딥러닝, python, 전이학습, 사전학습, Fine tuning, tensorflow, 다중분류, 이미지, CNN]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+# 목표
+
+1. CNN망 직접 설계하여 이미지 다중분류 하기(3개의 클래스)
+2. VGG16모델 전이학습 활용하여 모델 보완
+ 1. 전이학습 - 특성 추출 방식
+ 2. 전이학습 - 미세 조정 방식
+3. 데이터 증식(ImageDataGenerator 사용) 활용하여 모델 보완
+
+구글에 고슴도치, 햄스터, 푸들을 검색한 결과로 나온 이미지 각 400장을 크롤링하여 저장해 놓은 npz 데이터를 활용한다.
+
+저장된 npz 데이터를 활용하여 고슴도치, 햄스터, 푸들로 분류할 수 있는 CNN 모델 생성하기
+
+## 생성한 NPZ 파일 로드
+
+```python
+data = np.load('/content/drive/MyDrive/Colab Notebooks/2022GJAI_DL/GJAI_DL/data/animal.npz')
+```
+
+```python
+X_train = data['X_train']
+X_test = data['X_test']
+y_train = data['y_train']
+y_test = data['y_test']
+
+X_train.shape, X_test.shape, y_train.shape, y_test.shape
+```
+
+```
+((960, 224, 224, 3), (240, 224, 224, 3), (960,), (240,))
+```
+
+# 1. CNN 모델 만들기
+
+```python
+from tensorflow.keras.layers import Conv2D, MaxPool2D, Flatten
+import numpy as np
+import pandas as pd
+import matplotlib.pyplot as plt
+```
+
+- **Conv2D** : 2D 이미지 데이터에 대해 특징이 되는 부분들을 부각시켜줌
+ - input_shape : Input 데이터 크기(높이 ,넓이, 채널)
+ - filters : 필터의 갯수
+ - kernel_size : 필터의 크기
+ - padding=‘same’ : 원본 데이터의 크기에 맞게 알아서 패딩 적용(valid : 적용X)
+- **MaxPool2D** : 2D 이미지 데이터에 대해 필요 없는 정보를 삭제(축소 샘플링)
+ - pool_size : 디폴트 값은 2(2 X 2)
+
+```python
+# 모델 설계
+cnn_model = Sequential()
+
+# 특성 추출부(Conv층)
+cnn_model.add(Conv2D(input_shape=(224, 224, 3), filters=128, kernel_size=(3, 3), padding='same', activation='relu'))
+
+# 특성 추출부(Pooling)
+cnn_model.add(MaxPool2D())
+cnn_model.add(Conv2D(filters=256, kernel_size=(3, 3), padding='same', activation='relu'))
+cnn_model.add(MaxPool2D())
+cnn_model.add(Conv2D(filters=128, kernel_size=(3, 3), padding='same', activation='relu'))
+cnn_model.add(MaxPool2D())
+cnn_model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu'))cnn_model.add(MaxPool2D())
+
+# 분류기(MLP)
+cnn_model.add(Flatten())
+cnn_model.add(Dense(128, activation='relu'))
+cnn_model.add(Dense(64, activation='relu'))
+cnn_model.add(Dense(32, activation='relu'))
+cnn_model.add(Dense(3, activation='softmax'))
+```
+
+### **생성한 CNN 모델 정보 확인하기**
+
+```python
+cnn_model.summary()
+```
+
+```
+Model: "sequential_1"
+_________________________________________________________________
+ Layer (type) Output Shape Param #
+=================================================================
+ conv2d (Conv2D) (None, 224, 224, 128) 3584
+
+ max_pooling2d (MaxPooling2D (None, 112, 112, 128) 0
+ )
+
+ conv2d_1 (Conv2D) (None, 112, 112, 256) 295168
+
+ max_pooling2d_1 (MaxPooling (None, 56, 56, 256) 0
+ 2D)
+
+ conv2d_2 (Conv2D) (None, 56, 56, 128) 295040
+
+ max_pooling2d_2 (MaxPooling (None, 28, 28, 128) 0
+ 2D)
+
+ conv2d_3 (Conv2D) (None, 28, 28, 64) 73792
+
+ max_pooling2d_3 (MaxPooling (None, 14, 14, 64) 0
+ 2D)
+
+ flatten_1 (Flatten) (None, 12544) 0
+
+ dense_5 (Dense) (None, 128) 1605760
+
+ dense_6 (Dense) (None, 64) 8256
+
+ dense_7 (Dense) (None, 32) 2080
+
+ dense_8 (Dense) (None, 3) 99
+
+=================================================================
+Total params: 2,283,779
+Trainable params: 2,283,779
+Non-trainable params: 0
+_________________________________________________________________
+```
+
+### **모델 컴파일**
+
+```python
+cnn_model.compile(loss="sparse_categorical_crossentropy",
+ optimizer='Adam',
+ metrics=['acc']
+ )
+```
+
+### **모델 학습**
+
+```python
+h1 = cnn_model.fit(X_train, y_train, validation_split=0.2, epochs=50, batch_size=128)
+```
+
+### **학습 과정 시각화**
+
+```python
+plt.figure(figsize=(15, 5))
+plt.plot(h1.history['acc'], label='acc')
+plt.plot(h1.history['val_acc'], label='val_acc')
+plt.legend()
+plt.show()
+```
+
+![output_18_0.png](/assets/images/DL04/output_18_0.png)
+
+훈련 데이터에서는 정확도가 높지만, 검증셋에서 정확도가 매우 낮아지는 과적합 상태를 확인할 수 있다
+
+### **정확도 외에 정밀도, 재현율, F1스코어 까지 확인해보기**
+
+- 모델의 예측결과는 각 클래스에 대한 확률값으로 나오기 때문에(softmax)
+- 가장 높은 값의 인덱스를 반환해주는 np.argmax로 변환해서 점수 확인
+
+```python
+from sklearn.metrics import classification_report
+pred = cnn_model.predict(X_test)
+print(classification_report(y_test, np.argmax(pred, axis=1)))
+```
+
+```
+8/8 [==============================] - 2s 151ms/step
+ precision recall f1-score support
+
+ 0 0.52 0.43 0.47 76
+ 1 0.53 0.43 0.47 84
+ 2 0.46 0.62 0.53 80
+
+ accuracy 0.50 240
+ macro avg 0.50 0.50 0.49 240
+weighted avg 0.50 0.50 0.49 240
+```
+
+- precision(정밀도) : 모델이 True라고 분류한것 중 실제 True의 비율
+- recall(재현율) : 실제 True인 것 중 모델이 True라고 예측한 비율
+- accuracy(정확도) : 전체 중에서 모델이 옳게 예측한 비율
+- f1-score : 정밀도와 재현율의 조화평균
+
+정확도는 0.50으로 낮은 결과가 나왔다.
+
+즉, 직접 설계한 CNN 모델로는 한번에 좋은 결과를 도출하기 어려움
+
+구글에서 크롤링한 데이터이기 때문에, 좋은 결과를 얻기 위해 VGG16모델을 이용해 전이학습을 해보자.
+
+# 2. VGG16 전이학습 수행
+
+### VGG16 모델 불러오기
+
+```python
+from tensorflow.keras.applications import VGG16
+```
+
+```python
+pre_trained_model = VGG16(include_top=False,
+ weights='imagenet',
+ input_shape=(224, 224, 3)
+ )
+```
+
+- include_top=False : 불러온 모델의 MLP층(분류기)을 사용하지 않고 특성추출부만 사용(=특성 추출 방식)
+- weights=‘imagenet’ : 이미지넷 챌린지 대회에서 학습한 해당 모델의 w,b값을 그대로 사용(default)
+
+### VGG16 모델 정보 확인해보기
+
+```python
+pre_trained_model.summary()
+```
+
+```
+Model: "vgg16"
+_________________________________________________________________
+ Layer (type) Output Shape Param #
+=================================================================
+ input_1 (InputLayer) [(None, 224, 224, 3)] 0
+
+ block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
+
+ block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
+
+ block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
+
+ block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
+
+ block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
+
+ block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
+
+ block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
+
+ block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
+
+ block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
+
+ block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
+
+ block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
+
+ block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
+
+ block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
+
+ block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
+
+ block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
+
+ block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
+
+ block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
+
+ block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
+
+=================================================================
+Total params: 14,714,688
+Trainable params: 14,714,688
+Non-trainable params: 0
+_________________________________________________________________
+```
+
+## a. 전이학습 - 특성 추출 방식 이용
+
+imagenet 챌린지 대회에서는 1000개의 이미지를 분류했으나 여기선 3개의 이미지를 분류할것이기 때문에 MLP층만 다르게 설정하는 특성 추출 방식으로 전이학습을 해보자
+
+- VGG16의 특성추출부를 Sequential 객체에 추가하고, Flatten을 수행하여 직접 MLP를 정의해서 사용
+- 이전에 생성했던 CNN 모델과 비교를 하기 위해 은닉층의 형태와 컴파일 작업을 동일한 형태로 수행했다.
+
+```python
+cnn_model2 = Sequential()
+
+# VGG16의 특성추출부
+cnn_model2.add(pre_trained_model)
+# MLP
+cnn_model2.add(Flatten())
+cnn_model2.add(Dense(128, activation='relu'))
+cnn_model2.add(Dense(64, activation='relu'))
+cnn_model2.add(Dense(32, activation='relu'))
+cnn_model2.add(Dense(3, activation='softmax'))
+
+cnn_model2.compile(loss="sparse_categorical_crossentropy",
+ optimizer='Adam',
+ metrics=['acc']
+ )
+```
+
+```python
+cnn_model2.compile(loss="sparse_categorical_crossentropy",
+ optimizer='Adam',
+ metrics=['acc']
+ )
+```
+
+```python
+cnn_model2.fit(X_train, y_train, validation_split=0.2, epochs=50, batch_size=128)
+```
+
+### 정확도 확인해보기
+
+정확도만 먼저 비교해보기 위해 과적합 여부를 확인하기 위한 시각화는 수행하지 않았다.
+
+```python
+pred = cnn_model2.predict(X_test)
+print(classification_report(y_test, np.argmax(pred, axis=1)))
+```
+
+```
+8/8 [==============================] - 3s 370ms/step
+ precision recall f1-score support
+
+ 0 0.63 0.71 0.67 76
+ 1 0.49 0.50 0.49 84
+ 2 0.50 0.42 0.46 80
+
+ accuracy 0.54 240
+ macro avg 0.54 0.55 0.54 240
+weighted avg 0.54 0.54 0.54 240
+```
+
+직접 생성한 CNN모델보다 결과는 좀 더 좋아졌지만, 아직 많이 부족하기 때문에 미세 조정 방식을 사용해보자.
+
+## b. 전이학습 - 미세 조정 방식 이용
+
+이번엔, VGG16 특성추출부의 맨 마지막 부분의 합성곱층을 재학습하는 작업을 추가
+
+VGG16 모델을 다시 불러온다.
+
+```python
+pre_trained_model2 = VGG16(include_top=False,
+ weights='imagenet',
+ input_shape=(224, 224, 3)
+ )
+```
+
+```python
+pre_trained_model2.summary()
+```
+
+### **VGG16 모델의 Layer 이름에 접근해보기**
+
+모든 VGG16의 layer 이름을 확인해본 출력값이다.
+
+```python
+for layer in pre_trained_model2.layers:
+ print(layer.name)
+```
+
+```
+input_2
+block1_conv1
+block1_conv2
+block1_pool
+block2_conv1
+block2_conv2
+block2_pool
+block3_conv1
+block3_conv2
+block3_conv3
+block3_pool
+block4_conv1
+block4_conv2
+block4_conv3
+block4_pool
+block5_conv1
+block5_conv2
+block5_conv3
+block5_pool
+```
+
+맨 마지막 층인 block5_conv3 층만 재학습 시키고 나머지 Layer는 동결하기
+
+### **layer.trainable 이용**
+
+```python
+for layer in pre_trained_model2.layers:
+ if layer.name == 'block5_conv3':
+ layer.trainable = True
+ else:
+ layer.trainable = False
+pre_trained_model2.summary()
+```
+
+```
+Model: "vgg16"
+_________________________________________________________________
+ Layer (type) Output Shape Param #
+=================================================================
+ input_2 (InputLayer) [(None, 224, 224, 3)] 0
+
+ block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
+
+ block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
+
+ block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
+
+ block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
+
+ block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
+
+ block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
+
+ block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
+
+ block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
+
+ block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
+
+ block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
+
+ block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
+
+ block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
+
+ block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
+
+ block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
+
+ block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
+
+ block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
+
+ block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
+
+ block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
+
+=================================================================
+Total params: 14,714,688
+Trainable params: 2,359,808
+Non-trainable params: 12,354,880
+_________________________________________________________________
+```
+
+summary 정보를 확인해보면 Trainable params에 block5_conv3의 param 갯수가 표시된다
+
+즉, block5_conv3를 재학습 시킬 수 있다는 뜻이다.
+
+- Trainable params : 재학습 시킬 수 있는 파라미터 갯수
+
+### **MLP 설계**
+
+이제 MLP(분류기)층을 설계해준다. 이전에 수행했던 특성 추출 방식과 비교해보기 위해 동일한 형태로 설정해준다.
+
+```python
+cnn_model3 = Sequential()
+# VGG16의 특성추출부
+cnn_model3.add(pre_trained_model2)
+# MLP
+cnn_model3.add(Flatten())
+cnn_model3.add(Dense(128, activation='relu'))
+cnn_model3.add(Dense(64, activation='relu'))
+cnn_model3.add(Dense(32, activation='relu'))
+cnn_model3.add(Dense(3, activation='softmax'))
+cnn_model3.summary()
+```
+
+```
+Model: "sequential_5"
+_________________________________________________________________
+ Layer (type) Output Shape Param #
+=================================================================
+ vgg16 (Functional) (None, 7, 7, 512) 14714688
+
+ flatten_5 (Flatten) (None, 25088) 0
+
+ dense_21 (Dense) (None, 128) 3211392
+
+ dense_22 (Dense) (None, 64) 8256
+
+ dense_23 (Dense) (None, 32) 2080
+
+ dense_24 (Dense) (None, 3) 99
+
+=================================================================
+Total params: 17,936,515
+Trainable params: 5,581,635
+Non-trainable params: 12,354,880
+_________________________________________________________________
+```
+
+- MLP를 직접 추가한 모델
+
+ Trainable params에 MLP 파라미터 갯수까지 추가된 걸 확인할 수 있다.
+
+ 즉, 마지막 conv층 한개와 MLP(분류기)층을 다시 수행하고자 하는 목표에 맞게 재학습하게 될것이다.
+
+
+### **모델 컴파일, 학습 및 결과**
+
+```python
+cnn_model3.compile(loss="sparse_categorical_crossentropy",
+ optimizer='Adam',
+ metrics=['acc']
+ )
+```
+
+```python
+cnn_model3.fit(X_train, y_train, validation_split=0.2, epochs=50, batch_size=128)
+```
+
+```python
+pred = cnn_model3.predict(X_test)
+print(classification_report(y_test, np.argmax(pred, axis=1)))
+```
+
+```
+8/8 [==============================] - 1s 155ms/step
+ precision recall f1-score support
+
+ 0 0.85 0.79 0.82 76
+ 1 0.80 0.86 0.83 84
+ 2 0.91 0.90 0.91 80
+
+ accuracy 0.85 240
+ macro avg 0.85 0.85 0.85 240
+weighted avg 0.85 0.85 0.85 240
+```
+
+VGG16 모델을 미세 조정 방식으로 학습해본 결과 정확도는 0.85로 비교적 좋은 결과가 나왔다.
+
+즉, VGG16모델을 전이학습을 진행한 결과 직접 설계한 CNN모델에 비해 훨씬 결과가 잘 나오는 것을 확인할 수 있다.
+
+# 3. 데이터 증강(Data Augmantation)
+
+- 기존 이미지와 유사한 이미지를 추가로 생성하여 학습시 반영해주는 데이터 증식 기법
+
+## ImageDataGenerator
+
+- 이미지 데이터를 생성하기 위한 조건을 설정할 수 있다.
+- rotation_range : 이미지 회전 각도 설정
+- width_shift_range : 수평(x축) 이동 범위 설정
+- height_shift_range : 수직(y축) 이동 범위 설정
+- zoom_range : 축소/확대 비율 설정
+- horizontal_flip : 수평 방향으로 뒤집기 여부 설정
+- fill_mode : 이미지가 변형되면서 비는 공간에 어떻게 픽셀로 채워줄지(nearest: 가장 가까운 픽셀로 채우기)
+
+### **ImageDataGenerator 객체 생성**
+
+- 필요한 설정을 파라미터로 설정함
+
+```python
+from tensorflow.keras.preprocessing.image import ImageDataGeneratoraug = ImageDataGenerator(rotation_range=30, width_shift_range=0.2, # 20% 내외 수평이동 height_shift_range=0.2, # 20% 내외 수직이동 zoom_range=0.2, # 0.8 ~ 1.2배로 축소/확대 horizontal_flip=True, # 수평방향으로 뒤집기 fill_mode='nearest' )
+```
+
+### **VGG16 모델 불러오기**
+
+- 목적에 맞게 학습시키기 위해 마지막 합성곱층 외에 동결시키기(전이학습 - 미세 조정 방식)
+- VGG16의 마지막 합성곱층 이름은 block5_conv3로 확인할 수 있음
+
+```python
+pre_trained_model3 = VGG16(include_top=False, weights='imagenet', input_shape=(224, 224, 3) )for layer in pre_trained_model3.layers: if layer.name == 'block5_conv3': layer.trainable = True else: layer.trainable = False
+```
+
+```
+Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
+58889256/58889256 [==============================] - 0s 0us/step
+```
+
+### **MLP(분류기) 정의하기**
+
+- 목적에 맞게 입력층, 은닉층, 출력층 생성
+- 활성화함수 설정
+
+```python
+cnn_model4 = Sequential()# VGG16의 특성추출부cnn_model4.add(pre_trained_model3)# MLPcnn_model4.add(Flatten())cnn_model4.add(Dense(128, activation='relu'))cnn_model4.add(Dense(64, activation='relu'))cnn_model4.add(Dense(32, activation='relu'))cnn_model4.add(Dense(3, activation='softmax'))
+```
+
+### **모델 컴파일하기**
+
+```python
+cnn_model4.compile(loss='sparse_categorical_crossentropy', optimizer='Adam', metrics=['acc'])
+```
+
+### **ImageDataGenerator로 설정한 조건으로 모델 학습**
+
+- ImageDataGenerator를 사용하여 학습하는 방법
+ 1. .flow(x, y)
+ 2. .flow_from_directory(directory)
+- aug.flow() : ImageDataGenerator로 설정한 조건으로 생성된 이미지로 학습에 적용시켜준다.
+- steps_per_epoch = (훈련 샘플수 / 배치 사이즈) : 제너레이터로부터 얼마나 많은 샘플을 뽑을 것인지 결정
+ - steps_per_epoch를 (X_train 길이 / batch_size) 즉, 7.5로 설정이 되면 한 epoch당 128개의 이미지를 활용하므로(batch_size때문에) 1epoch당 총 960개의 데이터를 활용하게 된다.
+- 1epoch 때는 증강된 이미지 960개로 학습, 2epoch떄는 960개 추가되어 총 1920개로 학습
+
+```python
+cnn_model4.fit(aug.flow(X_train, y_train, batch_size=128),
+ steps_per_epoch=len(X_train) / 128,
+ epochs=50
+ )
+```
+
+```python
+from sklearn.metrics import classification_report
+pred = cnn_model4.predict(X_test)
+print(classification_report(y_test, np.argmax(pred, axis=1)))
+```
+
+```
+8/8 [==============================] - 1s 156ms/step
+ precision recall f1-score support
+
+ 0 0.80 0.93 0.86 76
+ 1 0.96 0.79 0.86 84
+ 2 0.89 0.91 0.90 80
+
+ accuracy 0.88 240
+ macro avg 0.88 0.88 0.87 240
+weighted avg 0.88 0.88 0.87 240
+```
+
+- ImageDataGenerator로 데이터 증식을 해서 학습하면 정확도가 약 88%로 더 나은 결과를 확인할 수 있음
+- 데이터의 수가 적을 경우 데이터 증강을 진행한 후 정확도가 더 향상됨
+- 데이터의 종류에 따라 정확도 개선의 정도는 다를 수 있음
\ No newline at end of file
diff --git "a/_posts/2022-10-16-springboot02_Spring Boot \354\227\220\354\204\234 jsessionid \353\254\270\354\240\234 \355\225\264\352\262\260.md" "b/_posts/2022-10-16-springboot02_Spring Boot \354\227\220\354\204\234 jsessionid \353\254\270\354\240\234 \355\225\264\352\262\260.md"
new file mode 100644
index 000000000000..d4a2e6d627a1
--- /dev/null
+++ "b/_posts/2022-10-16-springboot02_Spring Boot \354\227\220\354\204\234 jsessionid \353\254\270\354\240\234 \355\225\264\352\262\260.md"
@@ -0,0 +1,121 @@
+---
+layout: single
+title: "Spring Boot 에서 jsessionid 문제 해결"
+categories: SpringBoot
+tag: [Java, Spring, Spring Boot, STS, Eclipse]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+## jsessionid란?
+
+- jsessionid는 새 세션이 만들어지면 클라이언트가 쿠키를 지원하는지 여부를 서버가 알 수 없으므로, 쿠키와 URL에 모두 jsessionid를 만들어 주는 것을 의미한다.
+- url에 붙거나 헤더에 붙여서 표시된다.
+- jsessionid를 탈취당하면 **사용자 ID, Password를 몰라도 접근이 가능하게 된다.**
+
+# 해결방법
+
+### 1. application.properties에 아래와 같은 옵션을 추가한다.
+
+![00_1.png](/assets/images/springboot02/00_1.png)
+
+### 2. 클래스 계승 시작 SpringBootServletInitializer 재 작성 onStartup 방법
+
+```java
+@Override
+public void onStartup(ServletContext servletContext) throws ServletException {
+ super.onStartup(servletContext);
+ servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
+ SessionCookieConfig sessionCookieConfig=servletContext.getSessionCookieConfig();
+ sessionCookieConfig.setHttpOnly(true);
+}
+```
+
+### 3. @ Configuration 설정 클래스 에 bean 등록
+
+ServletContextInitializer 클래스를 Bean객체로 등록하여 스프링 부트가 jseesion과 관련된 설정을 읽도록 해 주면 된다.
+
+```java
+@Bean
+public ServletContextInitializer servletContextInitializer1() {
+ return new ServletContextInitializer() {
+ @Override
+ public void onStartup(ServletContext servletContext) throws ServletException {
+ servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE) );
+ }
+ };
+}
+```
\ No newline at end of file
diff --git "a/_posts/2022-10-20-DL05_\352\260\235\354\262\264 \355\203\220\354\247\200.md" "b/_posts/2022-10-20-DL05_\352\260\235\354\262\264 \355\203\220\354\247\200.md"
new file mode 100644
index 000000000000..e1ec57589c19
--- /dev/null
+++ "b/_posts/2022-10-20-DL05_\352\260\235\354\262\264 \355\203\220\354\247\200.md"
@@ -0,0 +1,211 @@
+---
+layout: single
+title: "객체 탐지 기술 정리"
+categories: 딥러닝
+tag: [딥러닝, python, 객체탐지]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+# 객체 탐지란
+
+- 이미지 내에서 객체(사람, 사물 등)를 감지해 내는 것
+
+![05_1.png](/assets/images/DL05/05_1.png)
+
+# 평가지표
+
+## IoU(Intersection over Union)
+
+- 이미지 내에 있는 **하나의 객체**를 탐지할 때 사용하는 평가지표이다.
+- 실제 객체 면적과 모델이 예측한 면적의 **(교차 영역 / 전체 영역) X 100**
+- 범위는 **0 ~ 1.0 사이** (일반적으로 **0.5**가 넘으면 맞게 예측했다고 판단)
+
+![05_2.png](/assets/images/DL05/05_2.png)
+
+## mAP(mean Average Precision)
+
+- 한 이미지에서 **여러 개의 객체(클래스)**를 찾을 때 사용되는 평가지표이다.
+- 각 객체(클래스)별 평균 정밀도(AP)를 계산한 후 **클래스 전체에 대한 평균(mean)**을 구하는 방식으로 범위값은 0 ~ 1.0 사이
+- IoU 기준에 따라 mAP는 달라진다(IoU가 높으면 mAP는 낮아짐)
+
+## 평균 정밀도(AP)
+
+- 일반적으로 정밀도와 재현율(Recall)은 **반비례** 관계이다.
+- 두 값을 모두 고려하여 모델의 성능을 판단하는 것이 합리적이다.
+- 재현율의 11개 지점(0.0 ~ 1.0)에 대해 정밀도를 구해서(11점 보간법) 평균을 낸 것이 AP이다.
+
+# 객체 탐지 알고리즘
+
+## 1. Traditional Detection Methods
+
+- **슬라이딩 윈도우(Sliding Window)**
+
+ 고정된 크기의 Window(=초록박스)로 이미지의 좌상단부터 우하단으로 **일일이 객체를 검출**해 나가는 방식
+
+- **문제점**
+
+ 객체가 없는 영역도 무조건 Sliding해야 하며 여러 Scale의 이미지를 스캔하여 검출하는 방식이므로 **수행시간은 늘고, 검출성능은 떨어진다.**
+
+
+## 2. Two-stage detector
+
+- **영역추정(Region Proposal)**과 **탐지(Detection)** 두 단계를 따로 수행하는 방식
+
+ Sliding Window의 비효율성으로 인해 R-CNN 알고리즘에서는 **객체가 있을 법한 2000개의 영역**을 찾고 **그 영역에 대해서만 객체를 탐지**하는 두 단계를 제안함
+
+ 대표적으로는 R-CNN, Fast R-CNN, Faster R-CNN 모델이 있음
+
+- **영역추정의 문제점**
+
+ 객체들이 각기 다른 크기와 형태를 가지고 있다면 후보 영역을 찾는 정확도가 떨어지게 됨
+
+ 영역추정의 정확도를 향상시키기 위해 **미리 이미지에서 객체 영역을 분할**해 두면 후보 영역을 찾기가 더 쉽지 않을까 연구 진행
+
+- **선택적 검색(Selective Search)**
+
+ 영역추정의 문제점을 해결하기 위해 고안된 방법
+
+ 1. 처음에는 분할된 모든 부분들을 Bounding box로 만들어 리스트에 추가
+ 2. 색상, 무늬, 크기, 형태에 따라 **유사도가 비슷한 부분들을 그룹핑**(Bbox 개수 감소)
+ 3. 1, 2단계를 계속 반복
+
+
+## 3. One-stage detector
+
+Two-stage detector는 Selective search 방식으로 인해 과거 대비 높은 정확도로 객체 탐지가 가능했지만, 여전히 낮은 속도로 **실시간 적용**은 어려웠음
+
+One-stage detector는 **영역추정**과 **객체탐지**를 통합해 **한 번에 수행**
+
+가장 큰 장점은 탐지 속도의 획기적인 향상으로 **실시간 탐지가 가능**하다.
+
+# YOLO(You Only Look Once)
+
+- 대표적인 **One-stage detector** 방식 실시간 객체 검출 알고리즘
+ - **객체 영역 판단**과 **객체 인식**을 동시에 진행하는 방식
+ - 기존 CNN은 이미지 전체를 하나의 레이블(클래스)로 표시한다면, Yolo는 이미지 내에 특정한 위치(영역 추정)와 객체 탐지를 동시에 진행한 후, 이를 설정된 레이블로 표시해줌
+- 16년 **version1**부터 22년 **version7**까지 오픈소스로 출시됨
+- Yolo v1(GoogLeNet 적용)은 Two-stage detector의 Faster RCNN(vgg16 적용)보다 6배 빠른 속도로 논문에 기재됨
+
+## YOLO(You Only Look Once) - v1
+
+![05_3.png](/assets/images/DL05/05_3.png)
+
+- 입력 이미지(448x448x3)를 7x7 Grid 영역으로 나눔
+- 각 Grid cell당 2개의 Bounding Box를 생성(총 98개)
+- 각각의 Bbox는 **x, y, w, h**와 **confidence**로 구성됨
+- **x, y**는 Bbox의 중심점, **w, h**는 너비, 높이
+ex) x가 cell의 가장 왼쪽에 있다면 0이고 y가 cell의 중간에 있다면 0.5
+ex) 바운딩 박스의 w가 이미지 전체 너비의 절반이라면 w는 0.5
+- **Confidence**는 Bbox가 객체를 포함한다는 예측을 얼마나 확신 하는지에 대한 지표
+
+![05_4.png](/assets/images/DL05/05_4.png)
+
+- **Pr** : Grid Cell 내에 물체가 존재할 확률 (존재하면 1, 존재하지 않으면 0)
+- confidence가 **0.5 이하**인 Bbox는 모두 삭제(0.5라는 기준은 사용자 지정 가능)
+- 또한 confidence가 **가장 높은** Bbox만 남기고, 중복된다면 첫번째를 제외한 나머지 Bbox들은 삭제하여 **한 객체당 하나의 Bbox만 남김**
+
+## v2
+
+- Bbox의 개수를 늘리고 GoogLeNet 대신 **Darknet-19** 모델을 사용하는 등 v1에 비해 **mAP 향상**
+- Multi-Scaling기법을 사용하여 v1의 문제점인 **작은 객체에 대한 인식률 향상**
+
+## v3
+
+- Darknet-53 모델로 변경하고 내부 구조를 조정하여 **FPS를 2배 이상 향상**
+- 특성맵의 크기를 조절하여 크기가 **큰 객체의 검출 성능 향상**
+- 다수의 객체 예측 시 softmax 대신 **개별 클래스별 sigmoid를 활용**하여 검출
+
+ (하나의 Bbox안에 복수의 객체가 존재하는 경우 softmax의 성능이 떨어짐)
+
+
+## v4
+
+- CSPDarknet53, SPP, PAN, BoF, Bos 등의 기법을 통해 v3에 비해 **mAP, FPS를 각각 10%, 12%씩 향상**
+
+## v5 ~ v6
+
+- 논문 없이 깃 허브로 코드만 공유
+- V4에 비해 **낮은 용량, 빠른 속도(높은 FPS), 비슷한 성능(mAP)**
+- Darknet 대신 **Pytorch**로 구현
+- 검출되는 객체의 **크기 별 전용 버전인 s, m, l, x**로 버전 세분화
+- Pascal VOC 데이터 셋 대신 **COCO 데이터 셋(20만개, 클래스 80개)**으로 훈련
+
+## v7
+
+- COCO 데이터 셋 기준 30FPS 이상의 실시간 감지에서 **AP 56.8%로 Yolo버전 중 가장 높음**
+- 인간의 포즈를 추정할 수 있는 **포즈추정 모델 포함**(Yolo에서 첫 등장)
+
+![05_5.png](/assets/images/DL05/05_5.png)
\ No newline at end of file
diff --git "a/_posts/2022-10-22-DL06_Yolov5 \354\213\244\354\212\265.md" "b/_posts/2022-10-22-DL06_Yolov5 \354\213\244\354\212\265.md"
new file mode 100644
index 000000000000..0d1dc8f493e8
--- /dev/null
+++ "b/_posts/2022-10-22-DL06_Yolov5 \354\213\244\354\212\265.md"
@@ -0,0 +1,320 @@
+---
+layout: single
+title: "Yolov5 파인 튜닝 실습"
+categories: 딥러닝
+tag: [딥러닝, python, 객체탐지, Yolov5]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+# 객체 탐지용 오픈소스 Yolov5 사용
+
+- 객체 영역 판단과 객체 인식을 동시에 진행하는 **One-stage detector** 방식
+- 기존 CNN은 이미지 전체를 하나의 레이블(클래스)로 표시한다면, Yolo는 이미지 내에 특정한 위치(영역 추정)와 객체 탐지를 동시에 진행한 후, 이를 설정된 레이블로 표시해줌
+
+## 1. 데이터 수집
+
+- CNN처럼 이미지와 정답만 있으면 되는 것이 아니라 이미지 내에 정답이 될 객체들을 일일이 분리(라벨링)해서 정답으로 설정해줘야 함
+- roboflow 사이트에서 이미 라벨링 된 권총 데이터 사용 https://roboflow.com/
+- 실제 프로젝트에서 사용할 만한 라벨링 데이터는 ‘labelimg’ 라는 툴이 있음
+
+```python
+import numpy as np
+import pandas as pd
+import matplotlib.pyplot as plt
+```
+
+### 라벨링 된 권총 데이터 불러오기(from roboflow)
+
+- 코드로 권총 데이터셋을 다운로드하면, export 폴더(images, labels 존재)와 README파일 2개, data.yaml 파일이 다운로드 된다.
+- 위 파일들을 roboflow_dataset이라는 디렉토리를 생성 후 이동시켜 줌
+- images
+ - 실제 학습 이미지 데이터
+ - labels의 첫번째 0은 권총이라는 label(class)를 의미
+- labels
+ - 객체에 대한 정보들이 표시되어 있음
+ - 나머지 값들은 Bbox의 x, y, w, h 값을 의미
+
+```python
+! curl -L "https://public.roboflow.com/ds/0wHxiSXST0?key=CMDIufmI48" > roboflow.zip; unzip roboflow.zip; rm roboflow.zip
+```
+
+### 환경설정 및 사전작업
+
+1. 소스코드 가져오기
+- Yolov5 github url : https://github.com/ultralytics/yolov5
+- 위의 url을 복사, github clone으로 yolov5 소스코드 복제해오기
+- Google Drive의 /content 내에 yolov5 코드 복제함
+
+```python
+%cd /content
+
+!git clone https://github.com/ultralytics/yolov5
+```
+
+1. yolov5 구동에 필요한 라이브러리 정의
+- yolov5 폴더 내에 requirements.txt에 필요한 라이브러리 정보가 정의되어 있음
+- 로컬 환경에서 작업하면 필요한 라이브러리 버전을 맞추는데에 어려움이 있어 Colab 환경에서 실행함
+
+```python
+# 해당 경로 파일의 모든 내용을 출력
+%cd /content/yolov5/
+
+!pip install -r requirements.txt
+```
+
+1. data.yaml 파일 내용 확인
+- 데이터에 대한 정보가 담겨져 있는 파일로 yolo 학습시 사용
+- data.yaml 파일 내용 출력해보기
+
+```python
+%cat /content/roboflow_dataset/data.yaml
+```
+
+```
+train: ../train/images
+val: ../valid/images
+
+nc: 1
+names: ['pistol']
+```
+
+1. 이미지 데이터 불러오기
+- glob : 많은 양의 파일들의 처리를 쉽게 해주는 라이브러리
+- glob처리하면 img_list 변수에는 이미지 데이터들의 경로값이 담기게 된다.
+
+```python
+from glob import glob
+
+img_list = glob('/content/roboflow_dataset/export/images/*.jpg')
+len(img_list)
+```
+
+```
+2971
+```
+
+- Train/Val 데이터 분리
+
+```python
+from sklearn.model_selection import train_test_split
+
+train_img_list, val_img_list = train_test_split(img_list, test_size=0.2, random_state=11)
+len(train_img_list), len(val_img_list)
+```
+
+```
+(2376, 595)
+```
+
+- 데이터 경로들을 하나의 txt파일에 담아주기(train, val 별도)
+
+```python
+# train
+with open('/content/roboflow_dataset/train.txt', 'w') as f:
+ f.write('\n'.join(train_img_list) + '\n')
+# val
+with open('/content/roboflow_dataset/val.txt', 'w') as f:
+ f.write('\n'.join(val_img_list) + '\n')
+```
+
+1. data.yaml 파일의 train, val 경로를 맞게 재설정해주기
+- data.yaml 파일 읽어오기
+
+```python
+import yaml
+with open('/content/roboflow_dataset/data.yaml', 'r') as f:
+ data = yaml.safe_load(f)data
+```
+
+```
+{'train': '../train/images',
+ 'val': '../valid/images',
+ 'nc': 1,
+ 'names': ['pistol']}
+```
+
+- data.yaml은 key, value 쌍의 딕셔너리 형태로 load됨
+- 경로 재설정하기
+
+```python
+data['train'] = '/content/roboflow_dataset/train.txt'
+data['val'] = '/content/roboflow_dataset/val.txt'data
+```
+
+```
+{'train': '/content/roboflow_dataset/train.txt',
+ 'val': '/content/roboflow_dataset/val.txt',
+ 'nc': 1,
+ 'names': ['pistol']}
+```
+
+- yaml.dump로 data.yaml파일에서 data의 값들을 f에 덮어씌우기
+
+```python
+with open('/content/roboflow_dataset/data.yaml', 'w') as f:
+ yaml.dump(data, f)
+```
+
+### 모델 학습
+
+- 모델을 학습시키는데 필요한 코드 파일인 train.py를 실행시킨다.
+
+### train.py 옵션
+
+- –img : 입력 이미지의 크기, 해당 이미지 데이터의 크기는 416 X 416이다.
+- –batch : 배치 사이즈 설정(데이터의 양이 많기 때문에 메모리를 고려하여 16정도까지만 높여줌)
+- –data : data.yaml 파일 경로 설정
+- –cfg : yolo 모델의 세부 모델 설정(s, m, l, x 등)
+- –weights : 기존 모델에 학습되어 있는 가중치 값을 그대로 사용(사용하는 모델의 가중치를 기입해야함, yolov5s.pt), 일부는 사용 목적에 맞게 재학습되도록 설정되어 있음
+- –name : 저장되는 결과 파일명
+
+```python
+%cd /content/yolov5
+
+!python train.py --img 416 --batch 16 --epochs 50 --data /content/roboflow_dataset/data.yaml --cfg ./models/yolov5s.yaml --weights yolov5s.pt --name gun_yolov5s_results
+```
+
+### yolov5모델 학습 결과 해석
+
+
+![result1.png](/assets/images/DL06/result1.png)
+
+
+
+![09_3.png](/assets/images/DL06/09_3.png)
+
+### 1. mAP50
+
+- IoU = 0.5(실제와 예측이 50% 이상 겹쳤을 때 정답이라고 본다)일 때의 점수
+
+### 2. mAP50-95
+
+- IoU값을 0.5에서 0.05씩 증가시키며 0.95까지의 mAP값들의 평균값
+
+보통 mAP50으로 모델의 성능을 판단하지만, 더 복잡해질 상황을 고려한다면 mAP50-95와 같이 판단, 고려해야함
+
+## 학습 완료 후 평가지표
+
+- 학습이 완료되면 모델 학습 설정에서 지정한 결과 파일명에 해당하는 디렉토리가 생성된다.
+- 해당 폴더의 ./weights의 best.pt, last.pt
+ - best.pt : 학습 진행 중 가장 mAP가 높았을 때의 가중치가 저장됨
+ - last.pt : 마지막 epoch에서의 가중치가 저장됨
+
+### 평가지표 시각화하기
+
+- 평가지표들을 tensorboard로 시각화해서 결과를 보기 쉽게 출력해보기
+
+```python
+%load_ext tensorboard
+%tensorboard --logdir /content/yolov5/runs
+```
+![09_4.jpg](/assets/images/DL06/result2.png)
+
+
+## 모델 테스트
+
+- 실제로 이미지를 넣어 제대로 검출되는지 확인해보기
+- 학습에 사용되지 않은 val 데이터로 확인
+
+### 1. 검증용 데이터에서 임의로 한장 불러오기
+
+```python
+from IPython.display import Image
+
+val_img_path = val_img_list[8]
+Image(val_img_path)
+```
+
+![09_4.jpg](/assets/images/DL06/09_4.jpg)
+
+### 2. 학습된 yolo 모델에 객체 검출 요청하기
+
+- detect.py 파일을 실행하여 모델에 요청한다
+- –weights 가중치 설정, 여기서는 best.pt(mAP가 가장 좋은 가중치)로 설정하였다.
+- –conf : 0.5로 설정하였으므로 점수가 0.5보다 낮은 결과가 나오면 출력이 되지 않는다.
+
+```python
+!python detect.py --weights /content/yolov5/runs/train/gun_yolov5s_results/weights/best.pt --img 416 --conf 0.5 --source "{val_img_path}"
+```
+
+![result3.png](/assets/images/DL06/result3.png)
+
+- 결과 확인은 runs/detect/exp로 저장되었다고 나와있음
+- 여러번 하면 exp2, exp3, … 로 저장되게 된다.
+- 결과 형태를 변경하고 싶거나, 다른 처리를 위해 핸들링하기 위해선 detect.py 파일 내의 코드를 수정하면 된다.
+
+
+![09_5.png](/assets/images/DL06/09_5.png)
\ No newline at end of file
diff --git a/_posts/2022-10-24-springboot03_Spring Data JPA.md b/_posts/2022-10-24-springboot03_Spring Data JPA.md
new file mode 100644
index 000000000000..fbac83b23e5a
--- /dev/null
+++ b/_posts/2022-10-24-springboot03_Spring Data JPA.md
@@ -0,0 +1,129 @@
+---
+layout: single
+title: "Spring Data JPA란?"
+categories: SpringBoot
+tag: [Java, Spring, JPA, Spring Boot, STS, Eclipse]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+
+## ORM이란?
+
+어플리케이션의 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해주는 것을 의미
+
+- Java의 데이터 클래스와 관계형 데이터베이스의 테이블을 매핑
+
+객체지향 프로그래밍과 관계형 데이터베이스의 차이로 발생하는 제약사항을 해결해주는 역할을 수행
+
+대표적으로 JPA, Hibernate 등이 있음 (Persistent API)
+
+## ORM의 장점
+
+1. SQL 쿼리가 아닌 직관적인 코드로 데이터를 조작할 수 있음
+ - 개발자가 보다 비즈니스 로직에 집중할 수 있음
+2. 재사용 및 유지보수가 편리
+ - ORM은 독릭접으로 작성되어 있어 재사용이 가능
+ - 매핑정보를 명확하게 설계하기 때문에 따로 데이터베이스를 볼 필요가 없음
+3. DBMS에 대한 종속성이 줄어듬
+ - DBMS를 교체하는 작업을 비교적 적은 리스크로 수행 가능
+
+## ORM의 단점
+
+1. 복잡성이 커질 경우 ORM만으로 구현하기 어려움
+ - 직접 쿼리를 구현하지 않아 복잡한 설계가 어려움
+2. 잘못 구현할 경우 속도 저하 발생
+3. 대형 쿼리는 별도의 튜닝이 필요할 수 있음
+
+## JPA (Java Persistance API)
+
+### **Hibernate**
+
+ORM Framework중 하나
+
+JPA의 실제 구현체 중 하나이며, 현재 JPA 구현체 중 가장 많이 사용됨
+
+![00_1.png](/assets/images/springboot03/00_1.png)
+
+### Spring Data JPA
+
+Spring Framework에서 JPA를 편리하게 사용할 수 있게 지원하는 라이브러리
+
+- CRUD 처리용 인터페이스 제공
+- Repository 개발 시 인터페이스만 작성하면 구현 객체를 동적으로 생성해서 주입
+- 데이터 접근 계층 개발시 인터페이스만 작성해도 됨
+
+Hibernate에서 자주 사용되는 기능을 조금 더 쉽게 사용할 수 있게 구현
\ No newline at end of file
diff --git "a/_posts/2022-10-30-DL07_RNN \354\210\234\355\231\230 \354\213\240\352\262\275\353\247\235 \354\240\225\353\246\254.md" "b/_posts/2022-10-30-DL07_RNN \354\210\234\355\231\230 \354\213\240\352\262\275\353\247\235 \354\240\225\353\246\254.md"
new file mode 100644
index 000000000000..90fb411a2345
--- /dev/null
+++ "b/_posts/2022-10-30-DL07_RNN \354\210\234\355\231\230 \354\213\240\352\262\275\353\247\235 \354\240\225\353\246\254.md"
@@ -0,0 +1,402 @@
+---
+layout: single
+title: "RNN 순환 신경망 정리"
+categories: 딥러닝
+tag: [딥러닝, python, 순환 신경망, RNN]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+# RNN의 필요성
+
+- 문장을 듣고 무엇을 의미하는지 알아야 하는 서비스 제공이 가능해진다.
+- 문장을 듣고 이해한다는 것은 많은 문장을 이미 학습해 놓았다는 것이다.
+- 문장의 의미를 전달하려면 각 단어가 **정해진 순서대로** 입력되어야 한다.
+- **과거에 입력된 데이터와 나중에 입력된 데이터 사이의 관계를 고려**해야 하는 문제가 생긴다.
+- **시간적 개념**이 들어간 데이터들을 해결하기 위해 **순환신경망(RNN)**이 고안되었다.
+
+# 순환신경망과 일반신경망의 차이
+
+- RNN은 여러 개의 데이터가 순서대로 입력되었을 때 **앞서 입력 받은 데이터의 연산 결과를 잠시 기억**해 놓는 방식이다.
+- 기억된 데이터를 가지고 다음 데이터로 넘어가면서 **함께 연산**한다.
+
+![07_1.png](/assets/images/DL07/07_1.png)
+
+- **앞에서 나온 입력에 대한 결과가 뒤에서 나오는 입력 값에 영향**을 주는 것을 알 수 있다.
+- 예를 들어, 비슷한 두 문장이 입력되어도 **앞에서 나온 입력 값을 구별**하여 출력 값에 반영할 수 있다.
+
+![07_2.png](/assets/images/DL07/07_2.png)
+
+- 모든 입력 값에 이 작업을 순서대로 실행하므로 같은 층을 맴도는 것처럼 보인다.
+- **같은 층안에서 맴도는 성질**때문에 순환 신경망이라고 부른다.
+
+![07_3_1.png](/assets/images/DL07/07_3_1.png)
+
+### RNN 활용 데이터 종류
+
+: 분석에 사용되는 특성들이 **시간적, 순차적 특징**을 지닌 데이터에 RNN 기법이 활용된다.
+
+- 시계열 데이터
+- 음악 데이터
+- 문장(자연어) 데이터
+- 번역 기술 등
+
+### RNN 수식 살펴보기
+
+![07_3_2.png](/assets/images/DL07/07_3_2.png)
+
+- 지금까지 신경망에서는 대부분 높은 성능을 위해 활성화 함수로 relu를 사용하였다.
+- 하지만, RNN에서는 이전 가중치를 기억해야하는데, relu는 0보다 작으면 0으로 만들어버리는 성질로 인해 이전 가중치에 대한 정보를 유지할 수 없다.
+- 따라서, RNN에서는 -1 ~ 1 값을 가지는 하이퍼볼릭 탄젠트(tanh)를 사용한다.
+
+# RNN 기본 신경망(SimpleRNN) 코드
+
+```python
+SimpleRNN(units=3, imput_shape=(4, 9))
+```
+
+- units : 퍼셉트론(뉴런의 개수)
+- input_shape : (timesteps, features) 형태의 튜플로 들어감
+ - timesteps : 순환 횟수 설정, 입력 시퀀스의 크기가 된다.
+
+
+# RNN 데이터 구조
+
+![07_4.png](/assets/images/DL07/07_4.png)
+
+- features : 특성의 갯수
+- examples : 데이터 갯수
+- timesteps : 시간의 순서
+
+# RNN 활용 구조
+
+## 1. 다수 입력 단일 출력
+
+![07_5.png](/assets/images/DL07/07_5.png)
+
+- ex) **문장을 읽고 뜻을 파악**할 때 활용 가능
+
+```python
+model = Sequential()
+model.add(SimpleRNN(units = output_size,
+ input_shape=(timesteps, features)))
+```
+
+## 2. 단일 입력 다수 출력
+
+![07_6.png](/assets/images/DL07/07_6.png)
+
+- ex) **사진의 캡션을 만들 때** 활용 가능
+
+```python
+model = Sequential()
+model.add(RepeatVector(number_of_times,
+ input_shape=input_shape))
+
+model.add(SimpleRNN(units = output_size,
+ return_sequences=True))
+```
+
+※ number_of_times : 출력 개수 설정, ex) 3개의 캡션을 원하면 3으로 설정
+
+※ return_sequences=True : SimpleRNN 신경망이 순환하며 단일 값을 계속 출력
+
+## 3. 다수 입력 다수 출력
+
+![07_7.png](/assets/images/DL07/07_7.png)
+
+- ex) **문장을 번역**할 때 활용, **Video에서 Frame 단위 분류**에 활용 가능
+- RNN층을 여러개 쌓기 위해서 활용 가능
+- 여러 층으로 쌓기 위해서는 이전 RNN층이 **다수입력 다수출력 상태**가 되어야한다.
+- 그래야 **다음 RNN층의 input 형태가 이전 RNN층과 같은 형태**가 되기 때문이다
+
+```python
+model = Sequential()
+model.add(SimpleRNN(units = output_size,
+ input_shape=(timesteps, features),
+ return_sequences=True))
+```
+
+# Simple RNN의 문제점
+
+## 장기 의존성 문제(Long-Term Dependency)
+
+활성화 함수로 tanh를 사용하기 때문에 **timesteps(순환횟수)가 길어질수록 역전파시 기울기가 점차 줄어** 학습 능력이 저하된다
+
+→ **기울기 소실 문제** 발생
+
+→ 시간이 지나면 이전의 입력값을 잊어버리게 된다.
+
+![07_8.png](/assets/images/DL07/07_8.png)
+
+# LSTM (Long Short Term Memory)
+
+: RNN의 문제점을 극복하기 위해 나온 대안
+
+- 순환횟수가 많더라도 앞에서 연산한 결과를 **장기간 유지할 수 있는 ‘구조’**가 필요
+: RNN에 **메모리 셀(cell)** 추가
+- **장기기억**과 **단기기억**의 중요성을 계산해준다.
+- 메모리 셀(cell)
+ - 시각 t에서 메모리 셀의 c에는 과거로부터 **현재시각 t까지의 필요한 대부분의 정보가 저장**
+ - 오차역전파 시 **tanh와 같은 활성화 함수를 통과하지 않아서 기울기 소실이 일어나지 않음**
+ - 데이터를 LSTM 계층 내에서만 주고 받으며 다른 계층으로는 전달하지 않음
+
+## LSTM의 구조
+
+- LSTM 1개는 3개의 gates**(forget, input, output)**로 구성
+- **forget gate**는 이전 상태 정보를 얼마나 버리고 얼마 만큼을 저장할지 결정하고,
+- **Input gate**는 입력되는 새로운 정보를 얼마만큼 저장할지 결정하며,
+- **output gate**는 현재 LSTM 셀의 어떤 부분을 다음 LSTM 셀로 전달할지를 결정
+
+![07_9.png](/assets/images/DL07/07_9.png)
+
+- **h는 단기 상태(Short-Term state)**를 **c는 장기 상태(Long-Term state)**라고 볼 수 있음
+- 이전 스텝의 장기 기억 ct -1은 왼쪽에서 오른쪽으로 통과하면서 Forget gate를 지나면서 일부 정보를 잃고(sigmoid가 곱해지므로), Input gate로부터 덧셈(+) 연산을 통해 새로운 정보를 추가하여 현재 타임 스텝의 장기 기억 ct 가 생성 됨
+- ct는 Output gate의 tanh 함수로 전달되어 단기 상태 ht를 만듦
+
+![07_10.png](/assets/images/DL07/07_10.png)
+
+- LSTM의 복잡성을 줄여 속도측면에서 더 빠른 효과를 볼 수 있는 **GRU**가 존재(목적에 맞는 속도에 따라 LSTM / GRU 선택)
+
+### 다중 LSTM Layer
+
+- LSTM층 또한, RNN과 마찬가지로 다중으로 쌓기 위해서는 이전 LSTM층이 **다수입력 다수출력 상태**가 되어야한다.
+- 그래야 **다음 RNN층의 input 형태가 이전 RNN층과 같은 형태**가 되기 때문이다
+- LSTM, RNN층에서 순환할때마다 출력값을 만들어주는 **return_sequences=True** 옵션을 사용해야함
+
+
+
+# 워드 임베딩(Word Embedding)
+
+- 컴퓨터가 자연어를 이해하고 효율적으로 처리하기 위해서는 **단순한 인코딩이 아닌 컴퓨터가 더 잘 이해할 수 있도록 변환** 할 필요가 있음
+- 워드 임베딩은 한 **단어의 의미를 풍부하게 만들어주는역할**(특성을 늘려주는 역할)을 함
+- 주로 **희소 표현(원 핫 인코딩)**에서 **밀집 표현(실수형태)**으로 변환하는 것을 의미
+- 밀집표현을 통해 해당 단어와 **유사한 다른 단어들의 수치(유사도)**까지 표시함
+
+![07_11.png](/assets/images/DL07/07_11.png)
+
+- 임베딩 과정을 통해 나온 결과를 **임베딩 벡터(embedding vector)**라고 함
+- 케라스에도 제공하는 도구인 **Embedding()**은 **랜덤한 값을 가지는 밀집 벡터로 변환**한 뒤에, 인공 신경망의 가중치를 학습하게 됨
+
+![07_12.png](/assets/images/DL07/07_12.png)
+
+### Embedding 사용
+
+- **Embedding(사용하는 단어사전의 수, 한 단어를 표현할 특징의 수)**을 순환신경망층 가장 앞에 추가하기
+- 사용하는 단어 사전의 수는 **학습에 사용되는 단어의 갯수**이다
+- 한 단어를 표현할 특징의 수는 **적절한 수로 설정**해서 모델이 알아서 특징을 검출하게 해준다
+
+# 순환 신경망 사용해보기 (SimpleRNN)
+
+## 1. 데이터 직접 준비
+
+- 5개의 단어로 문자 하나하나를 단위로 하여 RNN을 사용해보기
+- “hello”, “apple”, “lobby”, “daddy”, “bobby”
+- 문제 데이터 : “hell”, “appl”, “lobb”, “dadd”, “bobb”
+- 정답 데이터 : “o”, “e”, “y”, “y”, “y”
+
+입력 데이터의 문자 갯수는 모두 4개이므로, **timesteps(순환 횟수)를 4**로 설정
+
+### 학습을 위해 문자 데이터를 숫자 데이터로 인코딩하기
+
+- RNN 데이터의 구조를 파악하기 위해 직접 one-hot 인코딩 수행
+- 문제, 정답 데이터에 등장하는 모든 문자(unique value)는 **h, e, l, o, a, p, b, y, d로 총 9개**이다.
+ - h : [1,0,0,0,0,0,0,0,0]
+ - e : [0,1,0,0,0,0,0,0,0]
+ - l : [0,0,1,0,0,0,0,0,0]
+ - o : [0,0,0,1,0,0,0,0,0]
+ - a : [0,0,0,0,1,0,0,0,0]
+ - p : [0,0,0,0,0,1,0,0,0]
+ - b : [0,0,0,0,0,0,1,0,0]
+ - y : [0,0,0,0,0,0,0,1,0]
+ - d : [0,0,0,0,0,0,0,0,1]
+
+```python
+import numpy as np
+import pandas as pd
+import matplotlib.pyplot as plt
+
+# 문제 데이터
+X_train = np.array(
+ [
+
+ # 각각의 단어들
+ [[1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0],[0,0,1,0,0,0,0,0,0],[0,0,1,0,0,0,0,0,0]], # h, e, l, l
+ [[0,0,0,0,1,0,0,0,0],[0,0,0,0,0,1,0,0,0],[0,0,0,0,0,1,0,0,0],[0,0,1,0,0,0,0,0,0]], # a, p, p, l
+ [[0,0,1,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,1,0,0]], # l, o, b, b
+ [[0,0,0,0,0,0,0,0,1],[0,0,0,0,1,0,0,0,0],[0,0,0,0,0,0,0,0,1],[0,0,0,0,0,0,0,0,1]], # d, a, d, d
+ [[0,0,0,0,0,0,1,0,0],[0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,1,0,0]] # b, o, b, b
+ ])
+
+# 정답 데이터
+y_train = np.array(
+ [
+ [0,0,0,1,0,0,0,0,0], # o
+ [0,1,0,0,0,0,0,0,0], # e
+ [0,0,0,0,0,0,0,1,0], # y
+ [0,0,0,0,0,0,0,1,0], # y
+ [0,0,0,0,0,0,0,1,0] # y
+
+ ])
+
+X_train.shape, y_train.shape
+```
+
+```
+((5, 4, 9), (5, 9))
+```
+
+### 데이터 구조 확인
+
+- 문제 데이터의 크기 = (samples, timesteps, features) = (5, 4, 9)
+ - 5 : samples, 데이터의 갯수
+ - 4 : timesteps, 순환 횟수
+ - 9 : features, 특성 수(원핫 인코딩된 컬럼 수)
+- 출력되는 정답을 알파벳 전체로 하고 싶다면 26개로 원핫 인코딩을 시켜주면 됨
+- 현재는 간단한 실습을 위해 9개의 문자로만 문제와 정답 설정
+
+## 2. RNN 신경망 모델링
+
+- SimpleRNN(units, input_shape=(timesteps, features))
+ - units : 퍼셉트론(뉴런의 개수)
+ - input_shape : (timesteps, features) 형태의 튜플로 들어감
+
+```python
+from tensorflow.keras import Sequential
+from tensorflow.keras.layers import Dense, SimpleRNN
+
+model = Sequential()
+model.add(SimpleRNN(8, input_shape=(4, 9))) # 입력층 + 중간층
+model.add(Dense(9, activation='softmax')) # 출력층
+```
+
+- 입력 시퀀스의 크기(순환 해야하는 횟수가 됨)는 4, 입력 데이터의 특성은 9 이므로 input_shapes = (4, 9)
+- RNN층(중간층)에 사용되는 뉴런은 8개이다.
+- 9개의 특성에서 정답을 맞춰야 하므로 출력층의 뉴런은 9이다.
+
+```python
+model.summary()
+```
+
+```
+Model: "sequential_2"
+_________________________________________________________________
+ Layer (type) Output Shape Param #
+=================================================================
+ simple_rnn_2 (SimpleRNN) (None, 8) 144
+
+ dense_2 (Dense) (None, 9) 81
+
+=================================================================
+Total params: 225
+Trainable params: 225
+Non-trainable params: 0
+_________________________________________________________________
+```
+
+RNN은 가중치가 두 종류가 존재한다 (과거 데이터의 가중치, 현재 데이터의 가중치)
+
+- 현재 데이터의 가중치
+
+ → 9(입력 특성) X 8(RNN층 뉴런 수) + 8(RNN층 뉴런 수) = 80
+
+- 과거 데이터의 가중치
+
+ → 8(RNN층 뉴런 수) X 8(RNN층 뉴런 수) = 64
+
+ - RNN층의 순환 횟수와는 상관없이 최종적으로 출력되는 연산 결과에만 가중치가 존재하므로
+- 파라미터 갯수 → 80 + 64 = 144
+
+### 모델 컴파일 및 학습
+
+```python
+model.compile(loss='categorical_crossentropy',
+ optimizer='Adam',
+ metrics=['acc'])
+
+h = model.fit(X_train, y_train, epochs=300)
+```
+
+### 학습 현황 시각화
+
+```python
+plt.figure(figsize=(15, 5))
+
+plt.plot(h.history['acc'], label='acc', marker='.')
+plt.legend()
+plt.show()
+```
+
+![Untitled](/assets/images/DL07/Untitled.png)
\ No newline at end of file
diff --git "a/_posts/2022-11-05-DL08-1_RNN \355\231\234\354\232\251 \353\260\217 \354\213\244\354\212\265.md" "b/_posts/2022-11-05-DL08-1_RNN \355\231\234\354\232\251 \353\260\217 \354\213\244\354\212\265.md"
new file mode 100644
index 000000000000..4a603e60c40c
--- /dev/null
+++ "b/_posts/2022-11-05-DL08-1_RNN \355\231\234\354\232\251 \353\260\217 \354\213\244\354\212\265.md"
@@ -0,0 +1,387 @@
+---
+layout: single
+title: "RNN 실습, 뉴스 기사 분류"
+categories: 딥러닝
+tag: [딥러닝, python, 순환 신경망, RNN, 다중분류]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+# RNN을 활용한 로터스 뉴스 분류
+
+- 영국의 뉴스 통신사 로이터의 ’기사 내용’이 들어가면 어떤 ’주제’인지 분류하는 RNN 모델 실습
+
+## keras에서 제공하는 데이터셋 불러오기
+
+- 실제 뉴스 기사의 내용이 이미 단어단위로 토큰화, 라벨 인코딩 되어 저장이 된 상태이다.
+- 단어가 많은 경우 원핫인코딩 상태로 저장을 한다면, 저장공간 측면에서 매우 비효율적임
+- 또한, 텍스트 처리 분야에서는 문제 데이터에 라벨 인코딩을 활용하면 단어의 빈도수까지 고려해줄 수 있음
+- 1: 뉴스의 시작을 알리는 인덱스 번호
+- 2 : oov(Out of Vocabulary)로 사용
+- 3 ~ : 뉴스 전체 내용에서 빈도수 기준으로 랭크를 나타낸다
+
+```python
+import numpy as np
+import pandas as pd
+import matplotlib.pyplot as plt
+from tensorflow.keras.datasets import reuters
+
+data = reuters.load_data()
+(X_train, y_train), (X_test, y_test) = data
+
+X_train.shape, y_train.shape, X_test.shape, y_test.shape
+```
+
+```
+((8982,), (8982,), (2246,), (2246,))
+```
+
+0번째 훈련 데이터 에는 87개의 단어가 포함되어 있다.
+
+```python
+len(X_train[0])
+```
+
+```
+87
+```
+
+### 로이터 뉴스 기사의 단어들이 어떤 숫자로 인코딩 되어 있는지 확인
+
+1. reuters.get_word_index()로 확인이 가능
+- key, value 쌍의 딕셔너리 형태
+
+```python
+news_words = reuters.get_word_index()
+news_words
+```
+
+```
+{'mdbl': 10996,
+ 'fawc': 16260,
+ 'degussa': 12089,
+ 'woods': 8803,
+ 'hanging': 13796,
+ ...}
+```
+
+1. value값 기준으로 news_words 정렬하기
+
+```python
+sorted(news_words.items(), key=lambda x : x[1])
+```
+
+```
+[('the', 1),
+ ('of', 2),
+ ('to', 3),
+ ('in', 4),
+ ('said', 5),
+ ...]
+```
+
+1. 기사가 어떤 단어로 구성되어 있는지 단어들을 이어붙여 확인해보기
+- key값과 value 값의 위치를 교체
+
+```python
+word_of_news = {}
+
+for k, v in news_words.items():
+ word_of_news[v] = k
+```
+
+- 단어 이어 붙이기
+
+```python
+print(' '.join([word_of_news[w] for w in X_train[0]]))
+```
+
+```
+the wattie nondiscriminatory mln loss for plc said at only ended said commonwealth could 1 traders now april 0 a after said from 1985 and from foreign 000 april 0 prices its account year a but in this mln home an states earlier and rise and revs vs 000 its 16 vs 000 a but 3 psbr oils several and shareholders and dividend vs 000 its all 4 vs 000 1 mln agreed largely april 0 are 2 states will billion total and against 000 pct dlrs
+```
+
+## 뉴스 주제의 개수를 알아보기
+
+- 뉴스 카테고리 갯수 : 46가지
+
+```python
+np.unique(y_train)
+```
+
+```
+array([ 0, 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, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45])
+```
+
+## 데이터 가공
+
+- timestpes를 설정해야 하는데 각 문제 데이터(X_train)가 포함하는 단어의 갯수는 모두 다르다.
+- 그러므로, 문제 데이터의 **단어 개수를 같게(입력 시퀀스 맞춰주기)** 맞춰줘야 학습이 가능하다.
+- 즉, **긴 기사는 잘라내고, 짧은 기사는 붙여 넣는 작업**이 필요하다.
+
+### 시퀀스 길이 맞추기
+
+몇번 순환 시킬지(timesteps) 고정 시켜주기 위함 - 각 문제 데이터의 길이들을 불러와서 기술 통계값 확인해보기
+
+```python
+# 각 문제 데이터의 길이 저장
+train_len = [len(x) for x in X_train]
+
+# 기술 통계값 확인
+print(f'최댓값 : {max(train_len)}')
+print(f'최솟값 : {min(train_len)}')
+print(f'평균값 : {np.mean(train_len)}')
+print(f'중앙값 : {np.median(train_len)}')
+```
+
+```
+최댓값 : 2376
+최솟값 : 13
+평균값 : 145.5398574927633
+중앙값 : 95.0
+```
+
+- 히스토그램으로 데이터 밀도 구성 확인
+- x축은 뉴스 길이를 각 구간별로 표시, y축은 누적개수
+
+```python
+plt.hist(train_len, bins=20)
+plt.xlabel('news_len')
+plt.ylabel('count')plt.show()
+```
+
+![output_19_0.png](/assets/images/DL08-1/output_19_0.png)
+
+- 라인 차트로 기사 별 길이 시각화
+
+```python
+plt.figure(figsize=(15, 5))
+plt.plot(train_len)
+plt.xlabel('news_index')
+plt.ylabel('news_len')
+plt.show()
+```
+
+![output_21_0.png](/assets/images/DL08-1/output_21_0.png)
+
+## 시퀀스 길이 맞추는 작업 수행
+
+- 기술통계값을 확인해본 결과 시퀀스의 길이를 120으로 맞추는게 적절하다고 생각함
+- 긴 기사는 잘라내고, 짧은 기사는 패딩 작업을 해주기
+- sequence.pad_sequences() : maxlen에 지정된 수만큼 길이를 앞에서부터 자르거나 패딩하여 맞춘다. 옵션을 주면 뒤에서 부터 가능
+
+```python
+from tensorflow.keras.preprocessing import sequence
+
+X_train_seq = sequence.pad_sequences(X_train, maxlen=120)
+X_test_seq = sequence.pad_sequences(X_test, maxlen=120)
+```
+
+- 각 단어 데이터는 라벨 인코딩 상태이므로 feature는 1이된다.
+- RNN 학습을 위해 input_shape을 맞춰주기 : (samples, timesteps, feature)
+
+```python
+X_train_seq = X_train_seq.reshape(8982, 120, 1)
+X_test_seq = X_test_seq.reshape(2246, 120, 1)
+
+X_train_seq.shape, X_test_seq.shape
+```
+
+```
+((8982, 120, 1), (2246, 120, 1))
+```
+
+## SimpleRNN 모델링
+
+- 현재 한개의 feature는 단어의 빈도수를 의미하므로, 빈도수만을 이용해서 예측하는 RNN 모델을 설계하게 되는것이다
+- 다수 입력(input 120) 단일 출력(output 1) 형태
+
+```python
+from tensorflow.keras import Sequential
+from tensorflow.keras.layers import InputLayer, Dense, SimpleRNN
+from tensorflow.keras.optimizers import Adam
+
+model = Sequential()
+model.add(InputLayer(input_shape=(120, 1)))
+model.add(SimpleRNN(128))model.add(Dense(46, activation='softmax'))
+
+model.compile(loss='sparse_categorical_crossentropy',
+ optimizer=Adam(learning_rate=0.001),
+ metrics=['acc'])
+```
+
+```python
+history = model.fit(X_train_seq, y_train, validation_split=0.2, batch_size=128, epochs=20)
+```
+
+```python
+plt.figure(figsize=(15, 5))
+plt.plot(history.history['acc'], label='train_acc')
+plt.plot(history.history['val_acc'], label='val_acc')
+plt.legend()
+plt.show()
+```
+
+![output_29_0.png](/assets/images/DL08-1/output_29_0.png)
+
+데이터가 빈도수를 나타내는 feature만 존재하긴 하지만, SimpleRNN으로는 높은 성능을 얻기 힘들다는 것을 확인
+
+## LSTM 모델 학습
+
+- 다수 입력(input 120) 단일 출력(output 1)
+- LSTM을 여러 층으로 쌓기 위해서는 이전 LSTM층이 **다수입력 다수출력 상태**가 되어야한다.
+- 그래야 **다음 LSTM층의 input 형태가 이전 LSTM층과 같은 형태**가 되기 때문이다
+- LSTM, RNN층에서 순환할때마다 출력값을 만들어주는 (다수입력 다수출력 형태) **return_sequences=True** 옵션을 사용해야 한다.
+
+```python
+from tensorflow.keras.layers import LSTM, GRU
+
+model2 = Sequential()
+model2.add(InputLayer(input_shape=(120, 1)))
+model2.add(LSTM(128, return_sequences=True))
+model2.add(LSTM(128))model2.add(Dense(46, activation='softmax'))
+
+model2.compile(loss='sparse_categorical_crossentropy',
+ optimizer=Adam(learning_rate=0.001),
+ metrics=['acc'])
+```
+
+```python
+history2 = model2.fit(X_train_seq, y_train, validation_split=0.2, batch_size=128, epochs=20)
+```
+
+```python
+plt.figure(figsize=(15, 5))
+plt.plot(history2.history['acc'], label='train_acc')
+plt.plot(history2.history['val_acc'], label='val_acc')
+plt.legend()
+plt.show()
+```
+
+![output_34_0.png](/assets/images/DL08-1/output_34_0.png)
+
+## 워드 임베딩(Word Embedding)
+
+- 언어 모델의 성능을 높이는 방법은 모델의 구조를 변경하는 방법과 단어의 표현방법을 고도화 하는방법이 있다,
+- 단어의 표현을 **밀집되게 실수형태로 표현하게 하는 방법**론이 워드 임베딩이다.
+- 학습을 통해서 **각 단어들의 수치값을 정밀하게** 만드는 방법이다.
+
+### 데이터 불러올 때 등장 빈도가 낮은 단어 제거하기
+
+- num_words=1500 : reuters의 수치데이터 의미는 단어 빈도수 랭크이다. 해당 옵션을 주면 각 기사내용에 1500위까지의 단어만 가져오게 된다.
+- 1500위 외의 단어들은 oov 즉, 2값으로 표현된다.
+
+```python
+from tensorflow.keras.layers import Embedding
+
+(X_train, y_train), (X_test, y_test) = reuters.load_data(num_words=1500)
+
+# 시퀀스 길이 맞추기
+X_train_seq = sequence.pad_sequences(X_train, maxlen=120)
+X_test_seq = sequence.pad_sequences(X_test, maxlen=120)
+```
+
+### Embedding 추가 GRU 모델 설계
+
+- Embedding(사용하는 단어사전의 수, 한 단어를 표현할 특징의 수)을 가장 앞 층에 추가하기
+- 사용하는 단어 사전의 수는 학습에 사용되는 단어의 갯수이다
+- 한 단어를 표현할 특징의 수는 적절한 수로 설정해서 모델이 알아서 특징을 검출하게 해준다
+
+```python
+embedding_model = Sequential()
+
+embedding_model.add(Embedding(1500, 50))
+embedding_model.add(GRU(128, return_sequences=True))
+embedding_model.add(GRU(128))
+embedding_model.add(Dense(46, activation='softmax'))
+embedding_model.compile(loss='sparse_categorical_crossentropy',
+ optimizer=Adam(learning_rate=0.001),
+ metrics=['acc'])
+```
+
+```python
+history3 = embedding_model.fit(X_train_seq, y_train, epochs=20, validation_split=0.2, batch_size=128)
+```
+
+```python
+plt.figure(figsize=(15, 5))
+plt.plot(history3.history['acc'], label='train_acc')
+plt.plot(history3.history['val_acc'], label='val_acc')
+plt.legend()
+plt.show()
+```
+
+![output_40_0.png](/assets/images/DL08-1/output_40_0.png)
\ No newline at end of file
diff --git "a/_posts/2022-11-09-git01_Git\354\234\274\353\241\234 \355\230\221\354\227\205 \352\270\260\353\212\245 \354\240\225\353\246\254.md" "b/_posts/2022-11-09-git01_Git\354\234\274\353\241\234 \355\230\221\354\227\205 \352\270\260\353\212\245 \354\240\225\353\246\254.md"
new file mode 100644
index 000000000000..2c8707df8249
--- /dev/null
+++ "b/_posts/2022-11-09-git01_Git\354\234\274\353\241\234 \355\230\221\354\227\205 \352\270\260\353\212\245 \354\240\225\353\246\254.md"
@@ -0,0 +1,289 @@
+---
+layout: single
+title: "git을 활용한 협업 기능 정리"
+categories: git
+tag: [git, branch, merge, 에러, fetch, pull]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+## Git의 branch 관리
+
+### 1. **branch 만들기, branch 확인하기**
+
+브랜치 만들기 : `git branch [원하는 브랜치명]`
+
+브랜치 리스트 확인 : `git branch` 또는 `git branch —list`
+
+```bash
+$ git branch yoonkie
+
+$ git branch
+* master
+ yoonkie
+```
+
+### 2. 만들어진 branch로 이동
+
+**git switch [브랜치명]** 또는 **git checkout [브랜치명]**
+
+```bash
+$ git checkout yoonkie
+Switched to branch 'yoonkie'
+```
+
+### switch vs checkout ??
+
+기존에 git을 사용하면서 c**heckout**으로 브랜치를 이동했는데 최근 **switch** 명령어를 많이 사용(?)한다고 한다.
+
+알고보면, switch는 checkout의 분리된 기능이다.
+
+### switch : 브랜치를 변경한다
+
+**switch**를 통해 브랜치를 **변경**할 수도 있고, 기존에 없는 **브랜치를 생성하면서 변경**도 가능
+
+( master → yoonkie)
+
+```bash
+$ git switch yoonkie
+Switched to branch 'yoonkie'
+```
+
+### restore : 작업중인 파일을 되돌린다 (복원)
+
+작업중인 파일 중 기존 **마지막 커밋의 상태로 되돌리고자** 할 때 **restore**를 사용한다
+
+```bash
+$ git restore README.md
+```
+
+---
+
+## 3. 브랜치 병합하기 Merge
+
+**git merge** 명령어를 통해 다른 브랜치와 병합할 수 있다.
+
+1. **matser** 브랜치에서 **git merge yoonkie** 수행
+
+ : yoonkie 브랜치를 master 브랜치에 병합한다는 뜻
+
+2. **yoonkie** 브랜치에서 **git merge master** 수행
+
+ : master 브랜치를 yoonkie 브랜치에 병합한다는 뜻
+
+
+### Merge 충돌 관리
+
+여려명이 같은 기능, 파일을 수정하면 merge 하면서 **충돌**이 쉽게 발생한다.
+
+두 명이서 같은 파일을 작업한다면 기존의 내용이 서로 다를 수 있으며, 이를 한쪽에서 merge 하면 git은 **어떤 코드를 반영**해야할지 모른다면서 충돌이 나게 되는것이다.
+
+> 예시
+>
+- master 브랜치에서 수정한 README.md 파일을 commit한 상태
+
+![01.png](/assets/images/git01/01.png)
+
+- yoonkie 브랜치에서 수정한 README.md 파일을 commit한 상태
+
+![02.png](/assets/images/git01/02.png)
+
+- master 브랜치에서 yoonkie 브랜치 merge 수행
+
+![03.png](/assets/images/git01/03.png)
+
+충돌이 발생했다고 표시되며, 브랜치 표시가 **(master|MERGING)**으로 변경된 것을 확인할 수 있다.
+
+(master|MERGING) : 충돌을 해결하기 위한 임의의 브랜치라고 보면 된다.
+
+![04.png](/assets/images/git01/04.png)
+
+> *<<<<<
+>
+> *[HEAD]의 코드*
+>
+> *===========* : **현재 브랜치와 병합 브랜치의 구분선**
+>
+> *[병합 할 브랜치]의 코드*
+>
+> *>>>>>>[브랜치 명]*
+>
+
+실제로 README.md파일을 확인하면 위와같이 어떤 변경이 있었는지 확인할 수 있다.
+
+해당 부분을 **프로젝트 관리자**가 수정 후 다시 commit 하면 된다.
+
+- **git diff** : 병합 전 어떻게 바뀌었는지 확인할 수 있는 명령어
+
+```bash
+$ git diff
+diff --cc README.md
+index aa7a1fc,10703ad..0000000
+--- a/README.md
++++ b/README.md
+@@@ -1,3 -1,3 +1,7 @@@
+ # literate-engine
+
+- 마스터가 쓴 텍스트
+++<<<<<<< HEAD
+++마스터가 쓴 텍스트
+++=======
++
윤기가 만진 p태그
+++>>>>>>> yoonkie
+```
+
+두 주석 모두 변경사항으로 반영하기로 하고 commit 하기
+
+![05.png](/assets/images/git01/05.png)
+
+그러면 (master|MERGING)에서 다시 (master)브랜치로 돌아오게 된다.
+
+### Merge 취소하기
+
+merge 중에 발생한 충돌을 해결하는 또 다른 방법은 merge 전으로 다시 되돌리는 것이다.
+
+`git merge —abort`
+
+### 공백 무시하고 Merge 하기
+
+공백때문에 충돌이 나는 경우도 있는데, 해당 충돌이 단순한 공백으로 인해 충돌났을 경우엔 **Merge를 취소**한 다음에 해당 옵션을 주어 다시 Merge하면 된다.
+
+`git merge -Xignore-space-change [병합할 브랜치명]`
+
+또는
+
+`git merge -Xignore-all-space [병합할 브랜치명]`
+
+```bash
+$ git merge -Xignore-space-change yoonkie
+Auto-merging README.md
+Merge made by the 'recursive' strategy.
+ hello.rb | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+```
+
+## Git fetch와 pull의 차이
+
+`fetch`는 로컬 Git에게 원격 저장소에서 최신 메타데이터 정보를 확인하라는 명령을 전달하는 것이다.
+
+즉, `fetch`는 원격 저장소에 **변경사항이 있는지만 확인**하고, 변경된 데이터를 로컬에 실제로 가져오지는 않는다.
+
+`pull`은 원격 저장소에서 변경된 메타데이터 정보를 확인하고 **최신 데이터를 복사하여 로컬**에 가져온다.
+
+`fetch` 후 `merge`를 수행하면 `pull` 명령을 실행했을 때와 같은 이력이 만들어진다.
+
+### Fetch로 변경 사항 먼저 확인하는 법
+
+1. fetch 한 후에 FETCH_HEAD의 변경 사항을 확인하면 된다.
+2. git diff로 변경사항 확인
+- git fetch
+
+```bash
+$ git fetch origin master
+From https://github.com/minyoongi96/SSM-Project
+ * branch master -> FETCH_HEAD
+```
+
+- git diff
+
+![06.png](/assets/images/git01/06.png)
+
+### Pull로 원격 저장소의 최신 내용을 가져오기
+
+```bash
+$ git pull origin master
+From https://github.com/minyoongi96/SSM-Project
+ * branch master -> FETCH_HEAD
+Updating 85b7a2f..ceda8cd
+Fast-forward
+ README.md | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+```
+
+## LF will be replaced by CRLF in - Git 경고 메시지 뜰 경우
+
+txt, md 파일 등에서 개행문자(줄바꿈 : \n 등)가 운영체제마다 인식하는 방법이 달라서 git이 이 부분을 어떤 운영체제에 맞게 인식처리 할 지 몰라서 나는 오류이다.
+
+- **LF (Line-Feed)**
+ - Mac, 리눅스 (Unix 계열) 줄바꿈 문자열 : \n
+- **CRLF (Carriage-Return + Line-Feed)**
+ - 윈도우, DOS 줄바꿈 문자열 : \r\n
+ - CR(\r) + LF(\n) 두 동작을 합친것임
+
+### 해결방법 : git config 설정을 변경해주기
+
+- 윈도우, DOS인 경우 : git config --global core.autocrlf true 입력
+- Linux, Mac인 경우 : git config --global core.autocrlf input 입력
\ No newline at end of file
diff --git "a/_posts/2022-11-10-springboot04_Spring JPA \354\204\244\354\240\225 \353\260\217 \354\202\254\354\232\251 \354\226\264\353\205\270\355\205\214\354\235\264\354\205\230.md" "b/_posts/2022-11-10-springboot04_Spring JPA \354\204\244\354\240\225 \353\260\217 \354\202\254\354\232\251 \354\226\264\353\205\270\355\205\214\354\235\264\354\205\230.md"
new file mode 100644
index 000000000000..bfb3c289a6b3
--- /dev/null
+++ "b/_posts/2022-11-10-springboot04_Spring JPA \354\204\244\354\240\225 \353\260\217 \354\202\254\354\232\251 \354\226\264\353\205\270\355\205\214\354\235\264\354\205\230.md"
@@ -0,0 +1,252 @@
+---
+layout: single
+title: "Spring JPA 설정 및 사용 어노테이션"
+categories: SpringBoot
+tag: [Java, Spring, JPA, Spring Boot, STS, Eclipse]
+toc: true
+toc_sticky: true
+
+---
+
+
+
+
+
+
+## application.yml 설정
+
+```yaml
+spring:
+ datasource:
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ password: 1234
+ url: jdbc:mysql://localhost:3306/mysql
+ username: root
+ # JPA 설정
+ jpa:
+ database-platform: org.hibernate.dialect.MySQL5InnoDBDialect # 데이터베이스 종류
+ hibernate:
+ ddl-auto: update # jpa로 entity 처음 생성시 테이블 없으면 create, 만든 다음엔 update로 변경해야함
+ properties:
+ hibernate:
+ format_sql: true
+ show-sql: true
+```
+
+## 엔티티와 매핑
+
+### @Entity란 ?
+
+@Entity가 붙은 클래스는 JPA가 관리하는 객체이다.
+
+```java
+@Entity
+// 제약조건이나 테이블 명 등의 옵션 설정 가능
+@Table(name = "BOARD2")
+@Data
+public class Board {
+
+ @Id // PK라는 뜻
+ @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동증가 라는 뜻(strategy의 Identity: mysql)
+ private Long idx;
+
+ @Column(nullable = false)
+ private String memId;
+
+ @Column(length = 1000) // 컬럼 상세 설정
+ private String title;
+
+ @Column(length = 2000)
+ private String contents;
+
+ @ColumnDefault("0")
+ private int count;
+
+ @Column(length = 100)
+ private String writer;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private Date indate;
+
+}
+```
+
+- 객체와 테이블 매핑 : @Entity, @Table
+- 기본키 매핑 : @Id
+- 필드와 컬럼 매핑 : @Column
+- 연관관계 매핑 : @ManyToOne, @JoinColumn
+- 자동증가 : @GeneratedValue(strategy = GenerationType.IDENTITY)
+
+### 1. @Entity
+
+- 테이블과의 매핑
+- JPA가 관리하는 것으로 엔티티라고 불림
+- 속성
+ - name : JPA에서 사용할 엔티티 이름을 지정, 보통 기본값인 클래스 이름을 사용
+
+### 2. @Table
+
+- 에니티와 매핑할 테이블을 지정
+- 생략 시 매핑한 엔티티 이름을 테이블 이름으로 사용
+- 속성
+ - name : 매핑할 테이블 이름 (default : 엔티티 이름 사용)
+ - catalog : catalog 기능이 있는 DB에서 catalog를 매핑
+ - schema : schema 기능이 있는 DB에서 schema를 매핑
+ - uniqueConstraints : DDL 생성 시 **유니크 제약조건을 생성**, 스키마 자동생성 기능을 사용해서 DDL을 만들때만 사용됨
+
+### 3. @Column
+
+- 객체 필드를 테이블 컬럼에 매핑
+- 속성
+ - name : 필드와 매핑할 테이블 컬럼 이름 (default : 객체의 필드 이름)
+ - nullable (DDL) : **null 값의 허용 여부** 설정, false : not null (default : true)
+ - unique (DDL) : @Table의 uniqueConstraints와 같지만 **한 컬럼에 간단히 유니크 제약조건**을 적용
+ - columnDefinition (DDL) : 데이터베이스 **컬럼 정보**를 **직접** 줄수 있음
+ - length (DDL) : 문자 길이 제약조건, **String** 타입에만 적용 (default : 255)
+ - percision, scale (DDL) : **BigDecimal, BigInteger** 타입에만 적용, 아주 큰 숫자나 정밀한 소수를 다룰때 사용 (default : precision = 19, scale = 2)
+
+### 4. @Enumerated
+
+- 자바의 enum 타입을 매핑할 때 사용
+- EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
+- EnumType.STRING : enum 이름을 데이터베이스에 저장 (default : EnumType.ORDINAL)
+
+### 5. @Temporal
+
+- 날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용
+- 자바의 Date 타입에는 년월일 시분초가 있지만, 데이터베이스에는 date(날짜), time(시간), timestamp(날짜와 시간)라는 세 가지 타입이 별도로 존재
+- @Temporal을 생략하면 자바의 Date와 가장 유사한 **timestamp**로 정의
+- 하지만 timestamp대신에 **datetime**을 예약어로 사용하는 데이터베이스도 있는데, 데이터베이스 방언 덕분에 애플리케이션 코드는 변경하지 않아도 됨
+- datetime : MySQL
+- timestamp : H2, 오라클, PostgreSQL
+ 1. TemporalType.**DATE**
+ : 날짜, 데이터베이스 date 타입과 매핑 (예 : 2013-10-11)
+ 2. TemporalType.**TIME**
+ : 시간, 데이터베이스 time 타입과 매핑 (예 : 11:11:11)
+ 3. TemporalType.**TIMESTAMP**
+ : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑 (예 : 2013-10-11 11:11:!1)
+
+### Default 값을 넣는 방법
+
+**@DynamicInsert :** Default값을 적용하기 위해서는 이 어노테이션을 써야한다. Insert 시 지정된 Default값을 적용시킨다.
+
+**@ColumnDefault :** ColumnDefault는 Default값 설정을 할 때 사용한다.
+
+## @Builder 어노테이션 올바른 사용
+
+Entity를 선언할 때 주의점
+
+1. @Setter : 객체가 무분별하게 변경될 가능성이 있다
+2. @NoArgsConstructor : 기본 생성자의 접근 제어자가 불명확하다
+3. @AllArgsConstructor : 객체 내부의 인스턴스멤버들을 모두 가지고 있는 생성자를 생성한다
+
+@Builder 어노테이션을 사용하여 문제점들을 해결할 수 있다.
+
+- 객체 생성자
+
+```java
+@Entity
+@Getter
+@NoArgsConstructor(access = AccessLevel.PROTECTED)
+public class Member {
+
+ @Id
+ private String memId;
+
+ @Column(length = 100)
+ private String memPwd;
+
+ @Column(length = 100)
+ private String memName;
+
+ // 의미있는 객체 생성
+ @Builder
+ public Member(String memId, String memPwd, String memName) {
+ this.memId = memId;
+ this.memPwd = memPwd;
+ this.memName = memName;
+ }
+}
+```
+
+- 테스트 코드
+
+```java
+@Test
+ void insertMember() {
+ Member vo = Member.builder()
+ .memId("admin")
+ .memPwd("1234")
+ .memName("관리자").build();
+
+ mRepository.save(vo);
+ }
+```
\ No newline at end of file
diff --git "a/_posts/2022-11-14-springboot05_AssertJ \354\202\254\354\232\251\355\225\264\353\263\264\352\270\260.md" "b/_posts/2022-11-14-springboot05_AssertJ \354\202\254\354\232\251\355\225\264\353\263\264\352\270\260.md"
new file mode 100644
index 000000000000..2426423f5207
--- /dev/null
+++ "b/_posts/2022-11-14-springboot05_AssertJ \354\202\254\354\232\251\355\225\264\353\263\264\352\270\260.md"
@@ -0,0 +1,145 @@
+---
+layout: single
+title: "AssertJ 사용해보기"
+categories: SpringBoot
+tag: [Java, Spring, JPA, Spring Boot, STS, Eclipse, AssertJ, JUnit]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+
+
+
+
+## AssertJ의 특징
+
+JUit이 기본적으로 제공해주는 Assert는 너무 불편해서 AssertJ를 사용해보았다.
+
+## 장점
+
+- 메소드 체이닝을 지원해주기 때문에 좀 더 깔끔하고 읽기 쉬운 테스트 코드를 작성할 수 있다.
+- 테스트를 하면서 필요하다고 상상할 수 있는 거의 모든 메소드를 제공한다.
+
+## 라이브러리 의존성 설정
+
+Java8 이상은 3.x 버전을 사용해야 한다.
+
+- Gradle
+
+```yaml
+testCompile 'org.assertj:assertj-core:3.6.2'
+```
+
+- Maven
+
+```xml
+
+ org.assertj
+ assertj-core
+
+ 3.6.2
+ test
+
+```
+
+## 사용방법
+
+모든 테스트 코드는 assertThat() 메소드에서 출발한다. 다음과 같은 포맷으로 AssertJ에서 제공하는 다양한 메소드를 연쇄 호출하면서 작성할 수 있다.
+
+```java
+assertThat(테스트 타켓).메소드1().메소드2().메소드3();
+```
+
+### 문자열 테스트
+
+```java
+assertThat("Hello, world! Nice to meet you.") // 주어진 "Hello, world! Nice to meet you."라는 문자열은
+ .isNotEmpty() // 비어있지 않고
+ .contains("Nice") // "Nice"를 포함하고
+ .contains("world") // "world"도 포함하고
+ .doesNotContain("ZZZ") // "ZZZ"는 포함하지 않으며
+ .startsWith("Hell") // "Hell"로 시작하고
+ .endsWith("u.") // "u."로 끝나며
+ .isEqualTo("Hello, world! Nice to meet you."); // "Hello, world! Nice to meet you."과 일치합니다.
+```
+
+### 숫자 테스트
+
+```java
+assertThat(3.14d) // 주어진 3.14라는 숫자는
+ .isPositive() // 양수이고
+ .isGreaterThan(3) // 3보다 크며
+ .isLessThan(4) // 4보다 작습니다
+ .isEqualTo(3, offset(1d)) // 오프셋 1 기준으로 3과 같고
+ .isEqualTo(3.1, offset(0.1d)) // 오프셋 0.1 기준으로 3.1과 같으며
+ .isEqualTo(3.14); // 오프셋 없이는 3.14와 같습니다
+```
\ No newline at end of file
diff --git "a/_posts/2022-11-16-springboot06_JPA \354\227\260\352\264\200\352\264\200\352\263\204 \353\247\244\355\225\221.md" "b/_posts/2022-11-16-springboot06_JPA \354\227\260\352\264\200\352\264\200\352\263\204 \353\247\244\355\225\221.md"
new file mode 100644
index 000000000000..743f93ae9f7a
--- /dev/null
+++ "b/_posts/2022-11-16-springboot06_JPA \354\227\260\352\264\200\352\264\200\352\263\204 \353\247\244\355\225\221.md"
@@ -0,0 +1,169 @@
+---
+layout: single
+title: "JPA 연관관계 매핑"
+categories: SpringBoot
+tag: [Java, Spring, JPA, Spring Boot, join]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+
+
+
+
+
+## 연관관계 매핑
+
+연관관계 매핑이란 객체의 참조와 테이블의 **외래키를 매핑**하는 것을 의미한다.
+
+**JPA**에서는 **Mybatis**를 사용했을 때와 다르게 연관 관계에 있는 상대 테이블의 PK를 멤버변수로 갖지 않고, 엔티티 **객체 자체를 통째로 참조**한다.
+
+### 용어
+
+- **방향**
+1. 단방향 관계 : 두 엔티티가 관계를 맺을 때, **한 쪽의 엔티티만 참조**하고 있는 것을 의미한다.
+2. 양방향 관계 : 두 엔티티가 관계를 맺을 때, **양 쪽이 서로 참조**하고 있는 것을 의미한다.
+
+데이터 모델링에서는 관계를 맺어주기만 하면 자동으로 양방향 관계가 되어 서로 참조하지만, 객체지향 모델링에서는 구현하고자 하는 서비스에 따라 단방향 관계인지, 양방향 관계인지 적절한 선택을 할 필요가 있다.
+
+하지만, 어느 정도의 비즈니스에서는 단방향 관계만으로도 해결이 가능하기 때문에 양방향 관계를 꼭 해야하는 것은 아니다.
+
+그리고 양방향 관계란 서로 다른 단방향 관계 2개를 묶어서 양방향인 것처럼 보이게 할 뿐, 양방향 연관 관계는 사실 존재하지 않는다고 할 수 있다.
+
+- **다중성**
+1. ManyToOne : 다대일 (N : 1)
+2. OneToMany : 일대다 (1 : N)
+3. OneToOne : 일대일 (1 : 1)
+4. ManyToMany : 다대다 (N : M)
+
+- **연관관계의 주인 (Owner)**
+
+연관 관계에서 주인을 찾는 방법은 관계를 갖는 두 테이블에 대해서 **외래키를 갖는 테이블**이 연관 관계의 주인이라고 할 수 있다.
+
+연관 관계의 주인만이 **외래키를 등록, 수정, 삭제**할 수 있고, 반면 주인이 아닌 엔티티는 읽기만 할 수 있기 때문이다.
+
+### 예시 - @ManyToOne (단방향)
+
+```java
+@Entity
+@Table
+@Data
+public class Categories {
+ @Id
+ @Column(name = "cate_seq")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long cateSeq;
+
+ @Column(name = "cate_name", length = 400)
+ private String cateName;
+}
+
+@Entity
+@Table
+@Data
+public class Items {
+ @Id
+ @Column(name = "item_seq")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long itemSeq;
+
+ @Column(name = "item_name", length = 45)
+ private String itemName;
+
+ @Column(name = "item_price")
+ private int itemPrice;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "cate_seq")
+ private Categories categoriesVO;
+}
+```
+
+단방향은 한 쪽의 엔티티가 상대 엔티티를 참조하고 있는 상태이다.
+
+그래서 Items 엔티티에만 @ManyToOne 어노테이션을 추가했다.
+
+- **@ManyToOne**
+
+ @ManyToOne 어노테이션은 이름 그대로 다대일 관계 매핑 정보이다.
+
+ Items 입장에서는 Categories 와 다대일 관계이므로 ManyToOne 어노테이션을 사용했다.
+
+ 연관 관계를 매핑할 때는 이렇게 다중성을 나타내는 어노테이션을 필수로 사용해야 하며, **엔티티 자신을 기준**으로 다중성을 생각해야 한다.
+
+- @JoinColumn(name=”cate_seq”)
+
+ @JoinColumn 어노테이션은 외래 키를 매핑할 때 사용한다.
+
+ name 속성에는 매핑할 외래 키 이름을 지정한다.
+
+ Items 엔티티의 경우 Categories 엔티티의 PK를 “cate_seq”라는 이름의 외래키를 가진다는 뜻으로 작성이 된다.
\ No newline at end of file
diff --git "a/_posts/2022-11-20-springboot07_JPA ,Query \354\226\264\353\205\270\355\205\214\354\235\264\354\205\230, JPQL, DTO \353\247\244\355\225\221, function.md" "b/_posts/2022-11-20-springboot07_JPA ,Query \354\226\264\353\205\270\355\205\214\354\235\264\354\205\230, JPQL, DTO \353\247\244\355\225\221, function.md"
new file mode 100644
index 000000000000..b494fda49786
--- /dev/null
+++ "b/_posts/2022-11-20-springboot07_JPA ,Query \354\226\264\353\205\270\355\205\214\354\235\264\354\205\230, JPQL, DTO \353\247\244\355\225\221, function.md"
@@ -0,0 +1,357 @@
+---
+layout: single
+title: "JPA ,Query 어노테이션, JPQL, DTO 매핑, function 사용"
+categories: SpringBoot
+tag: [Java, Spring, JPA, Spring Boot, join]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+
+
+
+
+### JPA 장점
+
+- SQL문이 아닌 Method를 통해 DB를 조작할 수 있어 개발자가 비즈니스 로직 구성에 좀 더 집중할 수 있음
+- 쿼리문 등의 부수적인 코드가 줄어들어 가독성이 높아짐
+- 오직 객체지향적 접근만 고려되므로 생산정 증가
+- 매핑 정보가 Class로 명시되어 있어서 ERD를 보는 의존도를 낮출 수 있고 유지보수 및 리팩토링에 유리
+
+### JPA 단점
+
+- 프로젝트의 규모가 크고 복잡하여 설계가 잘못된 경우, 속도 저하 및 일관성을 무너뜨리는 문제점이 생길 수 있음
+- 복잡하고 무거운 Query는 속도를 위해 별도의 튜닝이 필요하기 때문에 결국 SQL문을 써야할 수도 있음
+
+JPA가 쿼리를 자동으로 생성해주지만 상황에 따라 직접 쿼리를 작성할 필요가 생긴다.
+
+### JPA에서 직접 쿼리를 작성할 수 있는 방법
+
+- JPQL 작성
+- 네이티브 쿼리(일반 SQL) 작성
+
+JPQL은 JPA의 일부분으로 정의된 플랫폼 독립적인 **객체지향 쿼리 언어**이다.
+
+**네이티브 쿼리는 데이터베이스를 바라보고 작성**한다면 **JPQL은 엔티티 클래스를 바라보고 작성**해야 한다.
+
+JPQL에서는 **대 소문자 구분**을 하고 select, from과 같은 **키워드는 구분하지 않는다.**
+
+## @Query 어노테이션
+
+JpaRepository에서 쿼리(JPQL, native query 둘 다)를 직접 작성해줄 때 사용한다.
+
+메서드 명은 기존 자동생성 방식과 달리 **자유롭게 작성**할 수 있다.
+
+그리고 **nativeQuery**라는 속성을 이용하여 JPQL로 작성한 것인지 SQL로 작성한 것인지 구분할 수 있다.
+
+- nativeQuery = false(default) → JPQL
+- nativeQuery = true → SQL
+
+### Entity : Broadcasting (방송 정보)
+
+```java
+@Entity
+@Table
+@Data
+public class Broadcasting {
+
+ @Id
+ @Column(name = "bc_seq")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long bcSeq;
+
+ @Column(name = "bc_title", nullable = false, length = 400)
+ private String bcTitle;
+```
+
+### Entity : ViewerReaction (시청자 반응)
+
+```java
+@Entity
+@Table(name = "viewer_reaction")
+@Data
+public class ViewerReaction {
+ @Id
+ @Column(name ="vr_seq")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long vrSeq;
+
+ @Column(name ="vr_viewers", nullable = false)
+ private int vrViewers;
+
+ @Column(name ="vr_sales", nullable = false)
+ private int vrSales;
+
+ @Column(name ="vr_comments", nullable = false)
+ private int vrComments;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "bc_seq")
+ private Broadcasting broadcastingVO;
+}
+```
+
+### 1. @Query 사용 방법 (일반 쿼리)
+
+JPQL은 **엔티티의 이름과 속성명을 사용**하고, 일반 SQL은 **설계된 테이블명과 칼럼명** 사용
+
+```java
+@Repository
+public interface ViewerReactionRepository extends JpaRepository {
+
+ // JPQL 사용
+ @Query(value = "select vr.vrSeq from ViewerReaction vr")
+ List selectAllVrSeq();
+ // 일반 SQL 사용
+ @Query(value = "select vr.vr_seq from viewer_reaction vr", nativeQuery = true)
+ List selectAllVr_seq();
+}
+```
+
+### 2. @Query 사용 방법 (파라미터 사용)
+
+```java
+@Repository
+public interface ViewerReactionRepository extends JpaRepository {
+
+ // JPQL 일반 파라미터 쿼리, @Param 사용 X, 엔티티 변수명 "vrSeq" 사용
+ @Query(value = "select vr from ViewerReaction " +
+ "vr where vr.vrSeq = ?1")
+ List selectAllByVrSeq(long seq);
+
+ // 일반 SQL문 파라미터 쿼리 ,@Param 사용 X, 테이블 컬럼명 "vr_seq" 사용
+ @Query(value = "select * from viewer_reaction " +
+ "where vr_seq = ?1", nativeQuery = true)
+ List selectAllByVr_seq(long seq);
+
+ // JPQL 일반 파라미터 쿼리, @Param 사용 O
+ @Query(value = "select vr from ViewerReaction vr where vr.vrSeq = :seq")
+ List selectAllByVrSeq2(@Param(value = "seq") long seq);
+
+ // 일반 SQL문 파라미터 쿼리 ,@Param 사용 O
+ @Query(value = "select * from viewer_reaction " +
+ "where vr_seq = :seq", nativeQuery = true)
+ List selectAllByVr_seq2(@Param(value = "seq") long seq);
+
+ // JPQL 객체 파라미터 쿼리, :#{#객체명}으로 사용
+ @Query(value = "select vr.vrTitle from ViewerReaction vr " +
+ "where vr.vrSeq < :#{#bc.bcSeq}")
+ List selectVrTitleByBc(@Param(value = "bc") Broadcasting bc)
+
+ // 일반 SQL문 객체 파라미터 쿼리, :#{#객체명}으로 사용
+ @Query(value = "select vr_title from viewer_reaction "
+ +"where vr_seq < :#{#bc.bcSeq}", nativeQuery = true)
+ List selectVrTitleByBc(@Param(value = "bc") Broadcasting bc)
+```
+
+### 3. @Query 사용 방법(집계 함수 단독)
+
+객체 파라미터를 사용할 때 여기서는 ManyToOne 매핑이 되어 ViewerReaction 엔티티가 Broadcasting의 매핑 주인이 된다.
+
+그러므로, JPQL 사용 할 때에는 외래키 속성 변수가 객체 형태가 되므로 주의해서 참고
+
+```java
+@Repository
+public interface ViewerReactionRepository extends JpaRepository {
+
+ // 집계함수 SUM 사용
+ // JPQL 사용, broadcastingVO 형태
+ @Query(value = "select SUM(vr.vrSales) from ViewerReaction vr "
+ + "where vr.broadcastingVO = :#{#bc}")
+ Integer vrSalesSum(@Param("bc") Broadcasting bc);
+
+ // 일반 SQL 사용, 테이블에선 컬럼이 객체 형태가 아님
+ @Query(value = "select SUM(vr.vr_sales) from viewer_reaction vr "
+ + "where vr.bc_seq = :bcSeq", nativeQuery = true)
+ Integer vrSalesSum(@Param("bcSeq") long bcSeq);
+```
+
+## DTO Mapping
+
+JPQL을 작성하면서 여러 `function`과 `join`을 사용하다보면 결과가 Entity 형태로 나오지 않을 경우도 있다. 이를 위해 **DTO 반환**이 필요하다.
+
+**@Query** 어노테이션을 사용하여 DTO 반환을 하기 위해서는 **select 구분에서 생성자를 통해 객체를 반환**해야 한다.
+
+### Entity : User
+
+```java
+@Entity
+@Table(name = "user")
+@Data
+public class User {
+ @Id
+ private String id;
+ private String name;
+ private String phone;
+ private String deptId;
+}
+```
+
+### JpaRepository
+
+```java
+public interface UserRepository extends JpaRepository {
+ @Query(value = "select u from User u where u.name = :name")
+ List findByName(@Param("name") String name);
+}
+```
+
+### DTO
+
+```java
+@Data
+public class UserDTO {
+ private String id;
+ private String name;
+ private String deptId;
+ private String deptName;
+}
+```
+
+### @Query로 DTO 반환하기
+
+```java
+public interface UserRepository extends JpaRepository {
+ @Query(value = "select" +
+ "new com.yoonkie.dto.UserDto(u.id, u.name, u.deptId, d.deptName " +
+ "from User u left outer join Dept d on u.deptId = d.deptId")
+ List findUserDept();
+}
+```
+
+## SQL Function
+
+JPQL에서는 기본적으로 select 구문의 **max, min, count, sum, avg**를 제공하며 `기본 function` 으로는 **COALESCE, LOWER, UPPER** 등을 지원하며 자세한 Function은 문서를 참고하면 된다.
+
+```java
+public interface UserRepository extends JpaRepository {
+ @Query(value = "select max(u.id) " +
+ "from User user " +
+ "where u.deptId is not null")
+ String findMaxUserId();
+}
+```
+
+이러한 JPQL에서 기본적으로 지원하는 `ANSI Query Function`만으로는 비지니스 조회를 해결하기에 한계가 존재한다.
+
+`DataBase Function` 을 사용하는 방식은 JPQL에서 `function()` 을 활용하여 **hibernate에 등록된** 각 DataBase의 `Dialect에 정의된 function`을 사용하는 방법이 있다.
+
+```java
+public interface UserRepository extends JpaRepository {
+ @Query(value = "select function('date_format', :date, '%Y/%m/%d') " +
+ "from User u"
+ String findNow(@Param("date") LocalDateTime date);
+}
+```
+
+하지만, **hibernate**에서 기본적으로 등록되는 function에서도 **누락되는 function이 존재**한다. 이러한 경우 `MetadataBuilderContributor`의 **구현체를 구현하는 방식**으로 사용할 수 있다.
+
+(이전에는 **Dialect를 상속받아 구현하는 방식** 사용)
+
+```java
+public class MyMetadataBuilderContributor implements MetadataBuilderContributor{
+ @Override
+ public void contribute(MetadataBuilder metadataBuilder) {
+ metadataBuilder.applySqlFunction("JSON_EXTRACT", new StandardSQLFunction("JSON_EXTRACT", StringType.INSTANCE))
+ .applySqlFunction("JSON_UNQUOTE", new StandardSQLFunction("JSON_UNQUOTE", StringType.INSTANCE))
+ .applySqlFunction("STR_TO_DATE", new StandardSQLFunction("STR_TO_DATE", LocalDateType.INSTANCE))
+ .applySqlFunction("MATCH_AGAINST", new SQLFunctionTemplate(DoubleType.INSTANCE, "MATCH (?1) AGAINST (?2 IN BOOLEAN MODE)"))
+ }
+}
+```
+
+`applySqlFunction`의 첫번째 파라미터는 **JPQL**에서 `function(”함수명”)`에서 **함수명**에 해당하는 등록명이다.
+
+`StandardSQLFunction`은 **기본적인 함수를 등록하기 위한 Class**로 생성자의 **첫번째 파라미터**는 `실제 DataVase Function명`이며, **두번째 파라미터**는 function의 `리턴 타입`이 되야 한다.
+
+`StandardSQLFunction`의 경우 파라미터는 함수에 순서에 맞게 **JPQL function(’등록 함수명’, 파라미터1, 파라미터2, …) 같이 정의**하여 사용하면 된다.
+
+`SQLFunctionTemplete`은 **문법이 존재하는 function을 등록할 때 사용가능**하며, **첫번째 파라미터**가 `function의 리턴타입`이고, **두번째 파라미터**가 `function`이다.
+
+**?1, ?2**와 같이 명시하여 JPQL function()에서 전달되는 **파라미터**의 순서대로 파싱된다.
+
+```java
+public interface UserRepository extends JpaRepository {
+ @Query(value = "select u from User u " +
+ "where function('JSON_UNQUOTE', function('JSON_EXTRACT', u.phone, '$.id')) = 'admin' ")
+ List findAllByPhoneAdmin();
+}
+```
+
+```java
+public interface UserRepository extends JpaRepository {
+ @Query(value = "select user from User u" +
+ "where function('MATCH_AGAINST', u.name, :name) > 0")
+ List findAllByName(@Param("name") String name);
+
+}
+```
\ No newline at end of file
diff --git "a/_posts/2022-11-27-springboot08_Spring \355\224\204\353\241\234\354\240\235\355\212\270 \352\263\204\354\270\265 \354\225\204\355\202\244\355\205\215\354\262\230 .md" "b/_posts/2022-11-27-springboot08_Spring \355\224\204\353\241\234\354\240\235\355\212\270 \352\263\204\354\270\265 \354\225\204\355\202\244\355\205\215\354\262\230 .md"
new file mode 100644
index 000000000000..e3ef9128a3ca
--- /dev/null
+++ "b/_posts/2022-11-27-springboot08_Spring \355\224\204\353\241\234\354\240\235\355\212\270 \352\263\204\354\270\265 \354\225\204\355\202\244\355\205\215\354\262\230 .md"
@@ -0,0 +1,162 @@
+---
+layout: single
+title: "Spring 프로젝트 계층 아키텍처"
+categories: SpringBoot
+tag: [Java, Spring, JPA, Spring Boot, 아키텍쳐]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+
+
+
+
+
+스프링의 계층은 **Presentation Layer**, **Business, Layer**, **Data Access Layer** 크게 3개로 나눌 수 있다.
+
+![01.png](/assets/images/springboot08/01.png)
+
+## 각 계층의 역할 및 특징 정리
+
+### 프레젠테이션 계층
+
+- 브라우저상의 웹 클라이언트의 요청 및 응답을 처리하는 계층이다
+- Service 계층, Data Access 계층에서 발생하는 Exception을 처리
+- @Controller 어노테이션을 사용하여 작성된 Controller 클래스가 이 계층에 속함
+
+### 서비스 계층
+
+- 애플리케이션 비즈니스 로직 처리와 비즈니스와 관련된 도메인 모델의 적합성 검증
+- 트랜잭션을 관리한다
+- Presentation 계층과 Data Access 계층 사이에서 직접적으로 통신하지 않게 함
+- Service 인터페이스와 @Service 어노테이션을 사용하여 작성된 Service 구현 클래스가 이 계층에 속함
+
+### 데이터 엑세스 계층
+
+- ORM(Mybatis 혹은 Hibernate)를 주로 사용하는 계층
+- DAO 인터페이스와 @Repository 어노테이션을 사용하여 작성된 DAO 구현 클래스가 이 계층에 속함
+- 데이터베이스에 CRUD하는 계층
+
+### 프로젝트에서 직접 작성했던 Repository 인터페이스
+
+![02.png](/assets/images/springboot08/02.png)
+
+### 도메인 모델 계층
+
+- DB의 테이블과 매칭될 클래스
+- Entity 클래스라고도 부른다.
+
+## 계층에 관한 용어 정리
+
+### DTO (Data Transfer Object)
+
+- 각 계층간 데이터 교환을 위한 객체 (데이터를 주고 받을 형태 혹은 포맷)
+- Domain, VO라고도 부름
+- DB에서 데이터를 얻어 Service, Controller 등으로 보낼때 사용함
+- 로직을 갖지 않고 순수하게 getter, setter 메소드를 가진다.
+
+![03.png](/assets/images/springboot08/03.png)
+
+### DAO (Data Access Object)
+
+- DB에 접근하는 객체 혹은 DB를 사용해 데이터를 조작하는 기능을 하는 객체
+- MyBatis 사용시에 DAO or Mapper, JPA 사용시에 Repository
+- Service 계층과 DB를 연결하는 고리 역할을 한다.
+
+### Entity 클래스
+
+- Domain 이라고도 부름 (JPA에서 사용)
+- 실제 DB 테이블과 매칭될 클래스
+- Entity 클래스 또는 가장 Core한 클래스라고 부름
+- Domain 로직만을 가지고 있어야하며 Presentation Logic을 가지고 있어서는 안됨
+
+![04.png](/assets/images/springboot08/04.png)
+
+## Domain 클래스와 DTO 클래스를 분리하는 이유
+
+![05.png](/assets/images/springboot08/05.png)
+
+- 테이블과 매핑되는 Entity 클래스가 변경되면 여러 클래스에 영향을 끼치게 되지만 View와 통신하는 DTO 클래스는 자주 변경되므로 분리할 필요가 있음
+- DTO는 Domain Model을 복사한 형태로, 다양한 Presentation Logic을 추가한 정도로 사용함
+- View Layer와 DB Layer의 역할을 철저하게 분리하기 위해
+
+## RestController와 @Service를 나누는 이유
+
+- 모든 기능들을 세분화해서 서비스 계층에 작성하고 나중에는 서비스의 기능들을 **조합**만 해서 새로운 기능으로 만들 수 있음
+- 중복되는 코드가 발생하면 따로 모듈화를 해서 나눠주면 **유지보수**하기 편리하다.
+- 비즈니스 로직을 서비스 구현체에서 구현하여 **확장성**과 **재사용성** 그리고 **중복 코드 제거**를 확보할 수 있다.
+
+### Service 계층에서 비즈니스 로직 처리
+
+프로젝트에서 내가 직접 구현했던 Service 구현 클래스
+
+![06.png](/assets/images/springboot08/06.png)
\ No newline at end of file
diff --git "a/_posts/2024-03-02-aws02_EC2, EBS, ELB \353\202\264\354\232\251 \354\240\225\353\246\254.md" "b/_posts/2024-03-02-aws02_EC2, EBS, ELB \353\202\264\354\232\251 \354\240\225\353\246\254.md"
new file mode 100644
index 000000000000..07e44df76aeb
--- /dev/null
+++ "b/_posts/2024-03-02-aws02_EC2, EBS, ELB \353\202\264\354\232\251 \354\240\225\353\246\254.md"
@@ -0,0 +1,110 @@
+---
+layout: single
+title: "EC2, EBS, ELB 뜻 정리"
+categories: [AWS]
+tag: [AWS, EC2, EBS, ELB]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+Elastic Compute Cloud의 약자로 가장 큰 장점인 클라우드라는 공간에서 크기가 유연하게 변경되는 기능을 제공한다.
+
+예측할 수 없는 데이터 처리 및 계산이 불가능한 크기의 데이터가 밀려오는 상황에 사용량이 많아지면 그만큼 늘리면 되고 반대로 적어지면 또 그만큼 줄여주는 Auto Scaling 가능
+
+## EC2의 다양한 지불 방법
+
+On-demand
+
+- 시간 단위로 가격이 고정되어 있음.
+- 시간당 정해진 비용을 지불하며 편하게 사용할 수 있고, 소프트웨어 및 서버 개발시 최초로 EC2인스턴스 deploy할 때에 종종 쓰임
+- 또는 사용 기간을 미리 알 수 없는 경우에 유용.
+
+Reverse
+
+- 한정된 EC2용량 사용 가능, 1~3년 동안 시간별로 할인 적용 받을 수 있다.
+- 선불로 특정한 금액을 지불할 경우 추가적으로 지정되는 컴퓨팅 시스템을 사용할 수 있음.
+- On-demand보다 조금 저렵한 가격에 사용할 수 있는 장점이 있지만, On-demand와 달리 크기를 늘리고 줄이는 기능이 없고 특정한 사이즈에 정해지기 때문에 가격이 저렴한 것 같음.
+- 무언가를 개발할 때 요구사항이 자주 반복되지 않거나 개발 시간에 대해 예측이 가능하다면 해당 방식 유용
+
+Spot
+
+- 경매와 같이 입찰 가격 적용. 가장 큰 할인률을 적용받으며 특히 인스턴스의 시작과 끝기간이 전혀 중요하지 않을 때 매우 유용
+
+## EBS (Elastic Block Storage)
+
+저장 공간이 생성되어지며 EC2 인스턴스에 부착된다.
+
+디스크 볼륨 위에 File System이 생성된다. 따라서, EC2인스턴스 접근 뿐만 아니라 파일을 로컬 디스크로 옮기는 작업도 가능하다.
+
+EBS는 특정 Availability Zone에 생성되므로 Availability Zone을 설정해주어야 함.
+
+- Availability Zone은 AZ라고도 종종 불리며 하나의 Region 안에 여러개의 AZ가 존재할 수 있음.
+- 중심부로부터 복사본들이 존재하여 한쪽 서버가 망가지거나 셧다운되었을 경우 AZ 백업을 통해 서비스 제공을 가능하게 해주는 일종의 Disaster Recovery가 가능.
+
+## EBS 볼륨 타입
+
+< SSD >
+
+1. General Purpose SSD (GP2)
+ - 최대 10K IOPS를 지원하며 1GB당 3IOPS 속도가 나옴.
+ - SSD중에 가장 보편적으로 사용됨.
+2. Provisioned IOPS SSD (IO1)
+ - 극도의 I/O률을 요구하는(ex. 매우 큰 DB관리) 환경에서 주로 사용됨. 10K이상의 IOPS를 지원함
+ - 매우 큰 빅데이터 분석 시에도 사용 가능
+
+< Magnetic / HDD >
+
+1. Throughput Optimized HDD (ST1)
+ - 빅데이터 Datawarehouse, Log 프로세싱시 주로 사용 (boot volume으로 사용 불가능)
+ - 운영체제를 가지고 있을 수 없음
+2. CDD HDD (SC1)
+ - 파일 서버와 같이 드문 입출력 즉, 드문 volume 접근 시 주로 사용
+ - boot volume으로는 사용 불가능하나 비용이 매우 저렴함
+ - 오랫동안 보관해도 괜찮은 데이터들을 처리하는 용도로 쓰기 좋음
+3. Magnetic (Standard)
+ - 디스크 1GB당 가장 싼 비용을 자랑함.
+ - boot volume으로 사용 가능.
+
+## ELB (Elastic Load Balancers)
+
+수많은 서버의 흐름을 균형있게 배분, 흘려보내는데 중추적인 역할을 함
+
+하나의 서버로 트래픽이 몰리는 병목현상을 방지
+
+Unhealth instance → Healthy instance
+
+- EC2 인스턴스는 예상치 못한 이유로 갑자기 셧다운되거나 시간초과 등이 발생하는 unhealthy상태가 됨. 이러한 트래픽 상태를 해결할 수 있음.
+
+### 1. Application Load Balancer
+
+OSI Layer7에서 작동됨 (가장 바깥부분)
+
+- HTTP, HTTPS와 같은 트래픽의 load balancing에 가장 적합함.
+- 별도의 라우팅 설정을 통하여 특정 서버로 request를 보낼 수 있음.
+
+ → ELB가 임의로 하지 않고 커스터마이즈인 라우팅이 가능하다는 뜻.
+
+
+### 2. Network Load Balancer
+
+OSI Layer4에서 작동됨 (Transport Layer). TCP 트래픽을 정리하는데 적합함.
+
+- 극도의 performance가 요구되는 TCP traffic에서 적합함
+- 초당 수백만개의 request를 아주 미세한 delay로 처리가 가능하다.
+- Google, Naver같이 큰 서버에서 적합할듯 하다.
+
+### 3. Classic Load Balancer
+
+Legacy ELB라고도 함. (거의 쓰이지 않음)
+
+- Layer7의 HTTP/HTTPS 라우팅 기능 지원
+- Layer4의 TCP 트래픽 라우팅 기능도 지원
+
+## Route 53
+
+AWS에서 제공하는 DNS 서비스이다.
+
+- EC2 instance, S3 Bucket, Load Balancer 등 사용하는 서버의 이름을 부여할 수 있다.
+- 도메인 주소를 생성하고 구매하여 위의 3가지 서버로 연결시켜줄 수 있다.
\ No newline at end of file
diff --git "a/_posts/2024-03-13-aws01_IAM \354\240\225\353\246\254.md" "b/_posts/2024-03-13-aws01_IAM \354\240\225\353\246\254.md"
new file mode 100644
index 000000000000..ffd117d89a73
--- /dev/null
+++ "b/_posts/2024-03-13-aws01_IAM \354\240\225\353\246\254.md"
@@ -0,0 +1,170 @@
+---
+layout: single
+title: "IAM 기본 정리"
+categories: [AWS]
+tag: [AWS, IAM]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+
+
+
+
+## IAM 이란?
+
+**유저를 관리하고 접근 레벨 및 권한에 대한 관리**
+
+- 접근키(Access Key), 비밀키(Secret Access Key)
+- 매우 세밀한 접근 권한 부여 기능 (Granular Permission)
+- 비밀번호를 수시로 변경 가능하게 해줌
+- Multi-Factor Authentication(다중 인증) 가능
+
+- 그룹(Group)
+- 유저(User)
+- 역할(Role): 유저와 의미는 비슷하나 역할에 하나 혹은 다수의 정책을 지정할 수 있음, 유저마다 다양한 정책을 부여
+- 정책(Policy) : 주로 JSON 형태로 되어 있는 다큐먼트, 세밀한 접근 권한을 일일히 설정하여 하나의 정책 다큐먼트를 만들 수 있음.
+ - 정책은 그룹, 역할에 추가시킬 수 있다. 유저에게 직접적으로 정책을 줄 수도 있지만 사용자 그룹에 대해서 줄수도 있다.
+ - 하나의 그룹 안에 다수의 유저가 존재 가능하다.
+ - 그룹에 역할 혹은 정책을 추가시키게 되면 그 안의 모든 유저에게 영향이 간다.
+
+- IAM은 유니버셜함 → 지역 변경이 필요 없음.
+
+### User 사용자 생성
+
+IAM > 액세스 관리 > 사용자 생성 클릭 후 사용자 이름 입력
+
+![스크린샷 2024-08-22 오전 11.06.53.png](/assets/images/aws01/01.png)
+
+자동 생성된 암호 선택 : 사용자 생성 후 자동 생성된 암호를 csv로 다운로드 후 닫기버튼 눌러야함. (닫은 후에는 다시 확인 불가)
+
+2단계 : 권한 설정
+
+![스크린샷 2024-08-22 오전 11.07.13.png](/assets/images/aws01/02.png)
+
+권한 옵션을 선택하여 생성하는 사용자를 기존 그룹에 추가할 수 있다.
+
+### Group 그룹
+
+![스크린샷 2024-08-22 오전 11.10.22.png](/assets/images/aws01/03.png)
+
+생성된 그룹 정보에서 사용자 및 권한을 추가할 수 있다.
+
+### Role 역할 생성
+
+![스크린샷 2024-08-22 오전 11.11.31.png](/assets/images/aws01/04.png)
+
+역할 유형을 선택(AWS 서비스)을 하고, 사용할 서비스를 선택한다.
+
+### Policy 정책 생성
+
+정책 생성 > 정책에 적용되는 서비스를 선택
+
+![스크린샷 2024-08-22 오전 11.56.10.png](/assets/images/aws01/05.png)
+
+여기서 액세스 수준을 선택할 수 있는데 읽기, 쓰기 모두 선택함.
+
+아래에 리소스를 모두 선택할 수 있고, 특정 리소스를 선택할 수도 있다.
+
+![스크린샷 2024-08-22 오전 11.57.07.png](/assets/images/aws01/06.png)
+
+권한 목록에서 생성한 권한을 클릭 후, JSON 형태로 확인/수정 가능하다.
+
+![스크린샷 2024-08-22 오전 11.15.21.png](/assets/images/aws01/07.png)
+
+## IAM 정책 시뮬레이터
+
+개발환경에서 실제 환경 프로덕션으로 빌드하기 전에 IAM 정책 또는 Role들이 잘 작동되는지 테스트하기 위한 툴
+
+IAM과 관련된 문제들을 디버깅하기에 최적화된 툴, 이미 실제로 유저에 부여된 다양한 정책들도 테스트 가능
+
+IAM > 대시보드 > 오른쪽 메뉴에 정책 시뮬레이터 클릭
+
+왼쪽 메뉴의 드롭다운에서 시뮬레이션 할 대상을 선택 (Users, Groups, Roles 선택 가능)
+
+![스크린샷 2024-08-22 오전 11.16.30.png](/assets/images/aws01/08.png)
+
+Select Service : 시뮬레이션 할 서비스 선택한다.
+
+![스크린샷 2024-08-22 오전 11.16.58.png](/assets/images/aws01/09.png)
+
+Select actions : 시뮬레이션할 기능들을 선택한다. (나는 Select All 클릭)
+
+![스크린샷 2024-08-22 오전 11.17.10.png](/assets/images/aws01/10.png)
+
+Run Simulation을 실행하면 시뮬레이션 결과로 권한이 access / denied로 나옴
+
+![스크린샷 2024-08-22 오전 11.17.27.png](/assets/images/aws01/11.png)
+
+시뮬레이션 한 유저에 AmazonDynamoDBReadOnlyAccess 추가 후 다시 테스트
+
+![스크린샷 2024-08-22 오전 11.19.57.png](aws01/12.png)
\ No newline at end of file
diff --git a/_posts/2024-04-25-aws03_X-Forwared-For.md b/_posts/2024-04-25-aws03_X-Forwared-For.md
new file mode 100644
index 000000000000..9609f718085d
--- /dev/null
+++ b/_posts/2024-04-25-aws03_X-Forwared-For.md
@@ -0,0 +1,31 @@
+---
+layout: single
+title: "X-Forwared-For란?"
+categories: [AWS]
+tag: [AWS]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+### X-Forwared-For 헤더
+
+단순히 포트만 열어두고 Application 서비스를 올리는 경우가 아닌 NGINX 및 AWS CloudFront 또는 Application Load Balancer 같이 앞단에 프록시 서버를 두는 경우가 있다.
+
+이러한 경우 앱 서버(WAS)는 유저의 request가 리버스 프록시를 통해 접속하는데, 이 경우 서버의 접속 로그에 찍히는 IP는 리버스 프록시 서버의 IP(Private IP)만 가져온다. 출처를 알 수 없음
+
+![스크린샷 2024-08-22 오후 1.48.39.png](/assets/images/aws03/01.png)
+
+이러한 문제를 해결하기 위해 표준헤더인 X-Forwarded-For가 등장하게 되고, HTTP 헤더에 타고 있는 X-Forwarded-For를 통해 프록시 및 로드밸런서 아이피를 기록한다.
+
+> X-Forwared-For: <client>, <proxy1>, <proxy2>
+>
+
+HTTP HEAD에 타고 있는 형태로 구성되며, client IP → Proxy Server1 → Proxy Server2 → … 순차적으로 추가되는 방식으로 구성
+
+이 설정은 각 프록시 서버별로 세팅이 필요하거나 자동으로 해더에 같이 넣어줌
+
+- AWS ELB → 자동으로 X-Forwarded-For 헤더가 추가되거나 새롭게 생성
+
+즉, 순차적으로 서버를 넘어가면서 받은 아이피를 기록하는 해더에서 실제 출처 IP를 찾을 수 있다.
\ No newline at end of file
diff --git "a/_posts/2024-05-02-aws4_AWS VPC\354\231\200 Public,Private Subnet \354\203\235\354\204\261.md" "b/_posts/2024-05-02-aws4_AWS VPC\354\231\200 Public,Private Subnet \354\203\235\354\204\261.md"
new file mode 100644
index 000000000000..26007c5d3ee9
--- /dev/null
+++ "b/_posts/2024-05-02-aws4_AWS VPC\354\231\200 Public,Private Subnet \354\203\235\354\204\261.md"
@@ -0,0 +1,282 @@
+---
+layout: single
+title: "AWS VPC와 Public,Private Subnet 생성"
+categories: [AWS]
+tag: [AWS, EC2, VPC]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+## 구축 순서
+
+VPC 생성 → 서브넷 생성 → 인터넷 게이트웨이 생성 → 퍼블릭 라우팅 → 라우팅 테이블 생성 및 설정
+
+![스크린샷 2024-08-23 오후 3.33.55.png](/assets/images/aws04/01.png)
+
+## VPC (Virtual Private Cloud)
+
+- AWS 클라우드의 프라이빗 가상 네트워크
+- 보통 AWS 리전 및 가용 영역의 고가용성을 기반으로 구축한다.
+- VPC는 한 리전 내에 상주하며, 여러 가용영역에 걸쳐 사용 가능하다.
+- VPC는 네트워크 구성을 완벽하게 제어할 수 있도록 허용한다.
+- VPC 내부의 리소스를 격리하고 노출할 수 있는 기능이 있다, (서브넷, 액세스 제어 목록 정의, 라우팅 규칙 등)
+- 여러 계층의 보안 제어 기능을 제공한다.
+- 특정 인터넷 및 내부 트래픽을 허용 및 거부할 수 있는 기능이 있다.
+- 다른 AWS 서비스를 VPC에 배포할 수 있다.
+
+## 1. VPC 생성
+
+VPC 이름은 이름-리전-vpc로 작성하였다.
+
+이후, IPv4 CIDR 블록에 생성할 VPC IP 대역대를 입력
+
+![스크린샷 2024-08-22 오후 4.05.26.png](/assets/images/aws04/02.png)
+
+## 2. Public subnet 생성
+
+### Subnet이란?
+
+VPC를 나누는 데 사용된다. VPC안에 나누어진 부분 네트워크라고 할 수 있다.
+
+보통 VPC를 IP로 구분해 나눈 후에 다중 AZ(가용영역)에 걸쳐 서브넷을 구성한다.
+
+- 퍼블릭 서브넷
+ - 인터넷에 직접 엑세스가 가능한 서브넷이다.
+ - 인터넷 게이트웨이를 VPC에 연결하고 퍼블릭 서브넷의 라우팅 테이블을 업데이트하여 로컬이 아닌 트래픽을 인터넷 게이트웨이로 보내면 퍼블릭 서브넷처럼 사용할 수 있다.
+- 프라이빗 서브넷
+ - 인터넷에 직접 액세스가 불가능한 서브넷이다.
+ - 보통 회사 내부 서버나 프로그램들은 프라이빗 서브넷에 위치시켜 인터넷을 통해 아무나 접근이 불가능하게 한다.
+
+### Public Subnet을 각각 A,C 가용영역에 생성해보기
+
+![스크린샷 2024-08-22 오후 4.01.51.png](/assets/images/aws04/03.png)
+
+서브넷을 생성할 VPC를 목록에서 선택하고, 서브넷 이름은 이름-public-subnet-가용영역으로 생성하였다.
+
+![스크린샷 2024-08-22 오후 4.09.50.png](/assets/images/aws04/04.png)
+
+첫번째로, 가용영역 A에 서브넷을 생성해준다.
+
+IPv4 CIDR 블록에는 선택한 VPC의 IP범위 내, 생성할 서브넷의 IP 대역대를 입력한다.
+
+![스크린샷 2024-08-22 오후 4.12.16.png](/assets/images/aws04/05.png)
+
+새 서브넷 추가를 클릭하여 가용영역 C에 서브넷을 하나 더 추가해준다.
+
+![스크린샷 2024-08-22 오후 4.54.01.png](/assets/images/aws04/06.png)
+
+## 3. Internet Gateway 생성
+
+Internet Gateway란
+
+- VPC에 부착되어, VPC와 인터넷 간에 통신할 수 있게 해주는 출입문 역할을 한다.
+- 방금 만든 서브넷들이 퍼블릭 서브넷 역할을 하게끔 해주려면, 인터넷으로 접속할 수 있어야 하기 때문이다.
+
+![스크린샷 2024-08-22 오후 4.17.29.png](/assets/images/aws04/07.png)
+
+이제 방금 만든 인터넷 게이트웨이를 선택해서 VPC와 연결을 해준다.
+
+![스크린샷 2024-08-22 오후 4.18.42.png](/assets/images/aws04/08.png)
+
+![스크린샷 2024-08-22 오후 4.19.53.png](/assets/images/aws04/09.png)
+
+![스크린샷 2024-08-22 오후 4.20.27.png](/assets/images/aws04/10.png)
+
+## 4. Public 전용 라우팅 테이블 생성
+
+Routing Table 이란
+
+- IP 주소에 트래픽 라우팅 경로를 정의하여 Subnet 안팎으로 나가는 트래픽에 대한 라우팅 경로 설정 기능을 수행한다.
+- 인터넷을 통해 요청이 들어왔을 때, 요청이 들어올 경로 안내를 하는 네비게이션 역할을 한다.
+
+라우팅 테이블이 사용할 VPC를 목록에서 선택 후 생성해준다.
+
+![스크린샷 2024-08-22 오후 4.24.05.png](/assets/images/aws04/11.png)
+
+그다음, 라우팅 테이블 목록에서 라우팅 테이블을 체크 후 ‘서브넷 연결 편집’ 메뉴를 통해 서브넷과 연결해준다.
+
+![스크린샷 2024-08-22 오후 4.26.06.png](/assets/images/aws04/12.png)
+
+‘서브넷 연결 편집’은 해당 라우팅 테이블이 어떤 서브넷에 적용이 되는지 설정해주는 곳이다.
+
+퍼블릭 서브넷 역할을 하게 할 라우팅 테이블이므로, 퍼블릭 역할을 하게 될 서브넷들만 선택한다.
+
+![스크린샷 2024-08-22 오후 4.27.49.png](/assets/images/aws04/13.png)
+
+이제 어떤 라우팅을 해줄 것인지 설정해주면 된다.
+
+방금 등록한 라우팅 테이블을 선택 후 ‘라우팅 편집 버튼’을 클릭하여 설정해준다.
+
+![스크린샷 2024-08-22 오후 4.28.47.png](/assets/images/aws04/14.png)
+
+local : 현재 기본 설정되어 있는 라우팅, VPC 대역대에 있는 IP들 (즉, VPC 내부의 Private IP)들이 서로 알고있게끔 하는 기본 설정이다.
+
+라우팅을 추가하여 대상에는 0.0.0.0/0을 입력, 만든 Internet Gateway로 설정한다.
+
+즉, 위치 무관 아무나 들어올 수 있게 추가한다는 의미
+
+![스크린샷 2024-08-22 오후 4.32.17.png](/assets/images/aws04/15.png)
+
+이제 VPC에 priavte subnet을 구축해보자
+
+프라이빗 서브넷 생성 → 프라이빗 라우팅 테이블 생성 및 설정 순으로 진행
+
+## 5. Private Subnet 생성
+
+이전과 비슷한 방식으로 가용영역 A,C에 생성해준다.
+
+이름-private-subnet-가용영역 으로 생성하고, 서브넷의 IP대역대를 설정해준다.
+
+![스크린샷 2024-08-22 오후 4.44.27.png](/assets/images/aws04/16.png)
+
+![스크린샷 2024-08-22 오후 4.47.24.png](/assets/images/aws04/17.png)
+
+## 6. Private 라우팅 테이블 생성
+
+라우팅 테이블 이름과 사용될 VPC를 선택하고 생성해준다.
+
+![스크린샷 2024-08-22 오후 4.48.23.png](/assets/images/aws04/18.png)
+
+‘서브넷 연결 편집’ 메뉴에서 방금 만든 private subnet들을 선택하여 등록해준다.
+
+![스크린샷 2024-08-22 오후 4.50.01.png](/assets/images/aws04/19.png)
+
+private subnet에 위치하게 될 리소스들은 private IP만 가지기 때문에 내부가 아닌 외부의 리소스들과 통신을 할 수 없게 된다.
+
+### NAT 인스턴스 생성
+
+private IP를 public IP로 변환해 private IP는 감추고, 통신을 할 수 있도록 하게 해준다.
+
+NAT Gateway는 비용이 비싸므로 NAT역할을 할 수 있는 NAT Instance를 생성하여 EC2의 t2.micro 비용으로 NAT 역할을 하는 서버를 만들것이다.
+
+프라이빗 라우팅 테이블에 이 NAT Instance를 추가하면 private subnet안의 리소드들은 이를 통해 외부 리소스들과 통신할 수 있게 된다.
+
+## 7. EC2(NAT Instance) 생성
+
+- private subnet 내의 웹 서버들이 외부로 통신을 하기 위해 사용하는 서버
+- 보통 NAT서버를 public subnet안에 구축하여 NAT를 통해 외부로 통신함
+
+AMI 선택
+
+AMI > ‘nat’로 검색 > 아무버전이나 선택 > AMI로 인스턴스 시작
+
+![스크린샷 2024-08-22 오후 5.46.13.png](/assets/images/aws04/20.png)
+
+인스턴스 유형 : t2.micro 선택
+
+VPC : 내가 만든 vpc 선택
+
+서브넷 : public subnet - a 선택
+
+스토리지 : default
+
+![스크린샷 2024-08-22 오후 5.51.53.png](/assets/images/aws04/21.png)
+
+새로운 keypair 생성
+
+보안 그룹 추가 : 내 PC에서만 SSH 접속이 가능하도록 설정
+
+마지막으로, NAT는 소스/대상 확인을 하면 안됩니다
+
+그렇기 때문에 방금 생성한 nat instance 서버를 체크하고 작업-네트워킹-소스/대상 확인 변경 클릭
+
+소스/대상 확인의 ‘중지’를 체크하고 저장하기
+
+![스크린샷 2024-08-22 오후 5.58.21.png](/assets/images/aws04/22.png)
+
+## 8. 탄력적 IP 주소 할당
+
+- 탄력적 IP 주소는 인터넷에서 연결 가능한 퍼블릭 IPv4 주소 이다.
+- AWS 계정에 할당되며 릴리스할 때까지 할당된 상태로 유지된다.
+- 탄력적 IP주소를 생성해 방금 만든 인스턴스에 연결해주면 해당 인스턴스 IP는 고정 IP주소가 된다.
+
+![스크린샷 2024-08-22 오후 6.01.05.png](/assets/images/aws04/23.png)
+
+생성할 때, 맨 아래에 Name 태그를 하나 추가해줘서 식별해주기
+
+![스크린샷 2024-08-22 오후 6.02.07.png](/assets/images/aws04/24.png)
+
+### 탄력적 IP주소 연결
+
+EIP를 생성했으면 해당 EIP를 사용할 인스턴스를 연결해야 한다.
+
+해당 EIP를 체크해주고, 작업 매뉴에서 탄력적 IP 주소 연결 실행
+
+![스크린샷 2024-08-22 오후 6.02.57.png](/assets/images/aws04/25.png)
+
+연결할 인스턴스를 선택하고 연결 버튼 클릭.
+
+주의) EIP는 AWS에게 IP주소를 빌려오는 개념이기 때문에 EIP에 인스턴스를 연결해주지 않으면 오히려 요금이 부과되는 형태이다. 만약 EC2 인스턴스를 릴리즈(종료)할려면, 꼭 EIP도 같이 릴리즈하기
+
+![스크린샷 2024-08-22 오후 6.04.44.png](/assets/images/aws04/26.png)
+
+이제 NAT Instance 생성 및 설정이 완료되었으니, 0.0.0.0/0 트래픽을 NAT를 통해 들어올 수 있도록 바꾸면 된다.
+
+라우틴 테이블 편집하여 대상을 0.0.0.0/0, 인스턴스 선택 → nat instance를 선택한다.
+
+![스크린샷 2024-08-22 오후 6.07.37.png](/assets/images/aws04/27.png)
+
+이제 private subnet a에 EC2 인스턴스 생성하여 웹서버를 구축해준다.
+
+기존에 가지고 있던 간단한 AMI로 생성해준다.
+
+keypair는 nat instance의 keypair로 사용.
+
+private subnet으로 네트워크 설정을 했으므로 아래와 같이 퍼블릭 IP주소는 할당이 안되게 잘 생성해주자.
+
+![스크린샷 2024-08-22 오후 6.52.48.png](/assets/images/aws04/28.png)
+
+## 9. ALB & Target Group 생성
+
+### ALB(Application Load Balancer)
+
+- 둘 이상의 가용 영역에서 EC2 인스턴스, 컨테이너, IP주소 등 여러 대상에 걸쳐 수신되는 트래픽을 자동으로 분산하는 서비스
+- LB는 등록된 대상의 상태를 모니터링하며, 상태가 양호한 대상으로만 트래픽을 라우팅 해준다.
+- LB에는 여러 종류가 있음(Application LB, Network LB, Gateway LB, Classic LB)
+- 특히, ALB는 HTTP의 URL, FTP의 파일명, 쿠키 정보 등을 분석해 더 정교한 로드 밸런싱이 가능한 서비스이다.
+
+EC2 - 로드 밸런싱 - 로드밸런서 클릭
+
+![스크린샷 2024-08-22 오후 7.00.33.png](/assets/images/aws04/29.png)
+
+[Application Load Balancer 선택]
+
+이름 : tester-alb
+
+체계 : 인터넷 경계
+
+VPC : tester-seoul-vpc
+
+가용영역 : a,c체크 및 public-subnet-a,c 선택
+
+보안그룹 : 인바인드 규칙 0.0.0.0/0 80port
+
+![스크린샷 2024-08-22 오후 7.02.06.png](/assets/images/aws04/30.png)
+
+![스크린샷 2024-08-22 오후 7.03.10.png](/assets/images/aws04/31.png)
+
+리스너 및 라우팅
+
+간단하게 http 통신을 해볼것이기 때문에 80포트 사용(spring, node.js 등의 웹서버를 올리려면 해당 웹서버에서 사용하는 포트로 지정)
+
+![스크린샷 2024-08-22 오후 7.11.11.png](/assets/images/aws04/32.png)
+
+대상 그룹 생성 클릭하여 대상 그룹 지정해주기
+
+ALB 대상은 인스턴스이므로 인스턴스 선택
+
+프로토콜 : 포트 지정
+
+![스크린샷 2024-08-22 오후 7.13.19.png](/assets/images/aws04/33.png)
+
+![스크린샷 2024-08-22 오후 7.13.42.png](/assets/images/aws04/34.png)
+
+ALB가 해당 옵션으로 타겟의 healthy/unhealty 상태를 검사함.
+
+![스크린샷 2024-08-22 오후 7.14.00.png](/assets/images/aws04/35.png)
+
+생성을 클릭하면 아래와 같은 화면에서 등록할 대상 즉, 인스턴스를 선택할 수 있다.
+
+![스크린샷 2024-08-22 오후 7.16.26.png](/assets/images/aws04/36.png)
\ No newline at end of file
diff --git "a/_posts/2024-05-04-OLAP\354\231\200 OLTP.md" "b/_posts/2024-05-04-OLAP\354\231\200 OLTP.md"
new file mode 100644
index 000000000000..1f8a10e1942f
--- /dev/null
+++ "b/_posts/2024-05-04-OLAP\354\231\200 OLTP.md"
@@ -0,0 +1,80 @@
+---
+layout: single
+title: "OLAP와 OLTP"
+categories: [CS]
+tag: [cs]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+
+
+
+
+## 1. OLTP (Online Transaction Processing)
+
+### OLTP 정의
+
+- ‘운영’계 데이터 및 데이터를 처리하는 방법을 의미한다.
+- 복수의 사용자 PC에서 발생되는 트랜잭션을 DB서버가 처리, 그 결과를 요청한 사용자에게 실시간으로 결과값을 되돌려주는 과정
+- 1개의 트랜잭션에서 발생되는 INSERT, UPDATE, DELETE를 무결성 보장하여 처리하고 결과를 SELECT하는 과정
+
+### OLTP의 특징
+
+- 과거에는 주로 RDBMS 기반의 시스템을 근간으로 했으나 NoSQL도 운영계 데이터의 성격을 띤다면 OLTP로 분류 가능
+- 현재 데이터가 처리가 얼마나 정확하고 무결한지가 중요
+- 실질적인 데이터의 저장, 삭제, 수정 등의 작업을 의미
+- 비교적 작은 규모의 트랜잭션들로 구성
+- CRUD와 관련된 쿼리들이 주를 이룸
+- 전통적인 DBMS들이 주로 사용됨
+
+## 2. OLAP (Online Analytical Processing)
+
+### OLAP의 정의
+
+- ‘분석’계 데이터 및 데이터를 처리하는 방법을 의미한다.
+- 데이터 웨어하우스(DW), DB에 저장되어 있는 데이터를 분석, 사용자에게 유의미한 정보를 제공해주는 처리 방법이다.
+- 기존에 저장되어 있는 데이터를 사용자의 요구와 목적에 맞게 분석하여 정보를 제공하는 개념
+
+### OLAP의 특징
+
+- 분석을 통해 BI(Business Intelligence)와 연계하여 특정 지표 추출, 리포트 생산, 의사 결정에 도움
+- 이미 저장된 데이터를 바탕으로 어떤 정보를 제공하는지가 중요
+- 데이터가 무결, 정확하다는 전재 하에 정보를 어떤 식으로 표현하고 제공하는지를 의미
+- 대용량 데이터를 취급
+- 통계/집계 등의 복잡한 쿼리들이 주를 이룸
+- DW(Data Warehouse)를 구축
+- 데이터가 어느정도 중복이 되더라도 별 상관이 없으며 많은 데이터 수집이 필요
+
+## OLTP와 OLAP 비교
+
+| 구분 | OLTP | OLAP |
+| --- | --- | --- |
+| 목적 | 비즈니스 활동 지원 | 비즈니스 활동에 대한 평가, 분석 |
+| 주 트랜잭션 형태 | SELECT, INSERT, UPDATE, DELETE | SELECT |
+| 속도 | 수 초 이내 | 수 초 이상 수 분 이내 |
+| 데이터 표현 시간 | 실시간 | 과거 |
+| 관리 단위 | 테이블 | 분석된 정보 |
+| 최적화 방법 | 트랜잭션 효율화, 무결성 극대화 | 조회 속도, 정보의 가치, 편의성 |
+| 데이터의 특성 | 트랜잭션 중심 | 정보 중심 |
+| 중요점 | 데이터의 정확도, 무결성 | 결과의 속도, 표현 방식 |
+| 활용자 | 운영자 | 분석가, 의사결정자1 |
+
+- OLTP와 OLAP 중 가장 선행되어야 할 부분은 OLTP (데이터 처리 과정 및 데이터 자체의 무결성 중요)
+- OLTP가 원천 데이터의 제공처이며 ETL작업을 통해 OLAP에 데이터를 제공
\ No newline at end of file
diff --git "a/_posts/2024-05-10-RDS\354\235\230 ElastiCache.md" "b/_posts/2024-05-10-RDS\354\235\230 ElastiCache.md"
new file mode 100644
index 000000000000..8d303edc99a0
--- /dev/null
+++ "b/_posts/2024-05-10-RDS\354\235\230 ElastiCache.md"
@@ -0,0 +1,45 @@
+---
+layout: single
+title: "RDS의 ElastiCache"
+categories: [AWS]
+tag: [AWS, RDS]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+## ElastiCache
+
+- 클라두으 내에서 In-memory 캐시를 만들어줌
+- 데이터베이스에서 데이터를 읽어오는것이 아니라 캐시에서 빠른 속도로 데이터를 읽어옴
+ - 수백, 수천만 개의 프로세싱을 동시다발적으로 처리할 경우 큰 차이가 생김
+ - 종종 불러오는 레코드들은 예를 들면 SNS, 네이버 실시간 검색어 Top10 등 많은 사람들에 의해서 읽혀지는 데이터들을 캐시에 넣음으로써 빠른 로딩을 가능하게 함
+- Read-Heavy 어플리케이션에서 상당한 Latency 감소 효과가 있음
+- 초반 어플리케이션 개발 및 테스트 용도로는 적합하지 않음
+- Elasti Cache는 Memcached와 Redis가 존재한다.
+
+## Memcached
+
+- Object 캐시 시스템으로 잘 알려져 있음
+- ElastiCache는 Memcached의 프로토콜을 디폴트로 따름
+- EC2 Auto Scaling처럼 데이터 처리 사용량에 따라 캐시의 크기가 커졌다 작아졌다 가능함
+- Memcached는 오픈 소스이다.
+
+### Memcached는 이럴때 사용하면 좋다!
+
+1. 가장 단순한 캐싱 모델이 필요한가요? Yes
+2. Object caching이 주된 모기적인가요? Yes
+3. 캐시 크기를 마음대로 scaling하기를 원하나요? Yes
+
+## Redis
+
+- Key-Value, Set, List와 같은 형태의 데이터를 In-Memory에 저장 가능함
+- 오픈 소스이다.
+- Multi-AZ 기능을 지원한다. (Disaster Recovery 기능)
+
+### Redis는 이럴때 사용하면 좋다!
+
+1. List, Set과 같은 데이터셋을 사용하나요? Yes
+2. 리더보드처럼 데이터셋의 랭킹을 정렬하는 용도가 필요한가요? Yes
+3. Multi AZ기능이 필요하나요? Yes
\ No newline at end of file
diff --git "a/_posts/2024-05-10-aws5_AWS RDS \353\260\261\354\227\205.md" "b/_posts/2024-05-10-aws5_AWS RDS \353\260\261\354\227\205.md"
new file mode 100644
index 000000000000..2f5d652b8edd
--- /dev/null
+++ "b/_posts/2024-05-10-aws5_AWS RDS \353\260\261\354\227\205.md"
@@ -0,0 +1,40 @@
+---
+layout: single
+title: "AWS RDS 백업"
+categories: [AWS]
+tag: [AWS, RDS]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+AWS RDS에는 두 가지 백업 기능이 존재한다.
+
+- Automated Backups (자동 백업)
+- DB Snapshots (데이터베이스 스냅샷)
+
+## Automated Backups(AB) - 자동 백업
+
+1. Retention Period(1 ~ 35일) 안의 어떤 시간으로 돌아가게 할 수 있음
+ - 현 시점부터 35일 전까지가 Retenntion Period에 해당
+2. AB는 그날 생성된 스냅샷과 Transaction logs(TL)을 참고함
+ - AB는 복원을 대비하기 위해 매일 스냅샷과 트랜잭션 로그를 끊임없이 생성함
+ - 유저가 고른 날짜로 돌아가길 원한다면 그 날짜에 해당하는 스냅샷과 트랜잭션 로그를 참조한다.
+3. 디폴트로 AB기능이 설정되어 있으며 백업 정보는 S3에 저장됨
+ - RDS 인스턴스 크기만큼에 해당되는 용량까지만 무료로 사용 가능
+4. AB동안 약간의 I/O suspension이 존재할 수 있음(체감상 크게 느껴지지는 않지만 어느정도 딜레이 존재)
+
+## DB Snapshots - 데이터베이스 스냅샷
+
+1. 주로 사용자에 의해 실행됨
+2. 원본 RDS Instance를 삭제해도 스냅샷은 존재함
+ - 원본 RDS 인스턴스를 삭제해도 스냅샷은 S3에 존재함
+ - AB 기능은 원본 인스턴스를 삭제할 시 사라짐
+
+## 데이터베이스 백업했을 때
+
+![스크린샷 2024-08-24 오후 9.52.55.png](/assets/images/aws05/1.png)
+
+- 전혀 다른 RDS 인스턴스가 생성된다.
+- 전혀 다른 RDS 엔드포인트가 생성된다.
\ No newline at end of file
diff --git "a/_posts/2024-05-10-aws6_RDS\354\235\230 Multi AZ, Read Replicas.md" "b/_posts/2024-05-10-aws6_RDS\354\235\230 Multi AZ, Read Replicas.md"
new file mode 100644
index 000000000000..d5089602a22e
--- /dev/null
+++ "b/_posts/2024-05-10-aws6_RDS\354\235\230 Multi AZ, Read Replicas.md"
@@ -0,0 +1,39 @@
+---
+layout: single
+title: "RDS의 Multi AZ, Read Replicas"
+categories: [AWS]
+tag: [AWS, RDS]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+## Multi AZ
+
+- 원래 존재하는 RDS DB에 무언가 변화(ex. write)가 생길 때 다른 Availability Zone에 똑같은 복제본이 만들어짐 = Synchronize
+- AWS에 의해서 자동으로 관리가 이루어짐 (No admin intervention)
+- 원본 RDS DB에 문제가 생길 시 자동으로 다른 AZ의 복제본이 사용됨 (Disaster Recovery)
+- 성능 개선을 위해서 사용되지는 않음 → 성능 개선을 기대하기 위해선 Read Replica 사용
+
+![스크린샷 2024-08-24 오후 10.00.31.png](/assets/images/aws06/1.png)
+
+- 3개의 인스턴스가 하나의 프로덕션 RDS DB에 연결되어 있고 쓰기 기능이 실행된다면,
+- 현재 RDS 엔드포인트는 ap-northeast-2a 이지만 쓰기 기능이 실행된 후 똑같은 복제본이 다른 AZ(ap-northeast-2b)에 쓰여진다.
+- 만약 AZ 2a의 RDS에 문제가 생긴다면 RDS는 자동으로 AZ 2b로 failover를 한다.
+
+## Read Replica
+
+- 프로덕션 DB의 읽기 전용 복제본이 생성됨
+- 주로 Read-Heavy DB 작업시 효율성의 극대화를 위해 사용된다 (Scaling)
+- Disaster Recovery 용도가 아님
+- 최대 5개의 Read Replica DB가 허용됨
+- Read Replica의 Read Replica 생성이 가능(단, 약간의 Latency 발생)
+- 각각의 Read Replica는 자기만의 고유 엔드포인트가 존재한다.
+- RDS DB는 IP 주소가 아닌 엔드포인트로 고유 식별을 할 수 있다.
+
+![스크린샷 2024-08-24 오후 10.29.56.png](/assets/images/aws06/2.png)
+
+- 3개의 인스턴스가 하나의 메인 프로덕션 RDS에 연결되어 있을 때 쓰기 작업이 실행될 시 read replica에 의해 똑같은 RDS 복제본이 생성된다,
+- 그리고 3개의 인스턴스에서 Read Traffic이 일어날 때, 메인 프로덕션 DB로 모두 연결시키는것이 아니라 하나의 EC2 인스턴스를 각각의 Read Replica로 연결시켜줌
+- 따라서, 메인 DB의 워크로드를 현저히 낮출 수 있으며 성능 개선 효과를 누릴 수 있다.
\ No newline at end of file
diff --git "a/_posts/2024-05-15-aws07_RDS \354\203\235\354\204\261 \353\260\217 EC2 \354\235\270\354\212\244\355\204\264\354\212\244 \354\227\260\352\262\260.md" "b/_posts/2024-05-15-aws07_RDS \354\203\235\354\204\261 \353\260\217 EC2 \354\235\270\354\212\244\355\204\264\354\212\244 \354\227\260\352\262\260.md"
new file mode 100644
index 000000000000..858e9cc649d2
--- /dev/null
+++ "b/_posts/2024-05-15-aws07_RDS \354\203\235\354\204\261 \353\260\217 EC2 \354\235\270\354\212\244\355\204\264\354\212\244 \354\227\260\352\262\260.md"
@@ -0,0 +1,154 @@
+---
+layout: single
+title: "RDS 생성 및 EC2 인스턴스 연결하기"
+categories: [AWS]
+tag: [AWS, RDS]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+## RDS 생성
+
+RDS > 데이터베이스 생성 > MySQL로 생성 > 버전은 기본으로 선택(MySQL 8.0.35)
+
+![스크린샷 2024-08-26 오전 12.24.32.png](/assets/images/aws07/1.png)
+
+템플릿에서 프로덕션과 개발/테스트 를 선택하면 아래에 Multi AZ 기능을 사용할 수 있다.
+
+프리티어에서는 사용 불가.
+
+![스크린샷 2024-08-26 오전 12.25.56.png](/assets/images/aws07/2.png)
+
+DB인스턴스 이름과 어드민 사용자 이름, 암호를 설정한다.
+
+![스크린샷 2024-08-26 오전 12.27.22.png](/assets/images/aws07/3.png)
+
+그다음에 인스턴스 구성을 한다. 프리티어를 선택했기 때문에 버스터블 클래스 이외에는 선택사항이 없다.
+
+버스터블 클래스란 상황에 따라서 CPU의 성능을 버스트시킬 수 있다는 뜻이다.
+
+![스크린샷 2024-08-26 오전 12.34.24.png](/assets/images/aws07/4.png)
+
+스토리지 유형은 범용 SSD(gp2)로 선택한다. 스토리지 유형 목록을 보면 GP3란게 있는데, 이건 추가 비용을 냄으로써 IOPS 처리량을 늘릴 수 있다.
+
+할당된 스토리지의 크기는 간단한 시스템을 유지하기 위해 20GIB로 설정한다.
+
+스토리지 자동 조정 활성화란게 있는데 오토 스케일링을 뜻한다. 최대 스토리지 임계값은 디폴트(1000GIB)로 설정해준다.
+
+![스크린샷 2024-08-26 오전 12.35.57.png](/assets/images/aws07/5.png)
+
+## EC2 인스턴스 연결
+
+그 다음은 컴퓨팅 리소스에 대해서 묻는데, 최근 UI 업데이트를 통해 여기서 직접 EC2 인스턴스를 만들어서 RDS와 바로 연결시킬 수 있다.
+
+![스크린샷 2024-08-26 오전 12.40.32.png](/assets/images/aws07/6.png)
+
+여기서 RDS와 연결해줄 EC2 인스턴스를 생성해둔다.
+
+- 인스턴스명 : aws-learner-rds-ec2-instance, 내가 가지고 있는 기존 키페어(testkey.pem) 선택
+- 보안 그룹 : http 80포트와 ssh 22포트를 위치무관 접속할 수 있게 설정.
+
+ ![스크린샷 2024-08-26 오전 12.50.23.png](/assets/images/aws07/7.png)
+
+- 고급 세부 정보 > 사용자 데이터 에서 편리한 설정을 위해 EC2 인스턴스가 생성되면서 실행될 스크립트 내용을 넣어준다.
+- EC2 인스턴스 생성 후 apache, php, mysql을 yes 옵션으로 설치 후 아파치 실행
+- 간단한 php파일을 아파치 서버 디렉토리 내에 index.php로 저장
+- wget 명령어로 S3내의 connect.php 파일을 다운로드
+
+connect.php 파일 내용
+
+```php
+";
+$selected = mysql_select_db("$dbname",$dbhandle) or die("MySQL DB 연결 실패... - 다시 시도해보세요!");
+?>
+```
+
+EC2 인스턴스 생성이 완료되었으면 다시 RDS 생성 화면으로 돌아와서 방금 생성한 EC2 인스턴스를 선택해준다.
+
+![스크린샷 2024-08-26 오전 12.53.56.png](/assets/images/aws07/8.png)
+
+VPC는 디폴트로 만들어질것이고, DB 서브넷 그룹은 기존 항목을 선택하거나 자동설정으로 선택해준다.
+
+VPC 보안 그룹은 선택/생성이 있는데 기존에 생성했던 ssh, http 접근이 가능한 보안그룹으로 선택해줬다.
+
+![스크린샷 2024-08-26 오전 12.57.35.png](/assets/images/aws07/9.png)
+
+다음으로 가용영역이 있는데, 지금은 프리티어 용이라 Multi-AZ 기능을 사용할 수 없으므로 선택 권한이 없다.
+
+추가 구성에서 데이터베이스 포트를 지정할 수 있다. (MySQL default 포트는 3306)
+
+![스크린샷 2024-08-26 오전 12.58.21.png](/assets/images/aws07/10.png)
+
+다음은 데이터페이스 암호 인증을 선택할 수 있는 곳이다. 여기선 위에서 부여했던 어드민 사용자, 암호를 가지고 데이터베이스에 접속할 수 있게끔 ‘암호 인증’을 선택해 줬다.
+
+![스크린샷 2024-08-26 오전 1.00.07.png](/assets/images/aws07/11.png)
+
+마지막으로 추가구성에서 데이터베이스 옵션에서는 초기 데이터베이스 이름을 설정해주고 나머지는 디폴트로 설정해줬다.
+
+![스크린샷 2024-08-26 오전 1.03.15.png](/assets/images/aws07/12.png)
+
+## EC2 인스턴스 확인
+
+방금 RDS와 연결한 인스턴스를 퍼블릭 IP주소로 접속해보면 php 화면이 뜬다.
+
+![스크린샷 2024-08-26 오전 1.54.05.png](/assets/images/aws07/13.png)
+
+이제 이 EC2 인스턴스에 터미널로 접속해본다.
+
+![스크린샷 2024-08-26 오전 1.56.45.png](/assets/images/aws07/14.png)
+
+아까 EC2를 생성할 때 입력했던 구문중 connect.php 파일 내용 확인
+
+/var/www/html 폴더에 wget 이동
+
+![스크린샷 2024-08-26 오전 1.58.31.png](/assets/images/aws07/15.png)
+
+- vi connect.php
+- hostname 값을 생성한 RDS 인스턴스의 엔드포인트명으로 바꿔준다.
+
+ ![스크린샷 2024-08-26 오전 3.20.47.png](/assets/images/aws07/16.png)
+
+
+수정 한 후 ec2 DNS명/connect.php로 확인해보기
+
+확인해보면 아래와 같이 MySQL에 연결할 수 없다고 나온다.
+
+![스크린샷 2024-08-26 오전 2.06.19.png](/assets/images/aws07/17.png)
+
+이유는 현재 RDS 보안그룹은 RDS 인스턴스 안에서만 존재하며,
+
+우리가 웹에서 접속한 EC2 인스턴스에서는 별개의 보안그룹이 존재한다.
+
+두 개의 서로 다른 클라우드에서 다른 보안 그룹이 존재하므로 현재 EC2에서 RDS로 통신이 불가능한 상태이다.
+
+## RDS 보안 그룹 확인하기
+
+생성한 RDS의 보안 그룹 > 인바운드 규칙 확인
+
+그다음, 이 소스를 지우고 아까 EC2 인스턴스가 속해 있는 보안 그룹을 찾아서 연결해준다.
+
+![스크린샷 2024-08-26 오전 2.34.04.png](/assets/images/aws07/18.png)
+
+그러면 이렇게 ‘기존 IPv4 CIDR 규칙에 a 참조된 그룹 ID를 지정할 수 없습니다.’ 라는 에러가 뜬다.
+
+위 에러를 해결하려면, 이 규칙을 삭제하고 다시 똑같이 만들어주면 지정이 된다.
+
+![스크린샷 2024-08-26 오전 2.36.24.png](/assets/images/aws07/19.png)
+
+다시 똑같이 만들어 준 후에 저장을 누른다.
+
+(DB 파라미터 그룹은 따로 정리.)
+
+다시 /connect.php 화면을 로딩해서 접속 성공 여부를 확인한다.
+
+![스크린샷 2024-08-26 오전 3.21.41.png](/assets/images/aws07/20.png)
\ No newline at end of file
diff --git "a/_posts/2024-05-15-aws08_RDS \355\214\214\353\235\274\353\257\270\355\204\260 \352\267\270\353\243\271.md" "b/_posts/2024-05-15-aws08_RDS \355\214\214\353\235\274\353\257\270\355\204\260 \352\267\270\353\243\271.md"
new file mode 100644
index 000000000000..7ac610f3d0ce
--- /dev/null
+++ "b/_posts/2024-05-15-aws08_RDS \355\214\214\353\235\274\353\257\270\355\204\260 \352\267\270\353\243\271.md"
@@ -0,0 +1,106 @@
+---
+layout: single
+title: "RDS 파라미터 그룹"
+categories: [AWS]
+tag: [AWS, RDS]
+toc: true
+toc_sticky: true
+post-header: false
+
+---
+
+
+
+
+
+## RDS 파라미터 그룹 설정
+
+데이터베이스 파라미터 그룹은 데이터베이스 구성 방법을 지정해준다. 데이터베이스에 할당할 메모리 등의 리소스 양을 지정할 수 있다.
+
+또한, DB 인스턴스와 다중 AZ DB 클러스터를 파라미터 그룹과 연결하여 데이터베이스 구성을 관리하는 작업도 지원한다고 한다.
+
+RDS > 파라미터 그룹에서 새로운 파라미터 그룹을 생성한다.
+
+![스크린샷 2024-08-26 오전 2.46.02.png](/assets/images/aws08/2.46.02.png)
+
+아래와 같이 설정을 마치고 생성해준다.
+
+- 파라미터 그룹 이름 입력
+- 엔진 유형 : MySQL Community
+- 파라미터 그룹 패밀리 : mysql8.0
+- 유형 : DB Parameter Group
+
+![스크린샷 2024-08-26 오전 2.51.27.png](/assets/images/aws08/2.51.27.png)
+
+파라미터 그룹을 생성한 후에 해당 파라미터 그룹을 클릭한다.
+
+편집을 눌러서 파라미터 값을 수정해주면 된다.
+
+![스크린샷 2024-08-26 오전 2.54.49.png](/assets/images/aws08/2.54.49.png)
+
+1. Character Set (문자 인코딩 설정)
+ - 기본적으로 utf8은 많이 들어보았지만, 가변3바이트인 utf8에는 이모지 문자가 입력이 되지 않는다.
+ - 따라서, 4바이트를 사용하는 utf8mb4로 설정한다.
+2. Time Zone(시간 설정)
+3. Collation (데이터의 정렬 기준을 위한 설정)
+
+### 1. Character Set 설정
+
+- character_set_client, character_set_connection, character_set_database, character_set_server, character_set_filesystem, character_set_results = utf8mb4
+- MySQL의 character에 대한 정리
+
+
+| 파라미터 | 설명 |
+| ---| --- |
+| **character_set_client** | - MySQL Client의 Default Character set - Client로부터 전송되는 쿼리문장의 문자집합을 말함 - 각 커넥션에서 임의의 문자집합으로 변경해서 사용 가능 |
+| **character_set_connection** | - MySQL Server가 Client로부터 전달받은 쿼리 문장에서 인트로듀서(Introducer)가 없는 리터럴(literal) 또는 숫자(number) 값을 문자(String)열로 변환할 때 사용하는 Character set - 각 커넥션에서 임의의 문자집합으로 변경해서 사용 가능 |
+| **character_set_database** | - MySQL Database의 Default Character set - 이 변수가 지정되지 않았다면 character_set_server와 같은 값을 가짐 - 각 DB, TABLE, COLUMN은 기본 문자셋과 관계없이 개별적인 문자집합을 가질 수 있으며 DB를 생성할 때 아무런 문자집합이 명시되지 않았다면, 이 변수의 값이 기본값으로 사용됨 |
+| **character_set_filesystem** | - LOAD DATA INFILE ... 또는 SELECT ... INTO OUTFILE 문장이 실행될 때 파일의 읽고 쓰기에 사용되는 Character set - 데이터 파일의 내용을 읽을 때 사용하는 문자집합이 아닌, 파일의 이름을 찾을 때 사용하는 문자 집합 - 파일을 오픈하려는 시도가 있기 전에 character_set_client에서 character_set_filesystem으로 변환 - 기본값은 binary인데, 이것은 아무런 변환이 없다는 것을 의미 - 멀티 바이트 파일 이름을 사용할 수 있는 시스템에서는 서로 다른 값을 사용하도록 함 - 예를 들면 시스템이 UTF8로 파일이름을 표시한다면, 'utf8'로 설정 - 이 변수는 MySQL 5.1.6에서 추가 - 각 커넥션에서 임의의 문자집합으로 변경해서 사용 가능 |
+| **character_set_results** | - MySQL Server가 쿼리의 처리 결과 또는 error 를 Client로 retuen 할 때 사용하는 Character set - 각 커넥션에서의 임의의 문자집합으로 변경해서 사용 가능 |
+| **character_set_server** | - MySQL Server의 Default Character set - DB나 TABLE 또는 COLUMN에 아무런 문자집합이 설정되지 않았을 때, 이 변수의 값이 기본값으로 사용됨 - 각 커넥션에서의 임의의 문자집합으로 변경해서 사용 가능 |
+| **character_set_system** | - MySQL Server가 T 식별자(Identifier, 테이블명이나 컬럼명 등)를 저장하기 위해 사용하는 캐릭터셋 - 항상 utf8로 설정되어있으며, 사용자가 설정하거나 변경할 수 없음 |
+
+
+### 2. Time Zone 설정
+
+- time_zone = **Asia/Seoul**
+
+### 3. Collation 설정
+
+- collation_connection, collation_server = utf8_unicode_ci
+
+파라미터 그룹 설정 완료 후 아까 만들어둔 RDS 인스턴스에 접속하여 수정 진행.
+
+파라미터 그룹을 방금 만든것으로 수정 후 즉시적용 선택
+
+![스크린샷 2024-08-26 오전 3.04.03.png](/assets/images/aws08/3.04.03.png)
+
+RDS 인스턴스 수정이 완료되면 상태가 되면, 재부팅을 해주어야 적용이 된다.
\ No newline at end of file
diff --git a/_sass/minimal-mistakes/_reset.scss b/_sass/minimal-mistakes/_reset.scss
index 2259fd0c2388..1574e3058ca9 100644
--- a/_sass/minimal-mistakes/_reset.scss
+++ b/_sass/minimal-mistakes/_reset.scss
@@ -8,18 +8,18 @@ html {
/* apply a natural box layout model to all elements */
box-sizing: border-box;
background-color: $background-color;
- font-size: 16px;
+ font-size: 14px;
@include breakpoint($medium) {
- font-size: 18px;
+ font-size: 16px;
}
@include breakpoint($large) {
- font-size: 20px;
+ font-size: 16px;
}
@include breakpoint($x-large) {
- font-size: 22px;
+ font-size: 16px;
}
-webkit-text-size-adjust: 100%;
diff --git a/assets/css/main.scss b/assets/css/main.scss
index 23346e773b1b..0f204fabe737 100644
--- a/assets/css/main.scss
+++ b/assets/css/main.scss
@@ -5,4 +5,11 @@
@charset "utf-8";
@import "minimal-mistakes/skins/{{ site.minimal_mistakes_skin | default: 'default' }}"; // skin
-@import "minimal-mistakes"; // main partials
\ No newline at end of file
+@import "minimal-mistakes"; // main partials
+
+@import url('https://fonts.googleapis.com/css?family=Inconsolata');
+
+.archive a {
+ color: #696969; // 메인 포스트 a태그 제목 색
+ text-decoration: none;
+}
\ No newline at end of file
diff --git a/assets/images/DL01/img1.png b/assets/images/DL01/img1.png
new file mode 100644
index 000000000000..0e153986b85a
Binary files /dev/null and b/assets/images/DL01/img1.png differ
diff --git a/assets/images/DL01/img10.png b/assets/images/DL01/img10.png
new file mode 100644
index 000000000000..90b91a1906cb
Binary files /dev/null and b/assets/images/DL01/img10.png differ
diff --git a/assets/images/DL01/img2.png b/assets/images/DL01/img2.png
new file mode 100644
index 000000000000..f1408e5bbb0e
Binary files /dev/null and b/assets/images/DL01/img2.png differ
diff --git a/assets/images/DL01/img3.png b/assets/images/DL01/img3.png
new file mode 100644
index 000000000000..d41985d31c26
Binary files /dev/null and b/assets/images/DL01/img3.png differ
diff --git a/assets/images/DL01/img4.png b/assets/images/DL01/img4.png
new file mode 100644
index 000000000000..1da3d50907a0
Binary files /dev/null and b/assets/images/DL01/img4.png differ
diff --git a/assets/images/DL01/img5.png b/assets/images/DL01/img5.png
new file mode 100644
index 000000000000..67e776e29b4d
Binary files /dev/null and b/assets/images/DL01/img5.png differ
diff --git a/assets/images/DL01/img6.png b/assets/images/DL01/img6.png
new file mode 100644
index 000000000000..0bb59b24ce4f
Binary files /dev/null and b/assets/images/DL01/img6.png differ
diff --git a/assets/images/DL01/img9.png b/assets/images/DL01/img9.png
new file mode 100644
index 000000000000..c8e227108f57
Binary files /dev/null and b/assets/images/DL01/img9.png differ
diff --git a/assets/images/DL02/01_1.png b/assets/images/DL02/01_1.png
new file mode 100644
index 000000000000..8d8bd74d2d44
Binary files /dev/null and b/assets/images/DL02/01_1.png differ
diff --git a/assets/images/DL02/01_2.png b/assets/images/DL02/01_2.png
new file mode 100644
index 000000000000..20587b24b6ba
Binary files /dev/null and b/assets/images/DL02/01_2.png differ
diff --git a/assets/images/DL02/01_3.png b/assets/images/DL02/01_3.png
new file mode 100644
index 000000000000..d60cc061e47b
Binary files /dev/null and b/assets/images/DL02/01_3.png differ
diff --git a/assets/images/DL02/01_4.png b/assets/images/DL02/01_4.png
new file mode 100644
index 000000000000..0bcc59971120
Binary files /dev/null and b/assets/images/DL02/01_4.png differ
diff --git a/assets/images/DL02/01_5.png b/assets/images/DL02/01_5.png
new file mode 100644
index 000000000000..7266182da7c4
Binary files /dev/null and b/assets/images/DL02/01_5.png differ
diff --git a/assets/images/DL02/01_6.png b/assets/images/DL02/01_6.png
new file mode 100644
index 000000000000..bba4c5815fa4
Binary files /dev/null and b/assets/images/DL02/01_6.png differ
diff --git a/assets/images/DL03/02_1.png b/assets/images/DL03/02_1.png
new file mode 100644
index 000000000000..cf5f18351691
Binary files /dev/null and b/assets/images/DL03/02_1.png differ
diff --git a/assets/images/DL03/02_2.png b/assets/images/DL03/02_2.png
new file mode 100644
index 000000000000..b0fd03e1df86
Binary files /dev/null and b/assets/images/DL03/02_2.png differ
diff --git a/assets/images/DL04/output_18_0.png b/assets/images/DL04/output_18_0.png
new file mode 100644
index 000000000000..fa793d294c1b
Binary files /dev/null and b/assets/images/DL04/output_18_0.png differ
diff --git a/assets/images/DL05/05_1.png b/assets/images/DL05/05_1.png
new file mode 100644
index 000000000000..099bcab97138
Binary files /dev/null and b/assets/images/DL05/05_1.png differ
diff --git a/assets/images/DL05/05_2.png b/assets/images/DL05/05_2.png
new file mode 100644
index 000000000000..9cf687c7ad25
Binary files /dev/null and b/assets/images/DL05/05_2.png differ
diff --git a/assets/images/DL05/05_3.png b/assets/images/DL05/05_3.png
new file mode 100644
index 000000000000..279fe352763a
Binary files /dev/null and b/assets/images/DL05/05_3.png differ
diff --git a/assets/images/DL05/05_4.png b/assets/images/DL05/05_4.png
new file mode 100644
index 000000000000..fe8458176494
Binary files /dev/null and b/assets/images/DL05/05_4.png differ
diff --git a/assets/images/DL05/05_5.png b/assets/images/DL05/05_5.png
new file mode 100644
index 000000000000..3ff90cbd12c9
Binary files /dev/null and b/assets/images/DL05/05_5.png differ
diff --git a/assets/images/DL06/09_3.png b/assets/images/DL06/09_3.png
new file mode 100644
index 000000000000..65712511017d
Binary files /dev/null and b/assets/images/DL06/09_3.png differ
diff --git a/assets/images/DL06/09_4.jpg b/assets/images/DL06/09_4.jpg
new file mode 100644
index 000000000000..0156801efe43
Binary files /dev/null and b/assets/images/DL06/09_4.jpg differ
diff --git a/assets/images/DL06/09_5.png b/assets/images/DL06/09_5.png
new file mode 100644
index 000000000000..767e6622e00e
Binary files /dev/null and b/assets/images/DL06/09_5.png differ
diff --git a/assets/images/DL06/result1.png b/assets/images/DL06/result1.png
new file mode 100644
index 000000000000..7739c4188cb7
Binary files /dev/null and b/assets/images/DL06/result1.png differ
diff --git a/assets/images/DL06/result2.png b/assets/images/DL06/result2.png
new file mode 100644
index 000000000000..7ba83434b4e3
Binary files /dev/null and b/assets/images/DL06/result2.png differ
diff --git a/assets/images/DL06/result3.png b/assets/images/DL06/result3.png
new file mode 100644
index 000000000000..a3586100ce9f
Binary files /dev/null and b/assets/images/DL06/result3.png differ
diff --git a/assets/images/DL07/07_1.png b/assets/images/DL07/07_1.png
new file mode 100644
index 000000000000..a1ac68c58b92
Binary files /dev/null and b/assets/images/DL07/07_1.png differ
diff --git a/assets/images/DL07/07_10.png b/assets/images/DL07/07_10.png
new file mode 100644
index 000000000000..6a54ce6331ae
Binary files /dev/null and b/assets/images/DL07/07_10.png differ
diff --git a/assets/images/DL07/07_11.png b/assets/images/DL07/07_11.png
new file mode 100644
index 000000000000..27e2a8115178
Binary files /dev/null and b/assets/images/DL07/07_11.png differ
diff --git a/assets/images/DL07/07_12.png b/assets/images/DL07/07_12.png
new file mode 100644
index 000000000000..8988b93f138f
Binary files /dev/null and b/assets/images/DL07/07_12.png differ
diff --git a/assets/images/DL07/07_2.png b/assets/images/DL07/07_2.png
new file mode 100644
index 000000000000..b4add6ed0c9a
Binary files /dev/null and b/assets/images/DL07/07_2.png differ
diff --git a/assets/images/DL07/07_3_1.png b/assets/images/DL07/07_3_1.png
new file mode 100644
index 000000000000..2554a51aa369
Binary files /dev/null and b/assets/images/DL07/07_3_1.png differ
diff --git a/assets/images/DL07/07_3_2.png b/assets/images/DL07/07_3_2.png
new file mode 100644
index 000000000000..5722c1545f0e
Binary files /dev/null and b/assets/images/DL07/07_3_2.png differ
diff --git a/assets/images/DL07/07_4.png b/assets/images/DL07/07_4.png
new file mode 100644
index 000000000000..7498d21b9b69
Binary files /dev/null and b/assets/images/DL07/07_4.png differ
diff --git a/assets/images/DL07/07_5.png b/assets/images/DL07/07_5.png
new file mode 100644
index 000000000000..eea3893c6880
Binary files /dev/null and b/assets/images/DL07/07_5.png differ
diff --git a/assets/images/DL07/07_6.png b/assets/images/DL07/07_6.png
new file mode 100644
index 000000000000..828ffd936d43
Binary files /dev/null and b/assets/images/DL07/07_6.png differ
diff --git a/assets/images/DL07/07_7.png b/assets/images/DL07/07_7.png
new file mode 100644
index 000000000000..8758383debaf
Binary files /dev/null and b/assets/images/DL07/07_7.png differ
diff --git a/assets/images/DL07/07_8.png b/assets/images/DL07/07_8.png
new file mode 100644
index 000000000000..5322883164f6
Binary files /dev/null and b/assets/images/DL07/07_8.png differ
diff --git a/assets/images/DL07/07_9.png b/assets/images/DL07/07_9.png
new file mode 100644
index 000000000000..d0f12a9fd54d
Binary files /dev/null and b/assets/images/DL07/07_9.png differ
diff --git a/assets/images/DL07/Untitled.png b/assets/images/DL07/Untitled.png
new file mode 100644
index 000000000000..9e1b58f5dc21
Binary files /dev/null and b/assets/images/DL07/Untitled.png differ
diff --git a/assets/images/DL08-1/output_19_0.png b/assets/images/DL08-1/output_19_0.png
new file mode 100644
index 000000000000..b7e2522d6ec7
Binary files /dev/null and b/assets/images/DL08-1/output_19_0.png differ
diff --git a/assets/images/DL08-1/output_21_0.png b/assets/images/DL08-1/output_21_0.png
new file mode 100644
index 000000000000..2bf2efc14a70
Binary files /dev/null and b/assets/images/DL08-1/output_21_0.png differ
diff --git a/assets/images/DL08-1/output_29_0.png b/assets/images/DL08-1/output_29_0.png
new file mode 100644
index 000000000000..d17687a2a8ba
Binary files /dev/null and b/assets/images/DL08-1/output_29_0.png differ
diff --git a/assets/images/DL08-1/output_34_0.png b/assets/images/DL08-1/output_34_0.png
new file mode 100644
index 000000000000..70b54f8eff1d
Binary files /dev/null and b/assets/images/DL08-1/output_34_0.png differ
diff --git a/assets/images/DL08-1/output_40_0.png b/assets/images/DL08-1/output_40_0.png
new file mode 100644
index 000000000000..1f1827a14da9
Binary files /dev/null and b/assets/images/DL08-1/output_40_0.png differ
diff --git "a/assets/images/GRU\354\205\200.png" "b/assets/images/GRU\354\205\200.png"
new file mode 100644
index 000000000000..67604eec7eb5
Binary files /dev/null and "b/assets/images/GRU\354\205\200.png" differ
diff --git a/assets/images/LSTM_cell_update.png b/assets/images/LSTM_cell_update.png
new file mode 100644
index 000000000000..d838218861a1
Binary files /dev/null and b/assets/images/LSTM_cell_update.png differ
diff --git "a/assets/images/LSTM_cell\354\203\201\355\203\234.png" "b/assets/images/LSTM_cell\354\203\201\355\203\234.png"
new file mode 100644
index 000000000000..1e15571e388b
Binary files /dev/null and "b/assets/images/LSTM_cell\354\203\201\355\203\234.png" differ
diff --git "a/assets/images/LSTM_forget\352\262\214\354\235\264\355\212\270.png" "b/assets/images/LSTM_forget\352\262\214\354\235\264\355\212\270.png"
new file mode 100644
index 000000000000..ebf842727866
Binary files /dev/null and "b/assets/images/LSTM_forget\352\262\214\354\235\264\355\212\270.png" differ
diff --git "a/assets/images/LSTM_input\352\262\214\354\235\264\355\212\270.png" "b/assets/images/LSTM_input\352\262\214\354\235\264\355\212\270.png"
new file mode 100644
index 000000000000..a23c5f6f793a
Binary files /dev/null and "b/assets/images/LSTM_input\352\262\214\354\235\264\355\212\270.png" differ
diff --git "a/assets/images/LSTM_output\352\262\214\354\235\264\355\212\270.png" "b/assets/images/LSTM_output\352\262\214\354\235\264\355\212\270.png"
new file mode 100644
index 000000000000..c651d44b34b0
Binary files /dev/null and "b/assets/images/LSTM_output\352\262\214\354\235\264\355\212\270.png" differ
diff --git "a/assets/images/LSTM\352\265\254\354\241\260.png" "b/assets/images/LSTM\352\265\254\354\241\260.png"
new file mode 100644
index 000000000000..2a078543b6a7
Binary files /dev/null and "b/assets/images/LSTM\352\265\254\354\241\260.png" differ
diff --git "a/assets/images/LSTM\352\270\260\355\230\270.png" "b/assets/images/LSTM\352\270\260\355\230\270.png"
new file mode 100644
index 000000000000..a112c1c77bc1
Binary files /dev/null and "b/assets/images/LSTM\352\270\260\355\230\270.png" differ
diff --git a/assets/images/MyProfile.png b/assets/images/MyProfile.png
new file mode 100644
index 000000000000..f7b066a32ecc
Binary files /dev/null and b/assets/images/MyProfile.png differ
diff --git a/assets/images/RNN.png b/assets/images/RNN.png
new file mode 100644
index 000000000000..b40d64761f3c
Binary files /dev/null and b/assets/images/RNN.png differ
diff --git "a/assets/images/RNN\354\210\230\354\213\235.PNG" "b/assets/images/RNN\354\210\230\354\213\235.PNG"
new file mode 100644
index 000000000000..d1586b88dda2
Binary files /dev/null and "b/assets/images/RNN\354\210\230\354\213\235.PNG" differ
diff --git "a/assets/images/RNN\355\231\234\354\232\251.PNG" "b/assets/images/RNN\355\231\234\354\232\251.PNG"
new file mode 100644
index 000000000000..ac2062badb32
Binary files /dev/null and "b/assets/images/RNN\355\231\234\354\232\251.PNG" differ
diff --git a/assets/images/Sigmoid.png b/assets/images/Sigmoid.png
new file mode 100644
index 000000000000..a7d3be13c4b7
Binary files /dev/null and b/assets/images/Sigmoid.png differ
diff --git "a/assets/images/Sigmoid_\354\204\261\354\247\210.png" "b/assets/images/Sigmoid_\354\204\261\354\247\210.png"
new file mode 100644
index 000000000000..444bdd5fb35c
Binary files /dev/null and "b/assets/images/Sigmoid_\354\204\261\354\247\210.png" differ
diff --git a/assets/images/aws01/01.png b/assets/images/aws01/01.png
new file mode 100644
index 000000000000..9f0aee5d5f9d
Binary files /dev/null and b/assets/images/aws01/01.png differ
diff --git a/assets/images/aws01/02.png b/assets/images/aws01/02.png
new file mode 100644
index 000000000000..0cc1c3089152
Binary files /dev/null and b/assets/images/aws01/02.png differ
diff --git a/assets/images/aws01/03.png b/assets/images/aws01/03.png
new file mode 100644
index 000000000000..f0f12d71c8a1
Binary files /dev/null and b/assets/images/aws01/03.png differ
diff --git a/assets/images/aws01/04.png b/assets/images/aws01/04.png
new file mode 100644
index 000000000000..d5e6d4852a35
Binary files /dev/null and b/assets/images/aws01/04.png differ
diff --git a/assets/images/aws01/05.png b/assets/images/aws01/05.png
new file mode 100644
index 000000000000..c961b49623ea
Binary files /dev/null and b/assets/images/aws01/05.png differ
diff --git a/assets/images/aws01/06.png b/assets/images/aws01/06.png
new file mode 100644
index 000000000000..7a8f353aa509
Binary files /dev/null and b/assets/images/aws01/06.png differ
diff --git a/assets/images/aws01/07.png b/assets/images/aws01/07.png
new file mode 100644
index 000000000000..f565c55a7647
Binary files /dev/null and b/assets/images/aws01/07.png differ
diff --git a/assets/images/aws01/08.png b/assets/images/aws01/08.png
new file mode 100644
index 000000000000..d5b5dd061700
Binary files /dev/null and b/assets/images/aws01/08.png differ
diff --git a/assets/images/aws01/09.png b/assets/images/aws01/09.png
new file mode 100644
index 000000000000..3523548a1750
Binary files /dev/null and b/assets/images/aws01/09.png differ
diff --git a/assets/images/aws01/10.png b/assets/images/aws01/10.png
new file mode 100644
index 000000000000..87be6e619762
Binary files /dev/null and b/assets/images/aws01/10.png differ
diff --git a/assets/images/aws01/11.png b/assets/images/aws01/11.png
new file mode 100644
index 000000000000..6cadf899ad93
Binary files /dev/null and b/assets/images/aws01/11.png differ
diff --git a/assets/images/aws01/12.png b/assets/images/aws01/12.png
new file mode 100644
index 000000000000..5901e4f38d0b
Binary files /dev/null and b/assets/images/aws01/12.png differ
diff --git a/assets/images/aws03/01.png b/assets/images/aws03/01.png
new file mode 100644
index 000000000000..1616d0b660cd
Binary files /dev/null and b/assets/images/aws03/01.png differ
diff --git a/assets/images/aws04/01.png b/assets/images/aws04/01.png
new file mode 100644
index 000000000000..7515804fbb2c
Binary files /dev/null and b/assets/images/aws04/01.png differ
diff --git a/assets/images/aws04/02.png b/assets/images/aws04/02.png
new file mode 100644
index 000000000000..55d05762d595
Binary files /dev/null and b/assets/images/aws04/02.png differ
diff --git a/assets/images/aws04/03.png b/assets/images/aws04/03.png
new file mode 100644
index 000000000000..3bcf250140d6
Binary files /dev/null and b/assets/images/aws04/03.png differ
diff --git a/assets/images/aws04/04.png b/assets/images/aws04/04.png
new file mode 100644
index 000000000000..8ca8beaee775
Binary files /dev/null and b/assets/images/aws04/04.png differ
diff --git a/assets/images/aws04/05.png b/assets/images/aws04/05.png
new file mode 100644
index 000000000000..a18d20dbd007
Binary files /dev/null and b/assets/images/aws04/05.png differ
diff --git a/assets/images/aws04/06.png b/assets/images/aws04/06.png
new file mode 100644
index 000000000000..4ad7a07d5029
Binary files /dev/null and b/assets/images/aws04/06.png differ
diff --git a/assets/images/aws04/07.png b/assets/images/aws04/07.png
new file mode 100644
index 000000000000..277ec2097296
Binary files /dev/null and b/assets/images/aws04/07.png differ
diff --git a/assets/images/aws04/08.png b/assets/images/aws04/08.png
new file mode 100644
index 000000000000..b0f38ef3c4fc
Binary files /dev/null and b/assets/images/aws04/08.png differ
diff --git a/assets/images/aws04/09.png b/assets/images/aws04/09.png
new file mode 100644
index 000000000000..12fcfbae8714
Binary files /dev/null and b/assets/images/aws04/09.png differ
diff --git a/assets/images/aws04/10.png b/assets/images/aws04/10.png
new file mode 100644
index 000000000000..5867e85c491e
Binary files /dev/null and b/assets/images/aws04/10.png differ
diff --git a/assets/images/aws04/11.png b/assets/images/aws04/11.png
new file mode 100644
index 000000000000..22c5c3cab252
Binary files /dev/null and b/assets/images/aws04/11.png differ
diff --git a/assets/images/aws04/12.png b/assets/images/aws04/12.png
new file mode 100644
index 000000000000..760888565d58
Binary files /dev/null and b/assets/images/aws04/12.png differ
diff --git a/assets/images/aws04/13.png b/assets/images/aws04/13.png
new file mode 100644
index 000000000000..a2399e5ffce4
Binary files /dev/null and b/assets/images/aws04/13.png differ
diff --git a/assets/images/aws04/14.png b/assets/images/aws04/14.png
new file mode 100644
index 000000000000..a60965e1a420
Binary files /dev/null and b/assets/images/aws04/14.png differ
diff --git a/assets/images/aws04/15.png b/assets/images/aws04/15.png
new file mode 100644
index 000000000000..61325c92b5f8
Binary files /dev/null and b/assets/images/aws04/15.png differ
diff --git a/assets/images/aws04/16.png b/assets/images/aws04/16.png
new file mode 100644
index 000000000000..24a47f1050dd
Binary files /dev/null and b/assets/images/aws04/16.png differ
diff --git a/assets/images/aws04/17.png b/assets/images/aws04/17.png
new file mode 100644
index 000000000000..e6fff3cda6fc
Binary files /dev/null and b/assets/images/aws04/17.png differ
diff --git a/assets/images/aws04/18.png b/assets/images/aws04/18.png
new file mode 100644
index 000000000000..8eca004ddab7
Binary files /dev/null and b/assets/images/aws04/18.png differ
diff --git a/assets/images/aws04/19.png b/assets/images/aws04/19.png
new file mode 100644
index 000000000000..8b43d279ce4e
Binary files /dev/null and b/assets/images/aws04/19.png differ
diff --git a/assets/images/aws04/20.png b/assets/images/aws04/20.png
new file mode 100644
index 000000000000..d202e99b0c2b
Binary files /dev/null and b/assets/images/aws04/20.png differ
diff --git a/assets/images/aws04/21.png b/assets/images/aws04/21.png
new file mode 100644
index 000000000000..4e378d9aa71c
Binary files /dev/null and b/assets/images/aws04/21.png differ
diff --git a/assets/images/aws04/22.png b/assets/images/aws04/22.png
new file mode 100644
index 000000000000..759543dc4283
Binary files /dev/null and b/assets/images/aws04/22.png differ
diff --git a/assets/images/aws04/23.png b/assets/images/aws04/23.png
new file mode 100644
index 000000000000..8a8405476eec
Binary files /dev/null and b/assets/images/aws04/23.png differ
diff --git a/assets/images/aws04/24.png b/assets/images/aws04/24.png
new file mode 100644
index 000000000000..39b7fba5cbd1
Binary files /dev/null and b/assets/images/aws04/24.png differ
diff --git a/assets/images/aws04/25.png b/assets/images/aws04/25.png
new file mode 100644
index 000000000000..f0e74de6bd11
Binary files /dev/null and b/assets/images/aws04/25.png differ
diff --git a/assets/images/aws04/26.png b/assets/images/aws04/26.png
new file mode 100644
index 000000000000..99b7ad265676
Binary files /dev/null and b/assets/images/aws04/26.png differ
diff --git a/assets/images/aws04/27.png b/assets/images/aws04/27.png
new file mode 100644
index 000000000000..39e537c0959c
Binary files /dev/null and b/assets/images/aws04/27.png differ
diff --git a/assets/images/aws04/28.png b/assets/images/aws04/28.png
new file mode 100644
index 000000000000..4df0bfc1c229
Binary files /dev/null and b/assets/images/aws04/28.png differ
diff --git a/assets/images/aws04/29.png b/assets/images/aws04/29.png
new file mode 100644
index 000000000000..401031309f9d
Binary files /dev/null and b/assets/images/aws04/29.png differ
diff --git a/assets/images/aws04/30.png b/assets/images/aws04/30.png
new file mode 100644
index 000000000000..87666f43ce10
Binary files /dev/null and b/assets/images/aws04/30.png differ
diff --git a/assets/images/aws04/31.png b/assets/images/aws04/31.png
new file mode 100644
index 000000000000..07eed66ebef2
Binary files /dev/null and b/assets/images/aws04/31.png differ
diff --git a/assets/images/aws04/32.png b/assets/images/aws04/32.png
new file mode 100644
index 000000000000..b6070dd1f203
Binary files /dev/null and b/assets/images/aws04/32.png differ
diff --git a/assets/images/aws04/33.png b/assets/images/aws04/33.png
new file mode 100644
index 000000000000..4e74958cf99b
Binary files /dev/null and b/assets/images/aws04/33.png differ
diff --git a/assets/images/aws04/34.png b/assets/images/aws04/34.png
new file mode 100644
index 000000000000..166ed48a076e
Binary files /dev/null and b/assets/images/aws04/34.png differ
diff --git a/assets/images/aws04/35.png b/assets/images/aws04/35.png
new file mode 100644
index 000000000000..12d4c85216ff
Binary files /dev/null and b/assets/images/aws04/35.png differ
diff --git a/assets/images/aws04/36.png b/assets/images/aws04/36.png
new file mode 100644
index 000000000000..a98debf0d498
Binary files /dev/null and b/assets/images/aws04/36.png differ
diff --git a/assets/images/aws05/1.png b/assets/images/aws05/1.png
new file mode 100644
index 000000000000..142897b0eb14
Binary files /dev/null and b/assets/images/aws05/1.png differ
diff --git a/assets/images/aws06/1.png b/assets/images/aws06/1.png
new file mode 100644
index 000000000000..2f482266d8af
Binary files /dev/null and b/assets/images/aws06/1.png differ
diff --git a/assets/images/aws06/2.png b/assets/images/aws06/2.png
new file mode 100644
index 000000000000..e1a06937e120
Binary files /dev/null and b/assets/images/aws06/2.png differ
diff --git a/assets/images/aws07/1.png b/assets/images/aws07/1.png
new file mode 100644
index 000000000000..6d58e79034cd
Binary files /dev/null and b/assets/images/aws07/1.png differ
diff --git a/assets/images/aws07/10.png b/assets/images/aws07/10.png
new file mode 100644
index 000000000000..e4ab75edd31f
Binary files /dev/null and b/assets/images/aws07/10.png differ
diff --git a/assets/images/aws07/11.png b/assets/images/aws07/11.png
new file mode 100644
index 000000000000..9da53722cd04
Binary files /dev/null and b/assets/images/aws07/11.png differ
diff --git a/assets/images/aws07/12.png b/assets/images/aws07/12.png
new file mode 100644
index 000000000000..5888b1144f83
Binary files /dev/null and b/assets/images/aws07/12.png differ
diff --git a/assets/images/aws07/13.png b/assets/images/aws07/13.png
new file mode 100644
index 000000000000..90e173c2d490
Binary files /dev/null and b/assets/images/aws07/13.png differ
diff --git a/assets/images/aws07/14.png b/assets/images/aws07/14.png
new file mode 100644
index 000000000000..3a0c5d002bfb
Binary files /dev/null and b/assets/images/aws07/14.png differ
diff --git a/assets/images/aws07/15.png b/assets/images/aws07/15.png
new file mode 100644
index 000000000000..17897c2cb72c
Binary files /dev/null and b/assets/images/aws07/15.png differ
diff --git a/assets/images/aws07/16.png b/assets/images/aws07/16.png
new file mode 100644
index 000000000000..1fee2a06d406
Binary files /dev/null and b/assets/images/aws07/16.png differ
diff --git a/assets/images/aws07/17.png b/assets/images/aws07/17.png
new file mode 100644
index 000000000000..0ba178e80b99
Binary files /dev/null and b/assets/images/aws07/17.png differ
diff --git a/assets/images/aws07/18.png b/assets/images/aws07/18.png
new file mode 100644
index 000000000000..1762d5582800
Binary files /dev/null and b/assets/images/aws07/18.png differ
diff --git a/assets/images/aws07/19.png b/assets/images/aws07/19.png
new file mode 100644
index 000000000000..4833172d6838
Binary files /dev/null and b/assets/images/aws07/19.png differ
diff --git a/assets/images/aws07/2.png b/assets/images/aws07/2.png
new file mode 100644
index 000000000000..1fd5b26ce2b5
Binary files /dev/null and b/assets/images/aws07/2.png differ
diff --git a/assets/images/aws07/20.png b/assets/images/aws07/20.png
new file mode 100644
index 000000000000..d3506d3f7344
Binary files /dev/null and b/assets/images/aws07/20.png differ
diff --git a/assets/images/aws07/3.png b/assets/images/aws07/3.png
new file mode 100644
index 000000000000..5856a367771f
Binary files /dev/null and b/assets/images/aws07/3.png differ
diff --git a/assets/images/aws07/4.png b/assets/images/aws07/4.png
new file mode 100644
index 000000000000..b6eae43d83d7
Binary files /dev/null and b/assets/images/aws07/4.png differ
diff --git a/assets/images/aws07/5.png b/assets/images/aws07/5.png
new file mode 100644
index 000000000000..482558826cc1
Binary files /dev/null and b/assets/images/aws07/5.png differ
diff --git a/assets/images/aws07/6.png b/assets/images/aws07/6.png
new file mode 100644
index 000000000000..d18e4d680787
Binary files /dev/null and b/assets/images/aws07/6.png differ
diff --git a/assets/images/aws07/7.png b/assets/images/aws07/7.png
new file mode 100644
index 000000000000..06e79dcb346c
Binary files /dev/null and b/assets/images/aws07/7.png differ
diff --git a/assets/images/aws07/8.png b/assets/images/aws07/8.png
new file mode 100644
index 000000000000..7ddd7825ed39
Binary files /dev/null and b/assets/images/aws07/8.png differ
diff --git a/assets/images/aws07/9.png b/assets/images/aws07/9.png
new file mode 100644
index 000000000000..3f21629cd27f
Binary files /dev/null and b/assets/images/aws07/9.png differ
diff --git a/assets/images/aws08/2.46.02.png b/assets/images/aws08/2.46.02.png
new file mode 100644
index 000000000000..6d120db4863d
Binary files /dev/null and b/assets/images/aws08/2.46.02.png differ
diff --git a/assets/images/aws08/2.51.27.png b/assets/images/aws08/2.51.27.png
new file mode 100644
index 000000000000..c99d7af02b96
Binary files /dev/null and b/assets/images/aws08/2.51.27.png differ
diff --git a/assets/images/aws08/2.54.49.png b/assets/images/aws08/2.54.49.png
new file mode 100644
index 000000000000..708ccc069591
Binary files /dev/null and b/assets/images/aws08/2.54.49.png differ
diff --git a/assets/images/aws08/3.04.03.png b/assets/images/aws08/3.04.03.png
new file mode 100644
index 000000000000..1f84e0ff2c2d
Binary files /dev/null and b/assets/images/aws08/3.04.03.png differ
diff --git a/assets/images/git01/01.png b/assets/images/git01/01.png
new file mode 100644
index 000000000000..78a6f0d6724e
Binary files /dev/null and b/assets/images/git01/01.png differ
diff --git a/assets/images/git01/02.png b/assets/images/git01/02.png
new file mode 100644
index 000000000000..d05c3e51879f
Binary files /dev/null and b/assets/images/git01/02.png differ
diff --git a/assets/images/git01/03.png b/assets/images/git01/03.png
new file mode 100644
index 000000000000..8bd8862ccad1
Binary files /dev/null and b/assets/images/git01/03.png differ
diff --git a/assets/images/git01/04.png b/assets/images/git01/04.png
new file mode 100644
index 000000000000..a2df38409840
Binary files /dev/null and b/assets/images/git01/04.png differ
diff --git a/assets/images/git01/05.png b/assets/images/git01/05.png
new file mode 100644
index 000000000000..6d50148fbdcd
Binary files /dev/null and b/assets/images/git01/05.png differ
diff --git a/assets/images/git01/06.png b/assets/images/git01/06.png
new file mode 100644
index 000000000000..e44dc307dfa8
Binary files /dev/null and b/assets/images/git01/06.png differ
diff --git a/assets/images/ml01/01.png b/assets/images/ml01/01.png
new file mode 100644
index 000000000000..984e1d40e74e
Binary files /dev/null and b/assets/images/ml01/01.png differ
diff --git a/assets/images/ml01/02.png b/assets/images/ml01/02.png
new file mode 100644
index 000000000000..0ee416d8c61a
Binary files /dev/null and b/assets/images/ml01/02.png differ
diff --git a/assets/images/ml02/01.png b/assets/images/ml02/01.png
new file mode 100644
index 000000000000..03f43ce97b83
Binary files /dev/null and b/assets/images/ml02/01.png differ
diff --git a/assets/images/ml02/02.png b/assets/images/ml02/02.png
new file mode 100644
index 000000000000..6b9cb1a745b6
Binary files /dev/null and b/assets/images/ml02/02.png differ
diff --git a/assets/images/ml03/01.png b/assets/images/ml03/01.png
new file mode 100644
index 000000000000..d46c1d4b120e
Binary files /dev/null and b/assets/images/ml03/01.png differ
diff --git a/assets/images/ml03/02.png b/assets/images/ml03/02.png
new file mode 100644
index 000000000000..9da015d9730f
Binary files /dev/null and b/assets/images/ml03/02.png differ
diff --git a/assets/images/ml03/output_20_0.svg b/assets/images/ml03/output_20_0.svg
new file mode 100644
index 000000000000..48e0ac096b9e
--- /dev/null
+++ b/assets/images/ml03/output_20_0.svg
@@ -0,0 +1,396 @@
+
+
+
+
+
diff --git a/assets/images/ml04/output_61_0.png b/assets/images/ml04/output_61_0.png
new file mode 100644
index 000000000000..64939ca6457d
Binary files /dev/null and b/assets/images/ml04/output_61_0.png differ
diff --git a/assets/images/springboot01/00_1.png b/assets/images/springboot01/00_1.png
new file mode 100644
index 000000000000..bb80801ee633
Binary files /dev/null and b/assets/images/springboot01/00_1.png differ
diff --git a/assets/images/springboot01/01_1.png b/assets/images/springboot01/01_1.png
new file mode 100644
index 000000000000..dbe7035149fd
Binary files /dev/null and b/assets/images/springboot01/01_1.png differ
diff --git a/assets/images/springboot02/00_1.png b/assets/images/springboot02/00_1.png
new file mode 100644
index 000000000000..cc0213dae9e7
Binary files /dev/null and b/assets/images/springboot02/00_1.png differ
diff --git a/assets/images/springboot03/00_1.png b/assets/images/springboot03/00_1.png
new file mode 100644
index 000000000000..e0584ab96c05
Binary files /dev/null and b/assets/images/springboot03/00_1.png differ
diff --git a/assets/images/springboot08/01.png b/assets/images/springboot08/01.png
new file mode 100644
index 000000000000..ed32fbd23b64
Binary files /dev/null and b/assets/images/springboot08/01.png differ
diff --git a/assets/images/springboot08/02.png b/assets/images/springboot08/02.png
new file mode 100644
index 000000000000..c0e0e16af781
Binary files /dev/null and b/assets/images/springboot08/02.png differ
diff --git a/assets/images/springboot08/03.png b/assets/images/springboot08/03.png
new file mode 100644
index 000000000000..663dd8717810
Binary files /dev/null and b/assets/images/springboot08/03.png differ
diff --git a/assets/images/springboot08/04.png b/assets/images/springboot08/04.png
new file mode 100644
index 000000000000..8f2e5d73318a
Binary files /dev/null and b/assets/images/springboot08/04.png differ
diff --git a/assets/images/springboot08/05.png b/assets/images/springboot08/05.png
new file mode 100644
index 000000000000..7e571a62d443
Binary files /dev/null and b/assets/images/springboot08/05.png differ
diff --git a/assets/images/springboot08/06.png b/assets/images/springboot08/06.png
new file mode 100644
index 000000000000..402aa070e7a9
Binary files /dev/null and b/assets/images/springboot08/06.png differ
diff --git "a/assets/images/\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225.png" "b/assets/images/\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225.png"
new file mode 100644
index 000000000000..cc5809644ce4
Binary files /dev/null and "b/assets/images/\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225.png" differ
diff --git "a/assets/images/\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225_\352\263\274\354\240\225.png" "b/assets/images/\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225_\352\263\274\354\240\225.png"
new file mode 100644
index 000000000000..e8e5b0a800f4
Binary files /dev/null and "b/assets/images/\352\262\275\354\202\254\355\225\230\352\260\225\353\262\225_\352\263\274\354\240\225.png" differ
diff --git "a/assets/images/\352\263\265\354\213\235_MSE.png" "b/assets/images/\352\263\265\354\213\235_MSE.png"
new file mode 100644
index 000000000000..315f4f016420
Binary files /dev/null and "b/assets/images/\352\263\265\354\213\235_MSE.png" differ
diff --git "a/assets/images/\352\263\265\354\213\235_\354\265\234\354\206\214\354\240\234\352\263\261\353\262\225.png" "b/assets/images/\352\263\265\354\213\235_\354\265\234\354\206\214\354\240\234\352\263\261\353\262\225.png"
new file mode 100644
index 000000000000..516775f9c4db
Binary files /dev/null and "b/assets/images/\352\263\265\354\213\235_\354\265\234\354\206\214\354\240\234\352\263\261\353\262\225.png" differ
diff --git "a/assets/images/\353\246\254\355\204\264\354\213\234\355\200\270\354\212\244.PNG" "b/assets/images/\353\246\254\355\204\264\354\213\234\355\200\270\354\212\244.PNG"
new file mode 100644
index 000000000000..ff015f94cbf7
Binary files /dev/null and "b/assets/images/\353\246\254\355\204\264\354\213\234\355\200\270\354\212\244.PNG" differ
diff --git "a/assets/images/\353\247\245\354\212\244\355\222\200\353\247\201.png" "b/assets/images/\353\247\245\354\212\244\355\222\200\353\247\201.png"
new file mode 100644
index 000000000000..7266182da7c4
Binary files /dev/null and "b/assets/images/\353\247\245\354\212\244\355\222\200\353\247\201.png" differ
diff --git "a/assets/images/\353\252\250\353\221\220\354\235\230\353\224\245\353\237\254\353\213\235.png" "b/assets/images/\353\252\250\353\221\220\354\235\230\353\224\245\353\237\254\353\213\235.png"
new file mode 100644
index 000000000000..431d79a6d0bc
Binary files /dev/null and "b/assets/images/\353\252\250\353\221\220\354\235\230\353\224\245\353\237\254\353\213\235.png" differ
diff --git "a/assets/images/\353\252\250\353\251\230\355\205\200.png" "b/assets/images/\353\252\250\353\251\230\355\205\200.png"
new file mode 100644
index 000000000000..0be08065b09c
Binary files /dev/null and "b/assets/images/\353\252\250\353\251\230\355\205\200.png" differ
diff --git "a/assets/images/\354\213\234\352\267\270\353\252\250\354\235\264\353\223\234\353\257\270\353\266\204.png" "b/assets/images/\354\213\234\352\267\270\353\252\250\354\235\264\353\223\234\353\257\270\353\266\204.png"
new file mode 100644
index 000000000000..debf33b19da7
Binary files /dev/null and "b/assets/images/\354\213\234\352\267\270\353\252\250\354\235\264\353\223\234\353\257\270\353\266\204.png" differ
diff --git "a/assets/images/\354\230\244\354\260\250\354\227\255\354\240\204\355\214\2141.png" "b/assets/images/\354\230\244\354\260\250\354\227\255\354\240\204\355\214\2141.png"
new file mode 100644
index 000000000000..2975e6e76087
Binary files /dev/null and "b/assets/images/\354\230\244\354\260\250\354\227\255\354\240\204\355\214\2141.png" differ
diff --git "a/assets/images/\354\230\244\354\260\250\354\227\255\354\240\204\355\214\2142.png" "b/assets/images/\354\230\244\354\260\250\354\227\255\354\240\204\355\214\2142.png"
new file mode 100644
index 000000000000..abec3e47f1ca
Binary files /dev/null and "b/assets/images/\354\230\244\354\260\250\354\227\255\354\240\204\355\214\2142.png" differ
diff --git "a/assets/images/\354\240\234\353\241\234\355\214\250\353\224\251.png" "b/assets/images/\354\240\234\353\241\234\355\214\250\353\224\251.png"
new file mode 100644
index 000000000000..0bcc59971120
Binary files /dev/null and "b/assets/images/\354\240\234\353\241\234\355\214\250\353\224\251.png" differ
diff --git "a/assets/images/\354\262\264\354\235\270\353\243\260.png" "b/assets/images/\354\262\264\354\235\270\353\243\260.png"
new file mode 100644
index 000000000000..c94e3bc0fb89
Binary files /dev/null and "b/assets/images/\354\262\264\354\235\270\353\243\260.png" differ
diff --git "a/assets/images/\355\215\274\354\205\211\355\212\270\353\241\240.png" "b/assets/images/\355\215\274\354\205\211\355\212\270\353\241\240.png"
new file mode 100644
index 000000000000..aacf1507317e
Binary files /dev/null and "b/assets/images/\355\215\274\354\205\211\355\212\270\353\241\240.png" differ
diff --git "a/assets/images/\355\225\251\354\204\261\352\263\261\354\213\240\352\262\275\353\247\235_\354\227\254\353\237\254\352\260\234\354\235\230\355\225\204\355\204\260.png" "b/assets/images/\355\225\251\354\204\261\352\263\261\354\213\240\352\262\275\353\247\235_\354\227\254\353\237\254\352\260\234\354\235\230\355\225\204\355\204\260.png"
new file mode 100644
index 000000000000..d60cc061e47b
Binary files /dev/null and "b/assets/images/\355\225\251\354\204\261\352\263\261\354\213\240\352\262\275\353\247\235_\354\227\254\353\237\254\352\260\234\354\235\230\355\225\204\355\204\260.png" differ
diff --git "a/assets/images/\355\225\251\354\204\261\352\263\261\354\213\240\352\262\275\353\247\235_\354\273\244\353\204\220.png" "b/assets/images/\355\225\251\354\204\261\352\263\261\354\213\240\352\262\275\353\247\235_\354\273\244\353\204\220.png"
new file mode 100644
index 000000000000..20587b24b6ba
Binary files /dev/null and "b/assets/images/\355\225\251\354\204\261\352\263\261\354\213\240\352\262\275\353\247\235_\354\273\244\353\204\220.png" differ
diff --git "a/assets/images/\355\231\225\353\245\240\354\240\201_\352\262\275\354\202\254_\355\225\230\352\260\225\353\262\225.png" "b/assets/images/\355\231\225\353\245\240\354\240\201_\352\262\275\354\202\254_\355\225\230\352\260\225\353\262\225.png"
new file mode 100644
index 000000000000..c2236b88f4e5
Binary files /dev/null and "b/assets/images/\355\231\225\353\245\240\354\240\201_\352\262\275\354\202\254_\355\225\230\352\260\225\353\262\225.png" differ
diff --git "a/assets/images/\355\231\234\354\204\261\355\231\224\355\225\250\354\210\230_\355\205\214\354\235\264\353\270\224.png" "b/assets/images/\355\231\234\354\204\261\355\231\224\355\225\250\354\210\230_\355\205\214\354\235\264\353\270\224.png"
new file mode 100644
index 000000000000..0016812b3269
Binary files /dev/null and "b/assets/images/\355\231\234\354\204\261\355\231\224\355\225\250\354\210\230_\355\205\214\354\235\264\353\270\224.png" differ
diff --git a/docs/_config.yml b/docs/_config.yml
index 6cba47ff893c..be2216581228 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -10,7 +10,7 @@ remote_theme : "mmistakes/minimal-mistakes@4.24.0"
minimal_mistakes_skin : "default" # "air", "aqua", "contrast", "dark", "dirt", "neon", "mint", "plum", "sunrise"
# Site Settings
-locale : "en-US"
+locale : "ko-KR" # "en-US"
title : "Minimal Mistakes"
title_separator : "-"
subtitle : "A Jekyll theme"
@@ -25,9 +25,9 @@ masthead_title : # overrides the website title displayed in the masthe
# breadcrumbs : false # true, false (default)
words_per_minute : 200
comments:
- provider : "false" # false (default), "disqus", "discourse", "facebook", "staticman_v2", "staticman", "utterances", "giscus", "custom"
+ provider : "disqus" # false (default), "disqus", "discourse", "facebook", "staticman_v2", "staticman", "utterances", "giscus", "custom"
disqus:
- shortname :
+ shortname : "yoonkienote"
discourse:
server : # https://meta.discourse.org/t/embedding-discourse-comments-via-javascript/31963 , e.g.: meta.discourse.org
facebook:
@@ -210,10 +210,11 @@ defaults:
values:
layout: single
author_profile: true
- read_time: true
+ read_time: false
+ show_date: true
comments: true
share: true
- related: true
+ related: false
# _pages
- scope:
path: "_pages"
diff --git a/docs/_pages/category-archive.md b/docs/_pages/category-archive.md
index 4cb3860e91be..6b7011e2ecf1 100644
--- a/docs/_pages/category-archive.md
+++ b/docs/_pages/category-archive.md
@@ -3,4 +3,5 @@ title: "Posts by Category"
layout: categories
permalink: /categories/
author_profile: true
+sidebar_main: true
---
diff --git a/google285e0ef783d2b56a.html b/google285e0ef783d2b56a.html
new file mode 100644
index 000000000000..4e85c74a3dac
--- /dev/null
+++ b/google285e0ef783d2b56a.html
@@ -0,0 +1 @@
+google-site-verification: google285e0ef783d2b56a.html
\ No newline at end of file