자습서: 텍스트 분류 모델 생성, 평가 및 채점
이 자습서에서는 Microsoft Fabric에서 텍스트 분류 모델에 대한 Synapse 데이터 과학 워크플로의 엔드투엔드 예시를 제공합니다. 이 시나리오에서는 Spark에서 word2vec 및 로지스틱 회귀를 사용하여 도서 제목만을 기준으로 British Library 도서 데이터 세트에서 도서의 장르를 결정합니다.
이 자습서에서는 다음 단계를 다룹니다.
- 사용자 지정 라이브러리 설치
- 데이터 로드
- 탐색적 데이터 분석을 통해 데이터 이해 및 처리
- word2vec 및 로지스틱 회귀를 사용하여 기계 학습 모델 학습, MLflow 및 Fabric 자동 로깅 기능을 사용하여 실험 추적
- 채점 및 예측을 위한 기계 학습 모델 로드
필수 조건
Microsoft Fabric 구독을 구매합니다. 또는 무료 Microsoft Fabric 평가판에 등록합니다.
Microsoft Fabric에 로그인합니다.
홈페이지 왼쪽의 환경 전환기를 사용하여 Synapse 데이터 과학 환경으로 전환합니다.
- Microsoft Fabric 레이크하우스가 없는 경우 Microsoft Fabric에서 레이크하우스 만들기의 단계에 따라 레이크하우스를 만들 수 있습니다.
Notebook에서 따라 하기
다음 옵션 중 하나를 선택하여 Notebook에서 따라할 수 있습니다.
- Synapse 데이터 과학 환경에서 기본 제공 Notebook을 열고 실행
- GitHub에서 Synapse 데이터 과학 환경으로 Notebook 업로드
기본 제공 Notebook 열기
이 자습서에는 샘플 타이틀 장르 분류 Notebook이 함께 제공됩니다.
Synapse 데이터 과학 환경에서 자습서의 기본 제공 샘플 Notebook을 열려면 다음을 수행합니다.
Synapse 데이터 과학 홈페이지로 이동합니다.
샘플 사용을 선택합니다.
해당 샘플을 선택합니다.
- 샘플이 Python 자습서용인 경우 기본 엔드투엔드 워크플로(Python) 탭에서 선택합니다.
- 샘플이 R 자습서용인 경우 엔드투엔드 워크플로(R) 탭에서 선택합니다.
- 샘플이 빠른 자습서용인 경우 빠른 자습서 탭에서 선택합니다.
코드 실행을 시작하기 전에 Notebook에 레이크하우스를 연결합니다.
GitHub에서 Notebook 가져오기
이 자습서에는 AIsample - Title Genre Classification.ipynb Notebook이 함께 제공됩니다.
이 자습서에 함께 제공되는 Notebook을 열려면 데이터 과학 자습서를 위한 시스템 준비의 지침에 따라 Notebook을 작업 영역으로 가져옵니다.
이 페이지에서 코드를 복사하여 붙여넣으려는 경우 새 Notebook을 만들 수 있습니다.
코드 실행을 시작하기 전에 Notebook에 레이크하우스를 연결해야 합니다.
1단계: 사용자 지정 라이브러리 설치
기계 학습 모델 개발 또는 임시 데이터 분석의 경우 Apache Spark 세션에 대한 사용자 지정 라이브러리를 신속하게 설치해야 할 수 있습니다. 라이브러리를 설치하는 데는 두 가지 옵션이 있습니다.
- 현재 Notebook에만 라이브러리를 설치하려면 Notebook의 인라인 설치 기능(
%pip
또는%conda
)을 사용합니다. - 또는 Fabric 환경을 만들거나, 공개 소스에서 라이브러리를 설치하거나, 사용자 지정 라이브러리를 업로드한 다음, 작업 영역 관리자가 해당 환경을 작업 영역의 기본값으로 연결할 수 있습니다. 그러면 환경의 모든 라이브러리를 작업 영역의 모든 Notebook 및 Spark 작업 정의에서 사용할 수 있게 됩니다. 환경에 대한 자세한 내용은 Microsoft Fabric에서 환경 생성, 구성 및 사용을 참조하세요.
분류 모델의 경우 wordcloud
라이브러리를 사용하여 텍스트에서 단어 빈도를 나타냅니다. 여기서 단어의 크기는 빈도를 나타냅니다. 이 자습서에서는 %pip install
을 사용하여 Notebook에 wordcloud
를 설치합니다.
참고 항목
%pip install
실행 후 PySpark 커널이 다시 시작됩니다. 다른 셀을 실행하기 전에 필요한 라이브러리를 설치해야 합니다.
# Install wordcloud for text visualization by using pip
%pip install wordcloud
2단계: 데이터 로드
데이터 세트에는 도서관과 Microsoft의 협업을 통해 디지털화된 British Library의 도서에 대한 메타데이터가 포함되어 있습니다. 메타데이터는 도서가 픽션인지 아니면 논픽션인지를 나타내는 분류 정보입니다. 이 데이터 세트로는 제목만을 기준으로 도서의 장르를 결정하는 분류 모델을 학습시키는 것이 목표입니다.
BL 레코드 ID | 리소스 유형 | 속성 | 이름과 연결된 날짜 | 이름 유형 | 역할 | 모든 이름 | 제목 | 변형 제목 | 시리즈 제목 | 시리즈 내의 숫자 | 출판 국가 | 출판 유형 | 출판사 | 출판 날짜 | 버전 | 물리적 설명 | 듀이 분류 | BL 서가 기호 | 토픽 | 장르 | 언어 | 주의 | 물리적 리소스에 대한 BL 레코드 ID | classification_id | user_id | created_at | subject_ids | annotator_date_pub | annotator_normalised_date_pub | annotator_edition_statement | annotator_genre | annotator_FAST_genre_terms | annotator_FAST_subject_terms | annotator_comments | annotator_main_language | annotator_other_languages_summaries | annotator_summaries_language | annotator_translation | annotator_original_language | annotator_publisher | annotator_place_pub | annotator_country | annotator_title | 디지털화된 도서 링크 | 주석 달림 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
014602826 | 논문 | Yearsley, Ann | 1753-1806 | person | More, Hannah, 1745-1833 [person]; Yearsley, Ann, 1753-1806 [person] | Poems on several occasions [With a prefatory letter by Hannah More.] | 영국 | 런던 | 1786 | 4판 원고 노트 | 지디털 스토어 11644.d.32 | 영어 | 003996603 | False | |||||||||||||||||||||||||||||||
014602830 | 논문 | A, T. | person | 올덤, 존, 1653-1683 [사람]; A, T. [person] | A Satyr against Vertue. (A poem: supposed to be spoken by a Town-Hector [By John Oldham. The preface signed: T. A.]) | 영국 | 런던 | 1679 | 15페이지(4°) | Digital Store 11602.ee.10. (2.) | 영어 | 000001143 | False |
다음 매개변수를 정의하여 이 Notebook을 다양한 데이터 세트에 적용할 수 있습니다.
IS_CUSTOM_DATA = False # If True, the user must manually upload the dataset
DATA_FOLDER = "Files/title-genre-classification"
DATA_FILE = "blbooksgenre.csv"
# Data schema
TEXT_COL = "Title"
LABEL_COL = "annotator_genre"
LABELS = ["Fiction", "Non-fiction"]
EXPERIMENT_NAME = "sample-aisample-textclassification" # MLflow experiment name
데이터 세트 다운로드 및 레이크하우스에 업로드
이 코드는 공개적으로 사용 가능한 버전의 데이터 세트를 다운로드한 다음 Fabric 레이크하우스에 저장합니다.
중요 사항
실행하기 전에 Notebook에 레이크하우스를 추가해야 합니다. 그렇게 하지 않으면 오류가 발생합니다.
if not IS_CUSTOM_DATA:
# Download demo data files into the lakehouse, if they don't exist
import os, requests
remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/Title_Genre_Classification"
fname = "blbooksgenre.csv"
download_path = f"/lakehouse/default/{DATA_FOLDER}/raw"
if not os.path.exists("/lakehouse/default"):
# Add a lakehouse, if no default lakehouse was added to the notebook
# A new notebook won't link to any lakehouse by default
raise FileNotFoundError(
"Default lakehouse not found, please add a lakehouse and restart the session."
)
os.makedirs(download_path, exist_ok=True)
if not os.path.exists(f"{download_path}/{fname}"):
r = requests.get(f"{remote_url}/{fname}", timeout=30)
with open(f"{download_path}/{fname}", "wb") as f:
f.write(r.content)
print("Downloaded demo data files into lakehouse.")
필수 라이브러리 가져오기
처리를 시작하기 전에 Spark 및 SynapseML의 라이브러리를 포함하여 필요한 라이브러리를 가져와야 합니다.
import numpy as np
from itertools import chain
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import seaborn as sns
import pyspark.sql.functions as F
from pyspark.ml import Pipeline
from pyspark.ml.feature import *
from pyspark.ml.tuning import CrossValidator, ParamGridBuilder
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import (
BinaryClassificationEvaluator,
MulticlassClassificationEvaluator,
)
from synapse.ml.stages import ClassBalancer
from synapse.ml.train import ComputeModelStatistics
import mlflow
하이퍼 매개 변수 정의
모델 학습에 대한 일부 하이퍼 매개 변수를 정의합니다.
중요 사항
각 매개 변수를 이해하는 경우에만 이러한 하이퍼 매개 변수를 수정해야 합니다.
# Hyperparameters
word2vec_size = 128 # The length of the vector for each word
min_word_count = 3 # The minimum number of times that a word must appear to be considered
max_iter = 10 # The maximum number of training iterations
k_folds = 3 # The number of folds for cross-validation
이 Notebook을 실행하는 데 필요한 시간 기록을 시작해야 합니다.
# Record the notebook running time
import time
ts = time.time()
MLflow 실험 추적 설정
자동 로깅은 MLflow 로깅 기능을 확장합니다. 자동 로깅은 기계 학습 모델을 학습할 때 해당 모델의 입력 매개 변수 값 및 출력 메트릭을 자동으로 캡처합니다. 그런 다음 이 정보를 작업 영역에 기록합니다. 작업 영역에서는 MLflow API를 사용하여 정보에 액세스하고 시각화하거나, 작업 공간에서 해당 실험을 수행할 수 있습니다. 자동 로깅에 대한 자세한 내용은 Microsoft Fabric의 자동 로깅을 참조하세요.
# Set up Mlflow for experiment tracking
mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True) # Disable Mlflow autologging
Notebook 세션에서 Microsoft Fabric 자동 로깅을 사용하지 않도록 설정하려면 mlflow.autolog()
을 호출하고 disable=True
를 설정합니다.
레이크하우스에서 원시 날짜 데이터 읽기
raw_df = spark.read.csv(f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True)
3단계: 탐색적 데이터 분석 수행
display
명령을 통해 데이터 세트를 탐색하고, 데이터 세트에 대한 고급 통계를 보고, 차트 보기를 표시합니다.
display(raw_df.limit(20))
데이터 준비
중복 항목을 제거하여 데이터를 정리합니다.
df = (
raw_df.select([TEXT_COL, LABEL_COL])
.where(F.col(LABEL_COL).isin(LABELS))
.dropDuplicates([TEXT_COL])
.cache()
)
display(df.limit(20))
클래스 밸런싱을 적용하여 바이어스를 해결합니다.
# Create a ClassBalancer instance, and set the input column to LABEL_COL
cb = ClassBalancer().setInputCol(LABEL_COL)
# Fit the ClassBalancer instance to the input DataFrame, and transform the DataFrame
df = cb.fit(df).transform(df)
# Display the first 20 rows of the transformed DataFrame
display(df.limit(20))
단락과 문장을 더 작은 단위로 분할하여 데이터 세트를 토큰화합니다. 이렇게 하면 의미를 더 쉽게 할당할 수 있습니다. 그런 다음 중지 단어를 제거하여 성능을 향상시킵니다. 중지 단어 제거는 말뭉치의 모든 문서에서 일반적으로 발생하는 단어를 제거하는 것을 의미합니다. 중지 단어 제거는 NLP(자연어 처리) 애플리케이션에서 가장 일반적으로 사용되는 전처리 단계 중 하나입니다.
# Text transformer
tokenizer = Tokenizer(inputCol=TEXT_COL, outputCol="tokens")
stopwords_remover = StopWordsRemover(inputCol="tokens", outputCol="filtered_tokens")
# Build the pipeline
pipeline = Pipeline(stages=[tokenizer, stopwords_remover])
token_df = pipeline.fit(df).transform(df)
display(token_df.limit(20))
각 클래스에 대한 wordcloud 라이브러리를 표시합니다. wordcloud 라이브러리는 텍스트 데이터에 자주 등장하는 키워드를 시각적으로 눈에 띄게 표현한 것입니다. wordcloud 라이브러리는 키워드를 구름과 같은 색 그림으로 렌더링하여 주요 텍스트 데이터를 한눈에 더 잘 포착할 수 있기 때문에 효과적입니다. wordcloud에 대해 자세히 알아보세요.
# WordCloud
for label in LABELS:
tokens = (
token_df.where(F.col(LABEL_COL) == label)
.select(F.explode("filtered_tokens").alias("token"))
.where(F.col("token").rlike(r"^\w+$"))
)
top50_tokens = (
tokens.groupBy("token").count().orderBy(F.desc("count")).limit(50).collect()
)
# Generate a wordcloud image
wordcloud = WordCloud(
scale=10,
background_color="white",
random_state=42, # Make sure the output is always the same for the same input
).generate_from_frequencies(dict(top50_tokens))
# Display the generated image by using matplotlib
plt.figure(figsize=(10, 10))
plt.title(label, fontsize=20)
plt.axis("off")
plt.imshow(wordcloud, interpolation="bilinear")
마지막으로, word2vec를 사용하여 텍스트를 벡터화합니다. word2vec 기술은 텍스트의 각 단어에 대한 벡터 표현을 만듭니다. 비슷한 컨텍스트에서 사용되거나 의미 체계 관계가 있는 단어는 벡터 공간에서의 근접성을 통해 효과적으로 캡처됩니다. 이 근접성은 유사한 단어에는 유사한 단어 벡터가 있음을 나타냅니다.
# Label transformer
label_indexer = StringIndexer(inputCol=LABEL_COL, outputCol="labelIdx")
vectorizer = Word2Vec(
vectorSize=word2vec_size,
minCount=min_word_count,
inputCol="filtered_tokens",
outputCol="features",
)
# Build the pipeline
pipeline = Pipeline(stages=[label_indexer, vectorizer])
vec_df = (
pipeline.fit(token_df)
.transform(token_df)
.select([TEXT_COL, LABEL_COL, "features", "labelIdx", "weight"])
)
display(vec_df.limit(20))
4단계: 모델 학습 및 평가
데이터를 확보한 상태에서 모델을 정의합니다. 이 섹션에서는 로지스틱 회귀 모델을 학습시켜 벡터화된 텍스트를 분류합니다.
학습 및 테스트 데이터 세트 준비
# Split the dataset into training and testing
(train_df, test_df) = vec_df.randomSplit((0.8, 0.2), seed=42)
기계 학습 실험 추적
기계 학습 실험은 모든 관련 기계 학습 실행에 대한 조직 및 제어의 기본 단위입니다. 실행은 모델 코드의 단일 실행에 해당합니다.
기계 학습 실험 추적은 매개 변수, 메트릭, 모델 및 기타 아티팩트와 같은 모든 실험과 해당 구성 요소를 관리합니다. 추적을 통해 특정 기계 학습 실험의 모든 필수 구성 요소를 구성할 수 있습니다. 또한 저장된 실험을 사용하여 과거 결과를 쉽게 재현할 수 있습니다. Microsoft Fabric의 기계 학습 실험에 대해 자세히 알아봅니다.
# Build the logistic regression classifier
lr = (
LogisticRegression()
.setMaxIter(max_iter)
.setFeaturesCol("features")
.setLabelCol("labelIdx")
.setWeightCol("weight")
)
하이퍼 매개 변수 튜닝
하이퍼 매개 변수를 검색하는 매개 변수 그리드를 작성합니다. 그런 다음, 교차 평가자 추정기를 빌드하여 CrossValidator
모델을 생성합니다.
# Build a grid search to select the best values for the training parameters
param_grid = (
ParamGridBuilder()
.addGrid(lr.regParam, [0.03, 0.1])
.addGrid(lr.elasticNetParam, [0.0, 0.1])
.build()
)
if len(LABELS) > 2:
evaluator_cls = MulticlassClassificationEvaluator
evaluator_metrics = ["f1", "accuracy"]
else:
evaluator_cls = BinaryClassificationEvaluator
evaluator_metrics = ["areaUnderROC", "areaUnderPR"]
evaluator = evaluator_cls(labelCol="labelIdx", weightCol="weight")
# Build a cross-evaluator estimator
crossval = CrossValidator(
estimator=lr,
estimatorParamMaps=param_grid,
evaluator=evaluator,
numFolds=k_folds,
collectSubModels=True,
)
모델 평가
테스트 데이터 세트의 모델을 평가하여 비교할 수 있습니다. 잘 학습된 모델은 유효성 검사 및 테스트 데이터 세트에 대해 실행할 때 관련 메트릭에서 고성능을 보여 주어야 합니다.
def evaluate(model, df):
log_metric = {}
prediction = model.transform(df)
for metric in evaluator_metrics:
value = evaluator.evaluate(prediction, {evaluator.metricName: metric})
log_metric[metric] = value
print(f"{metric}: {value:.4f}")
return prediction, log_metric
MLflow를 사용하여 실험 추적
학습 및 평가 프로세스를 시작합니다. MLflow를 사용하여 모든 실험을 추적하고 매개변수, 메트릭, 모델을 기록합니다. 이러한 모든 정보는 작업 영역에 실험 이름으로 기록됩니다.
with mlflow.start_run(run_name="lr"):
models = crossval.fit(train_df)
best_metrics = {k: 0 for k in evaluator_metrics}
best_index = 0
for idx, model in enumerate(models.subModels[0]):
with mlflow.start_run(nested=True, run_name=f"lr_{idx}") as run:
print("\nEvaluating on test data:")
print(f"subModel No. {idx + 1}")
prediction, log_metric = evaluate(model, test_df)
if log_metric[evaluator_metrics[0]] > best_metrics[evaluator_metrics[0]]:
best_metrics = log_metric
best_index = idx
print("log model")
mlflow.spark.log_model(
model,
f"{EXPERIMENT_NAME}-lrmodel",
registered_model_name=f"{EXPERIMENT_NAME}-lrmodel",
dfs_tmpdir="Files/spark",
)
print("log metrics")
mlflow.log_metrics(log_metric)
print("log parameters")
mlflow.log_params(
{
"word2vec_size": word2vec_size,
"min_word_count": min_word_count,
"max_iter": max_iter,
"k_folds": k_folds,
"DATA_FILE": DATA_FILE,
}
)
# Log the best model and its relevant metrics and parameters to the parent run
mlflow.spark.log_model(
models.subModels[0][best_index],
f"{EXPERIMENT_NAME}-lrmodel",
registered_model_name=f"{EXPERIMENT_NAME}-lrmodel",
dfs_tmpdir="Files/spark",
)
mlflow.log_metrics(best_metrics)
mlflow.log_params(
{
"word2vec_size": word2vec_size,
"min_word_count": min_word_count,
"max_iter": max_iter,
"k_folds": k_folds,
"DATA_FILE": DATA_FILE,
}
)
실험을 보려면 다음을 수행합니다.
- 왼쪽 탐색 창에서 작업 영역을 선택합니다.
- 실험 이름 찾기 및 선택 - 이 경우 sample_aisample-textclassification
5단계: 채점 및 예측 결과 저장
Microsoft Fabric을 사용하면 사용자가 PREDICT
확장 가능한 함수를 통해 기계 학습 모델을 운영할 수 있습니다. 이 함수는 모든 컴퓨팅 엔진에서 일괄 처리 채점(또는 일괄 처리 추론)을 지원합니다. 특정 모델의 Notebook 또는 항목 페이지에서 바로 일괄 처리 예측을 만들 수 있습니다. PREDICT 및 Fabric에서 이를 사용하는 방법에 대한 자세한 내용은 Microsoft Fabric에서 PREDICT를 통한 기계 학습 모델 채점을 참조하세요.
앞의 평가 결과에서 모델 1은 AUPRC(정밀도-재현율 곡선 아래 영역)과 AUC-ROC(곡선 수신자 작동 특성 아래 영역) 모두에 대해 가장 큰 메트릭을 가집니다. 따라서 예측에 모델 1을 사용해야 합니다.
AUC-ROC 측정값은 이진 분류자 성능을 측정하는 데 널리 사용됩니다. 그러나 때로는 AUPRC 측정값을 기반으로 분류자를 평가하는 것이 더 적절할 수 있습니다. AUC-ROC 차트는 TPR(진양성 비율)과 FPR(가양성 비율) 간의 절충을 시각화합니다. AUPRC 곡선은 단일 시각화로 정밀도(양수 예측 값 또는 PPV) 및 재현율(진양성률 또는 TPR)를 결합합니다.
# Load the best model
model_uri = f"models:/{EXPERIMENT_NAME}-lrmodel/1"
loaded_model = mlflow.spark.load_model(model_uri, dfs_tmpdir="Files/spark")
# Verify the loaded model
batch_predictions = loaded_model.transform(test_df)
batch_predictions.show(5)
# Code to save userRecs in the lakehouse
batch_predictions.write.format("delta").mode("overwrite").save(
f"{DATA_FOLDER}/predictions/batch_predictions"
)
# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")