세조목

최종 프로젝트 18일차(24.04.15) 본문

데이터 분석 공부/프로젝트

최종 프로젝트 18일차(24.04.15)

세조목 2024. 4. 15. 20:52

최종 프로젝트 17일차입니다.

금일은 앞으로의 방향성에 대해서 팀원들과 얘기 나누고,

관련해서 튜터님들께 튜터링을 받았습니다.

 

튜터링

튜터링 노트

일단 오늘 튜터링 주제는 크게 두 가지였습니다.

  1. 앞으로의 방향성 관련
  2. 사용할 데이터 개수 관련

 

앞으로의 방향성 관련

방향성의 경우 저희가 최종적으로 만들고자 하는 서비스는 '추천' 시스템인데

이 '추천'이라는 것이 정확히 어떠한 알고리즘으로 만들어지는 것인지 알 수 없었습니다.

관련해서 전담 튜터님께 문의드린 결과

저희가 하고자 하는 것은 '추천'보다는 '검색'에 가깝다고 하셨습니다.

왜냐하면 '추천'이라는 것은 개개인의 특성에 맞춰서 특성에 맞는 무언가를 알려주는 것인데

저희가 하고자 하는 것은 그러한 개인의 특성에 맞춰서 알려주는 것이 아니기 때문입니다.

 ※ 저희는 사용자가 특정 키워드를 입력하면 그 키워드가 가장 연관성이 높은 가게를 알려주는 시스템입니다.

그래서 UX(User Experience) 측면에서의 고민이 더욱 필요할 것으로 보여지므로

관련해서 팀원들과 더 얘기를 나눠보고 그게 정립이 됐을 때 기술 구현에 대해 이야기 나눠보는

순서로 진행하는 것이 적절할 것으로 보신다고 피드백 주셨습니다.

이 때 UX 측면에서의 고민이라 하면
'사용자가 무엇을 원해서 우리 서비스를 찾고 있는지',
'우리 서비스에 접속 후 검색까지 어떤 과정을 거칠 것인지'와 같은 고민을 의미합니다.

 

사용할 데이터 개수 관련

두번째 주제는 그래서 우리는 몇 개의 데이터를 가지고서 분석을 진행할 것인가 인데요,

기존에 두 분의 튜터님들께 여쭤봤을 때는 두 분의 의견이 달랐습니다(한 분은 전체 데이터, 한 분은 한 개 '구' 데이터만).

그래서 다른 튜터님의 의견도 궁금하여 여쭤보았는데

그 분께서는 이전에 여쭤본 튜터님들의 답변이 달랐던 건 아마 종사하셨던 도메인이 다르기 때문일 것이라고 하시며

중요한건 우리가 어느정도의 예산을 생각하고 있는지라고 하셨습니다.

튜터님이라면 최종 프로젝트에 30만원 이상 사용하는 것은 너무 무리하는 것 같다고 하셨으며,

일단은 gpt 버전별, 데이터 개수별 비용을 먼저 산정해보고 판단을 내려야 할 것 같다고 말씀하셨습니다.

추가적으로 튜터님 개인적인 생각으로는 2~3만 건 정도의 데이터도 크게 무리는 없을 것 같다고 얘기해주셨습니다.

 

매니저님과의 대화

튜터링이 끝난 후 내배캠 측에서 일부라도 비용을 지원해주지 않을까하는 혹시하 하는 마음으로

담임 매니저님께 문의를 드렸습니다.

그런데 감사하게도 관련해서 다른 팀에서도 프로젝트 진행하면서 비용이 발생하고 있는지 우선적으로 파악한 후

내배캠 측과 한 번 협상을 해보겠다고 말씀해주셨습니다.

안 될 가능성도 있지만 된다 한다면 단 1~2만원이라도 저희에게는 굉장히 크기 때문에

협상의 결과가 좋게 나오기를 기다리고 있습니다.

 

특성 및 긍/부정 점수 도출

그렇게 질의응답과 피드백이 끝난 후에는

프롬프트 수정, gpt를 활용한 특성 및 긍/부정 점수 도출 작업에 다시 착수했습니다.

내일까지는 데이터셋을 완성시키는 것으로 계획을 잡아놨기 때문에

더 이상 프롬프트 수정 작업에 시간을 할애할 수가 없어서

오후 3시부터 오후 7시까지 4시간 정도만 프롬프트 수정을 하고,

 

gpt api를 활용해서 특성 및 긍/부정 점수 도출을 시작했습니다.

아래는 gpt api를 활용할 때 사용한 코드입니다.

import pandas as pd
import openai

OPENAI_API_KEY="API_KEY"
client = openai.OpenAI(api_key = "")

system_prompt = "You must:1. Analyze keywords in detail from the provided bakery reviews and assign scores for all 27 characteristics. For characteristics 1 through 25, output scores between -100 and +100. The 'Pets' keyword must be related to the 'customer's' 'pet'. Wild animals do not qualify. 2. Read the input review text and determine the 26th characteristic, the emotional index, as either 0 or 1. 1 indicates a positive evaluation, and 0 indicates a negative evaluation. If the emotional index cannot be determined, give it a 1. 3. For the 27th characteristic, 'special menu item name', output the name of the special bread mentioned in the review in the order of the characteristics. If none, output 'None'. 4. The result should be output as a list of numbers only. Output example: [40, 50, 0, 0, 0, 10, -5, 0, 10, 0, 10, 30, -70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 'bread name'] Characteristics: 'delicious bread', 'delicious drinks', 'vegan', 'no senior zone', 'no kids zone', 'pets allowed', 'uses whole wheat', 'good view', 'good atmosphere', 'friendly', 'clean store', 'clean restrooms', 'parking available', 'spacious store', 'plenty of seating', 'comfortable seating', 'special menu available', 'photo', 'good music', 'reservation available', 'unique concept', 'beautiful interior', 'price', 'waiting', 'healthy', 'overall review emotional score', 'special menu item name' **Please make sure to output the results in the format shown in the example.** ** No explanation is needed.**"

bread = []
beverage = []
vegan = []
no_senior = []
no_kids = []
pet = []
wholewheat = []
nice_view = []
atmosphere = []
friendly = []
clean_store = []
restroom_clean = []
parking = []
spacious_store = []
plenty_seats = []
comfortable_seats = []
special_menu = []
photo = []
good_music = []
reservation_possible = []
unique_concept = []
beautiful_interior = []
price = []
wait = []
health = []
sentiment = []
bread_name = []

total_prompt_tokens = 0
total_completion_tokens = 0

def response_gpt(prompt):
  global total_prompt_tokens, total_completion_tokens
  response = client.chat.completions.create(
  model="gpt-4-turbo-2024-04-09",
  messages=[
    {"role": "system", "content": system_prompt},
    {"role": "user", "content": prompt}],
  temperature = 0
    )
  
  total_prompt_tokens+=response.usage.prompt_tokens
  total_completion_tokens+=response.usage.completion_tokens

  return response.choices[0].message.content

result = bread, beverage, vegan, no_senior, no_kids, pet, wholewheat, nice_view, atmosphere, friendly, clean_store, restroom_clean, parking, spacious_store, plenty_seats, comfortable_seats, special_menu, photo, good_music, reservation_possible, unique_concept, beautiful_interior, price, wait, health, sentiment, bread_name

for i in total['Review_text']:
  answer = response_gpt(i)
  answer2 = answer.replace('[', '').replace(']', '')
  answer_list = answer2.split(',')

  for i in range(len(answer_list)):
    if i < 26:
      result[i].append(answer_list[i].replace(' ',''))
    elif i == 26:
      text = [j.replace("'",'').replace(' ','') for j in answer_list[26:]]
      result[-1].append(text)

df = pd.DataFrame()
df['bread'] = bread
df['beverage'] = beverage
df['vegan'] = vegan
df['no_senior'] = no_senior
df['no_kids'] = no_kids
df['pet'] = pet
df['whole_wheat'] = wholewheat
df['view'] = nice_view
df['atmosphere'] = atmosphere
df['friendly'] = friendly
df['clean_store'] = clean_store
df['restroom_clean'] = restroom_clean
df['parking'] = parking
df['spacious_store'] = spacious_store
df['plenty_seats'] = plenty_seats
df['comfortable_seats'] = comfortable_seats
df['special_menu'] = special_menu
df['photo'] = photo
df['good_music'] = good_music
df['reservation_possible'] = reservation_possible
df['unique_concept'] = unique_concept
df['beautiful_interior'] = beautiful_interior
df['price'] = price
df['wait'] = wait
df['health'] = health
df['sentiment'] = sentiment
df['bread_name'] = bread_name
df

total_bill_USD = (total_prompt_tokens*0.01 + total_completion_tokens*0.03)/1000
# 24.04.15 기준 환율 1USD = 1383.50 KRW
total_bill_KRW = total_bill_USD*1383.50
print("총 소모 비용 : {} 원".format(total_bill_KRW))

 

 

저희는 '중구' 한 개 구만을 가지고서 분석을 진행하기로 했는데요,

'중구'의 데이터 개수는 대략 15,000개 정도였습니다.

혹시 몰라서 1,000개 먼저 돌려보고 아무런 문제 없으면 나머지 14,000개도 돌리기로 했습니다.

1,000개 데이터를 돌리는데 대략 1시간 16분 정도 소요됐고 비용은 $6.9 정도 발생했습니다.

15,000개 전부 돌리면 대략 $104(14만원)정도 발생할 것으로 예상됩니다.

오늘 코드를 돌려놓고 내일 중으로 데이터셋을 모두 완성시킨 후

바로 클러스터링 작업에 들어갈 예정입니다.