mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 14:40:37 +00:00
62 lines
3.6 KiB
Markdown
62 lines
3.6 KiB
Markdown
|
# 7.0. LoRA 개선 사항
|
||
|
|
||
|
## LoRA 개선 사항
|
||
|
|
||
|
{% hint style="success" %}
|
||
|
**LoRA는 이미 훈련된 모델을 미세 조정하는 데 필요한 계산을 많이 줄입니다.**
|
||
|
{% endhint %}
|
||
|
|
||
|
LoRA는 모델의 **작은 부분**만 변경하여 **대형 모델**을 효율적으로 미세 조정할 수 있게 합니다. 이는 훈련해야 할 매개변수의 수를 줄여 **메모리**와 **계산 자원**을 절약합니다. 그 이유는 다음과 같습니다:
|
||
|
|
||
|
1. **훈련 가능한 매개변수 수 감소**: 모델의 전체 가중치 행렬을 업데이트하는 대신, LoRA는 가중치 행렬을 두 개의 더 작은 행렬( **A**와 **B**라고 함)로 **분할**합니다. 이렇게 하면 훈련이 **더 빨라지고** 업데이트해야 할 매개변수가 적기 때문에 **메모리**가 **덜 필요**합니다.
|
||
|
1. 이는 레이어(행렬)의 전체 가중치 업데이트를 계산하는 대신, 두 개의 더 작은 행렬의 곱으로 근사하여 업데이트를 계산하는 것을 줄이기 때문입니다:\
|
||
|
|
||
|
|
||
|
<figure><img src="../../.gitbook/assets/image (9).png" alt=""><figcaption></figcaption></figure>
|
||
|
2. **원래 모델 가중치 변경 없음**: LoRA는 원래 모델 가중치를 동일하게 유지하고 **새로운 작은 행렬**(A와 B)만 업데이트할 수 있게 합니다. 이는 모델의 원래 지식이 보존되며 필요한 부분만 조정할 수 있다는 점에서 유용합니다.
|
||
|
3. **효율적인 작업별 미세 조정**: 모델을 **새로운 작업**에 적응시키고 싶을 때, 나머지 모델은 그대로 두고 **작은 LoRA 행렬**(A와 B)만 훈련하면 됩니다. 이는 전체 모델을 재훈련하는 것보다 **훨씬 더 효율적**입니다.
|
||
|
4. **저장 효율성**: 미세 조정 후, 각 작업에 대해 **전체 새로운 모델**을 저장하는 대신, 전체 모델에 비해 매우 작은 **LoRA 행렬**만 저장하면 됩니다. 이는 많은 작업에 모델을 적응시키는 데 너무 많은 저장 공간을 사용하지 않도록 쉽게 만듭니다.
|
||
|
|
||
|
미세 조정 중 Linear 대신 LoraLayers를 구현하기 위해, 여기에서 이 코드가 제안됩니다 [https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01\_main-chapter-code/appendix-E.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01\_main-chapter-code/appendix-E.ipynb):
|
||
|
```python
|
||
|
import math
|
||
|
|
||
|
# Create the LoRA layer with the 2 matrices and the alpha
|
||
|
class LoRALayer(torch.nn.Module):
|
||
|
def __init__(self, in_dim, out_dim, rank, alpha):
|
||
|
super().__init__()
|
||
|
self.A = torch.nn.Parameter(torch.empty(in_dim, rank))
|
||
|
torch.nn.init.kaiming_uniform_(self.A, a=math.sqrt(5)) # similar to standard weight initialization
|
||
|
self.B = torch.nn.Parameter(torch.zeros(rank, out_dim))
|
||
|
self.alpha = alpha
|
||
|
|
||
|
def forward(self, x):
|
||
|
x = self.alpha * (x @ self.A @ self.B)
|
||
|
return x
|
||
|
|
||
|
# Combine it with the linear layer
|
||
|
class LinearWithLoRA(torch.nn.Module):
|
||
|
def __init__(self, linear, rank, alpha):
|
||
|
super().__init__()
|
||
|
self.linear = linear
|
||
|
self.lora = LoRALayer(
|
||
|
linear.in_features, linear.out_features, rank, alpha
|
||
|
)
|
||
|
|
||
|
def forward(self, x):
|
||
|
return self.linear(x) + self.lora(x)
|
||
|
|
||
|
# Replace linear layers with LoRA ones
|
||
|
def replace_linear_with_lora(model, rank, alpha):
|
||
|
for name, module in model.named_children():
|
||
|
if isinstance(module, torch.nn.Linear):
|
||
|
# Replace the Linear layer with LinearWithLoRA
|
||
|
setattr(model, name, LinearWithLoRA(module, rank, alpha))
|
||
|
else:
|
||
|
# Recursively apply the same function to child modules
|
||
|
replace_linear_with_lora(module, rank, alpha)
|
||
|
```
|
||
|
## References
|
||
|
|
||
|
* [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
|