THUDM/glm-4-9b-chat 은 LogiKor 리더보드에서 공개 모델 중 상당한 순위를 자랑하는 중국산 모델인데요,
문제는 이 모델은 huggingface transformer 라이브러리에 등록되어있지 않아 인터넷에 공개되어있는 여러 예제 코드가 작동하지 않을 때가 많습니다.
peft_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
inference_mode=False,
r=8,
lora_alpha=32,
lora_dropout=0.1,
target_modules=["q_proj", "v_proj"],
)
model = get_peft_model(model, peft_config)
위의 코드는 많이들 사용하는 LoRAConfig 세팅인데요, chatglm 모델에 다음과 같은 코드를 적용하면 이런 에러를 볼 수 있습니다.
ValueError: Target modules ["q_proj", "v_proj"] not found in the base model. Please check the target modules and try again.
이는 chatglm의 모델링 코드 구조에서 "q_proj", "v_proj" 가 없어서 존재하는 오류로, 실제 내부 코드 "modeling_glm.py" 를 들여다보면 다음과 같습니다.
class SelfAttention(torch.nn.Module):
"""Parallel self-attention layer abstract class.
Self-attention layer takes input with size [s, b, h]
and returns output of the same size.
"""
def __init__(self, config: ChatGLMConfig, layer_number, device=None):
super(SelfAttention, self).__init__()
self.layer_number = max(1, layer_number)
self.projection_size = config.kv_channels * config.num_attention_heads
# Per attention head and per partition values.
self.hidden_size_per_attention_head = self.projection_size // config.num_attention_heads
self.num_attention_heads_per_partition = config.num_attention_heads
self.multi_query_attention = config.multi_query_attention
self.qkv_hidden_size = 3 * self.projection_size
if self.multi_query_attention:
self.num_multi_query_groups_per_partition = config.multi_query_group_num
self.qkv_hidden_size = (
self.projection_size + 2 * self.hidden_size_per_attention_head * config.multi_query_group_num
)
self.query_key_value = nn.Linear(config.hidden_size, self.qkv_hidden_size,
bias=config.add_bias_linear or config.add_qkv_bias,
device=device, **_config_to_kwargs(config)
)
self.core_attention = CORE_ATTENTION_CLASSES[config._attn_implementation](config, self.layer_number)
# Output.
self.dense = nn.Linear(self.projection_size, config.hidden_size, bias=config.add_bias_linear,
device=device, **_config_to_kwargs(config)
)
이상한점을 잘 모르시겠다면, transformers 라이브러리의 modeling_llama.py 를 한번 볼까요?
class LlamaAttention(nn.Module):
"""Multi-headed attention from 'Attention Is All You Need' paper"""
def __init__(self, config: LlamaConfig, layer_idx: Optional[int] = None):
super().__init__()
self.config = config
self.layer_idx = layer_idx
if layer_idx is None:
logger.warning_once(
f"Instantiating {self.__class__.__name__} without passing a `layer_idx` is not recommended and will "
"lead to errors during the forward call if caching is used. Please make sure to provide a `layer_idx` "
"when creating this class."
)
self.attention_dropout = config.attention_dropout
self.hidden_size = config.hidden_size
self.num_heads = config.num_attention_heads
self.head_dim = self.hidden_size // self.num_heads
self.num_key_value_heads = config.num_key_value_heads
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
self.max_position_embeddings = config.max_position_embeddings
self.rope_theta = config.rope_theta
self.is_causal = True
if (self.head_dim * self.num_heads) != self.hidden_size:
raise ValueError(
f"hidden_size must be divisible by num_heads (got `hidden_size`: {self.hidden_size}"
f" and `num_heads`: {self.num_heads})."
)
self.q_proj = nn.Linear(self.hidden_size, self.num_heads * self.head_dim, bias=config.attention_bias)
self.k_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=config.attention_bias)
self.v_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=config.attention_bias)
self.o_proj = nn.Linear(self.hidden_size, self.hidden_size, bias=config.attention_bias)
self._init_rope()
맞습니다. transformers 내부 코드의 modeling 코드에는 "q_proj", "v_proj"가 존재하지만, chatglm의 커스텀 코드에는 존재하지 않는 다는 것을 확인할 수 있죠.
따라서 LoRA 학습을 하기 위해서는 모델링 코드를 수정하거나(어려운 방법), 모델링 코드에서 지정해놓은 매개변수 이름으로 LoraConfig를 수정하면 됩니다.
chatglm의 모델링 코드에서 ["q_proj", "v_proj"] 와 유사한 기능을 하는 매개변수는 "query_key_value" 이므로, 다음과 같이 LoraConfig를 바꿔주면 학습을 할 수 있습니다.
peft_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
inference_mode=False,
r=8,
lora_alpha=32,
lora_dropout=0.1,
target_modules=["query_key_value"],
)
model = get_peft_model(model, peft_config)
이와 유사한 방법으로 사용하던 LoraConfig가 작동하지 않는 커스텀 코드를 사용하는 모델에 대해 Lora 학습을 해볼 수 있겠습니다.
혹시 틀린 점이 있다면 댓글로 달아주세요!
'공부' 카테고리의 다른 글
ValueError: The input size is not aligned with the quantized weight shape. This can be caused by too large tensor parallel size. (0) | 2024.06.18 |
---|---|
[논문 잘 읽는 법]How to Read a Paper (0) | 2023.01.07 |