본문 바로가기
데이터 사이언스

Claude 를 참고하여 신약개발경진대회 Baseline code 분석하기

by 빛나는존재 2024. 9. 17.

Baseline code 를 봐도 코드 뜻을 모르는 경우 

데이콘에서 기본적으로 모든 신약개발경진대회 참가자들에게 Baseline code 를 준다. 하지만 이는 도메인 지식이 없는 사람이 봤을 때에는 이게 대체 무슨 코드인지 모를 수 있는 부분이 있다. 나 역시 해당 도메인에 종사하지는 않고 단지 학부때 전공이 관련이 있고 며칠 전 LAIDD 에서 진행 하는 신약개발 부트캠프 3일간 풀데이로 참여했을 뿐이다. (참고로 다녀오고 나서 몸살 걸렸다..) 그나마 그 부트캠프를 통해 도메인 지식을 알게 되었고 어떤 코드가 어떤 도메인 지식에 해당하는지에 대해 알게 되었는데 다른 참가자들은 충분히 모를 수 있다. 따라서 그분들 입장이라면 어떻게 했을까 궁금해서 혹시 Claude 로 경진대회에 대해 설명하고 Baseline code 를 설명해 달라고 하면 제대로 해주려나 싶어서 실험삼아 해봤다.

 

Prompt 작성하기

Claude 에서 새 프로젝트를 생성하여 Project 에 대한 description 을 적었다.

Prompt 는 아래와 같이 영어로 적었다.

Below is the sample code gained as a baseline knowledge from the competetion event provider. Provide me with line-by-line interpretation.

라는 질문과 함께 그 밑에 baseline code 를 전부 복사 붙여넣기 해서 붙여넣었더니 claude 나름 line-by-line 으로 code 해설 해줬다.

def smiles_to_fingerprint(smiles):
    mol = Chem.MolFromSmiles(smiles)
    if mol is not None:
        fp = AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=CFG['NBITS'])
        return np.array(fp)
    else:
        return np.zeros((CFG['NBITS'],))

이 프롬프트에서 나온 Claude 의 설명은 너무 일반적이어서 크게 도움은 안되어서 그냥 신약개발 부트캠프 때 들었던 강의 자료를 참고하며 다음과 같이 이해했다.

 

이 smiles_to_fingerprint 라는 이름의 사용자 지정 함수는 smiles 형식의 화합물 데이터를 fingerprint 로 바꿔주는 역할을 하고 만약 없으면 0 값이 들어있는 vector return 하도록 되어 있다.

 

신약개발 도메인지식: SMILES? 웃으라는 뜻인가?

Smiles 형식이란 무엇이고 왜 이것을 fingerprint 로 바꿔주어야 하냐 하는 질문이 들 수 있다. 이에 대해서는 LAIDD 에서 주최하는 신약개발 부트캠프에서 먼저 들은 바가 있는데, SMILES Simplified Molecular Input Line Entry System 의 약자로, 약물 후보가 되는 화합물 분자의 복잡한 구조를 원자를 표현하는 알파벳과 그것들이 연결된 형태를 기호를 이용하여 텍스트로 표현을 한 것이다. 하지만 SMILES 표기법에는 한계가 있다.

1) 한 분자 화합물을 대표하는 SMILELS 표기법이 표준화 되어 있지 않는 경우가 있다. 따라서, 한 분자를 표현하는 SMILES표기가 여러개이다.

2) 2D, 3D 좌표가 없어서 MOL, SDF 등의 부가적인 데이터가 필요하다.

 

이러한 이유등으로 인해 SMILES 표기는 너무 단순화 된 표기법이라, 이것만으로는 분자 화합물의 구조를 Computer 가 알기 어려워 molecular descriptor 로 표기하여 숫자들로 한 분자의 특성을 표현해야 분석이 가능하다.

 

Molecular descriptor, 분자 구조 및 특성을 숫자들의 집합으로 나타낸 것으로 화학적 특성, 생화학적 activity, 물리적 특징을 예측하기 위해 사용된다. 이 중에는 그 유명한 ECFP 도 포함되어 있다. Extended Connectivity FingerPrint의 약자로, 사람이 마치 개인의 지문이 본인임을 특정하는 것 처럼, 특정 분자 화합물이 나는 이런 특성을 갖고 있고 이게 유일하게 분자 화합물을 대표하는 1:1 매칭이 되도록 한 것이다. ECFP 로 나타내는 2가지 parameter로는 radius (diameter 가 아닌 radius 를 사용한다!), nBits 가 있다.

 

이 코드에서는 제공된 train data 를 읽어다가 SMILES 로 표기된 기존의 data 를 위에서 정의 된 함수를 apply 하여 fingerprint 형태로 변환된 데이터가 들어간 column 을 추가한다.

train = chembl_data[['Smiles', 'pIC50']]
train['Fingerprint'] = train['Smiles'].apply(smiles_to_fingerprint)

Train_x, train_y 도 이렇게 정의한 후

train_x, val_x, train_y, val_y = train_test_split(train_x, train_y, test_size=0.3, random_state=42)

이렇게 train_test_split 함수를 사용하여 random 하게 train data 으로부터 validation set split 한다.

model = RandomForestRegressor(random_state=CFG['SEED'])
model.fit(train_x, train_y)

def pIC50_to_IC50(pic50_values):
    """Convert pIC50 values to IC50 (nM)."""
    return 10 ** (9 - pic50_values)

val_y_pred = model.predict(val_x)
mse = mean_squared_error(pIC50_to_IC50(val_y), pIC50_to_IC50(val_y_pred))
rmse = np.sqrt(mse)
print(f'RMSE: {rmse}')

여기가 제일 우리가 optimize 해야 할 부분이다. 여기서는 엄청 나이브하게 random forest regressor 를 사용하여 그 어떠한 hyperparameter tuning 도 없이, Automl 도 사용하지 않고 그냥 1번만 모델 피팅을 하긴 한수준으로만 진행 했다. 이 코드는 어디까지나 예시이고 참가자인 우리는 이 부분을 중점적으로 파고들어서 XGBoost 가 좋을지 아니면 딥러닝으로 할 지, 딥러닝으로 하면 layer는 몇 개 쌓아야 하고 layer 마다 어떤 특징을 갖게 할 것인지 고민고민하고 여러가지의 조합을 테스트 해봐야 한다.

참고로 저 코드에는 ‘pIC50_to_IC50’ 이라는 함수가 쓰였는데 우리에게 주어진 dataIC50_nM, pIC50 둘 다 있는데 이걸 왜 바꿔줘야 하고 수식은 왜 저렇게 되어있는지는 좀 더 공부해야 알겠다. (Claude 에 이런 걸 상세 질문하면 더 자세히 답해준다.)

test = pd.read_csv('./test.csv')
test['Fingerprint'] = test['Smiles'].apply(smiles_to_fingerprint)
test_x = np.stack(test['Fingerprint'].values)
test_y_pred = model.predict(test_x)

 

Model 을 만들었으면 이것으로 test data 를 이용하여 IC50 값을 예측한다. 이 때 test data 에서도 앞서 만든 smiles_to_fingerprint 함수를 이용하여 smiles fingerprint 로 바꾼 후 이를 입력으로 받아 model.predict 로 예측대상을 예측한다.

 

Claude 에서 Baseline code 복사 붙여넣기 한 것을 line-by-line 으로 설명해 달라고 한 것은 딱 1번 질문한 것으로, 깊이없는 일반적인 대답이 나와서 크게 도움은 안되었지만, 여기서 특정 코드를 다시 복사 붙여넣기 하여 이 코드에 대해 더 자세히 물어보면 그에 대한 설명을 해줄 것이다. 

 

예를 들어, 아래와 같은 프롬프트를 추가로 작성했더니 claude가 굉장히 상세하게 답변을 해줬다.

프롬프트에서는 왜 smiles 를 fingerprint 로 전환해야 하는지, 그리고 애초에 smiles 는 뭐고 fingerprint는 뭐냐고 물어봤다.

아래는 이에 대한 claude 의 답이다. 내가 원하는 정보를 이제 보다 상세한 레벨로 설명하고 있다. 이렇게 질문을 한 번 하고 너무 일반적인 답변이다 싶으면 거기서 더 파고드는 질문을 하면 이렇게 아래처럼 상세한 답변을 받아볼 수 있다. 그리고 꽤 내가 알고 있는 것과 일치해서 어느정도 도움이 되겠다 싶었다. 여기서 조금이라도 미심쩍으면 정말로 그런 개념이 있는지 구글링 하면 다 나오게 되어 있다. Claude 같은 생성형 AI가 주는 정보는 참고만 하고 다 믿으면 안된다. 이걸 기초로 해서 현실에서 이런 개념이 있는지 확인하면서 자신의 지식 범위를 확장하는 용도로 쓰면 좋을것 같다.

반응형