<jupyter_start><jupyter_text>간단한 모델 훈련하기데이터셋을 수집, 정제, 포맷팅하고 훈련 세트와 테스트 세트로 분할했습니다. 이전 [노트북](https://github.com/rickiepark/ml-powered-applications/blob/master/notebooks/exploring_data_to_generate_features.ipynb)에서 벡터 특성을 만들었습니다. 이제 첫 번째 간단한 모델을 훈련해 보죠.먼저 데이터를 로드하고 포맷팅합니다.<jupyter_code>import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, classification_report
import joblib
import sys
sys.path.append("..")
np.random.seed(35)
import warnings
warnings.filterwarnings('ignore')

from ml_editor.data_processing import (
    format_raw_df,
    add_text_features_to_df,
    get_feature_vector_and_label,
    get_split_by_author,
    get_vectorized_inputs_and_label,
    get_vectorized_series,
    train_vectorizer,
)


data_path = Path('../data/writers.csv')
df = pd.read_csv(data_path)
df = format_raw_df(df.copy())

df = df.loc[df["is_question"]].copy()<jupyter_output><empty_output><jupyter_text>그다음 특성을 추가하고 벡터로 변환하고 훈련/테스트 세트로 나눕니다.<jupyter_code>df = add_text_features_to_df(df.copy())
train_df, test_df = get_split_by_author(df, test_size=0.2, random_state=40)

vectorizer = train_vectorizer(train_df)
train_df["vectors"] = get_vectorized_series(train_df["full_text"].copy(), vectorizer)
test_df["vectors"] = get_vectorized_series(test_df["full_text"].copy(), vectorizer)
features = [
                "action_verb_full",
                "question_mark_full",
                "text_len",
                "language_question",
            ]
X_train, y_train = get_feature_vector_and_label(train_df, features)
X_test, y_test = get_feature_vector_and_label(test_df, features)<jupyter_output><empty_output><jupyter_text>특성과 레이블이 준비되면 `sklearn`을 사용해 몇 줄의 코드로 모델을 훈련할 수 있습니다.<jupyter_code>clf = RandomForestClassifier(n_estimators=100, class_weight='balanced', oob_score=True)
clf.fit(X_train, y_train)

y_predicted = clf.predict(X_test)
y_predicted_proba = clf.predict_proba(X_test)
y_train.value_counts()<jupyter_output><empty_output><jupyter_text>측정 지표모델을 훈련하고 나면 결과를 평가할 차례입니다. 단순 지표부터 시작해 보죠.<jupyter_code>def get_metrics(y_test, y_predicted):  
    # 진짜 양성 / (진짜 양성 + 가짜 양성)
    precision = precision_score(y_test, y_predicted, pos_label=None,
                                    average='weighted')             
    # 진짜 양성 / (진짜 양성 + 가짜 음성)
    recall = recall_score(y_test, y_predicted, pos_label=None,
                              average='weighted')
    
    # 정밀도와 재현율의 조화 평균
    f1 = f1_score(y_test, y_predicted, pos_label=None, average='weighted')
    
    # 진짜 양성 + 진짜 음성 / 전체
    accuracy = accuracy_score(y_test, y_predicted)
    return accuracy, precision, recall, f1
# 훈련 정확도
# https://datascience.stackexchange.com/questions/13151/randomforestclassifier-oob-scoring-method 참조
y_train_pred = np.argmax(clf.oob_decision_function_,axis=1)

accuracy, precision, recall, f1 = get_metrics(y_train, y_train_pred)
print("훈련 정확도 = %.3f, 정밀도 = %.3f, 재현율 = %.3f, f1 = %.3f" % (accuracy, precision, recall, f1))
accuracy, precision, recall, f1 = get_metrics(y_test, y_predicted)
print("검증 정확도 = %.3f, 정밀도 = %.3f, 재현율 = %.3f, f1 = %.3f" % (accuracy, precision, recall, f1))<jupyter_output>검증 정확도 = 0.625, 정밀도 = 0.626, 재현율 = 0.625, f1 = 0.622<jupyter_text>첫 번째 모델이 잘 동작하는 것 같습니다. 적어도 랜덤 예측보다는 성능이 낫기 때문에 첫 번째 시도로는 고무적입니다. 추후 분석과 사용을 위해 훈련된 모델과 벡터화 객체를 디스크에 저장합니다.<jupyter_code>model_path = Path("../models/model_1.pkl")
vectorizer_path = Path("../models/vectorizer_1.pkl")
joblib.dump(clf, model_path) 
joblib.dump(vectorizer, vectorizer_path)<jupyter_output><empty_output><jupyter_text>추론 함수훈련된 모델을 본 적 없는 데이터에서 사용하기 위해 추론 함수를 정의하고 사용합니다. 아래 함수는 임의의 질문을 받고 높은 점수를 받을 추정 확률을 출력합니다.<jupyter_code>from ml_editor.model_v1 import get_model_probabilities_for_input_texts


# The inference function expects an array of questions, so we created an array of length 1 to pass a single question
test_q = ["bad question"]
probs = get_model_probabilities_for_input_texts(test_q)

# Index 1 corresponds to the positive class here
print("이 질문이 양성 샘플일 확률: %s" % (probs[0][1]))<jupyter_output>이 질문이 양성 샘플일 확률: 0.19
{'fraction_non_alphanumeric': 0.10744197176357981, 'fraction_numerical': 0.014357501794687724, 'mean_word_length': 4.618279569892473, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '493495', 'license': 'MIT', 'n_tokens_mistral': 2020, 'n_tokens_neox': 2237, 'n_words': 348, 'path': 'notebooks/train_simple_model.ipynb', 'repo_name': 'rickiepark/mlpa', 'size': '4179'}