Добавление кнопки "домой" и гайда
Build and Push / build (push) Successful in 9s

This commit is contained in:
Dmitry
2026-05-18 15:57:22 +03:00
parent 4c8e7b9762
commit 26f4909ead
4 changed files with 95 additions and 11 deletions
+81
View File
@@ -0,0 +1,81 @@
# Как работает приложение
## Запуск
```bash
bundle install
ruby app.rb # веб-интерфейс на http://localhost:4567
# или
ruby main.rb # только CLI: загружает паттерны, обучает, выводит инфо
```
В Docker: собирается образ, `generate_excel.rb` генерирует `patterns.xlsx` при старте, Sinatra слушает на 4567.
---
## Данные
Паттерны хранятся в `patterns.xlsx`. Каждый лист = один символ (T, H, E, X...).
Ячейка `x``1`, остальное → `-1`. Размер: 8×8 = вектор из 64 значений.
`loader.rb` читает Excel через гем `roo` и возвращает `{name => matrix_8x8}`.
В вычислениях матрицы разворачиваются в векторы через `flatten`.
Если хочешь добавить/изменить паттерны — правь `generate_excel.rb` и перезапусти.
---
## Веб-интерфейс
Одна страница (`views/index.erb`), тёмная тема, 8×8 кликабельная сетка ввода.
**Что можно сделать:**
- Нарисовать паттерн кликами (или добавить шум кнопкой)
- Нажать «Распознать» — сервер прогоняет через обе сети
- Включить «Пошаговый режим» — видно, как Хопфилд сходится шаг за шагом
- Включить «Показывать формулы» — рядом с анимацией появляются LaTeX-формулы вычислений
---
## Маршруты (`app.rb`)
| Маршрут | Что делает |
|---|---|
| `GET /` | Загружает паттерны, отдаёт HTML |
| `POST /recall` | Быстро: вектор → итоговый результат обеих сетей |
| `POST /recall_steps` | То же + все промежуточные состояния для анимации |
| `POST /recall_trace` | То же + net-значения, сколько нейронов изменилось на каждом шаге, трассировка MAXNET |
Все POST принимают JSON `{vector: [...64 числа...]}`, возвращают JSON.
---
## Алгоритмы
### Хопфилд (`hopfield.rb`)
**Обучение** — один раз при запуске:
```
W[i][j] += v[i] * v[j] для каждого паттерна v, i ≠ j
```
Матрица весов 64×64, кэшируется в `weights.cache`.
**Recall** — итерации до сходимости:
```
new[i] = sign( Σ_j W[i][j] * x[j] ) # sign: ≥0 → 1, <0 → -1
```
Все нейроны обновляются синхронно. Стоп: состояние не изменилось (EPS=0.01) или 200 итераций.
### Хэмминг (`hamming.rb`)
**Шаг 1 — слой Хэмминга** (один раз):
```
output[k] = (dot(pattern_k, input) + 64) / 2
```
Результат: число от 0 до 64 — сколько бит совпало с k-м эталоном.
**Шаг 2 — MAXNET** (итерации до одного победителя):
```
new[i] = max(output[i] - eps * Σ_{j≠i} output[j], 0) # eps = 0.9 / кол-во паттернов
```
Нейроны конкурируют: слабые гаснут, остаётся один. Его индекс = ближайший паттерн.
+4 -6
View File
@@ -17,13 +17,11 @@ MAX_MAXNET_ITER = 100
def recall_hamming(pattern_vectors, input_vec)
eps = 0.9 / pattern_vectors.length
outputs = hamming_layer(pattern_vectors, input_vec)
MAX_MAXNET_ITER.times do
next_out = maxnet_step(outputs, eps)
return next_out.each_with_index.max_by { |v, _| v }[1] if next_out.count { |v| v > 1e-9 } <= 1
outputs = next_out
iter = 0
while outputs.count { |v| v > 1e-9 } > 1 && iter < MAX_MAXNET_ITER
outputs = maxnet_step(outputs, eps)
iter += 1
end
outputs.each_with_index.max_by { |v, _| v }[1]
end
+6 -4
View File
@@ -40,10 +40,12 @@ MAX_HOPFIELD_ITER = 200
def recall_hopfield(weights, input_vec)
current = input_vec.dup
MAX_HOPFIELD_ITER.times do
next_vec = step_hopfield(weights, current)
return current if vectors_equal?(current, next_vec)
next_vec = step_hopfield(weights, current)
iter = 1
while !vectors_equal?(current, next_vec) && iter < MAX_HOPFIELD_ITER
current = next_vec
next_vec = step_hopfield(weights, current)
iter += 1
end
current
next_vec
end
+4 -1
View File
@@ -263,7 +263,10 @@
</head>
<body>
<h1>Сети Хопфилда и Хэмминга</h1>
<div style="display:flex; align-items:center; gap:1rem; margin-bottom:2rem;">
<h1 style="margin-bottom:0;">Сети Хопфилда и Хэмминга</h1>
<a href="https://ada-dev.ru" class="secondary" style="padding:0.5rem 1.5rem; background:#2a2a4a; color:#8ab4f8; border:1px solid #8ab4f8; border-radius:4px; cursor:pointer; font-family:monospace; font-size:0.9rem; font-weight:bold; text-decoration:none;">Домой</a>
</div>
<div class="section">
<h2>Эталонные образы</h2>