Amazon Comprehend PlatoBlockchain 데이터 인텔리전스를 사용하여 리뷰에서 더 나은 통찰력을 얻으십시오. 수직 검색. 일체 포함.

Amazon Comprehend를 사용하여 리뷰에서 더 나은 통찰력 얻기

"구매자의 85%는 개인적인 추천만큼 온라인 리뷰를 신뢰합니다." – 가트너

소비자는 디지털 표면과 여러 접점을 통해 점점 더 비즈니스에 참여하고 있습니다. 통계에 따르면 대부분의 쇼핑객은 리뷰를 사용하여 구매할 제품과 사용할 서비스를 결정합니다. 당 슈피겔 연구센터, 리뷰가 270개 있는 제품의 구매 가능성은 리뷰가 없는 제품의 구매 가능성보다 XNUMX% 더 높습니다. 리뷰는 소비자의 결정에 영향을 미치고 브랜드 가치를 강화하는 힘이 있습니다.

이 게시물에서 우리는 아마존 이해 제품 리뷰에서 의미 있는 정보를 추출하고, 이를 분석하여 다양한 인구 통계학적 사용자가 제품에 어떻게 반응하는지 이해하고, 제품에 대한 사용자 선호도에 대한 집계 정보를 검색합니다. Amazon Comprehend는 문서 또는 텍스트의 콘텐츠에 대한 통찰력을 추출할 수 있는 완전 관리형의 지속적으로 훈련된 자연어 처리(NLP) 서비스입니다.

솔루션 개요

오늘날 고객은 별점, 자유 텍스트 또는 자연어, 소셜 미디어 공유 등 다양한 방식으로 리뷰를 제공할 수 있습니다. 무료 텍스트 또는 자연어 리뷰는 소비자의 독립적인 의견이므로 신뢰를 구축하는 데 도움이 됩니다. 제품 팀에서 리뷰 채널을 통해 고객과 상호 작용하는 데 자주 사용합니다. 고객이 소리를 들을 때 브랜드에 대한 느낌이 좋아진다는 것은 입증된 사실입니다. 별점 또는 소셜 미디어 공유를 분석하는 것이 비교적 쉬운 반면 자연어 또는 자유 텍스트 리뷰는 키워드 또는 구문, 주제 또는 개념, 감정 또는 엔터티 수준 감정 식별과 같은 여러 문제를 내포합니다. 문제는 주로 서면 텍스트의 길이가 다양하고 신호와 노이즈가 모두 존재하기 때문입니다. 또한 정보는 매우 명확하고 명시적(예: 키워드 및 핵심 문구 포함)이거나 불명확하고 암시적(추상적인 주제 및 개념)일 수 있습니다. 훨씬 더 어려운 것은 다양한 유형의 감정을 이해하고 이를 적절한 제품 및 서비스와 연결하는 것입니다. 그럼에도 불구하고 마찰 없는 고객 경험을 제공하려면 이 정보와 텍스트 신호를 이해하는 것이 매우 중요합니다.

이 게시물에서는 공개적으로 사용 가능한 NLP - fast.ai 고객이 제공한 상품평을 분석하기 위한 데이터세트입니다. 주제 모델링으로 알려진 비지도 머신 러닝(ML) 기술을 사용하여 시작합니다. 이것은 텍스트 리뷰 컬렉션에서 발생할 수 있는 추상적인 주제를 발견하는 인기 있는 감독되지 않은 기술입니다. 주제 모델링은 감독되지 않는 클러스터링 문제입니다. 즉, 모델이 가능한 대상 변수(예: 검토의 주제)에 대한 지식이 없습니다. 주제는 클러스터로 표시됩니다. 종종 문서 모음의 클러스터 수는 도메인 전문가의 도움을 받거나 일부 표준 통계 분석을 사용하여 결정됩니다. 모델 출력에는 일반적으로 번호가 매겨진 클러스터(주제 0, 주제 1 등), 각 클러스터와 관련된 키워드, 각 문서(또는 이 경우 검토)에 대한 대표 클러스터의 세 가지 구성 요소가 있습니다. 본질적으로 토픽 모델은 클러스터나 토픽에 대해 사람이 읽을 수 있는 레이블을 생성하지 않습니다. 이는 일반적인 오해입니다. 일반적으로 주제 모델링에 대해 주의해야 할 점은 모델의 모든 문서가 모든 주제와 유사할 수 있는 혼합 멤버십 모델이라는 것입니다. 토픽 모델은 각 문서가 주어진 테마 또는 토픽과 연관될 확률을 결정하기 위해 반복적인 베이지안 프로세스를 학습합니다. 모델 출력은 최적의 주제 수 선택에 따라 달라집니다. 적은 수의 주제로 인해 주제가 너무 광범위할 수 있으며, 많은 수의 주제로 인해 중복된 주제 또는 유사한 주제가 발생할 수 있습니다. 주제 모델을 평가하는 방법에는 여러 가지가 있습니다.

  • 인간의 판단 - 관찰 기반, 해석 기반
  • 정량적 메트릭 – 혼란, 일관성 계산
  • 혼합 접근 방식 – 판단 기반 접근 방식과 양적 접근 방식의 조합

복잡도는 데이터 세트를 훈련 세트와 테스트 세트의 두 부분으로 분할하여 계산됩니다. 가능성은 일반적으로 로그로 계산되므로 이 메트릭을 보류 로그 가능성이라고도 합니다. 당혹도는 예측 지표입니다. 훈련 세트에 대해 훈련된 후 테스트 세트를 예측하는 주제 모델의 능력을 평가합니다. 난처함의 단점 중 하나는 컨텍스트를 포착하지 못한다는 것입니다. 즉, 주제의 단어나 문서의 주제 간의 관계를 포착하지 못합니다. 그러나 의미론적 맥락의 개념은 인간의 이해에 중요합니다. 한 주제에서 단어가 공존할 수 있는 조건부 가능성과 같은 측정값이 도움이 될 수 있습니다. 이러한 접근 방식을 집합적으로 일관성이라고 합니다. 이 게시물에서는 인간의 판단(관찰 기반) 접근 방식, 즉 주제에서 상위 n개의 단어를 관찰하는 데 중점을 둡니다.

솔루션은 다음과 같은 고급 단계로 구성됩니다.

  1. 설정 아마존 세이지 메이커 노트북 인스턴스.
  2. 노트북을 만듭니다.
  3. 탐색 적 데이터 분석을 수행합니다.
  4. Amazon Comprehend 주제 모델링 작업을 실행합니다.
  5. 주제를 생성하고 감정을 이해합니다.
  6. 아마존 퀵 사이트 데이터를 시각화하고 보고서를 생성합니다.

이 솔루션은 모든 AWS 리전에서 사용할 수 있지만 Amazon Comprehend API와 SageMaker가 동일한 리전에 있는지 확인해야 합니다. 이 게시물에서는 미국 동부(버지니아 북부) 지역을 사용합니다.

SageMaker 노트북 인스턴스 설정

다음을 통해 Amazon Comprehend와 상호 작용할 수 있습니다. AWS 관리 콘솔, AWS 명령 줄 인터페이스 (AWS CLI), 또는 Amazon Comprehend API. 자세한 내용은 다음을 참조하십시오. Amazon Comprehend 시작하기. 이 게시물 전체에서 SageMaker 노트북과 Python(Boto3) 코드를 사용하여 Amazon Comprehend API와 상호 작용합니다.

  1. Amazon SageMaker 콘솔의 탐색 창에 있는 노트북에서 다음을 선택합니다.
    노트북 인스턴스.
  2. 노트북 인스턴스 생성을 선택합니다.노트북 인스턴스
  3. 노트북 인스턴스 이름을 지정하고 인스턴스 유형을 ml.r5.2xlarge로 설정합니다.
  4. 나머지 기본 설정은 그대로 둡니다.
  5. 를 생성 AWS 자격 증명 및 액세스 관리 (IAM) 역할 AmazonSageMakerFullAccess 및 필요한 모든 액세스 Amazon Simple Storage Service(Amazon S3) 버킷 및 Amazon Comprehend API.
  6. 노트북 인스턴스 생성을 선택합니다.
    몇 분 후 노트북 인스턴스가 준비됩니다.
  7. 노트북 인스턴스에서 Amazon Comprehend에 액세스하려면 다음을 연결해야 합니다. ComprehendFullAccess 정책을 IAM 역할에 적용합니다.

Amazon Comprehend의 보안 개요는 다음을 참조하십시오. Amazon Comprehend의 보안.

프로비저닝한 노트북 인스턴스를 연 후 Jupyter 콘솔에서 새로 만들기를 선택한 다음 Python 3(데이터 과학)을 선택합니다. 또는 샘플 코드 파일에 액세스할 수 있습니다. GitHub 레포. 파일을 노트북 인스턴스에 업로드하여 직접 실행하거나 복제할 수 있습니다.

GitHub 리포지토리에는 XNUMX개의 노트북이 포함되어 있습니다.

  • data_processing.ipynb
  • model_training.ipynb
  • topic_mapping_sentiment_generation.ipynb

탐색적 데이터 분석 수행

우리는 첫 번째 노트북을 사용합니다(data_processing.ipynb) 데이터를 탐색하고 처리합니다. S3 버킷의 데이터를 DataFrame으로 로드하는 것으로 시작합니다.

# Bucket containing the data
BUCKET = 'clothing-shoe-jewel-tm-blog'

# Item ratings and metadata
S3_DATA_FILE = 'Clothing_Shoes_and_Jewelry.json.gz' # Zip
S3_META_FILE = 'meta_Clothing_Shoes_and_Jewelry.json.gz' # Zip

S3_DATA = 's3://' + BUCKET + '/' + S3_DATA_FILE
S3_META = 's3://' + BUCKET + '/' + S3_META_FILE

# Transformed review, input for Comprehend
LOCAL_TRANSFORMED_REVIEW = os.path.join('data', 'TransformedReviews.txt')
S3_OUT = 's3://' + BUCKET + '/out/' + 'TransformedReviews.txt'

# Final dataframe where topics and sentiments are going to be joined
S3_FEEDBACK_TOPICS = 's3://' + BUCKET + '/out/' + 'FinalDataframe.csv'

def convert_json_to_df(path):
    """Reads a subset of a json file in a given path in chunks, combines, and returns
    """
    # Creating chunks from 500k data points each of chunk size 10k
    chunks = pd.read_json(path, orient='records', 
                                lines=True, 
                                nrows=500000, 
                                chunksize=10000, 
                                compression='gzip')
    # Creating a single dataframe from all the chunks
    load_df = pd.DataFrame()
    for chunk in chunks:
        load_df = pd.concat([load_df, chunk], axis=0)
    return load_df

# Review data
original_df = convert_json_to_df(S3_DATA)

# Metadata
original_meta = convert_json_to_df(S3_META)

다음 섹션에서는 데이터를 이해하기 위해 탐색적 데이터 분석(EDA)을 수행합니다. 데이터 및 메타데이터의 형태를 탐색하는 것으로 시작합니다. 진정성을 위해 검증된 리뷰만 사용합니다.

# Shape of reviews and metadata
print('Shape of review data: ', original_df.shape)
print('Shape of metadata: ', original_meta.shape)

# We are interested in verified reviews only
# Also checking the amount of missing values in the review data
print('Frequency of verified/non verified review data: ', original_df['verified'].value_counts())
print('Frequency of missing values in review data: ', original_df.isna().sum())

각 범주의 수를 더 자세히 조사하고 중복 데이터가 있는지 확인합니다.

# Count of each categories for EDA.
print('Frequncy of different item categories in metadata: ', original_meta['category'].value_counts())

# Checking null values for metadata
print('Frequency of missing values in metadata: ', original_meta.isna().sum())

# Checking if there are duplicated data. There are indeed duplicated data in the dataframe.
print('Duplicate items in metadata: ', original_meta[original_meta['asin'].duplicated()])

결과에 만족하면 데이터 전처리의 다음 단계로 이동합니다. Amazon Comprehend는 각 주제 모델링 작업에 최소 1,000개의 문서를 제공할 것을 권장하며, 각 문서는 최소 8문장입니다. 문서는 UTF-8 형식의 텍스트 파일이어야 합니다. 다음 단계에서는 데이터가 권장되는 UTF-5,000 형식이고 각 입력의 크기가 XNUMX바이트 이하인지 확인합니다.

def clean_text(df):
    """Preprocessing review text.
    The text becomes Comprehend compatible as a result.
    This is the most important preprocessing step.
    """
    # Encode and decode reviews
    df['reviewText'] = df['reviewText'].str.encode("utf-8", "ignore")
    df['reviewText'] = df['reviewText'].str.decode('ascii')

    # Replacing characters with whitespace
    df['reviewText'] = df['reviewText'].replace(r'r+|n+|t+|u2028',' ', regex=True)

    # Replacing punctuations
    df['reviewText'] = df['reviewText'].str.replace('[^ws]','', regex=True)

    # Lowercasing reviews
    df['reviewText'] = df['reviewText'].str.lower()
    return df

def prepare_input_data(df):
    """Encoding and getting reviews in byte size.
    Review gets encoded to utf-8 format and getting the size of the reviews in bytes. 
    Comprehend requires each review input to be no more than 5000 Bytes
    """
    df['review_size'] = df['reviewText'].apply(lambda x:len(x.encode('utf-8')))
    df = df[(df['review_size'] > 0) & (df['review_size'] < 5000)]
    df = df.drop(columns=['review_size'])
    return df

# Only data points with a verified review will be selected and the review must not be missing
filter = (original_df['verified'] == True) & (~original_df['reviewText'].isna())
filtered_df = original_df[filter]

# Only a subset of fields are selected in this experiment. 
filtered_df = filtered_df[['asin', 'reviewText', 'summary', 'unixReviewTime', 'overall', 'reviewerID']]

# Just in case, once again, dropping data points with missing review text
filtered_df = filtered_df.dropna(subset=['reviewText'])
print('Shape of review data: ', filtered_df.shape)

# Dropping duplicate items from metadata
original_meta = original_meta.drop_duplicates(subset=['asin'])

# Only a subset of fields are selected in this experiment. 
original_meta = original_meta[['asin', 'category', 'title', 'description', 'brand', 'main_cat']]

# Clean reviews using text cleaning pipeline
df = clean_text(filtered_df)

# Dataframe where Comprehend outputs (topics and sentiments) will be added
df = prepare_input_data(df)

그런 다음 데이터를 Amazon S3에 저장하고 노트북 인스턴스에 로컬 복사본도 보관합니다.

# Saving dataframe on S3 df.to_csv(S3_FEEDBACK_TOPICS, index=False) 

# Reviews are transformed per Comprehend guideline- one review per line
# The txt file will be used as input for Comprehend
# We first save the input file locally
with open(LOCAL_TRANSFORMED_REVIEW, "w") as outfile:
    outfile.write("n".join(df['reviewText'].tolist()))

# Transferring the transformed review (input to Comprehend) to S3
!aws s3 mv {LOCAL_TRANSFORMED_REVIEW} {S3_OUT}

이로써 데이터 처리 단계가 완료됩니다.

Amazon Comprehend 주제 모델링 작업 실행

그런 다음 전처리된 데이터를 사용하여 Amazon Comprehend를 사용하여 주제 모델링 작업을 실행하는 다음 단계로 이동합니다. 이 단계에서 두 번째 노트북(model_training.ipynb) 또는 Amazon Comprehend 콘솔을 사용하여 주제 모델링 작업을 실행합니다. 콘솔 사용에 대한 지침은 다음을 참조하십시오. 콘솔을 사용하여 분석 작업 실행. 노트북을 사용하는 경우 다음 예제와 같이 Boto3를 사용하여 Amazon Comprehend 클라이언트를 생성하여 시작할 수 있습니다.

# Client and session information
session = boto3.Session()
s3 = boto3.resource('s3')

# Account id. Required downstream.
account_id = boto3.client('sts').get_caller_identity().get('Account')

# Initializing Comprehend client
comprehend = boto3.client(service_name='comprehend', 
                          region_name=session.region_name)

주제 모델링을 위해 문서를 파일당 하나의 문서 또는 라인당 하나의 문서로 제출할 수 있습니다.

5개의 주제(k-숫자)로 시작하여 한 줄에 하나의 문서를 사용합니다. k 또는 토픽의 수를 선택하는 표준 관행으로서 가장 좋은 단일 방법은 없습니다. 다른 k 값을 시도하고 가능성이 가장 큰 값을 선택할 수 있습니다.

# Number of topics set to 5 after having a human-in-the-loop
# This needs to be fully aligned with topicMaps dictionary in the third script 
NUMBER_OF_TOPICS = 5

# Input file format of one review per line
input_doc_format = "ONE_DOC_PER_LINE"

# Role arn (Hard coded, masked)
data_access_role_arn = "arn:aws:iam::XXXXXXXXXXXX:role/service-role/AmazonSageMaker-ExecutionRole-XXXXXXXXXXXXXXX"

Amazon Comprehend 주제 모델링 작업을 통과해야 InputDataConfig S3가 있는 사전 객체, InputFormatDocumentReadAction 필수 매개변수로. 마찬가지로 다음을 제공해야 합니다. OutputDataConfig 객체 S3 및 DataAccessRoleArn 필수 매개변수로. 자세한 내용은 Boto3 설명서를 참조하십시오. start_topics_detection_job.

# Constants for S3 bucket and input data file
BUCKET = 'clothing-shoe-jewel-tm-blog'
input_s3_url = 's3://' + BUCKET + '/out/' + 'TransformedReviews.txt'
output_s3_url = 's3://' + BUCKET + '/out/' + 'output/'

# Final dataframe where we will join Comprehend outputs later
S3_FEEDBACK_TOPICS = 's3://' + BUCKET + '/out/' + 'FinalDataframe.csv'

# Local copy of Comprehend output
LOCAL_COMPREHEND_OUTPUT_DIR = os.path.join('comprehend_out', '')
LOCAL_COMPREHEND_OUTPUT_FILE = os.path.join(LOCAL_COMPREHEND_OUTPUT_DIR, 'output.tar.gz')

INPUT_CONFIG={
    # The S3 URI where Comprehend input is placed.
    'S3Uri':    input_s3_url,
    # Document format
    'InputFormat': input_doc_format,
}
OUTPUT_CONFIG={
    # The S3 URI where Comprehend output is placed.
    'S3Uri':    output_s3_url,
}

그런 다음 다음 예제와 같이 주제 수, 입력 구성 객체, 출력 구성 객체 및 IAM 역할을 전달하여 비동기 주제 감지 작업을 시작할 수 있습니다.

# Reading the Comprehend input file just to double check if number of reviews 
# and the number of lines in the input file have an exact match.
obj = s3.Object(input_s3_url)
comprehend_input = obj.get()['Body'].read().decode('utf-8')
comprehend_input_lines = len(comprehend_input.split('n'))

# Reviews where Comprehend outputs will be merged
df = pd.read_csv(S3_FEEDBACK_TOPICS)
review_df_length = df.shape[0]

# The two lengths must be equal
assert comprehend_input_lines == review_df_length

# Start Comprehend topic modelling job.
# Specifies the number of topics, input and output config and IAM role ARN 
# that grants Amazon Comprehend read access to data.
start_topics_detection_job_result = comprehend.start_topics_detection_job(
                                                    NumberOfTopics=NUMBER_OF_TOPICS,
                                                    InputDataConfig=INPUT_CONFIG,
                                                    OutputDataConfig=OUTPUT_CONFIG,
                                                    DataAccessRoleArn=data_access_role_arn)

print('start_topics_detection_job_result: ' + json.dumps(start_topics_detection_job_result))

# Job ID is required downstream for extracting the Comprehend results
job_id = start_topics_detection_job_result["JobId"]
print('job_id: ', job_id)

다음을 호출하여 작업의 현재 상태를 추적할 수 있습니다. DescribeTopicDetectionJob 작업. 작업 상태는 다음 중 하나일 수 있습니다.

  • SUBMITTED – 작업이 수신되었으며 처리 대기 중입니다.
  • IN_PROGRESS – Amazon Comprehend가 작업을 처리 중입니다.
  • COMPLETED – 작업이 성공적으로 완료되었으며 출력을 사용할 수 있습니다.
  • FAILED – 작업이 완료되지 않았습니다.
# Topic detection takes a while to complete. 
# We can track the current status by calling Use the DescribeTopicDetectionJob operation.
# Keeping track if Comprehend has finished its job
description = comprehend.describe_topics_detection_job(JobId=job_id)

topic_detection_job_status = description['TopicsDetectionJobProperties']["JobStatus"]
print(topic_detection_job_status)
while topic_detection_job_status not in ["COMPLETED", "FAILED"]:
    time.sleep(120)
    topic_detection_job_status = comprehend.describe_topics_detection_job(JobId=job_id)['TopicsDetectionJobProperties']["JobStatus"]
    print(topic_detection_job_status)

topic_detection_job_status = comprehend.describe_topics_detection_job(JobId=job_id)['TopicsDetectionJobProperties']["JobStatus"]
print(topic_detection_job_status)

작업이 성공적으로 완료되면 topic-terms.csv 및 doc-topics.csv라는 두 개의 파일이 포함된 압축 아카이브를 반환합니다. 첫 번째 출력 파일, topic-terms.csv, 컬렉션의 주제 목록입니다. 각 주제에 대해 목록에는 기본적으로 가중치에 따라 주제별 상위 용어가 포함됩니다. 두 번째 파일, doc-topics.csv, 주제와 관련된 문서 및 해당 주제와 관련된 문서의 비율을 나열합니다. 우리가 지정했기 때문에 ONE_DOC_PER_LINE 초기에 input_doc_format 변수에서 문서는 파일 이름과 파일 내에서 0으로 인덱싱된 행 번호로 식별됩니다. 주제 모델링에 대한 자세한 내용은 다음을 참조하십시오. 주제 모델링.
Amazon Comprehend의 출력은 다음 단계를 위해 로컬로 복사됩니다.

# Bucket prefix where model artifacts are stored
prefix = f'{account_id}-TOPICS-{job_id}'

# Model artifact zipped file
artifact_file = 'output.tar.gz'

# Location on S3 where model artifacts are stored
target = f's3://{BUCKET}/out/output/{prefix}/{artifact_file}'

# Copy Comprehend output from S3 to local notebook instance
! aws s3 cp {target}  ./comprehend-out/

# Unzip the Comprehend output file. 
# Two files are now saved locally- 
#       (1) comprehend-out/doc-topics.csv and 
#       (2) comprehend-out/topic-terms.csv

comprehend_tars = tarfile.open(LOCAL_COMPREHEND_OUTPUT_FILE)
comprehend_tars.extractall(LOCAL_COMPREHEND_OUTPUT_DIR)
comprehend_tars.close()

토픽의 수는 문서 컬렉션과 관련된 어휘보다 훨씬 적기 때문에 토픽 공간 표현은 차원 축소 과정으로도 볼 수 있습니다. 문서의 이 토픽 공간 표현을 사용하여 클러스터링을 수행할 수 있습니다. 반면에 각 클러스터에서 단어의 빈도를 분석하여 각 클러스터와 관련된 주제를 결정할 수 있습니다. 이 게시물에서는 클러스터링과 같은 다른 기술을 수행하지 않습니다.

우리는 세 번째 노트북을 사용합니다(topic_mapping_sentiment_generation.ipynb) 다양한 인구 통계의 사용자가 제품에 어떻게 반응하는지 찾고 특정 제품에 대한 사용자 선호도에 대한 집계 정보를 분석합니다.

이전 노트북의 출력을 결합하여 각 주제에 대한 주제 및 관련 용어를 얻을 수 있습니다. 그러나 주제는 번호가 매겨져 있으며 설명이 부족할 수 있습니다. 따라서 우리는 관련 용어를 보고 주제의 이름을 지정하기 위해 충분한 도메인 지식과 주제 전문 지식을 갖춘 휴먼 인 루프를 사용하는 것을 선호합니다. 이 프로세스는 주제 번호에서 주제 이름으로의 매핑으로 간주될 수 있습니다. 그러나 주제에 대한 개별 용어 목록은 상호 포괄적일 수 있으므로 여러 매핑을 생성할 수 있습니다. Human-in-the-loop는 사용 사례의 컨텍스트를 기반으로 매핑을 공식화해야 합니다. 그렇지 않으면 다운스트림 성능이 영향을 받을 수 있습니다.

변수 선언부터 시작합니다. 각 리뷰에는 여러 주제가 있을 수 있습니다. 빈도를 계산하고 가장 빈번한 주제를 최대 XNUMX개까지 선택합니다. 이러한 주제는 리뷰의 대표 주제로 보고됩니다. 먼저 변수를 정의합니다. TOP_TOPICS 대표 주제의 최대 수를 유지합니다. 둘째, 우리는 값을 정의하고 설정합니다. language_code Amazon Comprehend의 필수 언어 파라미터를 지원하는 변수. 마지막으로, 우리는 topicMaps, 주제 번호를 주제 이름에 매핑하는 사전입니다.

# boto3 session to access service
session = boto3.Session()
comprehend = boto3.client(  'comprehend',
                            region_name=session.region_name)

# S3 bucket
BUCKET = 'clothing-shoe-jewel-tm-blog'

# Local copy of doc-topic file
DOC_TOPIC_FILE = os.path.join('comprehend-out', 'doc-topics.csv')

# Final dataframe where we will join Comprehend outputs later
S3_FEEDBACK_TOPICS = 's3://' + BUCKET + '/out/' + 'FinalDataframe.csv'

# Final output
S3_FINAL_OUTPUT = 's3://' + BUCKET + '/out/' + 'reviewTopicsSentiments.csv'

# Top 3 topics per product will be aggregated
TOP_TOPICS = 3

# Working on English language only. 
language_code = 'en'

# Topic names for 5 topics created by human-in-the-loop or SME feed
topicMaps = {
    0: 'Product comfortability',
    1: 'Product Quality and Price',
    2: 'Product Size',
    3: 'Product Color',
    4: 'Product Return',
}

다음으로 Amazon Comprehend에서 생성한 topic-terms.csv 파일을 사용하여 각 주제와 연결된 고유한 용어를 연결합니다. 그런 다음 이 주제-용어 연관에 매핑 사전을 적용하여 고유한 용어를 주제 이름에 연결합니다.

# Loading documents and topics assigned to each of them by Comprehend
docTopics = pd.read_csv(DOC_TOPIC_FILE)
docTopics.head()

# Creating a field with doc number. 
# This doc number is the line number of the input file to Comprehend.
docTopics['doc'] = docTopics['docname'].str.split(':').str[1]
docTopics['doc'] = docTopics['doc'].astype(int)
docTopics.head()

# Load topics and associated terms
topicTerms = pd.read_csv(DOC_TOPIC_FILE)

# Consolidate terms for each topic
aggregatedTerms = topicTerms.groupby('topic')['term'].aggregate(lambda term: term.unique().tolist()).reset_index()

# Sneak peek
aggregatedTerms.head(10)

이 매핑은 다음 DataFrame에서 볼 수 있듯이 Amazon Comprehend에서 생성된 주제의 가독성과 설명성을 향상시킵니다.

또한 다음 단계와 같이 주제 번호, 용어 및 이름을 초기 입력 데이터에 조인합니다.

그러면 각 리뷰에 해당하는 주제 용어와 이름이 반환됩니다. 주제 번호와 용어는 각 리뷰에 결합된 다음 첫 번째 노트북에 저장한 원래 DataFrame에 다시 결합됩니다.

# Load final dataframe where Comprehend results will be merged to 
feedbackTopics = pd.read_csv(S3_FEEDBACK_TOPICS)

# Joining topic numbers to main data
# The index of feedbackTopics is referring to doc field of docTopics dataframe
feedbackTopics = pd.merge(feedbackTopics, 
                          docTopics, 
                          left_index=True, 
                          right_on='doc', 
                          how='left')

# Reviews will now have topic numbers, associated terms and topics names
feedbackTopics = feedbackTopics.merge(aggregatedTerms, 
                                      on='topic', 
                                      how='left')
feedbackTopics.head()

우리는 다음을 사용하여 리뷰 텍스트에 대한 감정을 생성합니다. detect_sentiment. 텍스트를 검사하고 지배적인 감정(긍정, 중립, 혼합 또는 부정)에 대한 추론을 반환합니다.

def detect_sentiment(text, language_code):
    """Detects sentiment for a given text and language
    """
    comprehend_json_out = comprehend.detect_sentiment(Text=text, LanguageCode=language_code)
    return comprehend_json_out

# Comprehend output for sentiment in raw json 
feedbackTopics['comprehend_sentiment_json_out'] = feedbackTopics['reviewText'].apply(lambda x: detect_sentiment(x, language_code))

# Extracting the exact sentiment from raw Comprehend Json
feedbackTopics['sentiment'] = feedbackTopics['comprehend_sentiment_json_out'].apply(lambda x: x['Sentiment'])

# Sneak peek
feedbackTopics.head(2)

주제와 감정은 모두 리뷰와 밀접하게 연결되어 있습니다. 제품 수준에서 주제와 감정을 집계할 것이기 때문에 Amazon Comprehend에서 생성된 주제와 감정을 결합하여 복합 키를 생성해야 합니다.

# Creating a composite key of topic name and sentiment.
# This is because we are counting frequency of this combination.
feedbackTopics['TopicSentiment'] = feedbackTopics['TopicNames'] + '_' + feedbackTopics['sentiment']

그런 다음 제품 수준에서 집계하고 각 제품에 대한 복합 키를 계산합니다.

이 마지막 단계는 제품별 리뷰의 세분성을 더 잘 이해하고 종합적인 방식으로 주제별로 분류하는 데 도움이 됩니다. 예를 들어 topicDF DataFrame에 대해 표시된 값을 고려할 수 있습니다. 첫 번째 제품에 대한 모든 리뷰 중 전반적으로 고객은 제품 반품, 크기 및 편안함에 대해 긍정적인 경험을 했습니다. 두 번째 제품의 경우 고객은 대부분 제품 반품에 대한 긍정적인 경험과 제품 크기에 대한 긍정적인 경험이 혼합되어 있었습니다.

# Create product id group
asinWiseDF = feedbackTopics.groupby('asin')

# Each product now has a list of topics and sentiment combo (topics can appear multiple times)
topicDF = asinWiseDF['TopicSentiment'].apply(lambda x:list(x)).reset_index()

# Count appreances of topics-sentiment combo for product
topicDF['TopTopics'] = topicDF['TopicSentiment'].apply(Counter)

# Sorting topics-sentiment combo based on their appearance
topicDF['TopTopics'] = topicDF['TopTopics'].apply(lambda x: sorted(x, key=x.get, reverse=True))

# Select Top k topics-sentiment combo for each product/review
topicDF['TopTopics'] = topicDF['TopTopics'].apply(lambda x: x[:TOP_TOPICS])

# Sneak peek
topicDF.head()

제품별 상위 주제

우리의 최종 DataFrame은 이 주제 정보와 감정 정보로 구성되어 있습니다. feedbackTopics 첫 번째 노트북에서 Amazon S3에 저장했습니다.

# Adding the topic-sentiment combo back to product metadata
finalDF = S3_FEEDBACK_TOPICS.merge(topicDF, on='asin', how='left')

# Only selecting a subset of fields
finalDF = finalDF[['asin', 'TopTopics', 'category', 'title']]

# Saving the final output locally
finalDF.to_csv(S3_FINAL_OUTPUT, index=False)

Amazon QuickSight를 사용하여 데이터 시각화

QuickSight를 사용하여 데이터를 시각화하고 보고서를 생성할 수 있습니다. QuickSight는 다양한 소스의 데이터를 사용하고 지능형 대시보드를 구축하는 데 사용할 수 있는 BI(비즈니스 인텔리전스) 서비스입니다. 이 예제에서는 다음 시각화 예제와 같이 생성한 최종 데이터 세트를 사용하여 QuickSight 분석을 생성합니다.

QuickSight 시각화

Amazon QuickSight에 대한 자세한 내용은 다음을 참조하십시오. Amazon Quicksight 시작하기.

대청소

마지막으로 이 실험에서 사용한 노트북 인스턴스를 AWS 콘솔에서 종료해야 합니다.

결론

이 게시물에서는 Amazon Comprehend를 사용하여 제품 리뷰를 분석하고 주제 모델링을 기법으로 사용하여 상위 주제를 찾는 방법을 시연했습니다. 주제 모델링을 사용하면 여러 주제를 살펴보고 대규모로 구성, 이해 및 요약할 수 있습니다. 데이터 전체에 존재하는 숨겨진 패턴을 빠르고 쉽게 발견한 다음 해당 통찰력을 사용하여 데이터 기반 의사 결정을 내릴 수 있습니다. 주제 모델링을 사용하여 자동으로 고객 지원 티켓에 태그 지정, 주제에 따라 적절한 팀으로 대화 라우팅, 지원 티켓의 긴급성 감지, 대화에서 더 나은 통찰력 얻기, 데이터 기반 계획 생성, 문제 생성과 같은 수많은 비즈니스 문제를 해결할 수 있습니다. - 집중 콘텐츠, 판매 전략 개선, 고객 문제 및 마찰 식별.

이는 몇 가지 예에 불과하지만 조직에서 매일 직면하는 더 많은 비즈니스 문제와 이를 해결하기 위해 다른 ML 기술과 함께 주제 모델링을 사용하는 방법을 생각할 수 있습니다.


저자에 관하여

구프리트 치마구르 프리트 캐나다에 기반을 둔 AWS Professional Services의 데이터 과학자입니다. 그녀는 고객이 기계 학습 및 인공 지능 기술로 혁신하여 데이터에서 비즈니스 가치와 통찰력을 활용할 수 있도록 돕는 데 열정을 쏟고 있습니다. 여가 시간에는 야외에서 하이킹과 책 읽기를 즐깁니다.i

루시디 샴스루시디 샴스 캐나다 AWS Professional Services의 데이터 과학자입니다. 그는 AWS 고객을 위한 기계 학습 제품을 구축합니다. 그는 공상 과학 소설을 읽고 쓰는 것을 좋아합니다.

릭 탈룩다르릭 탈룩다르 Amazon Comprehend Service 팀의 수석 아키텍트입니다. 그는 AWS 고객과 협력하여 대규모 기계 학습을 채택할 수 있도록 지원합니다. 일 외에는 독서와 사진 촬영을 즐깁니다.

타임 스탬프 :

더보기 AWS 기계 학습