-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.json
1 lines (1 loc) · 94.4 KB
/
content.json
1
{"meta":{"title":"Code Brewer","subtitle":"For Better Today","description":"The blog of KorChris","author":"KorChris","url":"http://korchris.github.io"},"pages":[{"title":"Categories","date":"2021-02-09T03:05:41.573Z","updated":"2018-09-10T16:50:18.000Z","comments":true,"path":"categories/index.html","permalink":"http://korchris.github.io/categories/index.html","excerpt":"","text":""},{"title":"About","date":"2024-01-10T07:10:02.951Z","updated":"2024-01-10T07:10:02.951Z","comments":true,"path":"about/index.html","permalink":"http://korchris.github.io/about/index.html","excerpt":"","text":"하나님의 선한 기술력으로 세상에 선한 영향력을 끼치는 사람이 되게 하소서. 저는 Natural Language Processing에 관심이 많은 정찬웅입니다. 딥러닝과 강화학습을 통해 대화가능한 AI를 만드는 것에 관심이 많으며 NLP를 이용하여 task를 해결하는 모든 것들에 관심이 있습니다. 2016년도에 한동대학교를 졸업하고 실리콘밸리에서 인턴쉽을 진행한 뒤, 알파고를 바라보며 꿈을 키우고,다시 귀국하여 석사과정을 밟은 뒤, 지금 이 길을 선택하게 되었습니다. God, let me be the person who informs good-hearted influence with good-hearted mind. I’m Chanung Jeong, interested in Natural language processing, Deep Learning and Reinforcement Learning. I’m interested in buliding a conversationable AI, and everything I can do to solve a task using NLP. After graduating from Handong University in 2016, I started my internship in Silicon Valley, and I looked at AlphaGo and dreamed. After I returned to Korea, I completed my master’s degree and I chose this path now. Chris Chanung Jeong GithubLinkedin"},{"title":"Tags","date":"2021-02-09T03:05:41.570Z","updated":"2018-09-10T16:50:35.000Z","comments":true,"path":"tags/index.html","permalink":"http://korchris.github.io/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"[PCCP 기출문제] 2번 / 퍼즐 게임 챌린지","slug":"PCCP2_puzzle_game_challenge","date":"2024-12-03T10:43:00.000Z","updated":"2024-12-03T11:11:32.956Z","comments":true,"path":"2024/12/03/PCCP2_puzzle_game_challenge/","link":"","permalink":"http://korchris.github.io/2024/12/03/PCCP2_puzzle_game_challenge/","excerpt":"","text":"[PCCP 기출문제] 2번 / 퍼즐 게임 챌린지문제 설명당신은 순서대로 n개의 퍼즐을 제한 시간 내에 풀어야 하는 퍼즐 게임을 하고 있습니다. 각 퍼즐은 난이도와 소요 시간이 정해져 있습니다. 당신의 숙련도에 따라 퍼즐을 풀 때 틀리는 횟수가 바뀌게 됩니다. 현재 퍼즐의 난이도를 diff, 현재 퍼즐의 소요 시간을 time_cur, 이전 퍼즐의 소요 시간을 time_prev, 당신의 숙련도를 level이라 하면, 게임은 다음과 같이 진행됩니다. diff ≤ level이면 퍼즐을 틀리지 않고 time_cur만큼의 시간을 사용하여 해결합니다. diff > level이면, 퍼즐을 총 diff - level번 틀립니다. 퍼즐을 틀릴 때마다, time_cur만큼의 시간을 사용하며, 추가로 time_prev만큼의 시간을 사용해 이전 퍼즐을 다시 풀고 와야 합니다. 이전 퍼즐을 다시 풀 때는 이전 퍼즐의 난이도에 상관없이 틀리지 않습니다. diff - level번 틀린 이후에 다시 퍼즐을 풀면 time_cur만큼의 시간을 사용하여 퍼즐을 해결합니다. 예를 들어 diff = 3, time_cur = 2, time_prev = 4인 경우, level에 따라 퍼즐을 푸는데 걸리는 시간은 다음과 같습니다. level = 1이면, 퍼즐을 3 - 1 = 2번 틀립니다. 한 번 틀릴 때마다 2 + 4 = 6의 시간을 사용하고, 다시 퍼즐을 푸는 데 2의 시간을 사용하므로 총 6 × 2 + 2 = 14의 시간을 사용하게 됩니다. level = 2이면, 퍼즐을 3 - 2 = 1번 틀리므로, 6 + 2 = 8의 시간을 사용하게 됩니다. level ≥ 3이면 퍼즐을 틀리지 않으며, 2의 시간을 사용하게 됩니다. 퍼즐 게임에는 전체 제한 시간 limit가 정해져 있습니다. 제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값을 구하려고 합니다. 난이도, 소요 시간은 모두 양의 정수며, 숙련도도 양의 정수여야 합니다. 퍼즐의 난이도를 순서대로 담은 1차원 정수 배열 diffs, 퍼즐의 소요 시간을 순서대로 담은 1차원 정수 배열 times, 전체 제한 시간 limit이 매개변수로 주어집니다. 제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값을 정수로 return 하도록 solution 함수를 완성해 주세요. 제한사항 1 ≤ diffs의 길이 = times의 길이 = n ≤ 300,000 diffs[i]는 i번째 퍼즐의 난이도, times[i]는 i번째 퍼즐의 소요 시간입니다. diffs[0] = 1 1 ≤ diffs[i] ≤ 100,000 1 ≤ times[i] ≤ 10,000 1 ≤ limit ≤ 1015 제한 시간 내에 퍼즐을 모두 해결할 수 있는 경우만 입력으로 주어집니다. 입출력 예 diffs times limit result [1, 5, 3] [2, 4, 7] 30 3 [1, 4, 4, 2] [6, 3, 8, 2] 59 2 [1, 328, 467, 209, 54] [2, 7, 1, 4, 3] 1723 294 [1, 99999, 100000, 99995] [9999, 9001, 9999, 9001] 3456789012 39354 입출력 예 설명입출력 예 #1 숙련도가 3인 경우 다음과 같이 진행됩니다. 1번째 퍼즐을 2의 시간을 사용하여 해결합니다. 2번째 퍼즐을 5 - 3 = 2번 틀려서 총 (4 + 2) × 2 + 4 = 16의 시간을 사용하여 해결합니다. 3번째 퍼즐을 7의 시간을 사용하여 해결합니다. 총 2 + 16 + 7 = 25의 시간을 사용하여 모든 퍼즐을 해결할 수 있습니다. 숙련도가 3보다 작은 경우 제한 시간인 30 이내에 모든 퍼즐을 해결할 수 없습니다. 따라서 3을 return 해야 합니다. 입출력 예 #2 숙련도가 2인 경우 다음과 같이 진행됩니다. 1번째 퍼즐을 6의 시간을 사용하여 해결합니다. 2번째 퍼즐을 4 - 2 = 2번 틀려서 총 (3 + 6) × 2 + 3 = 21의 시간을 사용하여 해결합니다. 3번째 퍼즐을 4 - 2 = 2번 틀려서 총 (8 + 3) × 2 + 8 = 30의 시간을 사용하여 해결합니다. 4번째 퍼즐을 2의 시간을 사용하여 해결합니다. 총 6 + 21 + 30 + 2 = 59의 시간을 사용하여 모든 퍼즐을 해결할 수 있습니다. 숙련도가 2보다 작은 경우 제한 시간인 59 이내에 모든 퍼즐을 해결할 수 없습니다. 따라서 2를 return 해야 합니다. 입출력 예 #3 숙련도가 294인 경우 다음과 같이 진행됩니다. 1번째 퍼즐을 2의 시간을 사용하여 해결합니다. 2번째 퍼즐을 328 - 294 = 34번 틀려서 총 (7 + 2) × 34 + 7 = 313의 시간을 사용하여 해결합니다. 3번째 퍼즐을 467 - 294 = 173번 틀려서 총 (1 + 7) × 173 + 1 = 1385의 시간을 사용하여 해결합니다. 4번째 퍼즐을 4의 시간을 사용하여 해결합니다. 5번째 퍼즐을 3의 시간을 사용하여 해결합니다. 총 2 + 313 + 1385 + 4 + 3 = 1707의 시간을 사용하여 모든 퍼즐을 해결할 수 있습니다. 숙련도가 294보다 작은 경우 제한 시간인 1723 이내에 모든 퍼즐을 해결할 수 없습니다. 따라서 294를 return 해야 합니다. 입출력 예 #4 숙련도가 39354인 경우 다음과 같이 진행됩니다. 1번째 퍼즐을 9999의 시간을 사용하여 해결합니다. 2번째 퍼즐을 99999 - 39354 = 60645번 틀려서 총 (9001 + 9999) × 60645 + 9001 = 1152264001의 시간을 사용하여 해결합니다. 3번째 퍼즐을 100000 - 39354 = 60646번 틀려서 총 (9999 + 9001) × 60646 + 9999 = 1152283999의 시간을 사용하여 해결합니다. 4번째 퍼즐을 99995 - 39354 = 60641번 틀려서 총 (9001 + 9999) × 60641 + 9001 = 1152188001의 시간을 사용하여 해결합니다. 총 9999 + 1152264001 + 1152283999 + 1152188001 = 3456746000의 시간을 사용하여 모든 퍼즐을 해결할 수 있습니다. 숙련도가 39354보다 작은 경우 제한 시간인 3456789012 이내에 모든 퍼즐을 해결할 수 없습니다. 따라서 39354를 return 해야 합니다. 풀이과정이 문제에서는 어떻게 적절한 최소한의 level은 찾는 방법을 구하는 것과 주어진 level에 따라서 시간이 얼마나 걸리는지를 구하는 방법을 구하는 것이 핵심이었다. 특히 주어진 diffs중에서 0번째는 항상 난이도가 1이므로 이를 중심으로 풀어나가야했다. diff에서 level을 뺀 후에 조심해야할 것은 음수가 time이 음수가 되지 않게 도와주는 것이다.문제에서는 level이 diff보다 같거나 클 때, time_cur만 소요된다 하였으므로 max를 이용하여 해당 항을 조절할 수 있도록 했다.12345def time_to_solve(level, diff, time_prev, time_cur): t = (max(0,(diff-level))) * (time_prev+time_cur) + time_cur return t 주어진 레벨에 따라서 총 소요시간을 구하는 방법.언제나 첫번째 diff는 time_cur만 소요하므로time_prev를 0으로 맞춰주고 그 이외에는 times[i-1]를 이용하여list index out이 일어나지 않도록 해주며 total 소요시간을 구해준다.12345678910def get_total_t(level, diffs, times): total_t = 0 for i in range(len(diffs)): if not i: time_prev = 0 else: time_prev = times[i-1] t = time_to_solve(level, diffs[i], time_prev, times[i]) total_t += t return total_t 중요한 것은 최소한의 level을 구하는 것. level이 무작정 높아도 문제는 해결이 되기에이 문제를 해결할 수 있는 모든 level들을 찾아 그 중 최소값을 구하면 되겠다고 생각했다.결국 Binary Search를 이용하여 모든 만족하는 level들을 찾아 그 중 최솟값을 answer로.123456789101112131415161718def solution(diffs, times, limit): start = 1 end = 100000 candidates = [] # Binary Search 시작 while start <= end: mid = (start+end)//2 total_t = get_total_t(mid, diffs, times) if total_t > limit: start = mid + 1 else: candidates.append(mid) end = mid - 1 print('level, total_t, limit', mid, total_t, limit) # 조건을 만족하는 많은 후보들 중에서 minimum을 answer로 내놓는다. minimum_level = min(candidates) answer = minimum_level return answer","categories":[{"name":"Practice","slug":"Practice","permalink":"http://korchris.github.io/categories/Practice/"}],"tags":[{"name":"Programmers","slug":"Programmers","permalink":"http://korchris.github.io/tags/Programmers/"}]},{"title":"[카카오톡 블라인드 채용] 오픈채팅방","slug":"kakao_openchat","date":"2024-12-03T10:43:00.000Z","updated":"2024-12-03T17:54:43.182Z","comments":true,"path":"2024/12/03/kakao_openchat/","link":"","permalink":"http://korchris.github.io/2024/12/03/kakao_openchat/","excerpt":"","text":"[카카오톡 블라인드 채용] 오픈채팅방문제 설명오픈채팅방카카오톡 오픈채팅방에서는 친구가 아닌 사람들과 대화를 할 수 있는데, 본래 닉네임이 아닌 가상의 닉네임을 사용하여 채팅방에 들어갈 수 있다. 신입사원인 김크루는 카카오톡 오픈 채팅방을 개설한 사람을 위해, 다양한 사람들이 들어오고, 나가는 것을 지켜볼 수 있는 관리자창을 만들기로 했다. 채팅방에 누군가 들어오면 다음 메시지가 출력된다. “[닉네임]님이 들어왔습니다.” 채팅방에서 누군가 나가면 다음 메시지가 출력된다. “[닉네임]님이 나갔습니다.” 채팅방에서 닉네임을 변경하는 방법은 다음과 같이 두 가지이다. 채팅방을 나간 후, 새로운 닉네임으로 다시 들어간다. 채팅방에서 닉네임을 변경한다. 닉네임을 변경할 때는 기존에 채팅방에 출력되어 있던 메시지의 닉네임도 전부 변경된다. 예를 들어, 채팅방에 “Muzi”와 “Prodo”라는 닉네임을 사용하는 사람이 순서대로 들어오면 채팅방에는 다음과 같이 메시지가 출력된다. “Muzi님이 들어왔습니다.”“Prodo님이 들어왔습니다.” 채팅방에 있던 사람이 나가면 채팅방에는 다음과 같이 메시지가 남는다. “Muzi님이 들어왔습니다.”“Prodo님이 들어왔습니다.”“Muzi님이 나갔습니다.” Muzi가 나간후 다시 들어올 때, Prodo 라는 닉네임으로 들어올 경우 기존에 채팅방에 남아있던 Muzi도 Prodo로 다음과 같이 변경된다. “Prodo님이 들어왔습니다.”“Prodo님이 들어왔습니다.”“Prodo님이 나갔습니다.”“Prodo님이 들어왔습니다.” 채팅방은 중복 닉네임을 허용하기 때문에, 현재 채팅방에는 Prodo라는 닉네임을 사용하는 사람이 두 명이 있다. 이제, 채팅방에 두 번째로 들어왔던 Prodo가 Ryan으로 닉네임을 변경하면 채팅방 메시지는 다음과 같이 변경된다. “Prodo님이 들어왔습니다.”“Ryan님이 들어왔습니다.”“Prodo님이 나갔습니다.”“Prodo님이 들어왔습니다.” 채팅방에 들어오고 나가거나, 닉네임을 변경한 기록이 담긴 문자열 배열 record가 매개변수로 주어질 때, 모든 기록이 처리된 후, 최종적으로 방을 개설한 사람이 보게 되는 메시지를 문자열 배열 형태로 return 하도록 solution 함수를 완성하라. 제한사항record는 다음과 같은 문자열이 담긴 배열이며, 길이는 1 이상 100,000 이하이다. 다음은 record에 담긴 문자열에 대한 설명이다. 모든 유저는 [유저 아이디]로 구분한다. [유저 아이디] 사용자가 [닉네임]으로 채팅방에 입장 - “Enter [유저 아이디] [닉네임]” (ex. “Enter uid1234 Muzi”) [유저 아이디] 사용자가 채팅방에서 퇴장 - “Leave [유저 아이디]” (ex. “Leave uid1234”) [유저 아이디] 사용자가 닉네임을 [닉네임]으로 변경 - “Change [유저 아이디] [닉네임]” (ex. “Change uid1234 Muzi”) 첫 단어는 Enter, Leave, Change 중 하나이다. 각 단어는 공백으로 구분되어 있으며, 알파벳 대문자, 소문자, 숫자로만 이루어져있다. 유저 아이디와 닉네임은 알파벳 대문자, 소문자를 구별한다. 유저 아이디와 닉네임의 길이는 1 이상 10 이하이다. 채팅방에서 나간 유저가 닉네임을 변경하는 등 잘못 된 입력은 주어지지 않는다. 입출력 예|record|result||——|——||[“Enter uid1234 Muzi”, “Enter uid4567 Prodo”,”Leave uid1234”,”Enter uid1234 Prodo”,”Change uid4567 Ryan”]|[“Prodo님이 들어왔습니다.”, “Ryan님이 들어왔습니다.”, “Prodo님이 나갔습니다.”, “Prodo님이 들어왔습니다.”]| 입출력 예 설명 입출력 예 #1문제의 설명과 같다. 풀이과정 1사실 문제를 처음 봤을 때에는 constructor를 사용해서 계속해서 업데이트를 해주면 좋겠다고 생각을 했다. 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758# User constructor 생성class User: def __init__(self, status, uid, nick): self.status = status self.uid = uid self.nick = nick def setStatus(self, new_status): self.status = new_status def setNick(self, new_nick): self.nick = new_nickdef solution(record): users = [] number = 0 for m in record: # message의 시작 단어에 따라 다르게 알고리즘을 짜줌. if m.startswith(\"Enter\"): s, u, n = m.split() if users: t = [user for user in users if user.uid == u] if not t: c = User(s, u, n) users.append(c) else: t[0].setStatus(\"Enter\") t[0].setNick(n) else: c = User(s, u, n) users.append(c) elif m.startswith(\"Leave\"): s, u = m.split() t = [user for user in users if user.uid ==u] if t: t[0].setStatus(\"Leave\") else: s, u, n = m.split() t = [user for user in users if user.uid == u] if t: t[0].setNick(n) # 모든 메세지를 통해 유저들을 최신화 시킨 뒤에 output answer생성 answer = [] for m in record: if m.startswith(\"Enter\"): s, u, n = m.split() t = [user for user in users if user.uid == u] nn = t[0].nick output = \"{}님이 들어왔습니다.\".format(nn) answer.append(output) elif m.startswith(\"Leave\"): s, u = m.split() t = [user for user in users if user.uid == u] nn = t[0].nick output = \"{}님이 나갔습니다.\".format(nn) answer.append(output) return answer 이면.. 풀릴 줄 알았는데 25번 문제부터 timeout이 걸리면서 멘붕.. 어떻게 해야 풀릴 수 있을까 생각하다가 dictionary를 사용하기로 마음을 먹었다. 더 가볍게 풀릴 수 있을 것 같았다. 풀이과정 212345678910111213141516171819202122232425262728293031323334353637383940414243def solution(record): users = [] number = 0 for m in record: if m.startswith(\"Enter\"): s, u, n = m.split() if users: t = [user for user in users if user['uid'] == u] if not t: c = {'status':s, 'uid':u, 'nick':n} users.append(c) else: t[0]['status'] = s t[0]['nick'] = n else: c = {'status':s, 'uid':u, 'nick':n} users.append(c) elif m.startswith(\"Leave\"): s, u = m.split() t = [user for user in users if user['uid'] == u] if t: t[0]['status'] = \"Leave\" else: s, u, n = m.split() t = [user for user in users if user['uid'] == u] if t: t[0]['nick'] = n answer = [] for m in record: if m.startswith(\"Enter\"): s, u, n = m.split() t = [user for user in users if user['uid'] == u] nn = t[0]['nick'] output = \"{}님이 들어왔습니다.\".format(nn) answer.append(output) elif m.startswith(\"Leave\"): s, u = m.split() t = [user for user in users if user['uid'] == u] nn = t[0]['nick'] output = \"{}님이 나갔습니다.\".format(nn) answer.append(output) return answer 그런데… 이것도 안 풀린다!! 도대체 25번 문제에 얼마나 많은 레코드들이 들어있는 것인지? 어떻게 해야 더 빨리 할 수 있지?? 풀이과정 3그래서 결국 참고하게 된 다른 분의 코드를 약간 수정한 버전.. 결국 ‘마지막’에 어떻게 nick이 남는지가 중요했고그냥 하나의 dictionary에다가 dict[uid] = nickname로 형태를 정하고Enter와 Change일 때마다 계속해서 덮어씌우면 되는 것이었다. 123456789101112131415161718def solution(record): dic = {} answer = [] record = [i.split(' ') for i in record] for i in record: if i[0] == \"Change\" and i[1] in dic: dic[i[1]] = i[2] elif i[0] == \"Enter\": dic[i[1]] = i[2] for j in record: if j[0] == \"Enter\": answer.append(\"{}님이 들어왔습니다.\".format(dic[j[1]])) elif j[0] == \"Leave\": answer.append(\"{}님이 나갔습니다.\".format(dic[j[1]])) return answer 재밌어보여서 시작했지만 코테에서 시간초과 걸려본건 처음이라 당황 코테 때 파이썬 쓸 때에는 dictionary를 잘 사용해봐야겠다.","categories":[{"name":"Practice","slug":"Practice","permalink":"http://korchris.github.io/categories/Practice/"}],"tags":[{"name":"Programmers","slug":"Programmers","permalink":"http://korchris.github.io/tags/Programmers/"}]},{"title":"[PCCP 기출문제] 1번 / 동영상 재생기","slug":"PCCP1_video","date":"2024-12-03T05:43:00.000Z","updated":"2024-12-03T11:11:30.280Z","comments":true,"path":"2024/12/03/PCCP1_video/","link":"","permalink":"http://korchris.github.io/2024/12/03/PCCP1_video/","excerpt":"","text":"[PCCP 기출문제] 1번 / 동영상 재생기문제 설명당신은 동영상 재생기를 만들고 있습니다. 당신의 동영상 재생기는 10초 전으로 이동, 10초 후로 이동, 오프닝 건너뛰기 3가지 기능을 지원합니다. 각 기능이 수행하는 작업은 다음과 같습니다. 10초 전으로 이동: 사용자가 “prev” 명령을 입력할 경우 동영상의 재생 위치를 현재 위치에서 10초 전으로 이동합니다. 현재 위치가 10초 미만인 경우 영상의 처음 위치로 이동합니다. 영상의 처음 위치는 0분 0초입니다. 10초 후로 이동: 사용자가 “next” 명령을 입력할 경우 동영상의 재생 위치를 현재 위치에서 10초 후로 이동합니다. 동영상의 남은 시간이 10초 미만일 경우 영상의 마지막 위치로 이동합니다. 영상의 마지막 위치는 동영상의 길이와 같습니다. 오프닝 건너뛰기: 현재 재생 위치가 오프닝 구간(op_start ≤ 현재 재생 위치 ≤ op_end)인 경우 자동으로 오프닝이 끝나는 위치로 이동합니다. 동영상의 길이를 나타내는 문자열 video_len, 기능이 수행되기 직전의 재생위치를 나타내는 문자열 pos, 오프닝 시작 시각을 나타내는 문자열 op_start, 오프닝이 끝나는 시각을 나타내는 문자열 op_end, 사용자의 입력을 나타내는 1차원 문자열 배열 commands가 매개변수로 주어집니다. 이때 사용자의 입력이 모두 끝난 후 동영상의 위치를 “mm:ss“ 형식으로 return 하도록 solution 함수를 완성해 주세요. 제한사항 video_len의 길이 = pos의 길이 = op_start의 길이 = op_end의 길이 = 5 video_len, pos, op_start, op_end는 “mm:ss“ 형식으로 mm분 ss초를 나타냅니다. 0 ≤ mm ≤ 59 0 ≤ ss ≤ 59 분, 초가 한 자리일 경우 0을 붙여 두 자리로 나타냅니다. 비디오의 현재 위치 혹은 오프닝이 끝나는 시각이 동영상의 범위 밖인 경우는 주어지지 않습니다. 오프닝이 시작하는 시각은 항상 오프닝이 끝나는 시각보다 전입니다. 1 ≤ commands의 길이 ≤ 100 commands의 원소는 “prev” 혹은 “next”입니다. “prev”는 10초 전으로 이동하는 명령입니다. “next”는 10초 후로 이동하는 명령입니다. 입출력 예 video_len pos op_start op_end commands result “34:33” “13:00” “00:55” “02:55” [“next”, “prev”] 13:00” “10:55” “00:05” “00:15” “06:55” [“prev”, “next”, “next”] “06:55” “07:22” “04:05” “00:15” “04:07” [“next”] “04:17” 입출력 예 설명입출력 예 #1 시작 위치 13분 0초에서 10초 후로 이동하면 13분 10초입니다. 13분 10초에서 10초 전으로 이동하면 13분 0초입니다. 따라서 “13:00”을 return 하면 됩니다. 입출력 예 #2 시작 위치 0분 5초에서 10초 전으로 이동합니다. 현재 위치가 10초 미만이기 때문에 0분 0초로 이동합니다. 0분 0초에서 10초 후로 이동하면 0분 10초입니다. 0분 10초에서 10초 후로 이동하면 0분 20초입니다. 0분 20초는 오프닝 구간이기 때문에 오프닝이 끝나는 위치인 6분 55초로 이동합니다. 따라서 “06:55”를 return 하면 됩니다. 입출력 예 #3 시작 위치 4분 5초는 오프닝 구간이기 때문에 오프닝이 끝나는 위치인 4분 7초로 이동합니다. 4분 7초에서 10초 후로 이동하면 4분 17초입니다. 따라서 “04:17”을 return 하면 됩니다. 풀이과정사실 이 문제에서 제일 헷갈리는 것은 바로 오프닝 스킵 기능이었다. 특히 입출력 예 3번에서 보여주는 4분 5초이기 때문에 4분 7초로 commands에 관련없이 ‘자동이동’한다는 것이었고 입출력 예 3번을 제대로 읽지 못한 나는 한동안 난리쇼를 펼쳤다는 것. 다른 분들은 mm, ss로 나누어서 비교를 많이 하셨던데나는 그럴 필요 없이 그냥 시간을 전부 seconds로 바꾸어서 단위 일체화를 시켜두었다.1234def time_to_sec(time): mm, ss = map(int, time.split(\":\")) secs = mm*60 + ss return secs answer를 내기 위해서 초단위가 되어버린 변수를 mm:ss 형태로 고치기 위해 필요한 함수12345def sec_to_time(sec): ss = sec%60 mm = sec//60 time = \"{}:{}\".format(str(mm).zfill(2),str(ss).zfill(2)) return time 오프닝을 스킵해야할지 말아야 할지에 대한 조건문12345def check_skip(spos, sos, soe): if spos >= sos and spos <= soe: return True else: return False 12345678910111213141516171819202122232425262728293031def solution(video_len, pos, op_start, op_end, commands): # 일단 모든 mm:ss화 된 변수들을 초단위로 바꾸어 비교하기 쉽게 만들어준다. spos= time_to_sec(pos) stotal = time_to_sec(video_len) sos = time_to_sec(op_start) soe = time_to_sec(op_end) # answer가 될 position은 일단 시작 시간인 현재 pos과 일치하게 initialize new_spos = spos # 시작부터 오프닝을 스킵해야 할지 말지 결정해준다. if check_skip(spos, sos, soe) : new_spos = soe # 스킵을 했건 안했건 그 다음으로 커맨드를 받아준다. for c in commands: # next면 10초를 추가해주고 if c == 'next': new_spos += 10 # prev면 10초를 감소해준다. else: new_spos -= 10 # 다만 영상길이가 -가 될 수는 없으므로 -가 되면 0으로 초기화 해준다. if new_spos < 0: new_spos = 0 # 커맨드를 받고 영상길이가 재조정 되었으니 이제 또 다시 오프닝 스킵인지 체크 if check_skip(new_spos, sos, soe) : new_spos = soe # 마지막으로 영상 재조정 된 길이가 영상 총 길이보다 길면 안되므로 조절해준다. if new_spos > stotal: new_spos = stotal answer = sec_to_time(new_spos) print(answer) return answer","categories":[{"name":"Practice","slug":"Practice","permalink":"http://korchris.github.io/categories/Practice/"}],"tags":[{"name":"Programmers","slug":"Programmers","permalink":"http://korchris.github.io/tags/Programmers/"}]},{"title":"M1 맥북 오류 / 크롬 오류 / 빨간 줄 / 빨간 썸네일 해결 방법","slug":"M1_chrome_issue","date":"2021-08-09T17:41:00.000Z","updated":"2021-08-09T17:46:25.109Z","comments":true,"path":"2021/08/10/M1_chrome_issue/","link":"","permalink":"http://korchris.github.io/2021/08/10/M1_chrome_issue/","excerpt":"","text":"M1 맥북 오류 / 크롬 오류 / 빨간 줄 / 빨간 썸네일 해결 방법갑자기 어느날부터 M1 맥북을 쓰는 나에게 크롬을 키면 이상한 현상이 일어나기 시작했다. 그 현상은 바로 밑과 같이 다른 브라우저에서는 잘만 보이던 이미지 / 사이트들이 이상하게 보인다는 것. 일단 간단하게 해결방법을 먼저 소개하겠다. 크롬에서 상단 오른쪽 맨 끝에 위치하고 있는 점 3개짜리 아이콘을 클릭하고나서 ‘고급’탭을 누르고 ‘시스템’ 탭을 누르면 가능한 경우 하드웨어 가속 사용이라는 탭이 적용되어 있을 것이다.( 위의 에러가 나타난다면) 위와 같이 하드웨어 가속 사용을 사용하지 않기로 설정을 하고 ‘다시 시작’ 버튼을 누르게 된다면 위와 같이 에러가 없어진 상태로 복구가 될 것이다. 원인 분석을 해보자면 아마도 기존 Intel 코어를 기준으로 만들어진 웹 라이브러리나 코드가 하드웨어 가속(Intel 코어가 아닌 M1 코어를 사용할 때)을 쓸 때 나타나는 오류인 것 같다. 구글에서도 찾아보았는데 이는 random issue(정해지지 않은 정상적이지 않은 버그)에서 발견이 되는 것 같다. 정확한 해결책은 아래의 링크에서 제공해주었다. Reference #chrome #크롬 #크롬오류 #빨간줄 #빨간아이콘 #빨간화면 #빨간썸네일 #검은줄 #검은아이콘 #검은화면 #검은썸네일 #M1 #맥북","categories":[{"name":"M1","slug":"M1","permalink":"http://korchris.github.io/categories/M1/"}],"tags":[{"name":"Chrome issue","slug":"Chrome-issue","permalink":"http://korchris.github.io/tags/Chrome-issue/"},{"name":"Chrome red line","slug":"Chrome-red-line","permalink":"http://korchris.github.io/tags/Chrome-red-line/"},{"name":"Chrome red thumbnail","slug":"Chrome-red-thumbnail","permalink":"http://korchris.github.io/tags/Chrome-red-thumbnail/"},{"name":"M1","slug":"M1","permalink":"http://korchris.github.io/tags/M1/"},{"name":"Macbook","slug":"Macbook","permalink":"http://korchris.github.io/tags/Macbook/"}]},{"title":"[DL:scratch] 0 - basic python","slug":"[DL-scratch] 0 - basic python","date":"2021-04-07T14:00:00.000Z","updated":"2021-04-14T09:53:33.600Z","comments":true,"path":"2021/04/07/[DL-scratch] 0 - basic python/","link":"","permalink":"http://korchris.github.io/2021/04/07/[DL-scratch] 0 - basic python/","excerpt":"","text":"Deep Learning from scratch : Plan Basic Python for Deep Learning Deep Learning을 위한 python을 기본적으로 다루는 방법을 배웁니다. Perceptron Perceptron을 통해 weight와 bias를 배우고 퍼셉트론의 한계, 그리고 다층 perceptron을 다룹니다. Neural Networks Activation Function과 vector에 대한 계산을 다루며, Neural Network를 직접 구현해봅니다. Training Neural Networks Neural Network를 학습시키기 위해 필요한 loss function과 간단한 미분/편미분에 대한 설명, 그리고 training algorithm을 구현합니다. Backpropagation Neural Network를 Training 시키는 방법인 backpropagation에 대해 좀 더 심층적으로 다루고 이를 구현합니다. Training methods Neural Network를 보다 잘 훈련시키기 위해 사용되어지는 여러가지 훈련방법을 소개하고 적용해봅니다. Type of Neural Networks 다양한 Neural Network를 살펴보고 어떻게 적용되는지, 어떤 분야에 사용하는지에 대해 알아봅니다. Deep Learning 여러가지 예제를 통해 직접 Deep Learning 모델을 만들어보고 이를 평가해봅니다. Basic python for Deep LearningDeep Learning을 직접 다루어보기 위해 쓰는 programming language는 다양한 것이 있지만, 본 블로그에서는 python을 다루기로 합니다. Colabpython을 직접 실행하기 위해서도 다양한 방법이 있지만, google에서 지원하는 Colab을 사용하여 브라우저에서 손쉽게 실행할 수 있는 방법을 쓰기로 하겠습니다. ‘새 노트’를 눌러서 python을 실행시킬 수 있는 창을 띄운 뒤에 단순한 계산을 실행시켜보겠습니다. 1+2를 입력하고 왼쪽의 재생버튼을 누르시면, 3이라는 결과가 하단에 뜨게 됩니다.화면에서 보시는 것처럼, 1+2를 입력하는 상자안에 입력하는 것을 ‘코드’라 하며, 한줄 뿐만 아니라 여러줄을 입력하여 한번에 실행시킬 수 있습니다. 이제부터는 화면으로 보여드리는 것보다 상자안에 입력할 것을 다음과 같은 포맷으로 보여드릴 예정입니다. 12341+23*815/25 ** 4 위의 코드를 입력해보시고 결과를 확인해보면 다음과 같은 결과가 나오게 됩니다. 625는 맨 마지막줄 계산의 결과입니다.저희가 상단에 써놓았던 모든 수식의 결과를 보려면, 각각 계산의 결과를 ‘변수’라는 것에 저장한 뒤에, 확인하는 작업이 필요합니다. 다음과 같이 코드를 작성하여 봅시다. 123456789a = 1+2b = 3*8c = 15/2d = 5 ** 4print(a)print(b)print(c)print(d) 그렇다면 다음과 같은 결과가 나오게 됩니다. 이와같이 프로그래밍은, ‘변수’라는 것을 선언하고 자신이 원하는 ‘작업’을 ‘변수’안에 저장한 뒤, 그 작업의 결과인 ‘변수’를 출력함으로써 원하는 결과를 얻는 것이라고 볼 수 있습니다. Type of Datapython 안에서 사용할 수 있는 Data의 type에는 다양한 것들이 있습니다. 여러개의 data를 한줄로 줄세워서 저장할 수 있는 List형여러개의 data를 key, value로 나누어서 원하는 value를 찾기 위해 key라는 것을 사용할 수 있는 dictionary형참과 거짓을 뜻하는 bool형이 대표적이며, int, float와 같은 숫자 표현형, 그리고 ‘문자열’을 뜻하는 string형이 있습니다. 직접 결과를 확인해보면서 보도록 하겠습니다. 123456789101112a = [0, 1, 2, 3, 4 ,5] # this is listb = {'zero':0, 'one':1, 'two':2} # this is dictionaryc = True # this is boold = 10 # this is int e = 10. # this is floatf = 'hello' # this is stringprint(type(a))print(type(b))print(type(c))print(type(d))print(type(e))print(type(f)) type(변수)는 변수의 type이 무엇인지를 확인할 수 있는 코드입니다.위 코드의 결과는 다음과 같이 나옵니다. 123456<class 'list'><class 'dict'><class 'bool'><class 'int'><class 'float'><class 'str'> list와 dictionary형의 내부에 접근하는 방법은 다음과 같습니다.먼저 list인 a에서 첫번째 요소인 0에 접근하고 싶을 때와dictionary안에서 ‘one’라는 key를 통해, 1이라는 value에 접근하고 싶을 때를 확인해보겠습니다. 12345678a = [0, 1, 2, 3, 4 ,5] # this is listb = {'zero':0, 'one':1, 'two':2} # this is dictionaryc = True # this is boold = 10 # this is int e = 10. # this is floatf = 'hello' # this is stringprint(a[0]) # print first element of list aprint(b['one']) # print value of key 'zero' 위의 코드를 통해 0과 1이라는 결과가 출력되는 것을 확인할 수 있습니다.a와 b의 데이터를 바꿔보시면서 출력을 해보시거나, 대괄호 안에 들어가는 순서(index)나 key(‘one’)를 바꿔보며 익숙해지는 것이 좋습니다. If else~한 조건이 ‘참’일때, ~을 실행하고 싶을 때 쓰는 ‘조건문’입니다.예를 들어, 사용자가 입력한 숫자가 10보다 작으면, 10보다 작다는 문구를 출력하고, 10이거나 10보다 크면 10보다 크다는 문구를 출력하고 싶다는 프로그램을 짜려면 어떻게 해야할까요? 12345number = input()if number < 10: print(f'{number} is less than 10')else: print(f'{number} is equal with 10 or greater than 10') 즉, if 바로 뒤에 오는 조건이 ‘True’일 경우에는 less than 문구를, False일 경우 그 이외의 경우인 ‘else’가 되어 출력되어지게 됩니다.만약, 사용자가 입력한 숫자가 10이면, 10입니다. 라고 출력을 하고 싶다면 다음과 같이 조건을 걸어주시면 됩니다. 1234567number = int(input())if number < 10: print(f'{number} is less than 10')elif number == 10: print(f'{number} is equal with 10')else: print(f'{number} is greater than 10') Loop0부터 9까지 숫자를 출력하고 싶으시다면, print를 여러번 써서 해결할 수도 있지만, 일정의 규칙이 있는 경우라면 loop 문을 쓰실 수 있습니다. 12345number = 0for i in range(0,10): print(i) print(number) number+=1 여기에서 i와 number의 차이는, i는 loop를 얼마나 반복할지를 참고하는 변수라는 것입니다.원래 출력에서는 i와 number가 계속 같이 1씩 증가하는 모습을 보여주었지만, 만약 저 코드에서 number+=1 부분을 없앤다면 어떻게 될까요? i만 증가하고 number는 0에 멈춰있는 것을 볼 수 있습니다. Function위의 if else에서 작성한 코드가 있습니다. 사용자가 입력한 변수가 같으면, 크면, 작으면 ~이다를 출력해주는 작업을 반복하게 되었다고 생각해보면, 저 7줄의 코드를 매번 써줘야 할까요? 한줄로 해결할 수는 없을까요? ‘반복’해서 쓰이지만, 특정 ‘변수’만 달라지는 환경이라면 ‘function’기능을 사용할 수 있습니다. 1234567891011121314151617def isTen(number): if number < 10: print(f'{number} is less than answer') return False elif number == 10: print(f'answer is : {number}') return True else: print(f'{number} is greater than answer') return Falsefor i in range(0,5): number = int(input()) correct = isTen(number) if correct: break # end the loop 위의 코드는 사용자가 10을 입력하면 꺼지는 숫자 맞추기 게임입니다.기회는 총 5번이 주어지며 (loop 5번) 5번 이내에 맞추면 승리하는 게임입니다. 이처럼 반복해서 필요한 기능들은 ‘function’화 하여서 코드를 더 간결하고 정확하게 만들 수 있습니다. Class","categories":[{"name":"DEEP LEARNING","slug":"DEEP-LEARNING","permalink":"http://korchris.github.io/categories/DEEP-LEARNING/"}],"tags":[{"name":"Deep Learning","slug":"Deep-Learning","permalink":"http://korchris.github.io/tags/Deep-Learning/"},{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://korchris.github.io/tags/Machine-Learning/"},{"name":"ML","slug":"ML","permalink":"http://korchris.github.io/tags/ML/"},{"name":"DL","slug":"DL","permalink":"http://korchris.github.io/tags/DL/"},{"name":"Python","slug":"Python","permalink":"http://korchris.github.io/tags/Python/"}]},{"title":"Google Certificate for ML","slug":"Google_Certificate","date":"2020-03-15T05:22:00.000Z","updated":"2020-11-19T10:24:17.000Z","comments":true,"path":"2020/03/15/Google_Certificate/","link":"","permalink":"http://korchris.github.io/2020/03/15/Google_Certificate/","excerpt":"","text":"Google Certificate for ML구글 Certificate에서 요구하는 능력은 다음과 같습니다.(합격기준 100점만점 90점 이상) Basic / Simple model Model from learning dataset CNN with real world image dataset NLP text classification with real world text dataset Sequence model with real world numeric dataset 시험에 참여하기 위해서는 다음을 만족해야합니다. ML과 DL의 중요한 개념들을 사용할 줄 알아야함 Tensorflow를 사용해서 ML models를 만들어야함 DNN, CNN을 이용하여 Image Recognition을 할줄 알며, 현실이미지를 다루는 것에 익숙하며 loss, accuracy를 plot하고 overfitting을 방지하는 전략들을 알아야함(augmentation, dropout등) Image Recognition뿐만 아니라, object detection, text recognition을 사용할 줄 알아야함(RNN(GRU, LSTMS)을 위한 text tokenization 포함) NLP 문제를 해결하기 위한 neural network를 설계할 줄 알아야함.(using Tensorflow) 시험 환경은 다음과 같습니다. 파이참 IDE를 사용하여 인터넷이 되는 어디든 본인의 컴퓨터로 시험을 볼 수 있습니다. 시험은 온라인으로 진행되며, 파이참을 통해 tensorflow를 이용합니다. 시험은 5시간동안 진행됩니다. 시험을 치르기 위해 파이참 IDE를 이용하여 Tensorflow Exam Plugin을 설치하게 됩니다. 파이참 IDE를 이용하는 것에 익숙해지기를 추천합니다. 5시간이 지나기 전에 시험을 완료했다면, 일찍 submit하실 수 있습니다. 만약 5시간이 지나게 되면, 자동적으로 submit이 진행됩니다. 이 문서를 모두 읽어보셨다면, Exam URL에 방문할 수 있습니다. 참여자 identification and authentication여권/운전면허증/주민등록증 중 1개 (primary) 시험 관련 시험을 보는 도중에는 브라우저를 이용하여 Tensorflow Documentation만을 참고 가능합니다. 반드시 혼자 시험을 치루셔야 합니다. 시험을 치르는 데에는 100불이 소요됩니다. 재시험 관련 1번째 시험 낙방 -> 2주가 지나야 시험을 칠 수 있습니다. 2번째 시험 낙방 -> 2달이 지나야 시험을 칠 수 있습니다. 3번째 시험 낙방 이후 -> 1년이 지나야 시험을 칠 수 있습니다. Reference GuideBook","categories":[{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://korchris.github.io/categories/Machine-Learning/"}],"tags":[{"name":"Tensorflow","slug":"Tensorflow","permalink":"http://korchris.github.io/tags/Tensorflow/"},{"name":"Certificate","slug":"Certificate","permalink":"http://korchris.github.io/tags/Certificate/"},{"name":"Machine learning","slug":"Machine-learning","permalink":"http://korchris.github.io/tags/Machine-learning/"},{"name":"Deep Learning","slug":"Deep-Learning","permalink":"http://korchris.github.io/tags/Deep-Learning/"}]},{"title":"chatGPT의 놀라운 대화능력에 대한 실험","slug":"chat_with_chatGPT","date":"2020-03-15T05:22:00.000Z","updated":"2024-01-11T07:32:46.524Z","comments":true,"path":"2020/03/15/chat_with_chatGPT/","link":"","permalink":"http://korchris.github.io/2020/03/15/chat_with_chatGPT/","excerpt":"","text":"chatGPT의 놀라운 대화능력에 대한 실험최근 openAI에서 발표한 chatGPT가 놀라운 대화능력을 보여주고 있다며 올라온 한 커뮤니티의 게시물을 보았다. 보면 볼수록 놀랍고 이런 통찰력과 지식을 가지고 사람과 이야기 할 수 있다는 것이 너무 놀라웠다. 해당 커뮤니티의 게시물처럼 나도 이 chatGPT와 서로 대화를 해보려는 시간을 가지게 되었다. 지금 현대인으로 봤을 때 성경의 많은 부분은 과학적으로 믿기 어려운 일이 일어났음을 보여주지만, 기독교인들은 이것이 모두 사실이라고 믿고있다. 나도 기독교인으로써, 이에 대해 어떻게 생각해야하는 것이 좋은가? 1A) 기독교인으로서 성경은 과학적 문서가 아니며 그렇게 해석되어서는 안 된다는 것을 기억하는 것이 중요하다.그것은 우리가 하나님과 하나님과의 관계를 이해하는 것을 돕기 위한 이야기와 가르침을 포함하는 종교적인 본문입니다.성경에 묘사된 사건들 중 일부는 과학적으로 불가능해 보일 수 있지만,이러한 이야기들을 적절한 맥락에서 해석하고 문자 그대로 받아들이지 않는 것이 중요하다.기독교인으로서 열린 마음과 마음으로 성경에 접근하고 기도와 공부를 통해 성경의 가르침과 메시지에 대한 더 깊은 이해를 구하는 것이 중요하다. 1-1. 그럼 기독교인이 아닌 사람으로써는? 1-1A) 기독교인이 아닌 사람으로서, 여러분은 성경과 성경의 가르침을 여러분에게 가장 이치에 맞는 어떤 방식으로든 자유롭게 해석할 수 있습니다.어떤 사람들은 성경을 허구의 작품으로 보는 반면, 다른 사람들은 그것을 지혜와 지침의 원천으로 보는 것을 선택할 수 있다.궁극적으로 성경을 어떻게 해석하느냐는 당신에게 달려 있으며,무엇이 당신에게 옳은지, 무엇이 당신 자신의 가치관과 신념과 일치하는지에 근거해야 한다.비록 다른 사람들의 믿음이 자신의 믿음과 다르더라도 그것을 존중하는 것은 중요하다. 과학력이 모여있는 chatGPT가 과연 종교적인 것과 과학적인 것을 구분 가능하고 무엇에 더 집중을 두는가를 확인하고 싶었다. 또한 각각의 입장에 따라 어떻게 생각해야할지를 구분하며 답변하는 부분도 볼 수 있었다. 놀라운 답변이었다.","categories":[{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://korchris.github.io/categories/Machine-Learning/"}],"tags":[{"name":"Tensorflow","slug":"Tensorflow","permalink":"http://korchris.github.io/tags/Tensorflow/"},{"name":"Certificate","slug":"Certificate","permalink":"http://korchris.github.io/tags/Certificate/"},{"name":"Machine learning","slug":"Machine-learning","permalink":"http://korchris.github.io/tags/Machine-learning/"},{"name":"Deep Learning","slug":"Deep-Learning","permalink":"http://korchris.github.io/tags/Deep-Learning/"}]},{"title":"[Pytorch]MNIST DNN부터 CNN까지","slug":"mnist","date":"2019-08-23T14:47:00.000Z","updated":"2020-11-19T10:23:40.000Z","comments":true,"path":"2019/08/23/mnist/","link":"","permalink":"http://korchris.github.io/2019/08/23/mnist/","excerpt":"","text":"MNIST DNN부터 CNN까지Deep Learning을 공부함에 있어서 제일 처음으로 접하는 Data는 바로 MNSIT라고 할 수 있습니다. MNIST는 사람들이 직접 필기로 쓴 숫자로써 0부터 9까지 검은 배경에 하얀 글씨로 쓰여져있는 28 x 28 사이즈의 이미지 데이터입니다. 이 포스팅을 통해서 MNIST 데이터를 Deep Learning을 통해서 숫자들을 구별할 수 있는 모델을 설계하고, DNN을 이용한 모델과 CNN을 이용한 모델을 직접 구현해 볼 것입니다. MNSIT 살펴보기MNIST데이터는 다음 그림과 같은 이미지로 구성되어있습니다. 위에서 설명한 바와 같이 위와 같은 이미지처럼 데이터가 구성되어 있으며, 데이터 하나하나는 다음과 같은 이미지를 구성하고 있습니다. Deep Learning 모델이 해야할 일은 input으로써 위와 같은 정보를 받고, 해당 데이터가 0부터 9라는 숫자중에 어떤 숫자인지를 알아맞추는 것입니다. 하지만 이 이미지 파일을 어떻게 Deep learning 모델이 받아들일 수 있도록 할 것인가? 보통 MNIST 데이터는 28 x 28의 숫자를 가진 텐서로 표현이 됩니다. 예를 들어서, 하나의 이미지 파일을 텐서로 표현한 데이터를 출력해보면 다음과 같이 나옵니다. 123456789101112131415161718192021222324252627[... 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.01171875 0.0703125 0.0703125 0.0703125 0.4921875 0.53125 0.68359375 0.1015625 0.6484375 0.99609375 0.96484375 0.49609375 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.1171875 0.140625 0.3671875 0.6015625 0.6640625 0.98828125 0.98828125 0.98828125 0.98828125 0.98828125 0.87890625 0.671875 0.98828125 0.9453125 0.76171875 0.25 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.19140625 0.9296875 0.98828125 0.98828125 0.98828125 0.98828125 0.98828125 0.98828125 0.98828125 0.98828125 0.98046875 0.36328125 0.3203125 0.3203125 0.21875 0.15234375 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.0703125 0.85546875 0.98828125 0.98828125 0.98828125 0.98828125 0.98828125 0.7734375 0.7109375 0.96484375 0.94140625 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.3125 0.609375 0.41796875 0.98828125 0.98828125 0.80078125 0.04296875 0. 0.16796875 0.6015] 출력된 값 전부를 표현하기에는 너무 많은 숫자들이기에 약간의 데이터만 포스팅하지만, 간단하게 총 784개의 숫자를 가진 데이터임을 확인할 수 있습니다.(28*28=784)DNN을 이용할 때에는 784의 길이를 가진 형태로 집어넣을 것이고, CNN을 이용할 때에는 28x28을 지닌 그대로의 형태로 집어넣을 것입니다. MNIST PracticePytorch에서 제공하는 기본 MNIST 예제는 CNN으로 이루어져있지만 MNIST는 간단한 데이터이기 때문에, DNN만으로도 충분히 다룰 수 있습니다. 먼저 전체적인 코드를 큰 파트별로 먼저 크게 살펴보고, 그 다음에 하나하나의 파트들을 Line by Line으로 살펴보도록 하겠습니다. DNN 모델 설계하기먼저 Pytorch에서 제공하는 라이브러리를 사용하기 위해 각 라이브러리들을 Import 해주는 작업을 해줍니다. 12345678#Importing Libraryimport torchimport torch.nn as nnimport torch.nn.functional as Fimport torch.optim as optimfrom torchvision import datasets, transforms 그 다음으로는 DNN을 설계를 할 것인데, 우리가 가진 MNIST데이터는 (1,784)의 데이터 형태를 가지고 있고, 구분하려는 숫자의 종류는 총 10가지라는 것을 생각한 뒤 모델을 설계한다고 생각하면 간단한 DNN은 대략 다음과 같이 구성할 수 있습니다. 123456789101112131415161718192021222324#Define Neural Networks Model.class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(784, 512) self.fc2 = nn.Linear(512, 256) self.fc3 = nn.Linear(256, 128) self.fc4 = nn.Linear(128, 64) self.fc5 = nn.Linear(64, 32) self.fc6 = nn.Linear(32, 10) def forward(self, x): x = x.float() h1 = F.relu(self.fc1(x.view(-1, 784))) h2 = F.relu(self.fc2(h1)) h3 = F.relu(self.fc3(h2)) h4 = F.relu(self.fc4(h3)) h5 = F.relu(self.fc5(h4)) h6 = self.fc6(h5) return F.log_softmax(h6, dim=1)print("init model done") 여러층의 Feed Forward Network를 설계해서, input size는 784, output size는 10이 되도록 설정해줍니다.(input data는 (1, 784)의 형태이고 정답(숫자의 종류)는 총 10가지) 이 다음에는 DNN을 Training시키기 위해 필요한 여러가지 변수들 및 hyper parameter들을 설정해줍니다. 1234567891011121314151617181920# Set Hyper parameters and other variables to train the model.batch_size = 64test_batch_size = 1000epochs = 10lr = 0.01momentum = 0.5no_cuda = Trueseed = 1log_interval = 200use_cuda = not no_cuda and torch.cuda.is_available()torch.manual_seed(seed)device = torch.device(\"cuda\" if use_cuda else \"cpu\")kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}print(\"set vars and device done\") 어느정도 필요한 변수들을 선언해줬다면, 그 다음으로는 pytorch의 torchvision이 제공하는 MNIST 데이터들과 데이터들을 읽어올 수 있는 Loader들을 선언해줍니다.그리고 Training을 위한 데이터와 모델의 성능을 평가할 수 있는 Test를 위한 데이터 로더를 선언해줍니다. 123456789101112131415#Prepare Data Loader for Training and Validationtransform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])train_loader = torch.utils.data.DataLoader( datasets.MNIST('../data', train=True, download=True, transform=transform), batch_size = batch_size, shuffle=True, **kwargs)test_loader = torch.utils.data.DataLoader( datasets.MNIST('../data', train=False, download=True, transform=transform), batch_size=test_batch_size, shuffle=True, **kwargs) 위와 같이 Data Loader들을 선언해주셨다면, 그 다음으로는 위에서 우리가 설계했던 DNN 모델을 불러오고, Training에 필요한 Optimizer를 선언해줍니다. 12model = Net().to(device)optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum) 그 다음으로는 모델을 직접 Training시키는 함수과 Test하는 함수를 구현해줍니다. 123456789101112131415161718192021222324252627282930313233#Define Train function and Test function to validate.def train(log_interval, model, device, train_loader, optimizer, epoch): model.train() for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = F.nll_loss(output, target) loss.backward() optimizer.step() if batch_idx % log_interval == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format( epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))def test(log_interval, model, device, test_loader): model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) test_loss += F.nll_loss(output, target, reduction='sum').item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format (test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset))) Training Data를 한차례 전부 학습에 사용했다면 그것을 하나의 Epoch이라고 부르는데, 모델을 학습시키는데에 하나의 Epoch보다 더 많은 Epoch이 필요하므로 Train과 Test의 과정을 반복하는 반복문을 선언해줍니다. 이 반복문이 끝나면, 마지막으로 Training된 모델을 저장합니다. 123456# Train and Test the model and save it.for epoch in range(1, 11): train(log_interval, model, device, train_loader, optimizer, epoch) test(log_interval, model, device, test_loader)torch.save(model, './model.pt') 여기까지가 Pytorch를 이용해서 DNN으로 MNSIT 데이터들을 분류하는 작업의 코드입니다. 이제는 각 파트별로 소스코드들이 무엇을 의미하는지를 알아보도록 하겠습니다. DNN Model.12345678910111213141516171819class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(784, 512) self.fc2 = nn.Linear(512, 256) self.fc3 = nn.Linear(256, 128) self.fc4 = nn.Linear(128, 64) self.fc5 = nn.Linear(64, 32) self.fc6 = nn.Linear(32, 10) def forward(self, x): x = x.float() h1 = F.relu(self.fc1(x.view(-1, 784))) h2 = F.relu(self.fc2(h1)) h3 = F.relu(self.fc3(h2)) h4 = F.relu(self.fc4(h3)) h5 = F.relu(self.fc5(h4)) h6 = self.fc6(h5) return F.log_softmax(h6, dim=1) 위의 DNN 모델은 총 6개의 Linear 레이어를 통해서 학습하게 됩니다. MNIST data는 간단한 toy data이고, 간단한 데이터이기 때문에 위처럼 단순한 neural networks만으로도 가능합니다. 784 dimension을 가진 MNIST data를 512, 256, 128, … dimension으로 옮겨가며 feature extraction을 할 수 있도록 하며, 각 레이어마다 끝단에는 Relu라는 activation function을 통해 neural network에 nonlinearity를 추가해줍니다. 마지막 단에 Log Softmax를 통해 마지막 레이어를 지난 10개의 값들을 return하는데 Log Softmax의 역할은 마지막 나온 결과값들을 확률로 취급하여 해석하기 위한 하나의 연산입니다. Hyper Parameters and Variables123456789101112131415161718batch_size = 64test_batch_size = 1000epochs = 10lr = 0.01momentum = 0.5no_cuda = Trueseed = 1log_interval = 200use_cuda = not no_cuda and torch.cuda.is_available()torch.manual_seed(seed)device = torch.device(\"cuda\" if use_cuda else \"cpu\")kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}print(\"set vars and device done\") 위의 parameter들은 보통 딥러닝 모델을 train할 때, 많이 쓰이는 변수들이며 딥러닝 모델에 큰 영향을 주는 parameter는 hyper parameter라고 합니다. batch_size란, cpu 혹은 gpu에 한번에 몇개씩의 data를 넣어줄 것인지를 정하는 것입니다. batch_size의 갯수에 따라서도 딥러닝 모델의 성능이 크게 달라집니다. epochs같은 경우에는 training data를 1번씩 모두 썼을 때까지를 1 epoch이 지났다고 합니다. 즉, training data가 10개가 있고, 그 data들을 모두 한번씩 training에 썼다면, 1 epoch이 지난 것입니다. Data Loader123456789101112131415#Prepare Data Loader for Training and Validationtransform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])train_loader = torch.utils.data.DataLoader( datasets.MNIST('../data', train=True, download=True, transform=transform), batch_size = batch_size, shuffle=True, **kwargs)test_loader = torch.utils.data.DataLoader( datasets.MNIST('../data', train=False, download=True, transform=transform), batch_size=test_batch_size, shuffle=True, **kwargs) transform을 통해서 data를 어떻게 처리해줄지 결정을 해줍니다. 함수를 보면, 이미지 데이터를 .ToTensor()를 통해서 tensor형태로 데이터를 변환해준 뒤 Normalize과정을 해주기 위해서 standard deviation와 variation 값을 직접 입력해줍니다. (모든 MNIST이미지를 통해 미리 구해놓은 값입니다.) 그리고 위의 함수에 따라 training set과 test set을 구분해서 만들어줍니다. 현재 torchvision의 함수 자체가 ‘train’이라는 parameter를 통해 training set과 test set을 쉽게 준비할 수 있도록 설계해놨기 때문에, 이를 그대로 사용하시면 됩니다. Optimizer12model = Net().to(device)optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum) Optimizer를 통해서 모델이 어떤 방식으로 training할지를 고르게 됩니다. 대표적인 training방식은 SGD, RMSprop, Adam, AdaDelta 등 여러가지 방식이 있는데 위의 코드는 SGD와 momentum을 사용하는 optimizer를 설정해준 뒤, model내의 parameter들을 training하도록 했습니다. Train and Test123456789101112131415161718192021222324252627282930313233#Define Train function and Test function to validate.def train(log_interval, model, device, train_loader, optimizer, epoch): model.train() for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) # send data to gpu or cpu optimizer.zero_grad() # set gradient zero. output = model(data) # get output from model loss = F.nll_loss(output, target) # calculate nll loss loss.backward() # do backpropagation optimizer.step() # update weight and biases if batch_idx % log_interval == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format( epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))def test(log_interval, model, device, test_loader): model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) test_loss += F.nll_loss(output, target, reduction='sum').item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format (test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset))) train함수를 통해서 train data들을 한번씩 살피도록 합니다. test함수를 통해서 test data를 통해 모델의 성능을 평가하게 됩니다. Make machine works123456# Train and Test the model and save it.for epoch in range(1, 11): train(log_interval, model, device, train_loader, optimizer, epoch) test(log_interval, model, device, test_loader)torch.save(model, './model.pt') train 함수와 test함수를 통해 model을 트레이닝 시키고모든 epoch이 끝나게 되면 torch.save를 통해 모델을 저장시켜줍니다. CNN modelCNN 모델은 28x28의 MNIST data를 1x784로 고쳐서 쓰는 것이 아닌, 2d data의 형태 그대로 사용하게 됩니다. 123456789101112131415161718192021222324class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 32, 3, 1) self.conv2 = nn.Conv2d(32, 64, 3, 1) self.dropout1 = nn.Dropout2d(0.25) self.dropout2 = nn.Dropout2d(0.5) self.fc1 = nn.Linear(9216, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = self.conv1(x) x = F.relu(x) x = self.conv2(x) x = F.relu(x) x = F.max_pool2d(x, 2) x = self.dropout1(x) x = torch.flatten(x, 1) x = self.fc1(x) x = F.relu(x) x = self.dropout2(x) x = self.fc2(x) output = F.log_softmax(x, dim=1) return output CNN을 이해하기 위해서는 filter size, padding, stride 라는 개념을 알아두셔야 합니다.","categories":[{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://korchris.github.io/categories/Machine-Learning/"}],"tags":[{"name":"Deep Learning","slug":"Deep-Learning","permalink":"http://korchris.github.io/tags/Deep-Learning/"},{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://korchris.github.io/tags/Machine-Learning/"},{"name":"ML","slug":"ML","permalink":"http://korchris.github.io/tags/ML/"},{"name":"DL","slug":"DL","permalink":"http://korchris.github.io/tags/DL/"},{"name":"Pytorch","slug":"Pytorch","permalink":"http://korchris.github.io/tags/Pytorch/"}]},{"title":"알파스타, 실시간 전략 게임 스타크래프트2 정복하기[딥마인드 소식 번역]","slug":"Alphastar","date":"2019-01-25T10:52:00.000Z","updated":"2020-11-19T10:24:36.000Z","comments":true,"path":"2019/01/25/Alphastar/","link":"","permalink":"http://korchris.github.io/2019/01/25/Alphastar/","excerpt":"","text":"AlphaStar: Mastering 실시간 전략 게임 스타크래프트2본문 LINK어설프지만 공부겸 번/의역 해가면서 글을 작성했습니다. 모든 오역에 대한 지적은 감사히 받습니다. 도움이 되었으면 합니다. 게임은 수십 년 동안 인공 지능 시스템의 성능을 테스트하고 평가하는 중요한 방법으로 사용되어 왔습니다. 역량(capability)이 향상됨에 따라 연구 커뮤니티는 과학 및 실제 문제를 해결하는 데 필요한 다양한 지능 요소를 포착하는, 복잡성이 증가하는 게임을 찾아 왔습니다. 최근 몇 년 동안, 가장 도전적인 실시간 전략 (RTS) 게임 중 하나로 간주되는 스타크래프트는 가장 긴 시간 동안 행해지는 스포츠 중 하나였으며, 인공 지능 연구를 위한 “큰 도전”이라는 것으로 의견이 일치되었습니다. Download 11 replays 최고의 프로 선수를 물리 칠 수 있는 최초의 인공지능 스타크래프트2 프로그램 AlphaStar를 소개합니다. 12월 19일에 열린 테스트 매치에서 AlphaStar는 세계 최강의 프로 스타크래프트 플레이어 중 하나인 팀 리퀴드의 Gregorz ‘ManA’ Komincz를 5-0으로 승리를 보이고, 그의 팀 동료 인 Dario ‘TLO’를 상대로도 승리를 거두었습니다. 경기는 프로 매치 경기에서 쓰이는 맵에서 경기를 하였고 게임에는 그 어떤 제약도 없었습니다. 인공지능 기술이 Atari, Mario, Quake Quake III Arena Capture the Flag, 그리고 Dota2에서는 뛰어난 성공 사례들이 있었지만, 아직까지는 스타크래프트와 같은 복잡성을 지닌 게임에는 좋은 결과를 내지 못했습니다. 가장 좋은 결과들은 시스템의 요소를 직접 제작하거나, 게임 규칙에 큰 제한을 걸거나, 초인적인 능력을 시스템에 주거나, 단순한 맵에서 게임을 진행함으로써 얻은 결과였습니다. 이런 노력에도 불구하고 그 어떤 시스템도 프로 선수들의 기술에 필적할만한 시스템은 거의 없습니다. 하지만, AlphaStar는 deep neural network(supervised learning and reinforcement learning)을 사용하여 게임의 raw data를 학습합니다. MaNa와의 경기에 대한 기록 스타크래프트가 “큰 도전”인 이유블리자드가 제작한 스타크래프트2는 공상과학세계를 배경으로 인간의 지성에 도전 할 수 있는 풍부한 멀티 플레이 게임을 지원합니다. 스타크래프트1과 함께, 스타크래프트2는 20년 이상 esports 토너먼트에서 경쟁하는 가장 크고 성공적인 게임중 하나입니다. 게임을 플레이하는 방법은 여러 가지 방법이 있지만 가장 일반적인 방법은 5개의 게임에서 1v1 토너먼트를 하는 것입니다. 시작하려면 플레이어는 저그, 프로토스 또는 테란이라는 세 가지 “종족” 중 하나를 선택해야합니다. 각각의 종족들은 특색 있는 특성과 능력을 지니고 있습니다(프로 선수는 한 종족을 전문으로 하는 경향이 있지만요). 각 플레이어는 많은 유닛과 구조물을 만들고 새로운 기술을 창출 할 수 있는 기본 자원을 모으는 다수의 일꾼 유닛으로 시작합니다. 이것들은 플레이어가 자원을 수확 할 수 있게 해주며, 보다 정교한 기반과 구조를 만들고, 상대방을 속일 수 있는 새로운 능력을 개발합니다. 게임에서 이기기 위해서는 큰 그림을 그려 정교하게 자원을 관리해야 하며(Macro라 알려진 것), 각각의 유닛을 직접 컨트롤 하는 것(Micro라 알려진 것)을 잘 관리해야 합니다. 장단기 목표의 균형을 맞추고 예상치 못한 상황에 적응해야하는 필요성 때문에 시스템은 종종 불안정하며 융통성이 없기도 합니다. 이 문제를 해결하기 위해서는 다음과 같은 몇 가지 인공 지능 연구 과제에서 혁신이 필요합니다. 게임 이론 : 스타크래프트는 가위바위보처럼 최고의 전략이 없는 게임입니다. 따라서 인공지능 교육 과정은 전략적 지식의 영역을 지속적으로 탐구하고 확장해야합니다. 불완전한 정보 : 플레이어가 모든 것을 볼 수있는 체스나 바둑 같은 게임과는 달리, 중요한 정보는 스타크래프트 플레이어에게 숨겨져 있으며 “정찰”로 직접 발견해야 합니다. 장기 계획 : 많은 실제 문제와 마찬가지로 인과 관계가 즉각적인 것은 아닙니다. 또한 게임을 완료하는 데 최대 1시간이 걸릴 수 있으므로 게임 초기에 수행한 작업이 오랜 기간 동안 성과를 내지 못할 수 있습니다. 실시간 : 선수가 후속 동작을 번갈아 번갈아하는 전통적인 보드 게임과 달리 스타크래프트 플레이어는 게임이 실시간으로 진행됨에 따라 계속해서 작업을 수행해야합니다. 대규모 작업 공간 : 수백 개의 다른 유닛과 건물을 실시간으로 한 번에 제어해야하며 조합 가능성이 생깁니다. 또한 행동은 계층적이며 변경 및 보완 될 수 있습니다. 인공지능은 매 time step마다 10개에서 26가지의 행동을 합니다. 이러한 엄청난 요구사항으로 인해 스타크래프트는 인공지능 연구를 위한 “큰 도전”으로 떠올랐습니다. 2009년 BroodWar API 출시 이후, 스타크래프트와 스타크래프트2가 현재 진행 중인 경쟁은 AIIDE 스타크래프트 AI 공모전, CIG 스타크래프트 공모전, 학생 스타크래프트 AI 토너먼트, 그리고 스타크래프트2 AI Ladder가 있습니다. 커뮤니티가 이러한 문제를 더욱 효과적으로 해결할 수 있도록 2016년과 2017년에 블리자드와 협력하여 PySC2로 알려진 오픈소스 도구 세트를 출시했습니다. 여기에는 지금까지 출시 된 익명의 게임 리플레이 세트가 포함됩니다. 저희는 AlphaStar를 제작하기위해 엔지니어링 및 알고리즘 혁신을 결합하여 이 작업을 수행했습니다. MaNa와의 2번째 경기 중 AlphaStar가 플레이하는 게임을 시각화한 모습. 즉, neural network에 있는 그대로의 화면을 input으로 넣어주고, neural network를 활성화시키고, AlphaStar가 클릭 할 위치와 대상, 그리고 예측된 결과와 같은 출력 값을 가질 수 있다. 그림에는 MaNa의 화면이 보이지만, AlphaStar는 이에 접근할 수 없다. AlphaStar는 어떻게 훈련되는가AlphaStar는 있는 그대로의 게임 인터페이스(유닛과 유닛속성의 목록)로부터 input을 받고 게임 내에서 조작하는 명령어를 생성하게 됩니다. 자세히 이야기하자면, neural network 구조중에 하나인 transformer를 메인으로 deep LSTM core, pointer network와 auto-regressive policy head, 그리고 centralised value baseline을 사용하였습니다. 저희는 이 진보된 모델이 long-term sequence와 큰 output spaces를 가지는 번역이나 언어 모델링, 그리고 시각적인 표현에 큰 도움을 줄 수 있을 거라 생각합니다. AlphaStar는 새로운 멀티 에이전트 학습 알고리즘을 사용합니다. 이 Neural network는 한 익명의 사람이 처음에 supervised learning으로 학습을 시켰고 블리자드는 이를 공개하였습니다. 이를 통해서 AlphaStar는 사람들을 따라하며 기본적인 Macro, Micro 전략을 배울 수 있었습니다. 초기의 에이전트는 게임내의 인공지능 레벨 ‘엘리트’를 95%의 승률로 이기기 시작했습니다. AlphaStar 리그. 에이전트는 처음에는 사람의 게임 리플레이에서 훈련을 한 후 리그내의 다른 경쟁자와 경기를 하며 훈련을 합니다. 각 iteration마다 새로운 경쟁자가 나타나고 원래의 경쟁자가 동결되며 각 에이전트의 매치를 결정하는 확률과 하이퍼 파라미터를 결정하는 학습 목표가 적용되며, 다양성을 유지하면서 난이도는 올라가도록 하였습니다. 에이전트의 parameter는 경쟁자에 대한 게임 결과로부터 강화 학습을 통해 업데이트됩니다. 최종 에이전트는 리그의 Nash 분포에서 샘플링됩니다. 그런 다음 멀티 에이전트 reinforcement learning을 통해 학습을 시작하였습니다. 지속적으로 리그가 생성되며 에이전트들은 경쟁자와 맞서 게임을 하게 됩니다. Starcraft Ladder와 같이, 에이전트들은 사람처럼 스타크래프트를 플레이하게 되는 것입니다. 새로운 경쟁자들이 계속해서 리그에 등장하게 되며, 새로운 경쟁자들은 원래의 에이전트들에게서 branch 되어 나옵니다. 각 에이전트들은 경쟁을 통해 학습을 진행하게 됩니다. Population-based reinforcement learning의 아이디어를 가져온 새로운 형태의 학습 과정으로, 각 에이전트가 가진 가장 강력한 전술을 상대하고, 빨리 상대방을 무릎을 꿇게 함과 동시에 지속적으로 스타크래프트의 방대한 양의 전술을 익히고 경험하게 됩니다. 추측 MMR(Match Making Rating)은 대략적인 플레이어의 실력을 측정한 것으로써, 현재 블리자드 온라인 리그와 비교를 해보았습니다. 리그가 진행되고 새로운 경쟁자가 만들어지면 이전 전략을 무력화 할 수 있는 새로운 대응 전략이 등장합니다. 일부 새로운 에이전트는 이전 전략을 단순화 한 전략을 실행하는 반면 다른 일부 에이전트는 새로운 빌드(전략)과 유닛 구성 및 micro-관리하는 방법 등 획기적인 새로운 전략을 발견했습니다. 예를 들면, AlphaStar 리그 초반에는 광자포과 암흑 기사를 이용하여 빠르게 적을 공략하는 “Cheesy”(역주: 싸구려) 전략이 선호되었습니다. 하지만 이러한 위험한 전략은 훈련이 진행됨에 따라 폐기되어 다른 전략을 이끌어 냈습니다. 예를 들어, 더 많은 일꾼들로 기지를 과도하게 확장함으로써 경제적 힘을 얻거나 두 마리의 예언자(역주. 일꾼 사냥에 좋은 유닛)을 통해 상대방의 일꾼과 경제를 혼란스럽게 합니다. 이 과정은 스타크래프트가 출시 된 이후로 플레이어가 새로운 전략을 발견하고 이전에 선호했던 전략을 버렸던 것과 유사합니다. 훈련이 진행됨에 따라 AlphaStar가 만드는 유닛의 조합이 바뀌었습니다. 리그의 다양성을 장려하기 위해 각 에이전트는 자체 학습 목표를 가지고 있습니다. 예를 들어, 어떤 에이전트는 다른 한 에이전트를 이겨야만 하는 추가적인 내부 motivation을 추가해줍니다. 한 에이전트는 특정 경쟁자를 이길 수 있는 목표를 가질 수 있지만 다른 에이전트는 대다수의 에이전트를 이겨야하는 경우도 있습니다. 그렇게 하기 위해서는 특정 유닛을 더 많이 만들어야 합니다. 이러한 학습 목표는 학습 과정에서 조정됩니다. AlphaStar 리그의 경쟁자를 보여주는 visualization. TLO 및 MaNa와 경쟁을 한 에이전트에는 특별히 레이블이 지정됩니다.(html을 긁어오기가 힘들어서 사진 캡처로 대체. detail in 본문) 각 에이전트들의 neural network weight은 경쟁자에 대한 게임으로부터 reinforcement learning을 통해 업데이트되어 개인 학습 목표를 최적화합니다. Weight을 업데이트하는 규칙으로는, off-policy actor-critic 방법과 함께 experience replay, self-imitation learning, 그리고 policy distillation이 사용되었습니다. 이 그림은 MaNa와의 플레이를 위해 선택된 한 명의 에이전트(검은 점)가 훈련 과정에서 전략과 경쟁자(색이 있는 점)들을 발전 시켰음을 보여줍니다. 각 점은 AlphaStar 리그의 경쟁자를 나타냅니다. 점의 위치는 전략(inset)을 나타내며 점의 크기는 Mana 에이전트와 얼마나 자주 겨루며 학습을 했는지를 보여줍니다. AlphaStar를 학습시키기 위해 저희는 구글의 스타크래프트2를 학습하는 수많은 에이전트들이 수천개의 병렬 instance들 안에서 학습할 수 있도록 지원하는 구글 v3 TPU를 사용하여 확장성이 뛰어난 distributed 학습 환경을 만들었습니다. AlphaStar 리그는 14일 동안, 16개의 TPU를 사용하며 훈련이 이루어졌고 각 에이전트들은 현실시간으로 약 200년의 스타크래프트 게임을 경험하게 되었습니다. 최종적인 AlphaStar 에이전트는 Nash 분포 리그를 구성하고 있으며, 이는 곧 가장 효율적인 전략들이 혼합된 모델이라는 것입니다. 그리고 이 모델은 단 한개의 GPU에서 구동이 가능합니다. 모든 기술적인 설명은 peer-reviewd 저널에 투고될 예정입니다. AlphaStar 리그가 진행되면서 Nash 분포 안에서도 새로운 경쟁자들이 등장했습니다. Nash 분포 안에서 상호 보완적인 경쟁자 중 가장 취약한 에이전트는 새로운 경쟁자에게 가장 큰 비중을 두고 있으며 이전 경쟁자들에 대한 지속적인 진전을 보여줍니다. AlphaStar는 어떻게 게임을 플레이하며 게임을 관찰하는가TLO와 MaNa같은 프로 스타크래프트 플레이어는 평균 분당 수백번의 동작(APM)을 실행할 수 있습니다. 이는 각 유닛을 독립적으로 제어하고 수천 또는 수만 개의 APM을 일관성 있게 유지 및 관리하는 기존 Bot들에 비해 현저하게 낮습니다. TLO와 MaNa와의 경기에서 AlphaStar의 평균 APM은 280으로 아무리 게임 플레이가 정교했다 하더라도 프로 선수보다 훨씬 낮았습니다. 이 낮은 APM은 부분적으로 AlphaStar가 리플레이를 사용하여 교육을 시작하기 때문에 인간이 게임을 하는 방식을 모방하기 때문입니다. 또한 AlphaStar는 관찰과 동작 사이의 평균 350ms의 지연시간을 가지고 있습니다. MaNa와 TLO에 대한 경기에서 AlphaStar가 가졌던 APM 분포와 총 지연 시간. TLO와 MaNa와의 경기 도중 AlphaStar는 직접 게임의 인터페이스를 통해 스타크래프트 게임 엔진을 사용하였습니다. 즉, 카메라를 움직이지 않고도 직접 맵에서 자신과 상대방의 눈에 보이는 유닛의 속성을 직접 관찰 할 수 있었습니다. 반대로 사람은 카메라를 사용해서 어디에 집중해야 할지 명확하게 결정을 해야만 합니다. 하지만 분석해보니 AlphaStar의 게임은 AlphaStar 스스로가 어디에 집중을 해야 할지 암시적으로 관리하는 모습을 보였습니다. AlphaStar는 TLO나 MaNa와 비슷하게 평균적으로 분당 30회 정도의 “switched context”를 하였습니다. 또한, 경기 후에 저희는 AlphaStar의 두 번째 버전을 개발했습니다. 인간 선수와 마찬가지로 AlphaStar의 두 번째 버전은 카메라를 언제, 어디서 움직일지를 결정하며, 화면의 정보로만 인식되며, 동작 위치는 볼 수있는 영역으로 제한됩니다. Raw 인터페이스와 카메라 인터페이스를 사용하는 AlphaStar의 성능. 새로 훈련된 카메라 에이전트가 raw 인터페이스를 사용하여 에이전트의 성능을 따르게 따라 잡을 수 있고 거의 동일하다는 것을 보여준다. Raw 인터페이스를 사용하는 것과 AlphaStar 리그를 상대로 카메라 제어법을 배우는 두 가지 새로운 에이전트를 교육했습니다. 각 에이전트는 처음에 인간 데이터를 통한 supervised learning과 위에서 설명한 reinforcement learning을 통해 훈련되었습니다. 카메라 인터페이스를 사용하는 AlphaStar 버전은 내부 인터페이스에서 7000 MMR을 초과하는 raw 인터페이스와 거의 비슷했습니다. 전시회 경기에서, MaNa는 7일 동안 훈련된 카메라 인터페이스를 사용하는 프로토타입의 AlphaStar를 이겼습니다. 이 결과는 MaNa 및 TLO에 대한 AlphaStar의 성공이 우수한 클릭률, 빠른 반응 시간 또는 raw 인터페이스보다는 우수한 macro와 micro-strategic decision-making(역주. 컨트롤) 때문인 것으로 나타났습니다. 프로선수의 AlphaStar 평가스타크래프트 게임을 통해 플레이어는 테란, 저그 또는 프로토스의 세 가지 종족 중 하나를 선택할 수 있습니다. 저희는 AlphaStar를 학습시키는 것에 교육시간과 편차를 줄이기 위해 현재 단 하나의 종족인 프로토스를 전문적으로 다루기로 결정했습니다. Note that, 동일한 교육을 모든 종족에 적용을 시킬 수 있습니다. 저희의 에이전트는 스타크래프트2(v4.6.2)에서 프로토스vs프로토스 게임을 진행하였고, CatalystLE라는 맵에서 진행되었습니다. AlphaStar의 성능을 평가하기 위해 저희는 TLO(저그가 주종족인 프로선수, 프로토스는 그랜드마스터의 실력)를 통해 테스트 하였고 AlphaStar는 다양한 빌드와 유닛으로 5-0으로 경기를 마무리했습니다. TLO는 “진짜 잘해서 놀랐어요. AlphaStar는 잘 알려진 전략과는 거리가 먼 플레이를 보여주었어요. 전혀 생각하지도 못한 전략으로 다가왔죠. 그 말은 곧 아직 우리가 경험하지 못한 새로운 방식의 전략들이 존재하다는 거겠죠” 라고 말했다. AlphaStar:inside story 1주일간 에이전트를 교육 한 후, 저희는 세계에서 가장 강력한 스타크래프트2의 플레이어 중 하나인 MaNa 와 가장 강력한 10명의 프로토스 선수들과 대전했습니다. AlphaStar는 5경기에서 무패로 우승하여 강력한 전략 기술을 보여주었습니다. “AlphaStar의 놀라운 움직임과 매 경기 다른 전략으로 다가오는 것에 큰 감명을 받았다. 내가 전혀 생각하지 못했던 사람 같은 플레이를 보여주었다.” “나는 내 전략이 상대방의 실수를 유도하고 그의 인간적인(감정적인) 반응을 나에게 유리하도록 하는 것에 의존하고 있다는 사실을 깨달았다.”고 말했다. AlphaStar, 그리고 다른 복잡한 문제들스타크래프트는 그냥 게임이지만, 아주 복잡한 게임입니다. 저희는 AlphaStar를 뒷받힘 하는 기술들이 다른 문제 해결에 유용할 것이라 생각합니다. 예를 들면, 장시간 동안 많은 행동이 필요한 긴 sequence(때로는 수천, 수만의 움직임을 하는 1시간 경기 같은)같은 것들-완전하지 않은 정보들을 기반으로-에 도움이 될 수 있다고 생각합니다. 스타크래프트의 각 프레임은 입력의 한 단계로 사용되며, neural network는 매 프레임마다 나머지 게임에 대한 예상 동작 순서를 예측합니다. 매우 긴 데이터 sequence에 대해 복잡한 예측을 하는 근본적인 문제는 날씨 예측, 기후 모델링, 언어 이해 등과 같은 많은 실제 과제에서 나타납니다. 저희는 또한 우리의 훈련 방법 중 일부가 안전하고 견고한 인공지능 연구에 유용 할 수 있다고 생각합니다. AI에서 커다란 난제 중 하나는 시스템이 잘못 훈련 될 수 있는 가능성이 있으며 스타크래프트 프로 선수들은 이러한 실수를 유발할 창의적인 방법을 찾아 인공지능 시스템을 쉽게 이길 수 있음을 알았습니다. AlphaStar의 혁신적인 리그 기반 학습 과정은 가장 신뢰할 수 있고 잘못 될 가능성이 적은 접근 방식을 찾습니다. 저희는 AI 시스템의 안전성과 견고성을 향상시킬 수있는 이러한 접근법의 잠재력, 특히 에너지와 같이 안전성이 중요한 분야에서 복잡한 상황을 다루는 것이 필수적이라는 점을 기쁘게 생각합니다. AlphaStar를 통해 만들어진 스타크래프트의 최고 수준의 플레이는 지금까지 만들어진 가장 복잡한 게임 중 하나를 돌파했다는 것을 의미합니다. 우리는 AlphaZero 및 AlphaFold와 같은 프로젝트와 함께 이러한 발전들은 언젠가는 세계에서 가장 중요하고 근본적인 과학적 문제에 대한 새로운 솔루션을 열어 줄 수 있는 지능형 시스템을 개발하려는 우리의 사명을 한 단계 진전시킨 것이라고 믿습니다. Team Liquid의 TLO 및 MaNa에 대한 지원과 엄청난 기술에 감사드립니다. 우리는 블리자드와 스타크래프트 커뮤니티가 이 작업을 가능하게 하기 위해 지속적으로 지원해 주신 것에 대해서도 감사드립니다. Download 11 replays hereWatch the exhibition game against MaNaWatch a visualisation of AlphaStar’s entire second game against MaNaAlphaStar Team: Oriol Vinyals, Igor Babuschkin, Junyoung Chung, Michael Mathieu, Max Jaderberg, Wojtek Czarnecki, Andrew Dudzik, Aja Huang, Petko Georgiev, Richard Powell, Timo Ewalds, Dan Horgan, Manuel Kroiss, Ivo Danihelka, John Agapiou, Junhyuk Oh, Valentin Dalibard, David Choi, Laurent Sifre, Yury Sulsky, Sasha Vezhnevets, James Molloy, Trevor Cai, David Budden, Tom Paine, Caglar Gulcehre, Ziyu Wang, Tobias Pfaff, Toby Pohlen, Dani Yogatama, Julia Cohen, Katrina McKinney, Oliver Smith, Tom Schaul, Timothy Lillicrap, Chris Apps, Koray Kavukcuoglu, Demis Hassabis, David Silver With thanks to: Ali Razavi, Daniel Toyama, David Balduzzi, Doug Fritz, Eser Aygün, Florian Strub, Guillaume Alain, Haoran Tang, Jaume Sanchez, Jonathan Fildes, Julian Schrittwieser, Justin Novosad, Karen Simonyan, Karol Kurach, Philippe Hamel, Ricardo Barreira, Scott Reed, Sergey Bartunov, Shibl Mourad, Steve Gaffney, Thomas Hubert, Yuhuai Wu, the team that created PySC2 and the whole DeepMind Team, with special thanks to the RPT, comms and events teams.","categories":[{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://korchris.github.io/categories/Machine-Learning/"}],"tags":[{"name":"Reinforcement_learning","slug":"Reinforcement-learning","permalink":"http://korchris.github.io/tags/Reinforcement-learning/"},{"name":"Deep learning","slug":"Deep-learning","permalink":"http://korchris.github.io/tags/Deep-learning/"},{"name":"Deep Mind","slug":"Deep-Mind","permalink":"http://korchris.github.io/tags/Deep-Mind/"},{"name":"AlphaStar","slug":"AlphaStar","permalink":"http://korchris.github.io/tags/AlphaStar/"}]},{"title":"[챗봇] 페이스북 챗봇 만들기","slug":"FB_chatbot","date":"2017-06-29T06:43:00.000Z","updated":"2024-01-11T07:32:32.794Z","comments":true,"path":"2017/06/29/FB_chatbot/","link":"","permalink":"http://korchris.github.io/2017/06/29/FB_chatbot/","excerpt":"","text":"나만의 페이스북 메신저 봇 만들기2020.03.19 Updates 수정사항 : 원래 사용했던 nodejs 대신 python을 이용합니다. 이 글은 Python, Heroku server를 이용하여 자신만의 페이스북 챗봇을 만들어보는 템플릿 예제입니다. 챗봇이란?챗봇은 사용자가 별도로 웹사이트나 앱을 따로 실행하지 않고도 대화하듯 정보를 얻을 수 있는 서비스다. 기존 사용자 자신이 쓰는 메신저를 통해 정보를 얻을 수 있다는 점이 현재 구글, 페이스북, 마이크로소프트, 텔레그램을 비롯해 국내 네이버, 다음 등 IT 분야 기업들이 챗봇을 기반으로 한 메신저 플랫폼을 선보이는 중이다. [네이버 지식백과] 채팅봇, 챗봇 - 메신저 서비스 인공지능(AI)과 만나다 (용어로 보는 IT) 준비 Python Version 3 Terminal 터미널 기반으로 배포하기 때문에 윈도우 사용자는 cmd나 터미널 환경을 갖추신 후에 따라하시면 됩니다. 윈도우 터미널 설치 가 도움이 되실겁니다. Git Git 설치는 생활코딩 지옥에서 온 Git 중 설치방법 강의를 보시면 수월하게 진행하실 수 있습니다. Heroku heroku 에 가입합니다. Heroku CLI가 필요합니다. Facebook Account Facebook account가 필요합니다. Ngrok Ngrok을 사용하여 Heroku에 배포하기 전, 내부 망에서 테스트를 하기 위해서 필요합니다. 디렉토리 설정 및 코드 작성이 프로젝트를 위한 디렉토리를 하나 만들어줍니다.1234mkdir chatbotcd chatbotpwd/Users/username/chatbot 또한 python library들을 다운 받습니다.1sudo pip3 install Flask requests gunicorn 혹은1pip3 install --user Flask requests gunicorn 폴더를 만드셨다면 chatbot 폴더 내부에 파이썬 코드를 작성해줍니다. app.py 라는 이름으로 코드를 작성해주시면 됩니다. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081from flask import Flask, requestimport requestsapp = Flask(__name__)FB_API_URL = 'https://graph.facebook.com/v2.6/me/messages'VERIFY_TOKEN=''PAGE_ACCESS_TOKEN=''def send_message(recipient_id, text): \"\"\"Send a response to Facebook\"\"\" payload = { 'message': { 'text': text }, 'recipient': { 'id': recipient_id }, 'notification_type': 'regular' } auth = { 'access_token': PAGE_ACCESS_TOKEN } response = requests.post( FB_API_URL, params=auth, json=payload ) return response.json()def get_bot_response(message): \"\"\"This is just a dummy function, returning a variation of what the user said. Replace this function with one connected to chatbot.\"\"\" return \"This is a dummy response to '{}'\".format(message)def verify_webhook(req): if req.args.get(\"hub.verify_token\") == VERIFY_TOKEN: return req.args.get(\"hub.challenge\") else: return \"incorrect\"def respond(sender, message): \"\"\"Formulate a response to the user and pass it on to a function that sends it.\"\"\" response = get_bot_response(message) send_message(sender, response)def is_user_message(message): \"\"\"Check if the message is a message from the user\"\"\" return (message.get('message') and message['message'].get('text') and not message['message'].get(\"is_echo\"))@app.route(\"/webhook\", methods=['GET'])def listen(): \"\"\"This is the main function flask uses to listen at the `/webhook` endpoint\"\"\" if request.method == 'GET': return verify_webhook(request)@app.route(\"/webhook\", methods=['POST'])def talk(): payload = request.get_json() event = payload['entry'][0]['messaging'] for x in event: if is_user_message(x): text = x['message']['text'] sender_id = x['sender']['id'] respond(sender_id, text) return \"ok\"@app.route('/')def hello(): return 'hello'if __name__ == '__main__': app.run(threaded=True, port=5000) VERIFY_TOKEN와 PAGE_ACCESS_TOKEN은 이 다음 과정에서 페이스북 세팅 후, 채워넣을 예정입니다. 위와 같이 코드를 작성하셨다면 다음 단계로 넘어가겠습니다. 페이스북 설정 Facebook Developer Page에 접속한 후 Create App을 눌러줍니다. App의 이름을 정해준 후에 Create App ID를 누릅니다. App이 만들어졌다면 다음과 같은 화면에서 Messenger의 Set Up 버튼을 눌러줍니다. Access Tokens 내부 화면에서 Create New Page를 눌러서 페이지 생성을 진행합니다. Page 생성이 완료되었다면 다시 Access Tokens 내부 화면으로 돌아와서 하단에 Add or Remove Pages를 눌러줍니다. Generate Token을 눌러줍니다. I Understand에 체크표시하시고 밑에 생성된 Token을 복사한 뒤 따로 보관해둡니다.(나중에 코드에 들어가게 됩니다.) Ngrok으로 테스트해보기Ngrok으로 챗봇을 테스트 하기전에 먼저 app.py 파일 내부를 수정해줍니다. 123456from flask import Flask, requestimport requestsapp = Flask(__name__)FB_API_URL = 'https://graph.facebook.com/v2.6/me/messages'VERIFY_TOKEN='my_secret_token'PAGE_ACCESS_TOKEN='ENNJLCNDJSLKABJVLNEJLKWANJLCNJEL.........' 위의 부분에서 VERIFY_TOKEN은 여러분이 원하는 비밀번호로, PAGE_ACCESS_TOKEN 안에는 아까 발급 받았던 그 token을 ‘’ 사이에 넣어주시면 됩니다.(이 파일을 open된 곳에 upload하지 마세요. 추후에 보안이 필요한 작업입니다.) 수정을 다 해주셨다면 Ngrok에 들어가셔서 Sign Up을 하신 뒤, ngrok을 다운받습니다. 저같은 경우에는 app.py가 위치하고 있는 폴더에 다운로드하였습니다. ngrok에서 설명하는 것 그대로 진행합니다. 다운로드 -> 압축해제를 진행한 뒤에 command 창에 3번 그대로 복사붙여넣기를 해주면, 접속을 위한 세팅이 완료되고 4번의 명령어와는 다르게 80대신 5000을 써줍니다. 1./ngrok http 5000 을 실행하게 되면 다음과 같은 화면이 뜨게 됩니다. 그리고 또 다른 터미널 창을 열어주신 뒤, app.py 파일을 실행해줍니다. 1python app.py 이와 같이 ngrok과 app.py 가 모두 준비가 되었다면 다시 브라우저를 통해 access tokens 하단에 있는 webhook에서 Add Callback URL을 클릭합니다. 이제 대략적인 세팅은 끝이 났습니다. 본인의 page에 hi라고 한번 메세지를 보내봅니다. 성공적으로 제가 한 말을 따라합니다. Heroku에 배포하기Heroku에 배포하기 위해서 설치했던 Heroku CLI를 이용하여 배포해줄 것입니다. heroku login을 실행하시고 기다리셨다가 press any key… 가 나오시면 enter 눌러주세요. 12345heroku loginheroku: Press any key to open up the browser to login or q to exit:Opening browser to https://cli-auth.heroku.com/auth/cli/browser/.......................heroku: Waiting for login... ⣷ 로그인을 진행해주시면 다음과 같이 커맨드창에 나타납니다. 12Logging in... doneLogged in as <your email address> 로그인이 성공적으로 완료되었다면 다음 명령어를 실행합니다. 1heroku create 실행하면, heroku는 자동적으로 웹 서버를 만들기 시작합니다. 이제 생성된 Heroku App에 우리가 만든 소스를 배포시키려고 합니다. 배포하기 전에 다음과 같은 내용을 가진 requirements.txt을 만들어주고 123Flask==1.0.2requests==2.21.0gunicorn==20.0.4 다음 내용을 가진 Procfile 을 만들어 줍니다. 1web: gunicorn app:app 위의 과정까지 마치셨다면 다음 명령어들을 차례대로 실행합니다. 12345git initgit add .git commit -m 'init'heroku git:remote -a <your_project_name>git push heroku master 밑의 사진들은 제가 실행시킨 결과입니다. 이와 같이 heroku에 배포를 완료했다면, 실행중인 ngrok을 꺼주시고 브라우저에서 callback을 수정합니다. 이 과정을 모두 수행하셨다면 마지막으로 page에 테스트 메세지를 보내봅니다. 마치며기존 버전이 2017년 버전으로 되어있어서 많은 부분이 다르기 때문에 급하게 블로그 내용을 수정하였습니다. 추가적으로 내용 수정을 들어가겠으며 질문이 있으시면 얼마든지 코멘트 달아주세요. 제가 다룬 코드는 제 Github에서 확인하실 수 있습니다. 감사합니다. Ref : https://github.com/davidchua/pymessenger https://hackernoon.com/beginners-guide-simple-chat-bot-fb-based-on-flask-and-heroku-2g7v32ab","categories":[{"name":"Chatbot","slug":"Chatbot","permalink":"http://korchris.github.io/categories/Chatbot/"}],"tags":[{"name":"chatbot","slug":"chatbot","permalink":"http://korchris.github.io/tags/chatbot/"},{"name":"facebook","slug":"facebook","permalink":"http://korchris.github.io/tags/facebook/"}]},{"title":"Hexo 시작하기","slug":"Start Hexo","date":"2017-02-23T06:32:22.000Z","updated":"2020-11-19T10:24:22.000Z","comments":true,"path":"2017/02/23/Start Hexo/","link":"","permalink":"http://korchris.github.io/2017/02/23/Start Hexo/","excerpt":"","text":"나만의 블로그Github을 모르던 시절, 제가 만들었던 코드를 저장할 수 있고 설명할 수 있는 개인 블로그를 가지고 싶었습니다. 그래서 처음에는 네이버 블로그로 시작했지만, code를 적기에는 너무나 협소한 환경이었고 Tistory에 초청받아 사용해보았지만 불편한 것은 여전했습니다. Github를 사용하기 시작하면서 markdown 언어를 알게 되었고 md를 통해서 블로그를 만들 수 있으면 좋겠다고 생각하고 Github Page를 통해 블로그를 만들기로 했습니다. Github? Github Page? Hexo?Github는 git을 사용하는 프로젝트를 지원하는 웹 호스팅 서비스이자 가장 인기있는 오픈소스 코드 저장소이기도 합니다. Github page는 사용자를 위해 static한 홈페이지(블로그)를 자동으로 만들어주고 이를 username.github.io으로 무료 호스팅해주는 서비스입니다. Hexo는 이 github pages를 이용한 블로그 프레임워크라고 말할 수 있죠. 초기 setting 후 간편한 명령어로 github에 deploy하면 자동으로 적용이 됩니다. Hexo의 특징 Blazing FastNodejs를 사용하여 빠른 속도로 생성하고, 빌드하는데에 필요한 수백개의 파일이 수초안에 해결이 됩니다. Markdown Support마크다운 언어를 지원합니다. One-Command Deployment하나의 명령어로 Github Page, Heroku, 다른 사이트에 배포가 가능합니다. Various PluginPowerful한 플러그인들을 제공합니다. 다양한 기능과 특징이 있지만 웹프로그래밍언어 지식이 없으시다면 사용하기가 굉장히 어려울 것이라고 생각됩니다. HTML, CSS, JS, Git에 대한 이해가 요구됩니다. Hexo 설치하기Hexo를 설치하기 위해서는 다음 2개의 요소가 필요합니다.-Node.js-Git이미 설치가 되신 상태라면 터미널에 다음과 같은 명령어를 입력하시면 됩니다.1$ npm install -g hexo-cli 자세한 설치 방법은 hexo hompage를 참고해주시기 바랍니다. Hexo Setup하기먼저 Blog를 구성하는 파일들을 저장할 폴더를 만듭니다. Github에 배포하실 분은 폴더명을 username.github.io로 만드시는 것을 추천해드립니다.123$ hexo init username.github.io$ cd username.github.io$ npm install 위의 절차를 거치셨다면 다음과 같은 디렉토리가 생성됩니다.12345678.├── _config.yml├── package.json├── scaffolds├── source| ├── _drafts| └── _posts└── themes 가장 기본적인 테마로 만들어진 여러분의 블로그 파일입니다.확인해보고 싶으시다면 로컬서버로 이를 확인할 수 있습니다.1$ hexo s 후에12INFO Start processingINFO Hexo is running at http://localhost:4000/. Press Ctrl+C to stop. 라는 문구가 뜨시면 localhost:4000으로 들어가셔서 확인하실 수 있습니다. 글쓰기먼저 글의 종류에는 다양하지만 일단 2가지를 설명하겠습니다.-draftdraft는 말 그대로 초안문서로써 posting은 하지 않으나 source폴더내의 _draft폴더 안에서 관리합니다.-postpost는 나의 Blog에 들어갈 문서입니다. 배포시에 Blog에 바로 적용이 됩니다. 글을 쓸 때에는 터미널에서 명령어를 입력해서 시작할 수 있습니다. 바로 post할 글을 쓰기 위해서는 1$ hexo new <filename> 초안문서를 먼저 만들고 싶으시다면1$ hexo new draft <filename> 로 글을 작성하실 수 있습니다.draft완성 후에 post로 옮기고 싶으시다면1$ hexo publish <filename> 으로 _draft폴더에서 _post폴더로 옮길 수 있습니다. 먼저 위의 글생성 명령어를 실행하시면 폴더내에 해당 파일 이름을 가진 markdown형식의 파일이 생성될 것입니다. 123456title : hexo inittags: -hexodate : 2017/02/23---My First Hexo!! 위와 같이 자신이 원하는 대로 글을 수정하시면 글을 생성하는 것이 완료되는 형식입니다. Github에 배포하기Github에 배포하기 위해서는 먼저 hexo-deployer-git이라는 플러그인이 필요합니다. 다른 플랫폼에 배포하기 원하시면 그에 해당하는 플러그인을 찾으신 후 설치하시면 됩니다.1$ npm install hexo-deployer-git --save 그리고 _config.yml에서 Github 정보를 입력해주셔야 합니다. 1234deploy: type: git repo: https://github.com/KorChris/korchris.github.io.git branch: master 위와 같이 본인의 git repo의 정보를 입력해주신 후에 1$ hexo generate 정적파일을 생성해줍니다. 혹시나 로컬서버에는 적용이 되는데 github에 적용이 되지 않으면 hexo clean 후에 hexo generate을 실행하시면 잘 되실꺼에요. 생성이 완료되었다면 마지막으로 1$ hexo deploy Deploy 명령어를 실행합니다. 디플로이가 완료가 되면 Github Repository와 Github Page에 적용된 것을 확인하실 수 있습니다.(약 1분의 시간이 걸릴 때도 있네요)","categories":[{"name":"Blog","slug":"Blog","permalink":"http://korchris.github.io/categories/Blog/"}],"tags":[{"name":"hexo","slug":"hexo","permalink":"http://korchris.github.io/tags/hexo/"}]}]}