HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
장지원 페이지/
📕
2024 UGRP
/
Member Page
Member Page
/
장지원
장지원
/
#29. ToDo 감정 라벨 바꾸기

#29. ToDo 감정 라벨 바꾸기

태그
연구
날짜
Oct 28, 2024
상태
완료
설문 데이터 label 변경 최종 코드
import pandas as pd import os import json import re import requests from PIL import Image from io import BytesIO from pdf2image import convert_from_path import tempfile # 엑셀 파일 경로 file_path = r'C:\Users\User\Desktop\감정 그림 그리기 설문조사(UGRP)(응답).xlsx' # 실제 파일 경로로 수정하세요. save_path = 'G:\\dataset' # 실제 저장 경로로 수정하세요. # 엑셀 파일 읽기 df = pd.read_excel(file_path) # 해당 키워드를 포함하는 열들 중 NaN이 아닌 첫 번째 값을 선택하는 함수 def find_first_non_empty_value(row, keyword): matching_columns = [col for col in df.columns if keyword in col] # NaN이 아닌 첫 번째 값을 반환 for col in matching_columns: if pd.notna(row[col]): return row[col] return None # 모든 값이 NaN일 경우 None 반환 # 구글 드라이브 링크를 다운로드 가능한 링크로 변환하는 함수 def convert_drive_link(drive_url): file_id = drive_url.split('=')[-1] return f"https://drive.google.com/uc?export=download&id={file_id}" # 이미지 다운로드 함수 def download_image(url, path): try: # 구글 드라이브 링크 변환 if 'drive.google.com' in url: url = convert_drive_link(url) # 이미지 다운로드 response = requests.get(url) # 응답 상태 코드 확인 if response.status_code != 200: print(f"Failed to download {url}: Status code {response.status_code}") return # 응답 데이터가 비어 있지 않은지 확인 if not response.content: print(f"Failed to download {url}: Empty response") return # 파일의 첫 바이트를 확인하여 PDF인지 판단 if response.content.startswith(b'%PDF'): # PDF 파일인 경우 with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as temp_pdf: temp_pdf.write(response.content) temp_pdf_path = temp_pdf.name # 임시 PDF 파일 경로 # PDF를 이미지로 변환 images = convert_from_path(temp_pdf_path) image = images[0] # 첫 번째 페이지를 선택 # 임시 PDF 파일 삭제 os.remove(temp_pdf_path) else: # 이미지 열기 image = Image.open(BytesIO(response.content)) # RGBA 모드일 경우 RGB로 변환 if image.mode == 'RGBA': image = image.convert('RGB') # 이미지 저장 경로에 해당 폴더가 없을 경우 생성 folder_path = os.path.dirname(path) if not os.path.exists(folder_path): os.makedirs(folder_path) image.save(path, 'JPEG') # JPG 형식으로 저장 print(f"Image saved to {path}") except Exception as e: print(f"Failed to download {url}: {e}") # 필요한 열 추출 df_selected = pd.DataFrame() df_selected['name'] = df.apply(lambda row: find_first_non_empty_value(row, '참여자 성명'), axis=1) df_selected['emotion'] = df.apply(lambda row: find_first_non_empty_value(row, '가까운 감정'), axis=1) df_selected['image'] = df.apply(lambda row: find_first_non_empty_value(row, '업로드 해주세요'), axis=1) df_selected['intention'] = df.apply(lambda row: find_first_non_empty_value(row, '그림의 의도를 적어주세요'), axis=1) df_selected['weight1'] = df.apply(lambda row: find_first_non_empty_value(row, '위 예시 사진'), axis=1) df_selected['weight2'] = df.apply(lambda row: find_first_non_empty_value(row, '자신이 그린 그림'), axis=1) # 감정 열에서 한글 설명 제거 및 감정 그룹화 df_selected['emotion'] = df_selected['emotion'].apply(lambda x: re.sub(r'\([^)]*\)', '', str(x)).strip() if pd.notnull(x) else x) df_selected['emotion'] = df_selected['emotion'].replace({"Amusement": "Happiness", "Excitement": "Happiness", "Contentment": "Happiness", "Awe": "Surprise"}) # 감정별 폴더 생성 (이미지 저장 폴더 'image'도 함께 생성) image_folder = os.path.join(save_path, 'image') if not os.path.exists(image_folder): os.makedirs(image_folder) # JSON 데이터 생성 json_data = [] for idx, row in df_selected.iterrows(): image_id = row['name'] emotion = row['emotion'] image_url = row['image'] intention = row['intention'] weight1 = row['weight1'] weight2 = row['weight2'] # 감정별 하위 폴더 생성 emotion_folder = os.path.join(image_folder, emotion) if not os.path.exists(emotion_folder): os.makedirs(emotion_folder) # 이미지 파일 저장 경로 (emotion/{image_id}.jpg 형식으로 저장) image_path = os.path.join(emotion_folder, f"{image_id}.jpg") # 이미지 다운로드 및 저장 if pd.notnull(image_url): download_image(image_url, image_path) # JSON 데이터 추가 json_data.append({ 'image': f"image/{emotion}/{image_id}.jpg", # 경로를 JSON에 포함 'label': emotion, 'image_id': image_id, 'weight1': weight1, 'weight2': weight2, 'intention': intention }) # JSON 파일 저장 json_file_path = os.path.join(save_path, 'dataset_info.json') with open(json_file_path, 'w', encoding='utf-8') as f: json.dump(json_data, f, ensure_ascii=False, indent=4) print("작업이 완료되었습니다.")
 

1. UGRP 주제 명 변경

  • Point: 감정이 라벨링 되어 있고, 의도가 담긴 데이터 셋 제작
  • Point: 데이터 셋을 바탕으로 감정 분류 가능한 모델 제작
  • Point: …
i.e. 감정 라벨링 스케치 데이터셋 구축 및 제한적 데이터 환경에서의 PEFT 기반 모델 성능 향상 연구

2. ToDo

  • 설문 데이터 11.03까지 마무리 → 11.05까지 확정 데이터 셋 제작
  • 최종 보고서 작성
  • 최종 학습
    • 호진:
    • 태완:
    • 지원:
    • 파인튜닝 메소드, 파라미터 fix 시키고 데이터 셋 test
      • emoset → form
      • emoset+form → form
      • emoset(GAN) → form
      • emoset(GAN)+form → form
      • emoset(GAN)+crawling → form
      • emoset(GAN)+crawling+form → form
    • 데이터 셋, 파라미터 fix 시키고, 파인튜닝 메소드 test
      • original fine tuning
      • adpter
      • LoRA
    • 파인튜닝 메소드, 데이터 셋 fix 시키고, 파라미터 test
      • LoRA’s param tuning
      GPT 정확도?
      import os import json import openai # OpenAI API 키 설정 openai.api_key = "sk-proj-비밀입니다.." # 자신의 API 키로 변경하세요 def test_model(api_key, dataset_path): openai.api_key = api_key # 데이터 로드 with open(dataset_path, 'r', encoding='utf-8') as f: dataset = json.load(f) # 모델 예측 레이블 possible_labels = ["Happiness", "Disgust", "Fear", "Sadness", "Surprise"] correct_predictions = 0 for data in dataset: prompt = ( f"Analyze the following image data and predict the emotion it represents. " f"Choose one of these labels only: {', '.join(possible_labels)}.\n\n" f"Data: {data}\n\n" "Label: " ) # 모델 호출 response = openai.ChatCompletion.create( model="gpt-4", messages=[ {"role": "system", "content": "You are an assistant that classifies emotions."}, {"role": "user", "content": prompt} ] ) # 모델이 예측한 레이블을 추출 predicted_label = response['choices'][0]['message']['content'].strip() # 실제 레이블과 비교하여 정확도 계산 actual_label = data['label'] if predicted_label == actual_label: correct_predictions += 1 accuracy = correct_predictions / len(dataset) print(f"Model accuracy: {accuracy * 100:.2f}%") # API 키와 데이터셋 경로 설정 api_key = "sk-proj-..." # 여기에 실제 API 키를 입력하세요 dataset_path = r'G:\dataset\dataset_info.json' # JSON 파일 경로 설정 # 모델 테스트 실행 test_model(api_key, dataset_path)
      Model accuracy: 100.00%
      meta data 가지고 한 것이라 한다.
      이미지 넣으려면 openAI clip이나 GPT-4 Vision 이용해야 한다.
      openAI-clip
      notion image
      import json import torch from PIL import Image from transformers import CLIPProcessor, CLIPModel import os # CLIP 모델 및 프로세서 로드 model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32") processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32") # 데이터셋과 레이블 목록 설정 dataset_path = r'G:\dataset\dataset_info.json' # JSON 파일 경로 설정 images_base_path = r'G:\dataset' # 이미지 기본 경로 설정 possible_labels = ["Happiness", "Disgust", "Fear", "Sadness", "Surprise"] # JSON 파일에서 데이터 로드 with open(dataset_path, 'r', encoding='utf-8') as f: dataset = json.load(f) correct_predictions = 0 # 데이터셋 반복 처리 for data in dataset: # 이미지 파일 경로 가져오기 image_filename = data['image'] image_path = os.path.join(images_base_path, image_filename) # 이미지 전체 경로 생성 label = data['label'] # 이미지 로드 및 전처리 try: image = Image.open(image_path).convert("RGB") except FileNotFoundError: print(f"파일을 찾을 수 없습니다: {image_path}") continue # 이미지가 없으면 다음으로 넘어감 # 텍스트 프롬프트 생성 text_inputs = [f"This image represents {label} emotion." for label in possible_labels] # 모델 입력 데이터 준비 inputs = processor(text=text_inputs, images=image, return_tensors="pt", padding=True) # 모델 예측 with torch.no_grad(): outputs = model(**inputs) logits_per_image = outputs.logits_per_image probs = logits_per_image.softmax(dim=1) predicted_label = possible_labels[probs.argmax().item()] # 예측이 맞는지 확인 if predicted_label == label: correct_predictions += 1 # 정확도 출력 accuracy = correct_predictions / len(dataset) print(f"Model accuracy: {accuracy * 100:.2f}%")
      Model accuracy: 41.67%
      GPT vision(GPT-4o) → 요거 넘기는 걸 목표로!!
      import json import requests import openai import base64 from PIL import Image # Image 클래스를 가져오는 부분 import os # OpenAI API 키 설정 openai.api_key = 'sk-proj-...' # 데이터셋과 레이블 목록 설정 dataset_path = r'G:\dataset\dataset_info.json' # JSON 파일 경로 설정 images_base_path = r'G:\dataset' # 이미지 기본 경로 설정 # JSON 파일에서 데이터 로드 with open(dataset_path, 'r', encoding='utf-8') as f: dataset = json.load(f) correct_predictions = 0 # 데이터셋 반복 처리 for data in dataset: # 이미지 파일 경로 가져오기 image_filename = data['image'] image_path = os.path.join(images_base_path, image_filename) # 이미지 전체 경로 생성 label = data['label'] # 이미지 로드 및 base64로 인코딩 try: with Image.open(image_path) as img: img = img.convert("RGB") # 이미지를 RGB로 변환 img = img.resize((256, 256)) # 이미지 크기 조정 (256x256) img.save("temp_image.jpg", format="JPEG") # 임시 JPEG 이미지로 저장 with open("temp_image.jpg", "rb") as image_file: image_data = image_file.read() image_base64 = base64.b64encode(image_data).decode('utf-8') # 이미지를 base64로 인코딩 except FileNotFoundError: print(f"파일을 찾을 수 없습니다: {image_path}") continue # 이미지가 없으면 다음으로 넘어감 # API 요청 possible_labels = ["Happiness", "Disgust", "Fear", "Sadness", "Surprise"] question = ( f"Analyze the following image data and predict the emotion it represents. " f"Choose one of these labels only: {', '.join(possible_labels)}.\n\n" # f"Data: {data}\n\n" # JSON 데이터 포함 f"[IMAGE] {image_base64}\n\n" # base64 인코딩된 이미지 추가 "Provide only the label without any explanation: " ) # OpenAI API 요청 response = requests.post( "https://api.openai.com/v1/chat/completions", headers={ "Authorization": f"Bearer {openai.api_key}", "Content-Type": "application/json" }, json={ "model": "gpt-4o-mini", # GPT 비전 모델 사용 "messages": [ {"role": "user", "content": question} ], "max_tokens": 50, } ) # API 응답 출력 # print(f"Response from API: {response.text}") # 응답 출력 # 예측된 라벨 추출 if response.status_code == 200: answer = response.json() predicted_label = answer['choices'][0]['message']['content'].strip() else: print(f"API 요청 실패: {response.status_code} - {response.text}") continue # 예측이 맞는지 확인 if predicted_label == label: correct_predictions += 1 # 임시 파일 삭제 if os.path.exists("temp_image.jpg"): os.remove("temp_image.jpg") # 정확도 출력 accuracy = correct_predictions / len(dataset) print(f"Model accuracy: {accuracy * 100:.2f}%")
      Model accuracy: 58.33%

3. 예산 처리하기

설문을 예술치료사들한테 보내보기??