VAE 신약 분자 생성 #4 전체 파이프라인 #
#2026-02-28
#1 전체 파이프라인 정리
MUV 데이터셋 (SMILES 문자열들)
↓ train_dataset.ids
train_smiles = ['CCO', 'CC(=O)...', ...]
↓ 문자 집합 + 최대 길이 계산
tokens = ['#', '(', ')', '=', 'C', 'N', 'O', ...]
max_length = 120
↓ AspuruGuzikAutoEncoder(tokens, max_length)
모델 구조:
인코더: 문자 시퀀스 → GRU×3 → μ(196), σ(196)
샘플링: z = μ + ε·σ (ε ~ N(0,1))
디코더: z → GRU×3 → 문자 확률 분포
↓ fit_sequences(generate_sequences(50))
학습: (SMILES, SMILES) 쌍 50 에포크
손실: 재구성 손실 + KL 발산
↓ predict_from_embeddings(np.random.normal(size=(1000,196)))
1000개 랜덤 z 샘플링 → 디코딩 → SMILES 문자열
↓ Chem.MolFromSmiles() 유효성 검증
유효한 분자만 필터링 → 새로운 분자 목록 출력
데이터셋은 MUV 데이터셋의 수만 개 분자다. 각 분자는 SMILES라는 문자열로 표현되어 있다. CCO, CC(=O)Oc1ccccc1C(=O)O 같은 문자열들이다. 이 문자열들이 train_dataset.ids에 담겨 있다.
이 문자열들을 모델에 넣으려면 먼저 “이 데이터에 어떤 글자들이 등장하는가"와 “가장 긴 문자열이 몇 글자인가"를 알아야 한다. 모든 SMILES를 훑어서 등장하는 고유 문자를 모으면 토큰 집합이 만들어진다. C, N, O, =, (, ) 같은 문자들이다. 이걸 정렬해서 순서를 고정하면 모델의 어휘가 완성된다. 가장 긴 SMILES의 길이가 120이라면, 모든 문자열을 120 길이로 패딩해서 입력 크기를 통일한다.
이 두 정보를 AspuruGuzikAutoEncoder에 넘기면 모델이 구성된다. 인코더 쪽에는 3층 GRU가 SMILES를 순서대로 읽어서 196차원의 μ와 σ를 내놓고, 재파라미터화 트릭으로 잠재 벡터 z를 샘플링한다. 디코더 쪽에는 3층 GRU가 z에서 SMILES를 한 글자씩 복원한다. 학습률은 0.001에서 시작해서 에포크마다 5%씩 줄어드는 ExponentialDecay를 쓴다.
학습은 generate_sequences라는 제너레이터가 (SMILES, SMILES) 쌍을 50 에포크 동안 공급하는 방식으로 진행된다. 같은 문자열을 입력으로도 정답으로도 주는 오토인코더 학습이다. 손실 함수는 재구성 손실(복원이 얼마나 정확한가)과 KL 발산(잠재 공간이 얼마나 규칙적인가)의 합이다. 이 두 힘이 균형을 이루면서, 모델은 분자를 정확히 복원하는 능력과 잠재 공간의 규칙성을 동시에 확보해나간다.
학습이 끝나면 생성 단계로 넘어간다. 표준 정규분포에서 196차원 벡터 1,000개를 랜덤으로 뽑아서 디코더에 넣으면, 1,000개의 SMILES 문자열이 한 글자씩 자기회귀적으로 생성된다. RDKit의 MolFromSmiles가 각 문자열의 화학적 유효성을 검증해서, 실제로 존재할 수 있는 분자만 걸러낸다.
#
#2 VAE가 일반 오토인코더보다 나은 이유
일반 오토인코더의 인코더는 각 분자를 잠재 공간의 하나의 고정된 점에 매핑한다. 학습이 잘 되면 그 점에서 디코딩하면 원래 분자가 나온다. 하지만 학습된 점들 사이의 빈 공간에서 디코딩하면 쓰레기가 나온다. 잠재 공간에 지도가 없는 셈이다.
VAE는 두 가지를 바꾼다. 첫째, 인코더가 점이 아닌 분포를 내놓고 거기서 샘플링한다. 덕분에 디코더가 한 점이 아니라 그 주변 영역 전체에서 올바르게 작동하도록 학습된다. 둘째, KL 발산이 모든 분포를 N(0,1) 근처로 모은다. 덕분에 잠재 공간 전체가 균일하게 채워져서 빈 곳이 사라진다.
이 두 가지가 합쳐진 결과가 바로 잠재 공간의 연속성과 규칙성이다. 그리고 이 성질이 VAE를 단순한 압축기가 아닌 생성기로 만들어주는 핵심이다.
| 항목 | 오토인코더 | 변분 오토인코더 |
|---|---|---|
| 잠재 벡터 | 결정론적 점 | 확률 분포 (μ, σ) |
| 잠재 공간 | 불규칙, 빈 곳 있음 | 균일하고 연속적 |
| 랜덤 샘플링 | 의미 없는 결과 가능 | 유효한 분자 생성 가능 |
| 학습 손실 | 재구성 손실만 | 재구성 손실 + KL 발산 |
| 분자 보간 | 불연속 점프 | 부드러운 전환 가능 |
#
#3 잠재 공간 보간(interpolation)
VAE의 잠재 공간이 연속적이라는 성질에서 아주 흥미로운 가능성이 열린다. 잠재 공간에서의 보간(interpolation)이다. 알려진 약물 분자 A의 SMILES를 인코더에 넣으면 잠재 벡터 zA가 나온다. 다른 약물 분자 B를 넣으면 zB가 나온다. 이제 zA와 zB의 정확히 중간 지점, 0.5 × zA + 0.5 × zB를 계산해서 디코더에 넣으면 어떻게 될까?
일반 오토인코더라면 이 중간 지점이 빈 공간일 수 있어서 쓰레기가 나올 가능성이 높다. 하지만 VAE에서는 잠재 공간이 연속적이므로, 이 중간 지점에서도 유효한 분자가 나올 가능성이 높다. 그리고 그 분자는 A와 B의 중간 성질을 가질 것이다. A가 항염증 효과가 강하고 B가 항균 효과가 강하다면, 중간 지점의 분자는 두 효과를 어느 정도 다 가진 분자일 수 있다.
분자 A의 잠재 벡터: zA
분자 B의 잠재 벡터: zB
z_mid = 0.5 × zA + 0.5 × zB → 디코딩
→ A와 B의 중간 성질을 가진 새 분자
이걸 더 발전시키면, zA에서 zB로 가는 경로를 잘게 나눠서 여러 중간 지점을 만들 수 있다. 각 지점을 디코딩하면 A에서 B로 서서히 변해가는 분자들의 연속체가 나온다. 이건 마치 색상 팔레트에서 빨강과 파랑 사이를 부드럽게 전환하면 보라색 계열이 나오는 것과 같다. 분자의 성질이 한쪽 극단에서 다른 극단으로 부드럽게 변하는 것이다.
이것이 VAE 기반 분자 설계의 핵심적인 응용이다. 이미 알려진 약물들 사이의 잠재 공간을 체계적으로 탐색하면서, 기존 약물의 좋은 성질을 조합한 새로운 후보 분자를 발견할 수 있다. 10의 60제곱이라는 방대한 화학 공간을 무작위로 탐색하는 대신, 196차원의 잘 정돈된 잠재 공간에서 의미 있는 방향으로 이동하며 탐색하는 것이다. 차원의 저주를 잠재 공간의 규칙성으로 극복하는 전략인 셈이다.
이것이 VAE 기반 분자 설계의 핵심 아이디어다: 알려진 두 약물 사이를 잠재 공간에서 탐색 → 새로운 후보 분자 발견
#
#3 이전 DNA 분석과의 비교
데이터 표현 방식은 일관된다. DNA는 A, C, G, T 네 글자를 원-핫으로 바꿨고, SMILES는 수십 종의 토큰을 역시 숫자로 바꿨다. 어떤 종류의 데이터든 결국 숫자 배열로 변환해서 신경망에 넣는다는 원칙은 동일하다.
시퀀스 처리 도구는 문제에 맞게 달라진다. DNA의 모티프는 위치 독립적이고 국소적이어서 Conv1D가 적합했다. SMILES의 문법 구조는 순서 의존적이고 장거리 의존성이 있어서(괄호 열기와 닫기, 고리 번호 매칭) GRU가 적합했다. 망막 이미지는 2차원 공간 패턴이어서 Conv2D 기반의 ResNet이 적합했다. 도구는 다르지만 “입력 데이터의 구조적 특성에 맞는 신경망을 선택한다"는 설계 원칙은 항상 같다.
가장 큰 차이는 문제의 성격이다. 이전 분석들은 모두 판별 문제였다. 입력이 주어지면 레이블이나 수치를 예측했다. 이 분석 생성 문제다. 잠재 공간에서 새로운 것을 만들어낸다. 판별에서 생성으로의 전환은 딥러닝의 응용 범위가 “분류와 예측"을 넘어 “창조"의 영역으로 확장되는 것을 보여준다. 그리고 그 확장을 가능하게 만든 핵심 아이디어가 바로 잠재 공간의 규칙화, 즉 KL 발산이라는 단 하나의 항을 손실 함수에 추가한 것이라는 점이 놀랍다.