Quiz-2 (2024.09.24) // 범위: 02wk-1 까지

Author

최규빈

Published

September 24, 2024

항목 허용 여부 비고
강의노트 참고 허용 수업 중 제공된 강의노트나 본인이 정리한 자료를 참고 가능
구글 검색 허용 인터넷을 통한 자료 검색 및 정보 확인 가능
생성 모형 사용 허용 안함 인공지능 기반 도구(GPT 등) 사용 불가
# pip install datasets evaluate accelerate

1. emotion 자료 탐색 – 10점

(1)-(2) 모두 부분점수 없음.

아래는 Hugging Face의 emotion 데이터셋을 로드하는 코드이다:

from datasets import load_dataset
emotion = load_dataset('emotion')
/home/cgb3/anaconda3/envs/hf/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm

emotion['train'][-2]는 훈련 데이터의 두 번째 마지막 항목을 출력한다. 출력된 샘플은 다음과 같다.

emotion['train'][-2]
{'text': 'i feel like this was such a rude comment and im glad that t',
 'label': 3}

출력된 샘플은 딕셔너리 형식으로, text에는 문장 “i feel like this was such a rude comment and im glad that t”이 담겨 있다. 이 문장의 감정은 label 항목에 저장되어 있으며, 값은 3으로 나타난다. label 값은 해당 텍스트가 표현하는 감정을 숫자로 표현한 것이다.

감정 레이블은 총 6가지로 나뉘며, 각각의 감정은 다음과 같이 정의된다:

emotion['train'].features['label'].names
['sadness', 'joy', 'love', 'anger', 'fear', 'surprise']
{
  0: 'sadness',
  1: 'joy',
  2: 'love',
  3: 'anger',
  4: 'fear',
  5: 'surprise'
}
{0: 'sadness', 1: 'joy', 2: 'love', 3: 'anger', 4: 'fear', 5: 'surprise'}

따라서, 문장 “i feel like this was such a rude comment and im glad that t” 의 감정은 label이 3이므로, “anger”에 해당한다.

(1) emotion 데이터셋의 각 분할(train, validation, test)에서 감정별로 몇 개의 데이터가 있는지를 조사하라. 즉 아래의 표에서 빈칸에 해당하는 숫자를 계산할 수 있는 코드를 제시하라. – 5점

Dataset 0:Sadness 1:Joy 2:Love 3:Anger 4:Fear 5:Surprise Total
Train ?? ?? ?? ?? ?? ?? 16000
Validation ?? ?? ?? ?? ?? ?? 2000
Test ?? ?? ?? ?? ?? ?? 2000

note: 정답예시: 아래와 같은 형식으로 출력하는 코드를 작성하면 정답으로 인정

train
{0: 4666, 1: 5362, 2: 1304, 3: 2159, 4: 1937, 5: 572}
--
validation
{0: 550, 1: 704, 2: 178, 3: 275, 4: 212, 5: 81}
--
test
{0: 581, 1: 695, 2: 159, 3: 275, 4: 224, 5: 66}
--

hint: 아래중 원하는 형태를 이용하여 풀이하면 편리하다.

  • emotion['train']['label']
  • emotion['train'].to_dict()
  • emotion['train'].to_pandas()

(풀이)

{key: {i:emotion[key]['label'].count(i) for i in set(emotion[key]['label'])} for key in emotion}
{'train': {0: 4666, 1: 5362, 2: 1304, 3: 2159, 4: 1937, 5: 572},
 'validation': {0: 550, 1: 704, 2: 178, 3: 275, 4: 212, 5: 81},
 'test': {0: 581, 1: 695, 2: 159, 3: 275, 4: 224, 5: 66}}

(2) emotion 데이터셋의 test셋에서 각 감정(label)별로 가장 짧은 길이를 가진 텍스트를 출력하는 코드를 작성하라. – 5점

note: 정답예시는 아래와 같다.

['i feels so lame',
 'i feel any better',
 'i just feel tender',
 'i feel so damn agitated',
 'i feel alarmed',
 'i feel all funny sometimes']

(풀이1)

_라벨0 = [dct['text'] for dct in emotion['test'] if dct['label']==0]
min(map(len,_라벨0))
[txt for txt in _라벨0 if len(txt)==min(map(len,_라벨0))]
['i feels so lame']
def func(_라벨0):
    min(map(len,_라벨0))
    return [txt for txt in _라벨0 if len(txt)==min(map(len,_라벨0))]
list(map(func,[[dct['text'] for dct in emotion['test'] if dct['label']==lbl] for lbl in range(6)]))
[['i feels so lame'],
 ['i feel any better'],
 ['i just feel tender'],
 ['i feel so damn agitated'],
 ['i feel alarmed'],
 ['i feel all funny sometimes']]

(풀이2)

df = emotion['test'].to_pandas()
df['length'] = list(map(len,df['text']))
df = df.sort_values('length')
df 
text label length
221 i feel alarmed 4 14
1632 id feel frantic 4 15
634 i feels so lame 0 15
873 i feel soo lonely 0 17
1389 i feel any better 1 17
... ... ... ...
611 i couldnt help feeling for him and this awful ... 0 284
119 i feel like i know who most of them are by now... 1 287
966 i have the joy of allowing kids to feel like t... 1 289
475 i feel very honored to have been shortlisted w... 1 294
618 i am feeling a little more relaxed i am certai... 1 296

2000 rows × 3 columns

for _,subdf in df.groupby('label'):
    display(subdf.text.iloc[0])
'i feels so lame'
'i feel any better'
'i just feel tender'
'i feel so damn agitated'
'i feel alarmed'
'i feel all funny sometimes'

2. emotion 자료 감성분석 – 80점

(1)은 부분점수 있음, (2)는 부분점수 없음.

(1) 아래의 reference 를 참고하여 emotion에 대한 감성분석모델을 학습하는 코드를 작성하라. – 60점

ref:

세부지침 – 세부지침을 따르지 않을시 감점이 있음 (지침1은 30점감점 지침2는 5점감점)

지침1. Trainer생성시 eval_dataset에는 emotion['validation']를 전처리한 데이터를 이용하라. (emotion['test'] 가 아니라)

지침2. TrainingArguments에서 num_train_epochs은 1로 설정하라.

hint: imdb 자료의 경우 num_labels = 2 이지만, emotion 자료의 경우 그렇지 않음을 유의하라.

(풀이)

import datasets
import transformers
import evaluate
import numpy as np
## Step1 
데이터불러오기 = datasets.load_dataset
데이터전처리하기1 = 토크나이저 = transformers.AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased") 
def 데이터전처리하기2(examples):
    return 데이터전처리하기1(examples["text"], truncation=True)
## Step2 
인공지능생성하기 = transformers.AutoModelForSequenceClassification.from_pretrained
## Step3 
데이터콜렉터 = transformers.DataCollatorWithPadding(tokenizer=토크나이저)
def 평가하기(eval_pred):
    predictions, labels = eval_pred
    predictions = np.argmax(predictions, axis=1)
    accuracy = evaluate.load("accuracy")
    return accuracy.compute(predictions=predictions, references=labels)
트레이너세부지침생성기 = transformers.TrainingArguments
트레이너생성기 = transformers.Trainer
## Step4 
강인공지능생성하기 = transformers.pipeline
/home/cgb3/anaconda3/envs/hf/lib/python3.12/site-packages/transformers/tokenization_utils_base.py:1601: FutureWarning: `clean_up_tokenization_spaces` was not set. It will be set to `True` by default. This behavior will be depracted in transformers v4.45, and will be then set to `False` by default. For more details check this issue: https://github.com/huggingface/transformers/issues/31884
  warnings.warn(
## Step1 
데이터 = 데이터불러오기('emotion')
전처리된데이터 = 데이터.map(데이터전처리하기2,batched=True)
전처리된훈련자료, 전처리된검증자료 = 전처리된데이터['train'], 전처리된데이터['validation']
## Step2 
인공지능 = 인공지능생성하기("distilbert/distilbert-base-uncased", num_labels=6)
## Step3 
트레이너세부지침 = 트레이너세부지침생성기(
    output_dir="my_awesome_model",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=1, # 전체문제세트를 2번 공부하라..
    weight_decay=0.01,
    eval_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
    push_to_hub=False,
)
트레이너 = 트레이너생성기(
    model=인공지능,
    args=트레이너세부지침,
    train_dataset=전처리된훈련자료,
    eval_dataset=전처리된검증자료,
    tokenizer=토크나이저,
    data_collator=데이터콜렉터,
    compute_metrics=평가하기,
)
트레이너.train()
Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert/distilbert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight', 'pre_classifier.bias', 'pre_classifier.weight']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
[1000/1000 00:26, Epoch 1/1]
Epoch Training Loss Validation Loss Accuracy
1 0.264700 0.203025 0.932500

TrainOutput(global_step=1000, training_loss=0.5039049835205078, metrics={'train_runtime': 27.0307, 'train_samples_per_second': 591.921, 'train_steps_per_second': 36.995, 'total_flos': 194625049506048.0, 'train_loss': 0.5039049835205078, 'epoch': 1.0})

(2) 1-(2)에서 구해진 text에 대하여 감성분석을 수행하라. – 20점

힌트 1-(2)를 풀지못하였다면 아래의 코드를 이용하여 강제설정할 것

['i feels so lame',
 'i feel any better',
 'i just feel tender',
 'i feel so damn agitated',
 'i feel alarmed',
 'i feel all funny sometimes']
## Step4 
강인공지능 = 강인공지능생성하기("sentiment-analysis", model="my_awesome_model/checkpoint-1000")
강인공지능([
    'i feels so lame',
    'i feel any better',
    'i just feel tender',
    'i feel so damn agitated',
    'i feel alarmed',
    'i feel all funny sometimes'
])
Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.
[{'label': 'LABEL_0', 'score': 0.9876920580863953},
 {'label': 'LABEL_1', 'score': 0.9838089942932129},
 {'label': 'LABEL_2', 'score': 0.9324933886528015},
 {'label': 'LABEL_3', 'score': 0.7004759907722473},
 {'label': 'LABEL_4', 'score': 0.9285796880722046},
 {'label': 'LABEL_5', 'score': 0.8900141716003418}]

3. O/X. – 10점

모두 맞출경우만 정답으로 인정

아래의 제시문을 읽고 올바르게 해석한 사람을 모두 고르라.

Note

나는 50,000개의 “텍스트-라벨” 데이터를 인공지능에게 학습시켰다. 학습이 끝난 후, 50,000개의 데이터 중 20개의 샘플을 무작위로 뽑아 테스트한 결과, 인공지능은 20개의 텍스트에 대한 라벨을 모두 정확히 맞췄다. 이 결과만으로 인공지능이 영화 리뷰에 대한 감성 분석(긍정/부정)을 성공적으로 학습했다고 결론을 내려도 될까?

민지: 제시문에 따르면 50,000개의 훈련 데이터를 사용하여 인공지능을 학습시켰으니, train_data의 크기는 50,000이라고 볼 수 있어.

하니: 50,000개의 데이터 중 일부를 무작위로 샘플링하여 평가하는 것은 올바른 방법이 아니야. 학습에 사용되지 않은 별도의 테스트 데이터를 사용해 성능을 평가해야 인공지능이 제대로 학습했는지 알 수 있어.

다니엘: 하니의 말이 맞아. 50,000개의 데이터 중 20개를 샘플링한 게 아니라, 50,000개의 데이터를 모두 올바르게 맞췄다고 하더라도, 새로운 데이터에 대해 성능이 좋다고 단정할 수는 없어. 중요한 건 새로운 데이터에 대한 예측 성능이지.

해린: 맞아, 훈련 데이터 (=학습 데이터) 를 너무 반복해서 학습하다 보면, 인공지능이 그 데이터에만 지나치게 맞춰져서 새로운 데이터를 잘 처리하지 못할 수 있어. 결국 모델이 학습 데이터에서는 좋은 성능을 내지만, 학습하지 않은 데이터나 실제 환경에서는 성능이 떨어질 위험이 생기는 거야.”

혜인: 그렇구나! 그래서 50,000개의 데이터가 있더라도, 그 중 일부만 학습에 사용하고, 나머지는 평가용으로 따로 남겨두기도 하는 거네. 이렇게 하면 인공지능이 새로운 데이터에서도 잘 작동하는지, 성능을 확인할 수 있는 거잖아?

모두 정답