기술나눔

[머신러닝 실전 전투] Datawhale 여름 캠프: 기본 집중 읽기 노트 2

2024-07-08

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

# AI 여름 캠프 # Datawhale # 여름 캠프

원래 기준선에 대한 교차 검증 외에도 기능 엔지니어링이라는 핵심 최적화 방법도 있습니다.

특징을 최적화하는 방법은 모델 예측의 정확성을 향상시키는 방법과 관련이 있습니다. 특성 추출은 변환에 대해 생각해야 하기 때문에 문제 영역에 대한 깊은 이해를 가진 사람이 잘 할 수 있는 부분인 경우가 많습니다.

Smiles 기능 외에도 귀중한 정보를 추출할 수 있는 기능이 많이 있습니다. 예를 들어 InChI는 일련의 부품으로 구성되어 있으며 분자 구조에 대한 자세한 정보를 제공합니다.예를 들어시작 식별, 분자식, 연결표, 수소 원자 수, 다중 회전 결합 수, 입체 화학 정보, 이성질체 정보, 혼합물 또는 호변 이성질체 정보, 전하 및 스핀 다중도 정보 등

또한 모델의 정확도를 높이고 싶다면 모델을 변경하는 것도 나쁘지 않습니다.

기능 최적화

분자식 추출

InChI 문자열에서 우리는 분자식이 다음과 같이 직접적으로 주어진다는 것을 알 수 있습니다./C47H61N7O6S 부분. 이는 분자가 47개의 탄소 원자, 61개의 수소 원자, 7개의 질소 원자, 6개의 산소 원자 및 1개의 황 원자로 구성되어 있음을 의미합니다.

분자량 계산

분자량은 각 원자의 원자 질량에 그 수를 곱한 다음 더하면 알 수 있습니다.

좋다

  • 탄소(C)의 원자 질량은 약 12.01g/mol입니다.

  • 수소(H)의 원자 질량은 약 1.008g/mol입니다.

  • 질소(N)의 원자 질량은 약 14.01g/mol입니다.

  • 산소(O)의 원자 질량은 약 16.00g/mol입니다.

  • 황(S)의 원자 질량은 약 32.07g/mol입니다.

양을 곱하고 더하면 분자량을 얻습니다.

원자 수

다양한 원자의 수를 직접 세어보고 확장해 보세요.

import pandas as pd
import re

atomic_masses = {
    'H': 1.008, 'He': 4.002602, 'Li': 6.94, 'Be': 9.0122, 'B': 10.81, 'C': 12.01,
    'N': 14.01, 'O': 16.00, 'F': 19.00, 'Ne': 20.180, 'Na': 22.990, 'Mg': 24.305,
    'Al': 26.982, 'Si': 28.085, 'P': 30.97, 'S': 32.07, 'Cl': 35.45, 'Ar': 39.95,
    'K': 39.10, 'Ca': 40.08, 'Sc': 44.956, 'Ti': 47.867, 'V': 50.942, 'Cr': 52.00,
    'Mn': 54.938, 'Fe': 55.845, 'Co': 58.933, 'Ni': 58.69, 'Cu': 63.55, 'Zn': 65.38
}

# 函数用于解析单个InChI字符串
def parse_inchi(row):
    inchi_str = row['InChI']
    formula = ''
    molecular_weight = 0
    element_counts = {}

    # 提取分子式
    formula_match = re.search(r"InChI=1S/([^/] )/c", inchi_str)
    if formula_match:
        formula = formula_match.group(1)

    # 计算分子量和原子计数
    for element, count in re.findall(r"([A-Z][a-z]*)([0-9]*)", formula):
        count = int(count) if count else 1
        element_mass = atomic_masses.get(element.upper(), 0)
        molecular_weight  = element_mass * count
        element_counts[element.upper()] = count

    return pd.Series({
        'Formula': formula,
        'MolecularWeight': molecular_weight,
        'ElementCounts': element_counts
    })

# 应用函数到DataFrame的每一行
train[['Formula', 'MolecularWeight', 'ElementCounts']] = train.apply(parse_inchi, axis=1)

# 定义存在的key
keys = ['H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn']

# 创建一个空的DataFrame,列名为keys
df_expanded = pd.DataFrame({key: pd.Series() for key in keys})

# 遍历数据,填充DataFrame
for index, item in enumerate(train['ElementCounts'].values):
    for key in keys:
        # 将字典中的值填充到相应的列中
        df_expanded.at[index, key] = item.get(key, 0)

df_expanded = pd.DataFrame(df_expanded)

모델 융합

지난번에 언급했듯이, 우리는 lightgbm과 xgboost를 시도하지 않았습니다. 이 세 가지 모델을 차례로 실행한 다음 융합을 위해 세 가지 모델의 결과를 평균화할 수 있습니다. ).

def cv_model(clf, train_x, train_y, test_x, clf_name, seed = 2023):
    folds = 5
    kf = KFold(n_splits=folds, shuffle=True, random_state=seed)
    oof = np.zeros(train_x.shape[0])
    test_predict = np.zeros(test_x.shape[0])
    cv_scores = []
    for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):
        print('************************************ {} ************************************'.format(str(i 1)))
        trn_x, trn_y, val_x, val_y = train_x.iloc[train_index], train_y[train_index], train_x.iloc[valid_index], train_y[valid_index]

        if clf_name == "lgb":
            train_matrix = clf.Dataset(trn_x, label=trn_y)
            valid_matrix = clf.Dataset(val_x, label=val_y)
            params = {
                'boosting_type': 'gbdt',
                'objective': 'binary',
                'min_child_weight': 6,
                'num_leaves': 2 ** 6,
                'lambda_l2': 10,
                'feature_fraction': 0.8,
                'bagging_fraction': 0.8,
                'bagging_freq': 4,
                'learning_rate': 0.35,
                'seed': 2024,
                'nthread' : 16,
                'verbose' : -1,
            }
            model = clf.train(params, train_matrix, 2000, valid_sets=[train_matrix, valid_matrix],
                              categorical_feature=[], verbose_eval=1000, early_stopping_rounds=100)
            val_pred = model.predict(val_x, num_iteration=model.best_iteration)
            test_pred = model.predict(test_x, num_iteration=model.best_iteration)

        if clf_name == "xgb":
            xgb_params = {
              'booster': 'gbtree', 
              'objective': 'binary:logistic',
              'num_class':3,
              'max_depth': 5,
              'lambda': 10,
              'subsample': 0.7,
              'colsample_bytree': 0.7,
              'colsample_bylevel': 0.7,
              'eta': 0.35,
              'tree_method': 'hist',
              'seed': 520,
              'nthread': 16
              }
            train_matrix = clf.DMatrix(trn_x , label=trn_y)
            valid_matrix = clf.DMatrix(val_x , label=val_y)
            test_matrix = clf.DMatrix(test_x)

            watchlist = [(train_matrix, 'train'),(valid_matrix, 'eval')]

            model = clf.train(xgb_params, train_matrix, num_boost_round=2000, evals=watchlist, verbose_eval=1000, early_stopping_rounds=100)
            val_pred  = model.predict(valid_matrix)
            test_pred = model.predict(test_matrix)

        if clf_name == "cat":
            params = {'learning_rate': 0.35, 'depth': 5, 'bootstrap_type':'Bernoulli','random_seed':2024,
                      'od_type': 'Iter', 'od_wait': 100, 'random_seed': 11, 'allow_writing_files': False}

            model = clf(iterations=2000, **params)
            model.fit(trn_x, trn_y, eval_set=(val_x, val_y),
                      metric_period=1000,
                      use_best_model=True, 
                      cat_features=[],
                      verbose=1)

            val_pred  = model.predict_proba(val_x)
            test_pred = model.predict_proba(test_x)

        oof[valid_index] = val_pred
        test_predict  = test_pred / kf.n_splits

        F1_score = f1_score(val_y, np.where(val_pred