File size: 5,242 Bytes
59f6375
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
---
license: apache-2.0
language:
- en
tags:
- bitnet
datasets:
- abideen/Cosmopedia-100k-pretrain
---


# Bitnet-Nous-Llama3-225M 🚀

Este modelo es una variante optimizada del **Llama3** utilizando la arquitectura **BitNet**, lo que reduce los pesos a los valores `-1`, `0`, y `1` para mejorar la eficiencia en el cómputo sin perder precisión.

![image/png](https://cdn-uploads.huggingface.co/production/uploads/66b0ba742cf20f2528a916bd/vtbKlK5l6yuj5uyJkAEgg.png)

## Modelo Base 🦙

- **Modelo Original**: [Meta-Llama3-8B](https://huggingface.co/meta-llama/Meta-Llama-3-8B)
- **Parámetros Reducidos**: 225M

## Arquitectura 🔧

El modelo transforma las capas lineales de Llama3 en capas **BitLinear**, aprovechando las siguientes técnicas de cuantización:

- **Cuantización de activaciones**: Escala a ±127
- **Cuantización de pesos**: Escala a ±1

### Especificaciones Técnicas 📋

- **Dimensiones**: 768
- **Capas**: 6
- **Contexto**: 256 tokens
- **Tamaño intermedio**: 1024
- **Número de cabezas de atención**: 6


## Dataset 📚

El modelo fue entrenado usando el dataset [Cosmopedia-100k-pretrain](https://huggingface.co/datasets/abideen/Cosmopedia-100k-pretrain), que contiene una variedad de datos de texto.

## Entrenamiento ⚙️

El modelo fue entrenado con la siguiente configuración:

- **Lote**: 16
- **Tasa de aprendizaje**: 1.5e-4
- **Épocas**: 2
- **Acumulación de gradientes**: 2 pasos
- **Decaimiento de pesos**: 0.01
- **Precisión Mixta**: FP16

### Monitoreo 📊

El proceso de entrenamiento fue monitoreado usando **Weights & Biases**.

## Uso del Modelo 💻

Para usar este modelo, puedes cargarlo desde Hugging Face con el siguiente código:
```python
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.models.llama.modeling_llama import *
import torch
from torch import nn
import torch.nn.functional as F
import coloredlogs
import logging

from utils.utils import count_parameters

coloredlogs.install(level='INFO', fmt='%(asctime)s - %(levelname)s - %(message)s', logger=logging.getLogger())
logger = logging.getLogger(__name__)




HF_TOKEN = "tuclaveaqui"
#model = "ejbejaranos/Bitnet-Llama3-from8BM-now2B"
model = "ejbejaranos/Bitnet-Nous-Llama3-225M" ## Working

# Load a pretrained BitNet model
tokenizer = AutoTokenizer.from_pretrained(model)

model = AutoModelForCausalLM.from_pretrained(
    model,
    token=HF_TOKEN
)


def count_parameters(model):
    # Calculate the number of parameters in billions
    num_params = sum(p.numel() for p in model.parameters() if p.requires_grad) / 10**9
    print(f"Model size: {num_params:.3f}B parameters")
    return int(num_params)



# Establece el pad_token_id
model.config.pad_token_id = tokenizer.eos_token_id

def activation_quant(x):
    scale = 127.0 / x.abs().max(dim=-1, keepdim=True).values.clamp_(min=1e-5)
    y = (x * scale).round().clamp_(-128, 127)
    y = y / scale
    return y

def weight_quant(w):
    scale = 1.0 / w.abs().mean().clamp_(min=1e-5)
    u = (w * scale).round().clamp_(-1, 1)
    u = u / scale
    return u

class BitLinear(nn.Linear):
    def forward(self, x):
        w = self.weight  # a weight tensor with shape [d, k]
        x = x.to(w.device)
        RMSNorm = LlamaRMSNorm(x.shape[-1]).to(w.device)
        x_norm = RMSNorm(x)
        x_quant = x_norm + (activation_quant(x_norm) - x_norm).detach()
        w_quant = w + (weight_quant(w) - w).detach()
        y = F.linear(x_quant, w_quant)
        return y

def convert_to_bitnet(model, copy_weights):
    for name, module in model.named_modules():
        if isinstance(module, LlamaSdpaAttention) or isinstance(module, LlamaMLP):
            for child_name, child_module in module.named_children():
                if isinstance(child_module, nn.Linear):
                    bitlinear = BitLinear(child_module.in_features, child_module.out_features, child_module.bias is not None).to(device="cuda:0")
                    if copy_weights:
                        bitlinear.weight = child_module.weight
                        if child_module.bias is not None:
                            bitlinear.bias = child_module.bias
                    setattr(module, child_name, bitlinear)
        elif isinstance(module, LlamaDecoderLayer):
            for child_name, child_module in module.named_children():
                if isinstance(child_module, LlamaRMSNorm) and child_name == "input_layernorm":
                    setattr(module, child_name, nn.Identity().to(device="cuda:0"))

convert_to_bitnet(model, copy_weights=True)
model.to(device="cuda:0")


logger.info(f"🔢 Number of parameters in the model after extracting weights: {count_parameters(model)}")
logger.info(f"📏 Reduced model structure:\n{model}")





prompt = "What is Machine Learning?"
inputs = tokenizer(prompt, return_tensors="pt", padding=True, truncation=True).to(model.device)
inputs['attention_mask'] = inputs['input_ids'] != model.config.pad_token_id

generate_ids = model.generate(inputs.input_ids, attention_mask=inputs['attention_mask'], max_length=250)
decoded_output = tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)

print(decoded_output[0])  # Print the generated response

```