Share
Sign In
Lighthouse LLM
데이터 전처리와 정규표현식
최윤진
👍🏻
1
😀
1
이번 글에서는 딥러닝 학습에서 데이터가 가지는 중요성을 살펴보고, 데이터 전처리에 사용되는 정규표현식에 대해 살펴보겠습니다.
1. 딥러닝 성공 배경
딥러닝이 성공할 수 있었던 이유는 크게 3가지 입니다.
1.
Algorithms
AlexNet, CNN, RNN, Transformer, BERT, GPT ..
1.
Computation
V100, A100 ..
1.
Data
MNIST, CIFAR, WikiText ..
Data - Model - Cuda
먼저, Backpropagation, ReLU, Dropout, CNN 과 같은 기술들을 통해 AlexNet 이 만들어졌습니다. 시계열 데이터의 경우 RNN-LSTM-Transformer-BERT/GPT 로 이어지는 모델 계보가 있습니다. 이러한 모델 아키텍쳐가 있었기 때문에 딥러닝이 성공할 수 있었습니다.
다음 Computation 능력의 경우 병렬 처리가 가능한 좋은 GPU가 덕분에 효과적으로 학습과 추론을 할 수 있었고, 이 때문에 딥러닝이 성공할 수 있었습니다.
마지막으로 데이터입니다. 딥러닝 모델과 GPU 모두 양질의 데이터가 있을 때 비로소 의미가 있습니다. MNIST, CIFAR, WikiText 와 같은 품질 좋은 거대 데이터셋이 있었기 때문에 오차 계산의 재료가 충분했습니다. 소프트웨어 개발에 있어서 코드(Code)는 딥러닝 개발에 있어서 데이터와 같습니다.
GPT-3 의 경우 753GB 의 데이터셋으로 학습시켰다. 출처 : https://devocean.sk.com/blog/techBoardDetail.do?ID=164626&boardType=techBlog
2. 데이터 & 데이터 전처리 필요성
세 가지 모두 중요한 요소이지만 이번 글에서는 데이터를 집중 조명해보고자 합니다. 세상엔 많은 것이 데이터입니다. 이미지도, 언어도, 소리도, 글씨도 모두 데이터입니다. 풀고 싶은 문제에 따라 문제의 정답율도, 광고의 클릭률도 데이터가 될 수 있습니다. 당연히도 아날로그로 존재하는 데이터는 디지털로 변환되고, 디지털 상에서 태어난 데이터는 일반적으로 크롤러에 의해 수집되고 데이터베이스에 저장 관리하는 방식으로 사용할 수 있는 데이터가 됩니다.
많은 것이 데이터지만 무한하지는 않습니다. 인터넷/웹 이후로 디지털 공간에서 만들어진 데이터는 빠르게 증가해왔습니다. 특히 모바일의 등장은 가파른 데이터 생산에 큰 기여를 했습니다. 하지만 학습에 사용하고 있는 데이터가 새롭게 공급되는 데이터를 추월하고 있는 상황입니다. 모델 학습에 필요한 데이터가 고갈 될거라는 우려가 존재합니다. 때문에 한정된 데이터를 효율적으로 사용하는 게 중요합니다. 특히 데이터셋 자체를 구하기 어려운 분야의 경우에는 더욱 그러합니다.
낮은 품질의 텍스트 데이터는 약 2040년에, 높은 품질의 텍스트 데이터는 약 2024년에, 이미지 데이터는 약 2035년에 중앙값 데이터가 고갈될 것으로 추정된다. 출처 : https://zdnet.co.kr/view/?no=20230110071207
수집된 원본(raw) 데이터는 노이즈를 포함하고 있습니다. 불필요한 정보들이 입력 되었을 때 모델의 성능은 나쁜 영향을 받습니다. 원본 데이터 3만개 보다 품질 좋은 데이터 300개가 더 좋을 수 있습니다. 수집된 원본 데이터가 전처리를 거쳐야 하는 이유입니다.
노이즈 데이터는 모델 학습에 악영향을 끼친다. 출처 : https://sci2s.ugr.es/noisydata
데이터 전처리는 데이터를 의도에 맞게 학습하고 싶은 방향으로 처리하는 과정입니다.
이미지 데이터의 경우 RGB로 표현되는 값을 정규화 시키거나 openCV 라이브러리를 활용하여 중요한 정보를 부각시키는 방식(크기 조정, 회전, 반전, 경계 검출, 색상 분할)으로 전처리를 할 수 있습니다.
텍스트 데이터의 경우 전처리하는 다양한 방법들이 존재하며 정규 표현식은 텍스트 전처리에 과정에서 사용되는 대표적인 문자열 처리 방법입니다.
텍스트 데이터 전처리 로직, 출처 : https://www.researchgate.net/figure/Text-pre-processing-method-flowchart_fig1_341937237
Remove Stop words (불용어 제거)
불용어(stop words)는 자주 등장하지만 실제 의미 분석에는 크게 도움이 되지 않는 단어
예를 들어, "a", "the", "and" 등이 있음.
Stemming (어간 추출)
어간 추출은 단어를 어간(stem)으로 변환하는 과정.
어간은 단어의 기본 형태로, 접사 등이 제거된 형태.
예를 들어, "running", "runs", "ran"은 모두 "run"이라는 어간으로 변환.
Remove generic words (일반적인 단어 제거):
일반적인 단어는 해당 도메인에서 자주 등장하지만 실제 분석에는 큰 도움이 되지 않는 단어들을 말함.
예를 들어, 의료 도메인에서는 "patient", "doctor" 등의 단어가 일반적인 단어에 해당할 수 있음.
Remove tagged names (태그된 이름 제거):
태그된 이름은 데이터에 포함된 개인정보나 식별 가능한 정보를 말함.
예를 들어, 사람 이름, 지명, 이메일, URL, 휴대폰 번호
개인정보 보호와 데이터 익명화를 위해 중요한 단계
3. 텍스트 데이터 전처리 방법 : 정규 표현식
출처 : https://hamait.tistory.com/342
정규표현식(Regular Expression)이란 문자열에서 특정 패턴을 찾기 위해 사용되는 문자와 메타문자의 조합입니다. 1951년 수학자 스티븐 클리니에 의해 처음 만들어졌으며, 고전적으로 컴파일러 개발에 많이 활용이 되었습니다. 현재는 그 범위가 확장되어 웹 개발과 텍스트 데이터 전처리에 많이 활용 되고 있습니다.
정규 표현식을 이용하면 간단하게 이메일 주소, 전화번호, 로그 데이터 등과 같은 다양한 패턴을 검증하거나 치환할 수 있습니다. Python, Javascript, Java 등 다양한 언어에서 내장 라이브러리를 기본적으로 제공합니다. Python 에서는 re 모듈을 통해 정규표현식을 사용할 수 있습니다.
3.1 re 메서드
python 에서 re 사용법을 간단하게 살펴봅니다.
re.search(pattern, string)
문자열에서 패턴과 첫 번째로 일치하는 부분을 찾아 Match 객체를 반환합니다.
일치하는 부분이 없으면 None을 반환합니다.
import re text = "Hello, World!" pattern = r"World" match = re.search(pattern, text) if match: print("패턴과 일치하는 부분:", match.group()) else: print("일치하는 부분이 없습니다.") # 패턴과 일치하는 부분: World
re.findall(pattern, string)
문자열에서 패턴과 일치하는 모든 부분 문자열을 리스트로 반환
import re text = "Hello, World! Hello, Python!" pattern = r"Hello" matches = re.findall(pattern, text) print("일치하는 부분 문자열:", matches) # 일치하는 부분 문자열: ['Hello', 'Hello']
re.sub(pattern, repl, string)
문자열에서 패턴과 일치하는 부분을 repl로 대체한 새로운 문자열을 반환
import re text = "Hello, World! Hello, Python!" pattern = r"Hello" replaced = re.sub(pattern, "Hi", text) print("대체된 문자열:", replaced) # 대체된 문자열: Hi, World! Hi, Python!
3.2 정규 표현식 문법
📌 . ? * +
특수 문자
설명
.
줄바꿈 문자를 제외한 모든 문자와 매치
?
앞의 문자가 0번 또는 1번 나타나는 패턴과 매치
*
앞의 문자가 0번 이상 반복되는 패턴과 매치
+
앞의 문자가 1번 이상 반복되는 패턴과 매치
1.
. (줄바꿈을 제외한 모든 문자)
import re text = "Hello, World!\nThis is a new line." pattern = r"." matches = re.findall(pattern, text) print(matches) # 출력: ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 'n', 'e', 'w', ' ', 'l', 'i', 'n', 'e', '.']
2.
? (앞의 문자가 0번 또는 1번 나타나는 패턴)
import re text = "a aa aaa abaa" pattern = r"a?" matches = re.findall(pattern, text) print(matches) # 출력: ['a', '', 'a', 'a', '', 'a', 'a', 'a', '', 'a', '', 'a', 'a', '']
3.
* (앞의 문자가 0번 이상 반복되는 패턴)
import re text = "a aa aaa abaa" pattern = r"a*" matches = re.findall(pattern, text) print(matches) # 출력: ['a', '', 'aa', '', 'aaa', '', 'a', '', 'aa', '']
+ (앞의 문자가 1번 이상 반복되는 패턴)
import re text = "a aa aaa abaa" pattern = r"a+" matches = re.findall(pattern, text) print(matches) # 출력: ['a', 'aa', 'aaa', 'a', 'aa']
📌 ^ $ {number}
특수 문자
설명
^
뒤의 문자열로 문자열이 시작됩니다.
$
앞의 문자열로 문자열이 끝납니다.
{숫자}
숫자만큼 반복합니다.
{숫자1, 숫자2}
숫자1 이상 숫자2 이하만큼 반복합니다. 
?, *, +를 이것으로 대체할 수 있습니다.
{숫자,}
숫자 이상만큼 반복합니다.
1.
^ (문자열의 시작)
import re text = "Hello, World!" pattern = r"^Hello" match = re.search(pattern, text) if match: print("문자열이 'Hello'로 시작합니다.") else: print("문자열이 'Hello'로 시작하지 않습니다.") #문자열이 'Hello'로 시작합니다.
2.
$ (문자열의 끝)
import re text = "Hello, World!" pattern = r"World!$" match = re.search(pattern, text) if match: print("문자열이 'World!'로 끝납니다.") else: print("문자열이 'World!'로 끝나지 않습니다.") # 문자열이 'World!'로 끝납니다.
3.
{숫자} (숫자만큼 반복):
import re text = "Hello, World!" pattern = r"l{2}" matches = re.findall(pattern, text) print("'l'이 2번 반복되는 부분:", matches) # 'l'이 2번 반복되는 부분: ['ll']
4.
{숫자1, 숫자2} (숫자1 이상 숫자2 이하만큼 반복)
import re text = "Hello, World! Look at that cooing dove!" pattern = r"o{1,2}" matches = re.findall(pattern, text) print("'o'가 1번 또는 2번 반복되는 부분:", matches) # 'o'가 1번 또는 2번 반복되는 부분: ['o', 'o', 'oo', 'oo', 'o']
5.
{숫자,} (숫자 이상만큼 반복)
import re text = "Hello, World! Look at that cooing dove!" pattern = r"o{1,}" matches = re.findall(pattern, text) print("'o'이 1번 이상 반복되는 부분:", matches) # 'o'이 1번 이상 반복되는 부분: ['o', 'o', 'oo', 'oo', 'o']
📌 [ ] [^문자] | \d \D \s \S \w \W
특수 문자
설명
[ ]
대괄호 안의 문자들 중 한 개의 문자와 매치합니다.
[amk]라고 한다면 a 또는 m 또는 k 중 하나라도 존재하면 매치를 의미합니다. 
[a-z]와 같이 범위를 지정할 수도 있습니다. 
[a-zA-Z]는 알파벳 전체를 의미하는 범위이며, 문자열에 알파벳이 존재하면 매치를 의미합니다.
[^문자]
해당 문자를 제외한 문자를 매치합니다
l
AlB와 같이 쓰이며 A 또는 B의 의미를 가집니다.
\\
역 슬래쉬 문자 자체를 의미합니다
\d
모든 숫자를 의미합니다. [0-9]와 의미가 동일합니다.
\D
숫자를 제외한 모든 문자를 의미합니다. [^0-9]와 의미가 동일합니다.
\s
공백을 의미합니다. [ \t\n\r\f\v]와 의미가 동일합니다.
space character 의 단축어
• 스페이스( ``)
• 탭(
t)
• 라인 피드 또는 새 줄(
n)
• 캐리지 리턴(
r)
• 폼 피드(
f)
• 수직 탭(
v)
\S
공백을 제외한 문자를 의미합니다. [^ \t\n\r\f\v]와 의미가 동일합니다.
\w
문자 또는 숫자를 의미합니다. [a-zA-Z0-9]와 의미가 동일합니다.
word character 의 단축어
\W
문자 또는 숫자가 아닌 문자를 의미합니다. [^a-zA-Z0-9]와 의미가 동일합니다.
1.
[] : 대괄호 안의 문자들 중 한 개의 문자와 매치
import re text = "Hello, World!" pattern = r"[aeiou]" matches = re.findall(pattern, text) print("모음:", matches)# 출력: ['e', 'o', 'o']
2.
[^문자] : 해당 문자를 제외한 문자를 매치
import re text = "Hello, World!" pattern = r"[^aeiou]" matches = re.findall(pattern, text) print("모음을 제외한 문자:", matches) # 출력: ['H', 'l', 'l', ',', ' ', 'W', 'r', 'l', 'd', '!']
3.
| (파이프): A 또는 B의 의미
import re text = "Hello, World!" pattern = r"Hello|World" matches = re.findall(pattern, text) print("'Hello' 또는 'World':", matches)# 출력: ['Hello', 'World']
4.
\\ (역슬래시): 역슬래시
import re text = "Hello, \\World!" pattern = r"\\" matches = re.findall(pattern, text) print("역슬래시 문자:", matches)# 출력: ['\\']
5.
\d : 숫자
import re text = "Hello, World! 123" pattern = r"\d" matches = re.findall(pattern, text) print("숫자:", matches)# 출력: ['1', '2', '3']
6.
\D : 숫자가 아닌 문자
import re text = "Hello, World! 123" pattern = r"\D" matches = re.findall(pattern, text) print("숫자가 아닌 문자:", matches) # 출력: ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', ' ']
7.
\s : 공백
import re text = "Hello, World! \t123\n" pattern = r"\s" matches = re.findall(pattern, text) print("공백 문자:", matches)# 출력: [' ', ' ', '\t', '\n']
8.
\S : 공백이 아닌 문자
import re text = "Hello, World! \t123\n" pattern = r"\S" matches = re.findall(pattern, text) print("공백이 아닌 문자:", matches)# 출력: ['H', 'e', 'l', 'l', 'o', ',', 'W', 'o', 'r', 'l', 'd', '!', '1', '2', '3']
9.
\w : 문자 또는 숫자
import re text = "Hello, World! 123" pattern = r"\w" matches = re.findall(pattern, text) print("문자 또는 숫자:", matches)# 출력: ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '1', '2', '3']
10.
\W : 문자 또는 숫자가 아닌 문자
import re text = "Hello, World! 123" pattern = r"\W" matches = re.findall(pattern, text) print("문자 또는 숫자가 아닌 문자:", matches)# 출력: [',', ' ', '!', ' ']
3.3 정규표현식을 통한 이메일 주소, URL 검증
📌 이메일 검증
💬
regex = r'^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$'
^[0-9a-zA-Z]
'시작을'  0~9 사이 숫자 or a-z A-Z 알바펫 아무거나로 시작하고
([-_\.]?[0-9a-zA-Z])*
[-_\.]?
중간에 - _  . 같은 문자가 있을수도 있고 없을수도 있으며
[0-9a-zA-Z]
그 후에 0~9 사이 숫자 or a-z A-Z 알바펫중 하나의 문자가 있어야함
→ 그러한 패턴이 0 번 이상 반복 (. 으로 끝날 수는 없다)
@
@ 가 반드시 존재하고
[0-9a-zA-Z]
0-9a-zA-Z 여기서 하나가 반드시 있어야 함.
([-_\.]?[0-9a-zA-Z])*
[-_\.]?
중간에 - _  . 같은 문자가 있을수도 있고 없을수도 있으며
[0-9a-zA-Z]
그 후에 0~9 사이 숫자 or a-z A-Z 알바펫중 하나의 문자가 있어야함
→ 그러한 패턴이 0 번 이상 반복 (. 으로 끝날 수는 없다)
\.
반드시 . 이 있어야 함.
[a-zA-Z]{2,3}$
[a-zA-Z] 의 문자가 2개나 3개가 존재 (대소문자 구분안함)
import re def valid_email(email): regex = r'^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$' valid = re.search(regex, email) if valid: print("Valid email") else: print("Invalid email") email = "mike@korea.co.kr" valid_email(email) # 제대로 된 이메일 email = "mike@daum.net" valid_email(email) # 제대로 된 이메일 email = "mike.j@korea.co.kr" valid_email(email) # 제대로 된 이메일 email = "mysite.com" valid_email(email) # 제대로 된 이메일이 아님 email = "mike@good" valid_email(email) # 제대로 된 이메일이 아님 # Valid email # Valid email # Valid email # Invalid email # Invalid email
📌 URL 검증
url 일반적인 구성 요소
스킴(Scheme): 웹페이지 (http), 보안 웹페이지 (https) 등과 같은 프로토콜을 나타냅니다.
호스트(Host): 도메인 이름 (예: www.example.com) 또는 IP 주소를 포함합니다.
포트(Port): 서버에서 특정 서비스를 제공하는 통신 포트를 나타냅니다 (예: :80, :443 등).
경로(Path): 서버의 파일 경로를 나타냅니다 (예: /path/to/myfile.html).
쿼리(Query): 서버에 제공하는 추가 파라미터 (예: ?key1=value1&key2=value2).
프래그먼트(Fragment): 페이지 내의 특정 부분으로 바로 가기 위한 앵커 (예: #section1).
💬
regex = r'^(https?):\/\/([^:\/\s]+)(:([^\/]*))?((\/[^\s/\/]+)*)?\/?([^#\s\?]*)(\?([^#\s]*))?(#(\w*))?$'
^(https?)
URL의 시작 부분에서 "http" 또는 "https"가 있어야 함.
s? 는 s 가 있거나 없거나 를 의미
:\/\/
:// 가 반드시 존재
([^:\/\s]+)
프로토콜 이후에 /:, 공백이 아닌 문자가 하나 이상 있어야 함
(:([^\/]*))?
선택적으로 포트 번호가 올 수 있습니다.
:로 시작하고 /가 아닌 문자가 0개 이상 올 수 있음.
→ 이러한 패턴이 0번 혹은 1번
((\/[^\s/\/]+)*)?
선택적으로 경로(path)가 올 수 있음.
/로 시작하고
공백(\s), /가 아닌 문자가 하나 이상 올 수 있으며, 이는 0번 이상 반복될 수 있음.
매치될 부분: /path/to/page
\/?
/ 가 0 번 혹은 1번 나올 수 있습니다.
경로의 마지막 슬래시(/) 매치
**http://example.com**과 http://example.com/ 둘 다 유효한 URL 임.
([^#\s\?]*)
쿼리 문자열 또는 프래그먼트 이전에 #, 공백, ?가 아닌 문자가 0개 이상 올 수 있음.
(\?([^#\s]*))?
?로 시작하고 #, 공백이 아닌 문자가 0개 이상 올 수 있음.
선택적으로 쿼리 스트링이 올 수 있음.
?key=value&anotherKey=anotherValue
→ 이러한 패턴이 0번 혹은 1번
(#(\w*))?$
선택적으로 프래그먼트가 올 수 있음.
#로 시작하고 단어 문자(알파벳, 숫자, 언더스코어)가 0개 이상 올 수 있음.
$ : 이것으로 문자열이 끝나야함.
→ 이러한 패턴이 0 번 혹은 1번
Kp
Subscribe to 'kpmg-lighthouse'
Welcome to 'kpmg-lighthouse'!
By subscribing to my site, you'll be the first to receive notifications and emails about the latest updates, including new posts.
Join SlashPage and subscribe to 'kpmg-lighthouse'!
Subscribe
👍🏻
1
😀
1
최윤진
MLE와 MAP로 살펴보는 딥러닝
이번 글에서는 딥러닝을 통계로 이해하는 방법인 MLE와 MAP에 대해서 살펴보겠습니다. 1. MLE MLE는 Maximum Likelihood Estimation의 약자입니다. 가능도(Likelihood) 가능도는 확률과 대비되는 개념입니다. 정육면체의 주사위의 각 면이 나올 ‘확률’은 1/6로 정의할 수 있습니다. 확률을 사용할 수 있는 이유는 확률 분포나 모델이 명확히 정의되어 있기 때문입니다. 특정 데이터가 관찰될 정도는 확률로 표현할 수 있습니다. 반면 가능도는 데이터가 미리 정의된 상황에서 어떠한 확률 분포 혹은 모델이 그것을 설명하는 정도를 측정할때 사용합니다. 예를 들어 형태를 모르는 주사위를 400번 던졌는데 1,2,3,4의 숫자만 100번씩 나온 상황이 있다고 해봅시다. 그렇다면 주사위의 모양은 정육면체가 아니라 정사면체로부터 나올 가능성이 높다고 생각할 수 있습니다. 이러한 정도를 측정할 때 가능도를 사용합니다. 아래 그림에서 특정 점에 위치하는 데이터 x 를 설명할 가능도가 높은 것은 분홍색 확률 분포라고 할 수 있습니다. 확률은 특정 모델이 정해진 상황에서 데이터를 예측하는데 사용하지만, 가능도는 데이터가 관찰된 상황에서 사용하기 때문에 딥러닝과 관련이 있습니다. 딥러닝은 MLE다. 신경망의 가중치들이 올바르게 학습될 수록, 신경망은 데이터를 더 잘 설명할 수 있습니다. 가능도가 커지고 있다고 볼 수 있습니다. 즉, 가능도를 최대화 하는 것(MLE)는 딥러닝의 목표입니다. 가능도 $L(\theta|Data)$는 조건부 확률 $P(Data|\theta)$로 계산하며 MLE 는 아래와 같이 적을 수 있습니다.
😍😀
2
Eunyoung Lee
Llama 3
이번 글에서는 메타의 LLM인 Llama3에 대해 살펴보도록 하겠습니다. LLaMA(Large Language Model Meta AI) 모델 메타의 오픈소스 LLM 모델로 2023년 2월에 Llama1이 처음 발표되었다. 트랜스포머 아키텍처를 기반으로 하며, Llama2의 경우 Llama1에서 학습 데이터를 40% 더 많이 사용하였다. 7B, 13B, 70B 등 여러 파라미터 사이즈의 모델이 존재하며, Alpaca와 Vinuca 같이 수많은 파생 모델이 존재한다. GPT-3와의 차이점 GeLU 대신 SwiGLU 활성화 함수 사용 Swish와 GLU의 조합인 활성화 함수로 실험적으로 성능이 뛰어나서 사용 Swish는 학습 가능한 파라미터인 $β$ 값에 따라 다른 특성을 가지는 활성화 함수 GLU(Gated Linear Units)는 모델이 신경망에서 정보가 흐르는 것을 선택적으로 조절할 수 있도록 해주는 방법 SwiGLU에서 β, W, b는 모두 학습 가능한 파라미터 SwiGLU(x) = x * sigmoid(β * x) + (**1** - sigmoid(β * x)) * (Wx + b) 절대 위치 임베딩 대신 Rotary Positional Embedding(RoPE) 사용 트랜스포머는 위치를 고려 못하기 때문에 위치 임베딩 추가 필요 기존 트랜스포머는 절대 위치 임베딩을 사용하여 위치에 따른 사인함수와 코사인 함수 값을 더하는 방식을 사용 RoPE는 시퀀스의 각 위치마다 고유한 값의 회전을 통하여 절대 위치 임베딩과 상대 위치 임베딩을 통합하는 방법 Root-Mean-Square(제곱평균제곱근) 레이어 정규화 사용 모델이 재스케일링에 영향을 받지 않고, 적절한 학습률을 자동으로 찾아가는 암시적 학습률 적응 능력을 갖게 됨 기본 레이어 정규화에 비하여 계산이 효율적이고 안정적 Grouped Query Attention 사용 기존 Multihead Attention에서는 계산된 key와 value 벡터를 디코딩 단계에 쓸 수 있도록 저장하는 Key-Value caching 때문에 연산에 비용이 많이 소요되고, 디코딩 단계마다 캐시를 로드하고 업데이트 해야 하기 때문에 메모리 오버헤드 발생 Grouped Query Attention은 Query를 그룹으로 나누고 각 그룹이 Key와 Value를 공유하도록 하여 긴 컨텍스트에서 어텐션 계산을 더 빨리 할 수 있도록 함
👍🏻
1
최윤진
DALLE 는 어떻게 이미지를 생성할까 ?
이번 글에서는 텍스트로 이미지를 생성할 수 있는(text to image) 모델인 DALLE에 대해 살펴보도록 하겠습니다. Image Generation 이미지 생성 분야의 경우 2014년 부터 GAN이라는 모델을 기반으로 빠르게 발전해왔습니다. 현재는 사람의 그림과 AI가 생성한 그림을 구분하는 게 불가능에 가까울 정도로 고도화 된 상황입니다. 2022년에는 미드저니라는 이미지 생성 AI 모델의 작품을 이용하여 그림 대회에서 우승한 사건이 있었습니다. DALLE를 살펴보기 앞서, GenAI에 대해 먼저 살펴보도록 하겠습니다. Gen AI Representation 일반적으로는 딥러닝 모델은 데이터의 정답을 기반으로 지도학습을 수행합니다. 개와 고양이를 구분하는 분류 문제를 푸는 경우, 이 과정에서 모델은 서로 다른 클래스의 구분하는 함수를 근사합니다. 오버피팅, 언더피팅이 되지 않고 잘 학습된 모델은 새로운 데이터에 대해서도 올바르게 예측을 할 수 있습니다. 이때 모델을 보고 데이터를 잘 representation 했다고 말합니다. AlexNet은 MNIST 손글씨 데이터셋 대해 잘 분류를 해냈기 때문에 MNIST 손글씨 데이터셋에 대해 좋은 representation 가진 모델이라 할 수 있습니다. Generation 하지만 이런 Representation을 잘한다고 해서 Generation 잘 하지는 않습니다. 영어를 잘 읽고 듣는 사람이, 쓰거나 말하지 못하는 경우와 마찬가지 입니다. 그런 이유로 Generation을 잘 할 수 있도록 모델을 설계하는 분야가 GenAI로써 별도로 존재합니다. GenAI 모델은 representaion Model 의 도움을 받아 생성을 수행할 수도 있으며 단독으로 생성을 학습할 수 도 있습니다.