BERT 모델을 M2 맥북에서 돌려보는데, 런타임에러가 해결이 안됩니다.

  • 어떻게 동작하도록 하고 싶은지에 대한 설명 : 전처리 작업이 된 '영어', '문장' 데이터를 학습 시킨 후 이후 문장을 집어넣었을 때 어떤 '레이블'로 예측되는지 알아내는 작업

  • 겪고 있는 문제에 대한 상세한 설명 (에러의 경우 에러 메시지 포함) : BERT 모델을 쓰고 싶은데 자꾸 런타임에러가 발생함

  • Python, PyTorch 및 사용하고 계신 주요 라이브러리의 버전 등을 포함한 환경 설명

  • 실행하셨던, 혹은 문제 발생의 원인으로 의심하는 코드
    !--> GPT에서 생성한 코드와 각종 커뮤니티에서 확인 한 결과를 조합해서 코드를 만들어내어 명확하지 않음.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from transformers import BertTokenizer, BertForSequenceClassification, Trainer, TrainingArguments
from torch.utils.data import Dataset
from sklearn.metrics import accuracy_score, precision_recall_fscore_support

import torch

Load data

data = pd.read_excel("/Users/jakedb/Downloads/BERT/미래엔_2학년_pp.xlsx")

mps_device = torch.device("mps")

Define the BERT model and tokenizer

model_name = 'bert-base-uncased'
tokenizer = BertTokenizer.from_pretrained(model_name)
number_of_labels = data['label'].nunique()
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=number_of_labels)

model.to(mps_device)

device = (
"cuda"
if torch.cuda.is_available()
else "mps"
if torch.backends.mps.is_available()
else "cpu"
)
print(f"Using {device} device")

Prepare the data

texts = data['text'].tolist()
labels = data['label'].tolist()

Initialize the LabelEncoder

encoder = LabelEncoder()

Fit the encoder and transform the labels

labels = encoder.fit_transform(labels)

Split the data into a training set and a test set

train_texts, test_texts, train_labels, test_labels = train_test_split(texts, labels, test_size=0.2, random_state=42)

Now you can tokenize your texts

train_encodings = tokenizer(train_texts, truncation=True, padding=True)
test_encodings = tokenizer(test_texts, truncation=True, padding=True)

Define a PyTorch Dataset

class EnglishTextDataset(Dataset):
def init(self, encodings, labels, device):
self.encodings = encodings
self.labels = labels
self.device = device

def __getitem__(self, idx):
    item = {key: torch.tensor(val[idx]).to(self.device) for key, val in self.encodings.items()}
    item['labels'] = torch.tensor(self.labels[idx]).to(self.device)
    return item

def __len__(self):
    return len(self.labels)

train_dataset = EnglishTextDataset(train_encodings, train_labels, device=device)
test_dataset = EnglishTextDataset(test_encodings, test_labels, device=device)

Define metrics

def compute_metrics(pred):
labels = pred.label_ids
preds = pred.predictions.argmax(-1)
precision, recall, f1, _ = precision_recall_fscore_support(labels, preds, average='binary')
acc = accuracy_score(labels, preds)
return {
'accuracy': acc,
'f1': f1,
'precision': precision,
'recall': recall
}

Define the training arguments

training_args = TrainingArguments(
output_dir='./results',
num_train_epochs=3,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
warmup_steps=500,
weight_decay=0.01,
logging_dir='./logs',
)

Create the Trainer and train the model

trainer = Trainer(
model=model.to(device),
args=training_args,
train_dataset=train_dataset,
eval_dataset=test_dataset,
compute_metrics=compute_metrics
)

Train the model

trainer.train()

Evaluate the model

eval_result = trainer.evaluate()
print(eval_result)

위까지 코드 전체.

Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertForSequenceClassification: ['cls.predictions.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.dense.bias', 'cls.seq_relationship.bias', 'cls.seq_relationship.weight', 'cls.predictions.transform.dense.weight', 'cls.predictions.transform.LayerNorm.bias']

  • This IS expected if you are initializing BertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).
  • This IS NOT expected if you are initializing BertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
    Some weights of BertForSequenceClassification were not initialized from the model checkpoint at bert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight']
    You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
    Using mps device
    /Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/optimization.py:411: FutureWarning: This implementation of AdamW is deprecated and will be removed in a future version. Use the PyTorch implementation torch.optim.AdamW instead, or set no_deprecation_warning=True to disable this warning
    warnings.warn(
    0%| | 0/16947 [00:00<?, ?it/s]Traceback (most recent call last):
    File "/Users/jakedb/Downloads/BERT/main.py", line 105, in
    trainer.train()
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/trainer.py", line 1645, in train
    return inner_training_loop(
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/trainer.py", line 1938, in _inner_training_loop
    tr_loss_step = self.training_step(model, inputs)
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/trainer.py", line 2759, in training_step
    loss = self.compute_loss(model, inputs)
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/trainer.py", line 2784, in compute_loss
    outputs = model(**inputs)
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/models/bert/modeling_bert.py", line 1562, in forward
    outputs = self.bert(
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/models/bert/modeling_bert.py", line 1013, in forward
    embedding_output = self.embeddings(
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/models/bert/modeling_bert.py", line 230, in forward
    inputs_embeds = self.word_embeddings(input_ids)
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/sparse.py", line 162, in forward
    return F.embedding(
    File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/functional.py", line 2210, in embedding
    return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)
    RuntimeError: Placeholder storage has not been allocated on MPS device!
    0%| | 0/16947 [00:00<?, ?it/s]

여기가 오류 메세지입니다.

질문1. 현재 커뮤니티에서 진행하라고 한 M2 Mac 환경 설정도 다 되었고, Using mps device 라고 정상으로 뜨는 상황인데, 계속 에러가 발생하는 이유는 무엇인가요?

질문2. model.to(device) 로 설정한 라인에서 계속 오류가 나오는데, 코드 전반적으로 틀린 부분이 많은가요?

코드나 인공지능 활용을 이제 막 배우는 단계입니다. 많은 도움 부탁드립니다. 감사합니다.

  • 아래 답변은 OpenAI의 GPT-3.5(ChatGPT) 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요! BERT 모델을 M2 맥북에서 실행하려고 하면 런타임 에러가 발생하는 문제에 대해 도움을 드리겠습니다.

  1. 질문1에 대한 답변:
    에러 메시지를 보면 "RuntimeError: Placeholder storage has not been allocated on MPS device!"라고 나와 있습니다. 이 에러는 MPS(Multi-Process Service) 디바이스에서 할당되지 않은 플레이스홀더(storage)로 인해 발생하는 것으로 보입니다. MPS는 텐서 연산을 병렬로 처리하기 위한 기술이며, 현재 코드에서는 MPS 디바이스를 사용하도록 설정되어 있습니다.

M2 맥북에서 MPS 디바이스를 사용하려면 몇 가지 추가 설정이 필요합니다. 아래의 링크에서 MPS 디바이스를 사용하는 방법에 대한 자세한 내용을 확인할 수 있습니다.

MPS 디바이스를 사용하지 않고 CPU 또는 GPU 디바이스를 사용하도록 변경하면 이 문제를 해결할 수 있습니다. 아래의 코드를 참고하여 디바이스를 변경해 보세요.

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using {device} device")

model.to(device)
  1. 질문2에 대한 답변:
    코드 전반적으로 큰 문제는 보이지 않습니다. 그러나 몇 가지 주의해야 할 점이 있습니다.
  • model.to(mps_device) 코드에서 mps_device 변수가 정의되어 있지 않습니다. 이 부분을 수정해야 합니다.
  • TrainingArguments 클래스의 per_device_train_batch_sizeper_device_eval_batch_size 매개변수는 GPU 메모리에 맞게 조정해야 합니다. 현재는 16과 64로 설정되어 있는데, GPU 메모리에 맞게 조정해 보세요.

이 외에는 큰 문제가 보이지 않습니다. 코드를 실행하기 전에 위의 사항을 수정하고 다시 시도해 보세요.

이 외에도 PyTorch 공식 튜토리얼과 한국어 튜토리얼을 참고하면 도움이 될 수 있습니다.

혹시 제가 잘못된 답변을 드렸을 경우 양해 부탁드립니다. 추가적인 도움이 필요하시면 언제든지 질문해 주세요. 감사합니다!


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 OpenAI의 GPT-4 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요, PyTorch를 사용하시는데 어려움을 겪고 계신 것 같아 곤란하시겠습니다. 질문을 정리해보면, BERT 모델을 M2 맥북에서 실행하려고 하는데 런타임 에러가 발생하고, 특히 model.to(device) 부분에서 문제가 생기는 것 같다는 내용이군요.

먼저, M1이나 M2 칩을 사용하는 맥에서 PyTorch를 사용하려면 몇 가지 추가적인 설정이 필요합니다. PyTorch는 기본적으로 Intel과 Nvidia의 하드웨어에 최적화되어 있기 때문에, Apple Silicon(M1, M2)에서는 추가적인 설정이 필요합니다.

그러나, 현재 PyTorch는 공식적으로 Apple Silicon을 지원하지 않습니다. 따라서 M1이나 M2 칩에서 PyTorch를 실행하려면 Rosetta 2를 통해 Intel 버전의 Python을 설치하고 사용해야 합니다. 이는 Apple Silicon의 성능을 최대로 활용하지 못하는 단점이 있습니다.

그리고 코드에서 mps_device = torch.device("mps")와 같이 MPS(Metal Performance Shaders)를 사용하려고 하신 것 같은데, 현재 PyTorch는 MPS를 지원하지 않습니다. 따라서 이 부분은 삭제하셔야 합니다.

그리고 model.to(device) 부분에서 문제가 발생하는 것은, 위에서 언급한 MPS를 사용하려고 하기 때문일 가능성이 큽니다. 이 부분을 model.to('cpu')로 변경하시면 됩니다.

따라서, 위의 내용을 종합하면 다음과 같이 코드를 수정하시면 됩니다.

# mps_device = torch.device("mps")  # MPS는 지원하지 않으므로 삭제합니다.
model_name = 'bert-base-uncased'
tokenizer = BertTokenizer.from_pretrained(model_name)
number_of_labels = data['label'].nunique()
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=number_of_labels)

model.to('cpu')  # MPS 대신 CPU를 사용합니다.

device = (
"cuda"
if torch.cuda.is_available()
else "cpu"  # MPS 대신 CPU를 사용합니다.
)
print(f"Using {device} device")

이렇게 수정하신 후에도 문제가 발생한다면, 추가적인 정보가 필요할 것 같습니다. 그럴 경우에는 사용하시는 Python, PyTorch, transformers 라이브러리의 버전 정보를 알려주시면 더욱 정확한 도움을 드릴 수 있을 것 같습니다.

마지막으로, 제가 제시한 해결책이 반드시 맞는 것은 아니므로, 다른 가능성도 고려하시면서 문제를 접근하시는 것이 좋습니다. PyTorch에 대한 자세한 내용은 PyTorch 공식 문서를 참고하시면 도움이 될 것입니다.

도움이 되었기를 바라며, 추가적인 질문이 있으시면 언제든지 말씀해주세요. 감사합니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  1. 모델은 MPS로 적용되었는데 입력이 그렇지 않은것 같습니다. EnglishTextDataset 입력 부분의 device가 MPS로 설정 되셨는지 확인 해보시면 좋겠습니다.

댓글 주셔서 감사합니다.
혹시 아래와 같이 수정하는게 맞을까요?

class EnglishTextDataset(Dataset):
def init(self, encodings, labels, device):
self.encodings = encodings
self.labels = labels
self.device = mps_device

def __getitem__(self, idx):
    item = {key: torch.tensor(val[idx]).to(self.device) for key, val in self.encodings.items()}
    item['labels'] = torch.tensor(self.labels[idx]).to(self.device)
    return item

def __len__(self):
    return len(self.labels)

train_dataset = EnglishTextDataset(train_encodings, train_labels, device=mps_device)
test_dataset = EnglishTextDataset(test_encodings, test_labels, device=mps_device)

class EnglishTextDataset(Dataset):
def init (self, encodings, labels, device):
self.encodings = encodings
self.labels = labels
self.device = device

EnglishTextDataset쪽은 기존처럼 이렇게 가시면 됩니다.

train_dataset = EnglishTextDataset(train_encodings, train_labels, device=mps_device)
test_dataset = EnglishTextDataset(test_encodings, test_labels, device=mps_device)

여기만 mps_device 들어가게 수정하시면 되구요.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from transformers import BertTokenizer, BertForSequenceClassification, Trainer, TrainingArguments
from torch.utils.data import Dataset
from sklearn.metrics import accuracy_score, precision_recall_fscore_support

import torch

# Load data
data = pd.read_excel("/Users/jakedb/Downloads/BERT/미래엔_2학년_pp.xlsx")
mps_device = torch.device("mps")


# Define the BERT model and tokenizer
model_name = 'bert-base-uncased'
tokenizer = BertTokenizer.from_pretrained(model_name)
number_of_labels = data['label'].nunique()
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=number_of_labels)

model.to(mps_device)



device = (
    "cuda"
    if torch.cuda.is_available()
    else "mps"
    if torch.backends.mps.is_available()
    else "cpu"
)
print(f"Using {device} device")


# Prepare the data
texts = data['text'].tolist()
labels = data['label'].tolist()

# Initialize the LabelEncoder
encoder = LabelEncoder()

# Fit the encoder and transform the labels
labels = encoder.fit_transform(labels)

# Split the data into a training set and a test set
train_texts, test_texts, train_labels, test_labels = train_test_split(texts, labels, test_size=0.2, random_state=42)

# Now you can tokenize your texts
train_encodings = tokenizer(train_texts, truncation=True, padding=True)
test_encodings = tokenizer(test_texts, truncation=True, padding=True)

# Define a PyTorch Dataset
class EnglishTextDataset(Dataset):
    def __init__(self, encodings, labels, device):
        self.encodings = encodings
        self.labels = labels
        self.device = device

    def __getitem__(self, idx):
        item = {key: torch.tensor(val[idx]).to(self.device) for key, val in self.encodings.items()}
        item['labels'] = torch.tensor(self.labels[idx]).to(self.device)
        return item

    def __len__(self):
        return len(self.labels)

train_dataset: EnglishTextDataset = EnglishTextDataset(train_encodings, train_labels, device=mps_device)
test_dataset = EnglishTextDataset(test_encodings, test_labels, device=mps_device)


# Define metrics
def compute_metrics(pred):
    labels = pred.label_ids
    preds = pred.predictions.argmax(-1)
    precision, recall, f1, _ = precision_recall_fscore_support(labels, preds, average='binary')
    acc = accuracy_score(labels, preds)
    return {
        'accuracy': acc,
        'f1': f1,
        'precision': precision,
        'recall': recall
    }

# Define the training arguments
training_args = TrainingArguments(
    output_dir='./results',
    num_train_epochs=3,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=64,
    warmup_steps=500,
    weight_decay=0.01,
    logging_dir='./logs',
)

# Create the Trainer and train the model
trainer = Trainer(
    model=model.to(device),
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
    compute_metrics=compute_metrics
)

# Train the model
trainer.train()

# Evaluate the model
eval_result = trainer.evaluate()
print(eval_result)

오류 메세지
warnings.warn(
0%| | 0/16947 [00:00<?, ?it/s]Traceback (most recent call last):
File "/Users/jakedb/Downloads/BERT/main.py", line 105, in
trainer.train()
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/trainer.py", line 1645, in train
return inner_training_loop(
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/trainer.py", line 1938, in _inner_training_loop
tr_loss_step = self.training_step(model, inputs)
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/trainer.py", line 2759, in training_step
loss = self.compute_loss(model, inputs)
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/trainer.py", line 2784, in compute_loss
outputs = model(**inputs)
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
return forward_call(*args, **kwargs)
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/models/bert/modeling_bert.py", line 1562, in forward
outputs = self.bert(
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
return forward_call(*args, **kwargs)
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/models/bert/modeling_bert.py", line 1013, in forward
embedding_output = self.embeddings(
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
return forward_call(*args, **kwargs)
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/transformers/models/bert/modeling_bert.py", line 230, in forward
inputs_embeds = self.word_embeddings(input_ids)
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
return forward_call(*args, **kwargs)
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/modules/sparse.py", line 162, in forward
return F.embedding(
File "/Users/jakedb/Downloads/yes/envs/tf29_py39/lib/python3.9/site-packages/torch/nn/functional.py", line 2210, in embedding
return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)
RuntimeError: Placeholder storage has not been allocated on MPS device!
0%| | 0/16947 [00:00<?, ?it/s]

이번에는 데이터 숫자가 줄어들었네요.

혹시 문제가 뭔지 한 번만 더 봐주실 수 있을까요?
바쁜 시간 내어주셔서 감사합니다.

# Create the Trainer and train the model
trainer = Trainer(
    model=model.to(device),
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
    compute_metrics=compute_metrics
)

위 코드에서 model.to(device) 로 되어 있는데 여기서 device가 mps로 되있는지 확인이 필요 할 것 같습니다.