Instructions to use hamingsi/SpikingLM with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use hamingsi/SpikingLM with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("fill-mask", model="hamingsi/SpikingLM")# Load model directly from transformers import AutoTokenizer, AutoModelForMaskedLM tokenizer = AutoTokenizer.from_pretrained("hamingsi/SpikingLM") model = AutoModelForMaskedLM.from_pretrained("hamingsi/SpikingLM", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Upload SpikingLM checkpoint and code
Browse files- README.md +2 -1
- scripts/finetune_glue.py +15 -26
- spiking_bert/modeling_spiking_bert.py +1 -32
README.md
CHANGED
|
@@ -16,8 +16,9 @@ SpikingLM is a BERT-base style masked-language model with spiking attention bloc
|
|
| 16 |
This checkpoint uses:
|
| 17 |
|
| 18 |
- temporal Spiking BERT with `T=4`
|
|
|
|
| 19 |
- LIF nodes for projection, Q, K, V, attention output, and MLP blocks
|
| 20 |
-
- `self.learnmax(attention_scores)` for attention normalization
|
| 21 |
|
| 22 |
## Files
|
| 23 |
|
|
|
|
| 16 |
This checkpoint uses:
|
| 17 |
|
| 18 |
- temporal Spiking BERT with `T=4`
|
| 19 |
+
- learnable Q/K/V scaling parameters initialized from `7`
|
| 20 |
- LIF nodes for projection, Q, K, V, attention output, and MLP blocks
|
| 21 |
+
- `FP16OptimizedExp2Softmax` through `self.learnmax(attention_scores)` for attention normalization
|
| 22 |
|
| 23 |
## Files
|
| 24 |
|
scripts/finetune_glue.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
#!/usr/bin/env python
|
| 2 |
-
# 添加从预训练checkpoint加载的功能
|
| 3 |
|
| 4 |
import argparse
|
| 5 |
import json
|
|
@@ -22,7 +21,7 @@ from datasets import load_dataset
|
|
| 22 |
from huggingface_hub import HfApi
|
| 23 |
from torch.utils.data import DataLoader
|
| 24 |
from tqdm.auto import tqdm
|
| 25 |
-
from safetensors.torch import load_file
|
| 26 |
|
| 27 |
import transformers
|
| 28 |
from transformers import (
|
|
@@ -212,41 +211,32 @@ def parse_args():
|
|
| 212 |
|
| 213 |
def load_model_from_checkpoint(checkpoint_path, config, num_labels):
|
| 214 |
"""
|
| 215 |
-
|
| 216 |
-
|
| 217 |
Args:
|
| 218 |
-
checkpoint_path:
|
| 219 |
-
config:
|
| 220 |
-
num_labels:
|
| 221 |
-
|
| 222 |
Returns:
|
| 223 |
-
|
| 224 |
"""
|
| 225 |
from spiking_bert.modeling_spiking_bert import BertForSequenceClassification
|
| 226 |
-
|
| 227 |
-
# 检查safetensors文件是否存在
|
| 228 |
safetensors_path = os.path.join(checkpoint_path, "model.safetensors")
|
| 229 |
if not os.path.exists(safetensors_path):
|
| 230 |
raise FileNotFoundError(f"Cannot find model.safetensors in {checkpoint_path}")
|
| 231 |
-
|
| 232 |
logger.info(f"Loading pretrained weights from {safetensors_path}")
|
| 233 |
-
|
| 234 |
-
# 修改config以适应分类任务
|
| 235 |
config.num_labels = num_labels
|
| 236 |
-
|
| 237 |
-
# 创建分类模型(会初始化新的分类头)
|
| 238 |
model = BertForSequenceClassification(config)
|
| 239 |
-
|
| 240 |
-
# 加载预训练的权重
|
| 241 |
pretrained_state_dict = load_file(safetensors_path)
|
| 242 |
-
|
| 243 |
-
# 获取当前模型的state_dict
|
| 244 |
model_state_dict = model.state_dict()
|
| 245 |
-
|
| 246 |
-
# 只加载匹配的权重(跳过分类头)
|
| 247 |
matched_keys = []
|
| 248 |
mismatched_keys = []
|
| 249 |
-
|
| 250 |
for key in pretrained_state_dict.keys():
|
| 251 |
if key in model_state_dict:
|
| 252 |
if pretrained_state_dict[key].shape == model_state_dict[key].shape:
|
|
@@ -257,10 +247,9 @@ def load_model_from_checkpoint(checkpoint_path, config, num_labels):
|
|
| 257 |
logger.warning(f"Shape mismatch for {key}: pretrained {pretrained_state_dict[key].shape} vs model {model_state_dict[key].shape}")
|
| 258 |
else:
|
| 259 |
logger.info(f"Key {key} not found in model, skipping...")
|
| 260 |
-
|
| 261 |
-
# 加载权重
|
| 262 |
model.load_state_dict(model_state_dict)
|
| 263 |
-
|
| 264 |
logger.info(f"Loaded {len(matched_keys)} matching weights from checkpoint")
|
| 265 |
logger.info(f"Skipped {len(mismatched_keys)} mismatched weights")
|
| 266 |
logger.info(f"Classifier head will be trained from scratch")
|
|
|
|
| 1 |
#!/usr/bin/env python
|
|
|
|
| 2 |
|
| 3 |
import argparse
|
| 4 |
import json
|
|
|
|
| 21 |
from huggingface_hub import HfApi
|
| 22 |
from torch.utils.data import DataLoader
|
| 23 |
from tqdm.auto import tqdm
|
| 24 |
+
from safetensors.torch import load_file
|
| 25 |
|
| 26 |
import transformers
|
| 27 |
from transformers import (
|
|
|
|
| 211 |
|
| 212 |
def load_model_from_checkpoint(checkpoint_path, config, num_labels):
|
| 213 |
"""
|
| 214 |
+
Load a sequence classification model from a checkpoint directory containing model.safetensors.
|
| 215 |
+
|
| 216 |
Args:
|
| 217 |
+
checkpoint_path: Checkpoint directory.
|
| 218 |
+
config: Model configuration.
|
| 219 |
+
num_labels: Number of labels for the classification task.
|
| 220 |
+
|
| 221 |
Returns:
|
| 222 |
+
Model initialized with matching pretrained weights.
|
| 223 |
"""
|
| 224 |
from spiking_bert.modeling_spiking_bert import BertForSequenceClassification
|
| 225 |
+
|
|
|
|
| 226 |
safetensors_path = os.path.join(checkpoint_path, "model.safetensors")
|
| 227 |
if not os.path.exists(safetensors_path):
|
| 228 |
raise FileNotFoundError(f"Cannot find model.safetensors in {checkpoint_path}")
|
| 229 |
+
|
| 230 |
logger.info(f"Loading pretrained weights from {safetensors_path}")
|
| 231 |
+
|
|
|
|
| 232 |
config.num_labels = num_labels
|
|
|
|
|
|
|
| 233 |
model = BertForSequenceClassification(config)
|
| 234 |
+
|
|
|
|
| 235 |
pretrained_state_dict = load_file(safetensors_path)
|
|
|
|
|
|
|
| 236 |
model_state_dict = model.state_dict()
|
|
|
|
|
|
|
| 237 |
matched_keys = []
|
| 238 |
mismatched_keys = []
|
| 239 |
+
|
| 240 |
for key in pretrained_state_dict.keys():
|
| 241 |
if key in model_state_dict:
|
| 242 |
if pretrained_state_dict[key].shape == model_state_dict[key].shape:
|
|
|
|
| 247 |
logger.warning(f"Shape mismatch for {key}: pretrained {pretrained_state_dict[key].shape} vs model {model_state_dict[key].shape}")
|
| 248 |
else:
|
| 249 |
logger.info(f"Key {key} not found in model, skipping...")
|
| 250 |
+
|
|
|
|
| 251 |
model.load_state_dict(model_state_dict)
|
| 252 |
+
|
| 253 |
logger.info(f"Loaded {len(matched_keys)} matching weights from checkpoint")
|
| 254 |
logger.info(f"Skipped {len(mismatched_keys)} mismatched weights")
|
| 255 |
logger.info(f"Classifier head will be trained from scratch")
|
spiking_bert/modeling_spiking_bert.py
CHANGED
|
@@ -197,7 +197,6 @@ class FP16OptimizedExp2Softmax(nn.Module):
|
|
| 197 |
init_value: Initial value for scale parameter
|
| 198 |
"""
|
| 199 |
super().__init__()
|
| 200 |
-
# 注册为可学习参数,维度 [T, head_size]
|
| 201 |
self.scale = nn.Parameter(torch.full((T,), init_value))
|
| 202 |
|
| 203 |
def forward(self, tensor, k=1.0):
|
|
@@ -211,9 +210,6 @@ class FP16OptimizedExp2Softmax(nn.Module):
|
|
| 211 |
tensor = tensor - tensor.max(dim=-1, keepdim=True)[0] - 1
|
| 212 |
tensor.clamp_(min=-30.0, max=30.0)
|
| 213 |
tensor = torch.exp2(tensor)
|
| 214 |
-
# tensor = tensor / (tensor.sum(dim=-1, keepdim=True) + 1e-6)
|
| 215 |
-
|
| 216 |
-
# scale: [T, head_size] -> [T, 1, head_size, 1, 1] for broadcasting
|
| 217 |
scale = self.scale[:, None, None, None, None]
|
| 218 |
tensor = tensor * scale
|
| 219 |
return tensor
|
|
@@ -240,13 +236,10 @@ class BertSelfAttention(nn.Module):
|
|
| 240 |
|
| 241 |
self.query = nn.Linear(config.hidden_size, self.all_head_size)
|
| 242 |
self.q_lam = nn.Parameter(torch.ones(self.all_head_size)*7)
|
| 243 |
-
# self.q_norm = nn.RMSNorm(config.hidden_size)
|
| 244 |
self.key = nn.Linear(config.hidden_size, self.all_head_size)
|
| 245 |
self.k_lam = nn.Parameter(torch.ones(self.all_head_size)*7)
|
| 246 |
-
# self.k_norm = nn.RMSNorm(config.hidden_size)
|
| 247 |
self.value = nn.Linear(config.hidden_size, self.all_head_size)
|
| 248 |
self.v_lam = nn.Parameter(torch.ones(self.all_head_size)*7)
|
| 249 |
-
# self.v_norm = nn.RMSNorm(config.hidden_size)
|
| 250 |
self.learnmax = FP16OptimizedExp2Softmax(T=config.T)
|
| 251 |
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
|
| 252 |
self.position_embedding_type = position_embedding_type or getattr(
|
|
@@ -258,7 +251,6 @@ class BertSelfAttention(nn.Module):
|
|
| 258 |
|
| 259 |
self.is_decoder = config.is_decoder
|
| 260 |
self.layer_idx = layer_idx
|
| 261 |
-
# True 时不做 q_lam/k_lam/v_lam 缩放(等价于恒等,便于与启用 lamb 的实验对比)
|
| 262 |
self.disable_qkv_lamb = bool(getattr(config, "disable_qkv_lamb", False))
|
| 263 |
|
| 264 |
@deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
|
|
@@ -275,7 +267,6 @@ class BertSelfAttention(nn.Module):
|
|
| 275 |
T, batch_size, seq_length, _ = hidden_states.shape
|
| 276 |
hidden_states = self.proj_lif(hidden_states)
|
| 277 |
query_layer = self.query(hidden_states)
|
| 278 |
-
# query_layer = self.q_norm(query_layer.reshape(T*batch_size, seq_length, -1)).reshape(T, batch_size, seq_length, -1)
|
| 279 |
if not self.disable_qkv_lamb:
|
| 280 |
query_layer = self.q_lam * query_layer
|
| 281 |
query_layer = self.q_lif(query_layer)
|
|
@@ -303,7 +294,6 @@ class BertSelfAttention(nn.Module):
|
|
| 303 |
value_layer = curr_past_key_value.layers[self.layer_idx].values
|
| 304 |
else:
|
| 305 |
key_layer = self.key(current_states)
|
| 306 |
-
# key_layer = self.k_norm(key_layer.reshape(T*batch_size, seq_length, -1)).reshape(T, batch_size, seq_length, -1)
|
| 307 |
if not self.disable_qkv_lamb:
|
| 308 |
key_layer = self.k_lam * key_layer
|
| 309 |
key_layer = self.k_lif(key_layer)
|
|
@@ -311,7 +301,6 @@ class BertSelfAttention(nn.Module):
|
|
| 311 |
2, 3
|
| 312 |
)
|
| 313 |
value_layer = self.value(current_states)
|
| 314 |
-
# value_layer = self.v_norm(value_layer.reshape(T*batch_size, seq_length, -1)).reshape(T, batch_size, seq_length, -1)
|
| 315 |
if not self.disable_qkv_lamb:
|
| 316 |
value_layer = self.v_lam * value_layer
|
| 317 |
value_layer = self.v_lif(value_layer)
|
|
@@ -354,27 +343,10 @@ class BertSelfAttention(nn.Module):
|
|
| 354 |
relative_position_scores_key = torch.einsum("bhrd,lrd->bhlr", key_layer, positional_embedding)
|
| 355 |
attention_scores = attention_scores + relative_position_scores_query.unsqueeze(0) + relative_position_scores_key.unsqueeze(0)
|
| 356 |
|
| 357 |
-
# attention_scores = attention_scores / math.sqrt(self.attention_head_size)
|
| 358 |
-
# print(attention_mask)
|
| 359 |
if attention_mask is not None:
|
| 360 |
-
# Apply the attention mask is (precomputed for all layers in BertModel forward() function)
|
| 361 |
attention_scores = attention_scores + attention_mask
|
| 362 |
|
| 363 |
-
# # # Normalize the attention scores to probabilities.
|
| 364 |
attention_probs = self.learnmax(attention_scores)
|
| 365 |
-
# attention_probs = nn.functional.softmax(attention_scores, dim=-1)
|
| 366 |
-
|
| 367 |
-
# # This is actually dropping out entire tokens to attend to, which might
|
| 368 |
-
# # seem a bit unusual, but is taken from the original Transformer paper.
|
| 369 |
-
# attention_probs = self.dropout(attention_probs)
|
| 370 |
-
# if attention_mask is not None:
|
| 371 |
-
# attention_scores = attention_scores * attention_mask.unsqueeze(0)
|
| 372 |
-
|
| 373 |
-
# attention_probs = attention_scores * self.scale
|
| 374 |
-
|
| 375 |
-
# Mask heads if we want to
|
| 376 |
-
# if head_mask is not None:
|
| 377 |
-
# attention_probs = attention_probs * head_mask
|
| 378 |
|
| 379 |
context_layer = torch.matmul(attention_probs, value_layer) # t,b,h,l,d -> t,b,l,h,d
|
| 380 |
|
|
@@ -580,7 +552,6 @@ class BertIntermediate(nn.Module):
|
|
| 580 |
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 581 |
hidden_states = self.mlp1_lif(hidden_states)
|
| 582 |
hidden_states = self.dense(hidden_states)
|
| 583 |
-
# hidden_states = self.intermediate_act_fn(hidden_states)
|
| 584 |
return hidden_states
|
| 585 |
|
| 586 |
|
|
@@ -1075,8 +1046,6 @@ class BertModel(BertPreTrainedModel):
|
|
| 1075 |
# input head_mask has shape [num_heads] or [num_hidden_layers x num_heads]
|
| 1076 |
# and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length]
|
| 1077 |
|
| 1078 |
-
### update extended_attention_mask during training here!!!
|
| 1079 |
-
# extended_attention_mask = attention_mask.unsqueeze(1).unsqueeze(1)
|
| 1080 |
head_mask = self.get_head_mask(head_mask, self.config.num_hidden_layers)
|
| 1081 |
encoder_outputs = self.encoder(
|
| 1082 |
embedding_output,
|
|
@@ -1879,4 +1848,4 @@ __all__ = [
|
|
| 1879 |
"BertModel",
|
| 1880 |
"BertPreTrainedModel",
|
| 1881 |
"load_tf_weights_in_bert",
|
| 1882 |
-
]
|
|
|
|
| 197 |
init_value: Initial value for scale parameter
|
| 198 |
"""
|
| 199 |
super().__init__()
|
|
|
|
| 200 |
self.scale = nn.Parameter(torch.full((T,), init_value))
|
| 201 |
|
| 202 |
def forward(self, tensor, k=1.0):
|
|
|
|
| 210 |
tensor = tensor - tensor.max(dim=-1, keepdim=True)[0] - 1
|
| 211 |
tensor.clamp_(min=-30.0, max=30.0)
|
| 212 |
tensor = torch.exp2(tensor)
|
|
|
|
|
|
|
|
|
|
| 213 |
scale = self.scale[:, None, None, None, None]
|
| 214 |
tensor = tensor * scale
|
| 215 |
return tensor
|
|
|
|
| 236 |
|
| 237 |
self.query = nn.Linear(config.hidden_size, self.all_head_size)
|
| 238 |
self.q_lam = nn.Parameter(torch.ones(self.all_head_size)*7)
|
|
|
|
| 239 |
self.key = nn.Linear(config.hidden_size, self.all_head_size)
|
| 240 |
self.k_lam = nn.Parameter(torch.ones(self.all_head_size)*7)
|
|
|
|
| 241 |
self.value = nn.Linear(config.hidden_size, self.all_head_size)
|
| 242 |
self.v_lam = nn.Parameter(torch.ones(self.all_head_size)*7)
|
|
|
|
| 243 |
self.learnmax = FP16OptimizedExp2Softmax(T=config.T)
|
| 244 |
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
|
| 245 |
self.position_embedding_type = position_embedding_type or getattr(
|
|
|
|
| 251 |
|
| 252 |
self.is_decoder = config.is_decoder
|
| 253 |
self.layer_idx = layer_idx
|
|
|
|
| 254 |
self.disable_qkv_lamb = bool(getattr(config, "disable_qkv_lamb", False))
|
| 255 |
|
| 256 |
@deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
|
|
|
|
| 267 |
T, batch_size, seq_length, _ = hidden_states.shape
|
| 268 |
hidden_states = self.proj_lif(hidden_states)
|
| 269 |
query_layer = self.query(hidden_states)
|
|
|
|
| 270 |
if not self.disable_qkv_lamb:
|
| 271 |
query_layer = self.q_lam * query_layer
|
| 272 |
query_layer = self.q_lif(query_layer)
|
|
|
|
| 294 |
value_layer = curr_past_key_value.layers[self.layer_idx].values
|
| 295 |
else:
|
| 296 |
key_layer = self.key(current_states)
|
|
|
|
| 297 |
if not self.disable_qkv_lamb:
|
| 298 |
key_layer = self.k_lam * key_layer
|
| 299 |
key_layer = self.k_lif(key_layer)
|
|
|
|
| 301 |
2, 3
|
| 302 |
)
|
| 303 |
value_layer = self.value(current_states)
|
|
|
|
| 304 |
if not self.disable_qkv_lamb:
|
| 305 |
value_layer = self.v_lam * value_layer
|
| 306 |
value_layer = self.v_lif(value_layer)
|
|
|
|
| 343 |
relative_position_scores_key = torch.einsum("bhrd,lrd->bhlr", key_layer, positional_embedding)
|
| 344 |
attention_scores = attention_scores + relative_position_scores_query.unsqueeze(0) + relative_position_scores_key.unsqueeze(0)
|
| 345 |
|
|
|
|
|
|
|
| 346 |
if attention_mask is not None:
|
|
|
|
| 347 |
attention_scores = attention_scores + attention_mask
|
| 348 |
|
|
|
|
| 349 |
attention_probs = self.learnmax(attention_scores)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
|
| 351 |
context_layer = torch.matmul(attention_probs, value_layer) # t,b,h,l,d -> t,b,l,h,d
|
| 352 |
|
|
|
|
| 552 |
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 553 |
hidden_states = self.mlp1_lif(hidden_states)
|
| 554 |
hidden_states = self.dense(hidden_states)
|
|
|
|
| 555 |
return hidden_states
|
| 556 |
|
| 557 |
|
|
|
|
| 1046 |
# input head_mask has shape [num_heads] or [num_hidden_layers x num_heads]
|
| 1047 |
# and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length]
|
| 1048 |
|
|
|
|
|
|
|
| 1049 |
head_mask = self.get_head_mask(head_mask, self.config.num_hidden_layers)
|
| 1050 |
encoder_outputs = self.encoder(
|
| 1051 |
embedding_output,
|
|
|
|
| 1848 |
"BertModel",
|
| 1849 |
"BertPreTrainedModel",
|
| 1850 |
"load_tf_weights_in_bert",
|
| 1851 |
+
]
|