mirror of
https://github.com/pese-git/simple-llm.git
synced 2026-01-23 13:03:55 +00:00
Комплексное обновление проекта
- Добавлена документация по эмбеддингам (markdown + drawio) - Реализован модуль PositionalEmbeddings - Обновлен .gitignore - Исправлено имя модуля token_embeddings.py
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -205,3 +205,6 @@ cython_debug/
|
||||
marimo/_static/
|
||||
marimo/_lsp/
|
||||
__marimo__/
|
||||
|
||||
|
||||
.vscode
|
||||
56
doc/positional_embeddings_ru.md
Normal file
56
doc/positional_embeddings_ru.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# PositionalEmbeddings - Позиционные эмбеддинги
|
||||
|
||||
## Назначение
|
||||
Позиционные эмбеддинги добавляют информацию о порядке элементов в последовательности. Критически важны для:
|
||||
- Transformer-архитектур
|
||||
- Моделей обработки текста (BERT, GPT)
|
||||
- Задач с временными рядами
|
||||
|
||||
## Алгоритм работы
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Создание слоя] --> B[Запрос длины последовательности]
|
||||
B --> C{Длина в допустимых пределах?}
|
||||
C -->|Да| D[Генерация индексов 0..seq_len-1]
|
||||
D --> E[Получение векторов из embedding-таблицы]
|
||||
E --> F[Возврат эмбеддингов]
|
||||
C -->|Нет| G[Ошибка IndexError]
|
||||
```
|
||||
|
||||
1. **Инициализация**:
|
||||
- Создается таблица размером `max_seq_len x emb_size`
|
||||
- Каждая позиция получает уникальный обучаемый вектор
|
||||
|
||||
2. **Работа**:
|
||||
- Принимает длину последовательности `seq_len`
|
||||
- Возвращает тензор формы `[seq_len, emb_size]`
|
||||
|
||||
## Пример использования
|
||||
```python
|
||||
# Инициализация
|
||||
pos_emb = PositionalEmbeddings(max_seq_len=512, emb_size=128)
|
||||
|
||||
# Получение эмбеддингов для 50 элементов
|
||||
embeddings = pos_emb(50) # shape: [50, 128]
|
||||
|
||||
# Интеграция в модель
|
||||
class TransformerBlock(nn.Module):
|
||||
def __init__(self):
|
||||
self.pos_emb = PositionalEmbeddings(512, 128)
|
||||
|
||||
def forward(self, x):
|
||||
pos = self.pos_emb(x.size(1)) # Добавляем к токенным эмбеддингам
|
||||
return x + pos
|
||||
```
|
||||
|
||||
## Сравнение подходов
|
||||
| Метод | Обучаемость | Плюсы | Минусы |
|
||||
|----------------------|-------------|--------------------------------|-----------------------|
|
||||
| Обучаемые | Да | Гибкость | Требует данных |
|
||||
| Синусоидальные | Нет | Хорошая обобщающая способность | Фиксированный паттерн |
|
||||
|
||||
## Оптимальные практики
|
||||
- Для `max_seq_len` берите с запасом (+20%)
|
||||
- Размерность делайте равной размерности токенных эмбеддингов
|
||||
- Для длинных последовательностей комбинируйте с синусоидальными
|
||||
0
doc/token_embeddings.md
Normal file
0
doc/token_embeddings.md
Normal file
21
doc/token_embeddings_flow.drawio
Normal file
21
doc/token_embeddings_flow.drawio
Normal file
@@ -0,0 +1,21 @@
|
||||
<mxfile>
|
||||
<diagram name="Token Embeddings Flow" id="0">
|
||||
<mxGraphModel>
|
||||
<root>
|
||||
<mxCell id="1"/>
|
||||
<mxCell id="2" parent="1"/>
|
||||
<mxCell id="3" value="Входные токены (индексы)" style="shape=rectangle" parent="2" vertex="1">
|
||||
<mxGeometry x="100" y="100" width="120" height="60"/>
|
||||
</mxCell>
|
||||
<mxCell id="4" value="Lookup в таблице эмбеддингов" style="shape=rectangle" parent="2" vertex="1">
|
||||
<mxGeometry x="100" y="200" width="120" height="60"/>
|
||||
</mxCell>
|
||||
<mxCell id="5" value="Выходные эмбеддинги" style="shape=rectangle" parent="2" vertex="1">
|
||||
<mxGeometry x="100" y="300" width="120" height="60"/>
|
||||
</mxCell>
|
||||
<mxCell id="6" source="3" target="4" parent="2" edge="1"/>
|
||||
<mxCell id="7" source="4" target="5" parent="2" edge="1"/>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
90
simple_llm/embedding/positional_embeddings.py
Normal file
90
simple_llm/embedding/positional_embeddings.py
Normal file
@@ -0,0 +1,90 @@
|
||||
import torch
|
||||
from torch import nn, Tensor
|
||||
|
||||
class PositionalEmbeddings(nn.Module):
|
||||
"""
|
||||
Класс для создания позиционных эмбеддингов через nn.Embedding.
|
||||
|
||||
Позиционные эмбеддинги используются в нейросетях для передачи информации
|
||||
о позиции элементов в последовательности (например, в Transformer).
|
||||
|
||||
Особенности:
|
||||
- Создаёт обучаемые позиционные эмбеддинги фиксированной длины
|
||||
- Поддерживает обработку последовательностей переменной длины
|
||||
- Автоматически размещает вычисления на том же устройстве, что и параметры
|
||||
|
||||
Args:
|
||||
max_seq_len (int): Максимальная длина последовательности
|
||||
emb_size (int): Размерность векторного представления позиций
|
||||
|
||||
Пример использования:
|
||||
>>> pos_encoder = PositionalEmbeddings(max_seq_len=100, emb_size=256)
|
||||
>>> # Получить эмбеддинги для последовательности из 10 элементов
|
||||
>>> embeddings = pos_encoder(10) # Tensor shape: [10, 256]
|
||||
>>> # Использование в модели
|
||||
>>> class MyModel(nn.Module):
|
||||
... def __init__(self):
|
||||
... super().__init__()
|
||||
... self.pos_emb = PositionalEmbeddings(100, 256)
|
||||
... def forward(self, x):
|
||||
... pos = self.pos_emb(x.size(1))
|
||||
... return x + pos # Добавляем позиционную информацию
|
||||
"""
|
||||
|
||||
def __init__(self, max_seq_len: int, emb_size: int):
|
||||
super().__init__()
|
||||
self.max_seq_len = max_seq_len
|
||||
self.emb_size = emb_size
|
||||
self.embedding = nn.Embedding(
|
||||
num_embeddings=max_seq_len,
|
||||
embedding_dim=emb_size
|
||||
)
|
||||
|
||||
def forward(self, seq_len: int) -> Tensor:
|
||||
"""
|
||||
Возвращает позиционные эмбеддинги для заданной длины последовательности.
|
||||
|
||||
Args:
|
||||
seq_len (int): Длина последовательности (1 <= seq_len <= max_seq_len)
|
||||
|
||||
Returns:
|
||||
Tensor: Тензор позиционных эмбеддингов формы [seq_len, emb_size]
|
||||
|
||||
Raises:
|
||||
IndexError: Если seq_len выходит за допустимые границы
|
||||
|
||||
Пример:
|
||||
>>> pos_encoder = PositionalEmbeddings(100, 64)
|
||||
>>> emb = pos_encoder(10) # Тензор 10x64
|
||||
"""
|
||||
if seq_len < 1 or seq_len > self.max_seq_len:
|
||||
raise IndexError(f"Длина {seq_len} должна быть от 1 до {self.max_seq_len}")
|
||||
positions = torch.arange(seq_len, device=self.embedding.weight.device)
|
||||
return self.embedding(positions)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Демонстрация работы
|
||||
print("Пример использования PositionalEmbeddings:")
|
||||
pos_emb = PositionalEmbeddings(max_seq_len=50, emb_size=128)
|
||||
|
||||
# Пример 1: Базовое использование
|
||||
print("\n1. Базовый пример:")
|
||||
emb = pos_emb(10)
|
||||
print(f"Форма выходного тензора: {emb.shape}")
|
||||
print(f"Среднее значение: {emb.mean().item():.4f}")
|
||||
|
||||
# Пример 2: Интеграция с моделью
|
||||
print("\n2. Пример интеграции с моделью:")
|
||||
class DemoModel(nn.Module):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.pos_emb = PositionalEmbeddings(50, 128)
|
||||
|
||||
def forward(self, x):
|
||||
pos = self.pos_emb(x.size(1))
|
||||
return x + pos # Добавляем позиционную информацию
|
||||
|
||||
model = DemoModel()
|
||||
input_tensor = torch.randn(2, 10, 128) # [batch, seq, features]
|
||||
output = model(input_tensor)
|
||||
print(f"Вход: {input_tensor.shape}, Выход: {output.shape}")
|
||||
Reference in New Issue
Block a user