보안이 뛰어난 비밀번호인지 검증하기 (난이도: 상)
보안이 뛰어난 비밀번호는 일반적으로 아래와 같은 조건들을 만족해야 합니다.
주어진 비밀번호들이 위의 조건들을 만족하는지 검증하고, 만족하면 True / 만족하지 않으면 False를 반환하는 함수를 작성해보도록 합시다.
import re
def MyFunction(password:str)->bool:
password_checker = re.compile("^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,30}$" )
mat = re.search(password_checker, password)
return bool(mat)
def myFunction(text):
# 문장(text) 중 slang_list에 있는 단어들이 포함되어있으면, 단어를 별표(*) 치환하는 코드를 작성해주세요!
for word in slang_list:
if word in text:
text = text.replace(word,'*'*len(word))
return text
def myFunction(text):
for word in slang_list:
if word in text:
text = text.replace(word,'*'*len(word))
for char_idx,char in enumerate(word):
for special_token in ['@','@@']:
special_word = word[:char_idx]+special_token+word[char_idx:]
if special_word in text:
text = text.replace(special_word,'*'*len(special_word))
return text
import re
def MyFunction(text):
# 이곳에 코드를 작성해주세요!
jaeum_list = ['ㄱ','ㄲ','ㄴ','ㄷ','ㄸ','ㄹ','ㅁ','ㅂ','ㅃ','ㅅ','ㅆ','ㅇ','ㅈ','ㅉ','ㅊ','ㅋ','ㅌ','ㅍ','ㅎ']
moeum_list = ['ㅏ','ㅑ','ㅓ','ㅕ','ㅗ','ㅛ','ㅜ','ㅠ','ㅡ','ㅣ','ㅘ','ㅚ','ㅙ','ㅜ','ㅟ','ㅝ','ㅢ']
jamo_checker = re.compile('['+''.join(jaeum_list)+''.join(moeum_list)+']+')
new_text = re.sub(jamo_checker,'',text)
return new_text
def make_clean_wiki_page(crawled_page:List[str]):
# 이곳에 전처리 코드를 작성해주세요!
sents = [re.sub(r'\(.*?\)', "", (re.sub(r'\<.*?\>', "", sent))).strip() for sent in crawled_page]
return sents
도메인 특화 task의 경우, 도메인 특화 된 학습 데이터만 사용하는 것이 성능이 더 좋다.
BERT의 [CLS] token vector를 classification하는 Dense layer 사용
주어진 2개의 문장에 대해, 두 문장의 자연어 추론과 의미론적인 유사성을 측정하는 task
Natural Language Inference(NLI)
Semantic text pair
BERT를 활용한 두 문장 관계 분류 방법
1. Sent A와 Sent B의 [CLS] token 임베딩 값을 이용해 유사도 비교
분류의 대상이 되는 모든 문장들을 미리 임베딩하여 저장, inference 대상이 되는 문장 1개만 임베딩하여 비교
2. [SEP] token을 이용해 두 문장 관계 분류 학습
문장의 관계 분류를 위해 학습된 모델로, 좋은 성능이 나타날 수 있습니다. 하지만, inference 시, 모든 조합들을 새롭게 계산해야하여 시간이 오래걸릴 수 있습니다.
3. Sentence BERT
동일한 BERT 모델이 각각의 Sent A, Sent B를 임베딩하여, 임베딩 벡터를 이용해 분류 혹은 유사한 정도를 예측하도록 학습, 결과적으로 BERT 모델이 문장의 의미를 더 정확하게 임베딩할 수 있도록 학습
주어진 문장의 각 Token이 어떤 범주에 속하는지 분류하는 task
문장 토큰 분류 모델을 학습하기 위해서는 형태소 단위의 토큰을 음절 단위의 토큰으로 분해하고, Entity tag 역시 음절 단위로 매핑시켜 주어야 한다.
Greedy Search
Beam Search
beam_output = model.generate(
input_ids,
max_length=50,
num_beams=5,
early_stopping=True
)
Greedy와 Beam Search 방식은 Word sequence를 반복하는 문제를 포함합니다.
단순한 해결법은 Paulus et al. (2017)과 Klein et al. (2017)의 논문에서 제안된 n-grams 패널티를 도입하는 것입니다. 가장 일반적인 n-grams 패널티는 이미 나타난 n-gram에 대해 다음 단어로 생성될 확률을 0으로 설정하여 두번 나타나지 않도록 하는 방법입니다.
no_repeat_ngram_size=2을 설정한다면 2-gram이 두번 나타나는 것을 막을 수 있습니다.
beam_output = model.generate(
input_ids,
max_length=50,
num_beams=5,
no_repeat_ngram_size=2,
early_stopping=True
)
n-gram 패널티는 신중하게 사용되어야 합니다. 예를 들면 city New York에 대해 생성된 기사는 n-gram을 사용하지 않는 것이 좋습니다. 2-gram을 사용하게 될 경우 시의 이름이 전체 텍스트에서 한 번만 나타나기 때문입니다.
Beam search의 또 다른 중요한 특징은 생성된 Top beam을 비교하여 목적에 가장 적합한 Beam을 선택할 수 있다는 것입니다.
Transformer에서 num_return_sequences 파라미터를 return 해야 하는 최대 num_beams 보다 작거나 같도록 설정합니다. num_return_sequences <= num_beams로 설정된 코드를 확인할 수 있습니다.
beam_outputs = model.generate(
input_ids,
max_length=50,
num_beams=5,
no_repeat_ngram_size=2,
num_return_sequences=5,
early_stopping=True
)
"""
Output:
----------------------------------------------------------------------------------------------------
0: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.
I've been thinking about this for a while now, and I think it's time for me to take a break
1: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.
I've been thinking about this for a while now, and I think it's time for me to get back to
2: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with her again.
I've been thinking about this for a while now, and I think it's time for me to take a break
3: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with her again.
I've been thinking about this for a while now, and I think it's time for me to get back to
4: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.
I've been thinking about this for a while now, and I think it's time for me to take a step
"""
Beam search은 반복 생성 문제에 취약합니다. 특히 Story Generation Task에서 n-gram또는 기타 패널티를 통해 문장을 제어하는 것이 어렵습니다. 왜냐하면 "반복이 없는 구문"과 "n=gram반복 주기" 사이에서 적당한 trade-off를 찾기 위해 많은 finetuning이 필요하기 때문입니다.
Beam search는 Machine translation 또는 Text summarization처럼 원하는 문장 생성 길이가 예측 가능한 Task에서는 잘 작동할 수 있습니다. 하지만 Dialog 또는 Story Generation Task처럼 출력길이가 크게 달라질 수 있는 개방형 생성에서는 원활하게 작동하지 않습니다. ( Murray et al. (2018), Yang et al. (2018))
Ari Holtzman et al. (2019) 논문에 따르면 고품질 인간 언어는 높은 확률의 다음 단어 분포를 따르지 않는다고 주장합니다. 쉽게 말하자면 인간입장에서 우리는 지루하거나 예측 가능한 문장이 아니라 우리를 놀라게 할 수 있는 문장생성을 원한다고 합니다. 저자는 모델이 인간 텍스트 대비 beam search text를 그래프로 보여주면서 beam search text가 그다지 놀랍지 않은 문장이라는 것을 보여줬습니다.
Sampling
sample_output = model.generate(
input_ids,
do_sample=True, # 완전 random sampling
max_length=50,
top_k=0 # w/o top_k 추출
)
흥미롭게도 본문은 괜찮은 것 같지만 자세히 보면 매우 일관성 없는 문장입니다. 3-grams의 new hand sense 와local batte harness 라는 문장은 이상하고 사람이 쓴것처럼 보이지 않습니다. 이것은 sampling word sequences를 할때 모델이 일관성없이 횡설수설하는 문장을 발생시키는 큰 문제입니다. (Ari Holtzman et al. (2019)).
한가지 트릭은 softmax. 의 이른바 temperature를 낮추어 분포 P(w|w1:t−1) 를 더 선명하게 만드는 것입니다. 높은 확률의 단어의 가능성은 증가시키고 낮은 확률의 단어 가능성은 감소시키는 효과가 있습니다.
sample_output = model.generate(
input_ids,
do_sample=True,
max_length=50,
top_k=0,
temperature=0.7
)
Top-K Sampling
지금까지 기법중 가장 인간적으로 보이는 텍스트를 생성했습니다. Top-K Sampling의 한 가지 우려되는 점은 다음 단어 확률 분포 P(w|w1:t−1) 에서 필터링된 단어 수를 동적으로 조정하지 않는 점입니다. 예를들면 위 그림에서 첫번째 step의 단어들은 전반적으로 평평한 분포에서 Sampling 되지만, 두번째 step의 어떤 단어들은 매우 Sharp한 분포에서 Sampling 될 수 있기 때문에 문제가 될 수 있습니다.
Step t=1 에서 Top-K은 꽤 합리적인 후보처럼 보이는 "people", "big", "house", "cat" 을 샘플링하는 가능성을 배제합니다. 반면에 Step t=2 에서 단어 Sample pool에 단어 "down", "a" 와 같은 부적절한 단어를 포함합니다. 그러므로 Sample pool이 고정크기 K로 제한되면 모형이 Sharp한 분포에서 횡설수설한 단어를 고를 위험이있고 평평한 분포에서는 문장의 창의성이 제한될 수 있습니다. (Ari Holtzman et al. (2019))
Top-p (nucleus) sampling
Conclusion
XLNet
RoBERTa
BART
T-5
Meena
Controllable LM
출처 : 네이버 커낵트 부스트캠프