설문 데이터 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

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. 예산 처리하기
설문을 예술치료사들한테 보내보기??