세포 하나의 유전자 발현량과 캐릭터 대화 한 구간은 전혀 다른 데이터처럼 보인다. 하지만 둘 다 지금의 관측에서 보이지 않는 상태를 읽고, 그 상태가 어디로 가는지 묻는다. 이 시리즈는 그 질문을 하나의 머신러닝 과정으로 다룬다.

$$ \boxed{\text{Observation}\to\text{Representation}\to\text{Geometry}\to\text{Trajectory}\to\text{Dynamics}\to\text{Fate}} $$

세포에서는 발현량으로 세포 상태와 분화 경로를 추정한다. 대화에서는 지금까지의 발화로 이야기 상태와 진행 방향을 추정한다. 두 사례를 같은 수식 옆에 놓되, 같은 수준의 증거가 있다고 가정하지는 않는다. 일반적인 단일세포 발현 측정은 세포를 파괴하므로 같은 세포를 계속 추적한 영상이 아니다. 대화 로그에는 세션 안의 실제 발화 순서가 남는다. 이 관측 방식의 차이가 쓸 수 있는 모델을 바꾼다.

점만 볼 때와 시간을 알 때

점만 볼 때와 시간을 알 때좌표 1좌표 2

교육용 2차원 합성 모식도다. 선은 알고리즘의 추론 결과가 아니라 시뮬레이터가 알고 있는 개체별 순서다. 스냅샷의 색에는 시간·분기 정답이 들어 있지 않다.

위 그림에서 시간을 숨기면 분기 모양은 보이지만 출발점과 이동 방향은 확정할 수 없다. 개체 ID와 시간을 공개하면 어떤 점을 연결해야 하는지 알 수 있다. 앞으로 7강까지는 주로 첫 번째 문제를, 8강부터는 두 번째 문제와 분포의 이동을 다룬다.

누구를 위한 수업인가

대상은 Python 배열 연산을 해 본 CS 학부 3학년 정도다. 내적, 행렬곱, 평균과 분산, 조건부확률, 미분을 알고 있으면 시작할 수 있다. 생물학 전공 지식은 필요하지 않다. 고유벡터는 2강에서 복습하고, 확률적 미분방정식과 인과추론의 세부 증명은 심화 읽기로 남긴다.

1–10강은 약 90분을 기준으로 설계했다. 설명 60분과 실습·토론 30분을 기본으로 배분하고, 연속 동역학을 다루는 11강은 100분, 마지막 통합 강의는 110분을 잡는다. 매번 문제와 작은 그림을 먼저 보고, 수식과 알고리즘을 세운 다음 Python으로 확인한다. 마지막에는 Bio와 character-chat에 어떻게 옮길지, 무엇을 아직 주장할 수 없는지 묻는다. 글은 강의용 원고이며 외부 강의의 번역이나 녹취가 아니다.

12강 지도

강의질문핵심 방법공통 프로젝트의 산출물
1. 관측과 숨은 상태점 하나가 무엇을 뜻하나?관측 모델, 식별 가능성데이터 계약과 평가 분리
2. PCA무엇을 잃으며 압축하나?공분산, 고유벡터, SVD투영과 재구성 오차
3. 표현학습휘어진 구조를 어떻게 담나?Autoencoder, VAE학습된 잠재 좌표
4. 매니폴드가까움의 기준은 무엇인가?kNN, Isomap, UMAP이웃 관계 비교
5. 확산과 스펙트럼지역 연결이 어떻게 전체 구조가 되나?Laplacian, Diffusion Map확산 좌표와 시간 척도
6. 군집과 커뮤니티상태의 경계를 어디에 긋나?k-means, DBSCAN, Louvain, Leiden해상도에 따른 상태 묶음
7. 경로 추론점을 경로로 어떻게 연결하나?MST, Principal Graph, PAGAroot에 의존하는 의사시간
8. 순차 모델관측 순서가 있으면 무엇이 달라지나?Markov, HMM, State Space Model전이와 숨은 상태 추론
9. 속도와 벡터장지금 어디로 움직이나?RNA Velocity, 회귀 벡터장다음 상태 예측과 오차
10. 분포의 이동개체 짝이 없어도 이동을 추정할 수 있나?Optimal Transport, Sinkhorn주변분포를 맞추는 수송 계획
11. 연속 동역학연속적인 이동 규칙을 학습할 수 있나?Neural ODE/SDE, Flow Matching벡터장을 적분한 분포
12. 결과와 인과무엇을 예측하고 무엇을 바꿀 수 있나?Survival, Fate Prediction, Causal Inference검열을 고려한 분석과 효과 추정

핵심 구현은 CPU에서 실행하는 작은 예제다. 모든 소개 방법을 처음부터 구현하지는 않는다. 예를 들어 7강 코드는 centroid MST 기준선이고 PAGA의 재구현이 아니다. 각 강의는 직접 구현하는 범위와 개념으로 배우는 확장을 구분한다.

실습 시작

실습 전체 ZIP 받기. 압축을 풀면 common.py, lesson01.py부터 lesson12.py, 실행기와 패키지 목록이 같은 폴더에 있다. Python 3.12 가상환경에서 다음 명령을 실행한다.

python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python run_all.py --output outputs

Windows에서는 활성화 명령만 .venv\Scripts\activate로 바꾼다. 패키지 설치에는 인터넷이 필요하지만, 실습은 외부 데이터나 API 키를 사용하지 않는다. GPU도 필요 없다. UMAP의 첫 실행은 컴파일 때문에 시간이 더 걸릴 수 있다.

python lesson02.py --output outputs
python run_all.py --lessons 2 5 7 --output outputs

그림과 수치는 outputs/에 저장된다. 검증 실행 결과는 사용한 Python·패키지 버전과 지표를 함께 기록한다. 난수 시드를 고정해도 BLAS나 운영체제에 따라 작은 수치 차이가 생길 수 있다. 고유벡터의 부호가 뒤집히는 것만으로 실패라고 판단하지 않는다.

매주 재사용할 데이터

공통 합성 데이터 NPZ도 바로 받을 수 있다. numpy.load("branching-trajectories.npz", allow_pickle=False)로 연다. 실습 생성기 기본값과 같은 데이터다.

시뮬레이터는 120개 개체를 각각 16시점에 관측한다. 따라서 행은 1,920개이고, 각 행의 관측 특징은 24개다. 알려진 2차원 분기 경로를 비선형 함수와 고정된 혼합 행렬로 옮긴 뒤 작은 잡음을 더한다. 실제 유전자 수나 언어 임베딩 차원보다 작은 이유는 모델의 동작을 노트북에서 확인하기 위해서다.

필드단위와 의미사용 범위
X1,920 × 24 관측 행렬모델 입력
z_true시뮬레이터의 2차원 상태그림·정답 비교 전용
time, session, next_index시점, 개체 ID, 다음 행 번호순차 실습, 마지막 행은 -1
branch행별 분기 부호 −1 또는 +1사후 평가용 정답
train세션 전체가 같은 분할에 속하는 행 마스크90개 학습 / 30개 평가 세션
fate세션별 마지막 분기, 0 또는 1결과 예측의 정답
duration, event세션별 추적 기간, 사건 관측 여부오른쪽 검열이 있는 생존분석
baseline, treatment, outcome처치 전 위험도, 무작위 처치, 후속 연속 결과인과추론 실습

duration의 시계는 16프레임 관측 구간이 끝난 다음 시작한다. 앞의 time은 0에서 1까지의 경로 시계다. 두 시계를 섞어 이미 이탈한 사람의 미래 프레임을 본 것처럼 분석하지 않는다. 12강에서는 경로의 앞부분만으로 fate를 예측하는 문제와, 별도의 후속 사건·처치 효과 문제를 나누어 푼다.

합성 처치 결과는 $Y=0.7B+0.8A+\epsilon$로 만든다. $A$는 무작위 배정이다. 따라서 이 세계의 평균 처치효과는 0.8이며 추정값을 정답과 비교할 수 있다. 이것은 실제 프롬프트의 효과가 0.8이라는 주장이 아니다. 원래 캐릭터 대화나 세포 데이터를 모사한 벤치마크라는 주장도 하지 않는다.

프로젝트를 평가하는 기준

예쁜 2차원 그림만으로 점수를 주지 않는다. 학습 목표마다 다른 검사를 붙인다.

목표확인할 것부족한 증거
표현평가 세션의 재구성 오차, 이웃 보존군집이 예쁘게 떨어진 그림
경로root 변화, 이웃 수 변화, 알려진 순서와의 일치의사시간 하나의 높은 상관
동역학다음 시점 예측과 여러 단계 rollout학습 데이터의 화살표
분포주변분포 오차, 수송 비용, held-out 분포한 개체의 이동을 맞췄다는 해석
결과분리된 세션의 Brier score·보정, 검열 고려accuracy 하나
인과무작위 배정 또는 식별 가정과 불확실성상태와 이탈의 상관

학습용 표준화와 PCA도 평가 세션을 보면 안 된다. 특히 이른 시점의 예측에서는 미래 프레임을 이용한 표현 선택까지 점검한다. 이 원칙의 구현상 이유는 scikit-learn의 데이터 누수 안내에서 더 볼 수 있다.

마지막 과제: 실제 대화로 옮기기

사용 권한을 확보하고 식별 정보를 제거한 대화, 또는 직접 만든 공개 가능한 대화를 쓴다. 분석 단위는 메시지 하나 또는 직전 몇 턴의 창으로 고정한다. 각 특징은 해당 시점까지의 텍스트만 사용한다. 전체 세션을 요약한 문장을 초기 상태의 입력으로 넣으면 결말이 새어 들어간다.

사용자나 캐릭터가 여러 세션에 걸쳐 반복되면 세션 분리만으로 충분하지 않을 수 있다. 보고서에는 사용자·캐릭터·시간 중 어떤 축으로 평가 데이터를 분리했는지 적는다. 단순한 대화 길이 기준선과 비교하고, 토픽 전환을 감정 변화로 오해한 사례도 검토한다.

제출물은 질문과 데이터 계약 1쪽, 재현 가능한 코드, 핵심 그림 3개, 실패 사례 2개, 결과의 한계 1쪽이다. 평가 비중은 문제·데이터 정의 20%, 누수 없는 평가 25%, 방법과 기준선 25%, 해석과 실패 분석 20%, 재현성 10%다. 세포 쪽 프로젝트를 선택하면 세션 대신 donor·batch의 분리를 검토하고, 실제 lineage tracing과 추론 경로를 구분한다.

첫 단계는 1강: 관측값과 숨은 상태다. 이후의 알고리즘을 외우기 전에, 우리가 가진 행 하나가 무엇을 관측한 것인지부터 정한다.