Нейросеть на ардуино

для тех кому реально захочется разобраться, легкую и полезную задачу придумать мне сложно… особенно что бы сделать материал для ее обучения легко…

#include <EEPROM.h>
// Структура нейросети для 256 клавиш
#define INPUT_NODES 32     // 16 строк + 16 столбцов
#define HIDDEN_NODES 64    // Больше нейронов для сложной задачи
#define OUTPUT_NODES 8     // 8 бит = 256 комбинаций (0-255)
// Параметры обучения
#define LEARNING_RATE 0.3
#define MOMENTUM 0.6
// ============================================================
// ==== ГЕНЕРАЦИЯ ОБУЧАЮЩЕЙ ВЫБОРКИ НА 256 КЛАВИШ ===========
// ============================================================
// Для клавиатуры 16x16:
// Вход: 16 строк + 16 столбцов (32 бита)
// Выход: 8-битный код клавиши (0-255)
#define TOTAL_KEYS 256
// Функция генерации примера для клавиши номер key (0-255)
void generateKeyExample(int key, float* input, float* target) {
int row = key / 16;// строка 0-15
int col = key % 16;// столбец 0-15
// Очищаем вход
for (int i = 0; i < 32; i++) { input[i] = 0; }
// Устанавливаем биты строки и столбца
input[row] = 1;          // строка row активна
input[16 + col] = 1;     // столбец col активен
// Заполняем target - 8-битный код клавиши
for (int i = 0; i < 8; i++) {
target[i] = (key >> (7 - i)) & 1;  // Старший бит первый
}
}

// Для хранения весов
float hiddenWeights[INPUT_NODES][HIDDEN_NODES];
float outputWeights[HIDDEN_NODES][OUTPUT_NODES];
float hiddenBias[HIDDEN_NODES];
float outputBias[OUTPUT_NODES];

// Для момента
float hiddenDeltaWeights[INPUT_NODES][HIDDEN_NODES];
float outputDeltaWeights[HIDDEN_NODES][OUTPUT_NODES];
float hiddenDeltaBias[HIDDEN_NODES];
float outputDeltaBias[OUTPUT_NODES];

bool isTraining = false;
float inputs[INPUT_NODES];
float targets[OUTPUT_NODES];

// ============================================================
// ==== НЕЙРОСЕТЕВЫЕ ФУНКЦИИ =================================
// ============================================================

float sigmoid(float x) { 
if (x < -15.0) return 0.0;
if (x > 15.0) return 1.0; 
return 1.0 / (1.0 + exp(-x));
} 
float sigmoidDerivative(float x) { return x * (1.0 - x); }

void forwardPass(float* hiddenOutput, float* finalOutput) {
// Скрытый слой
for (int j = 0; j < HIDDEN_NODES; j++) { float sum = hiddenBias[j];
for (int i = 0; i < INPUT_NODES; i++) {
sum += inputs[i] * hiddenWeights[i][j]; }
hiddenOutput[j] = sigmoid(sum); }
// Выходной слой
for (int k = 0; k < OUTPUT_NODES; k++) {
float sum = outputBias[k];
for (int j = 0; j < HIDDEN_NODES; j++) {
sum += hiddenOutput[j] * outputWeights[j][k]; }
finalOutput[k] = sigmoid(sum);
}
}

void trainEpoch(int key) {
// Генерируем пример для клавиши key
generateKeyExample(key, inputs, targets);
float hiddenOutput[HIDDEN_NODES];
float finalOutput[OUTPUT_NODES];
forwardPass(hiddenOutput, finalOutput);
// Ошибка выходного слоя
float outputDelta[OUTPUT_NODES];
for (int k = 0; k < OUTPUT_NODES; k++) {
float error = targets[k] - finalOutput[k];
outputDelta[k] = error * sigmoidDerivative(finalOutput[k]);
}
// Ошибка скрытого слоя
float hiddenDelta[HIDDEN_NODES];
for (int j = 0; j < HIDDEN_NODES; j++) {
float error = 0;
for (int k = 0; k < OUTPUT_NODES; k++) {
error += outputDelta[k] * outputWeights[j][k]; }
hiddenDelta[j] = error * sigmoidDerivative(hiddenOutput[j]);
}
// Обновление весов выходного слоя
for (int j = 0; j < HIDDEN_NODES; j++) {
for (int k = 0; k < OUTPUT_NODES; k++) {
float delta = LEARNING_RATE * outputDelta[k] * hiddenOutput[j];
outputDeltaWeights[j][k] = MOMENTUM * outputDeltaWeights[j][k] + delta;
outputWeights[j][k] += outputDeltaWeights[j][k];
}
}
// Обновление bias выходного слоя
for (int k = 0; k < OUTPUT_NODES; k++) {
float delta = LEARNING_RATE * outputDelta[k];
outputDeltaBias[k] = MOMENTUM * outputDeltaBias[k] + delta;
outputBias[k] += outputDeltaBias[k];
}
// Обновление весов скрытого слоя
for (int i = 0; i < INPUT_NODES; i++) {
for (int j = 0; j < HIDDEN_NODES; j++) {
float delta = LEARNING_RATE * hiddenDelta[j] * inputs[i];
hiddenDeltaWeights[i][j] = MOMENTUM * hiddenDeltaWeights[i][j] + delta;
hiddenWeights[i][j] += hiddenDeltaWeights[i][j];
}
}
// Обновление bias скрытого слоя
for (int j = 0; j < HIDDEN_NODES; j++) {
float delta = LEARNING_RATE * hiddenDelta[j];
hiddenDeltaBias[j] = MOMENTUM * hiddenDeltaBias[j] + delta;
hiddenBias[j] += hiddenDeltaBias[j];
}
}
// ============================================================
// ==== ИНИЦИАЛИЗАЦИЯ ========================================
// ============================================================
void initializeWeights() {
randomSeed(analogRead(0));
// Xavier инициализация
float scale = sqrt(2.0 / INPUT_NODES);
for (int i = 0; i < INPUT_NODES; i++) {
for (int j = 0; j < HIDDEN_NODES; j++) {
hiddenWeights[i][j] = (random(-1000, 1001) / 1000.0) * scale;
hiddenDeltaWeights[i][j] = 0;
}
}
for (int j = 0; j < HIDDEN_NODES; j++) {
hiddenBias[j] = 0; hiddenDeltaBias[j] = 0; }
scale = sqrt(2.0 / HIDDEN_NODES);
for (int j = 0; j < HIDDEN_NODES; j++) {
for (int k = 0; k < OUTPUT_NODES; k++) {
outputWeights[j][k] = (random(-1000, 1001) / 1000.0) * scale;
outputDeltaWeights[j][k] = 0;
}
}
for (int k = 0; k < OUTPUT_NODES; k++) {
outputBias[k] = 0;outputDeltaBias[k] = 0; }
}
// ============================================================
// ==== ТЕСТИРОВАНИЕ =========================================
// ============================================================
void testAllKeys() {
Serial.println(F("=== ТЕСТИРОВАНИЕ ВСЕХ 256 КЛАВИШ ==="));
int correct = 0;
for (int key = 0; key < 256; key++) {
generateKeyExample(key, inputs, targets);
float hidden[HIDDEN_NODES];
float output[OUTPUT_NODES];
forwardPass(hidden, output);
// Преобразуем выход в число
int predicted = 0;
for (int k = 0; k < 8; k++) {
if (output[k] > 0.5) { 
predicted |= (1 << (7 - k));
}
}

if (predicted == key) { correct++;
} else if (key % 50 == 0) {  // Показываем только каждую 50-ю ошибку
Serial.print(F("Клавиша "));       Serial.print(key);
Serial.print(F(": предсказано ")); Serial.print(predicted);
Serial.print(F(", биты: "));
for (int k = 0; k < 8; k++) {
Serial.print(output[k], 2); Serial.print(F(" ")); 
} Serial.println(); }
}
  
float accuracy = (float)correct / 256 * 100;
Serial.print(F("✅ ТОЧНОСТЬ: "));
Serial.print(accuracy, 2); 
Serial.println(F("%"));
  
if (accuracy == 100) {
Serial.println(F("ПОЛНЫЙ УСПЕХ! Нейросеть выучила все 256 комбинаций!"));
}
}

void testRandomKeys(int count) {
Serial.println(F("=== ТЕСТ СЛУЧАЙНЫХ КЛАВИШ ==="));
for (int t = 0; t < count; t++) {
int key = random(0, 256);
generateKeyExample(key, inputs, targets);
float hidden[HIDDEN_NODES];
float output[OUTPUT_NODES];
forwardPass(hidden, output);
// Преобразуем выход в число
int predicted = 0;
for (int k = 0; k < 8; k++) {
if (output[k] > 0.5) {
predicted |= (1 << (7 - k));
}
}
Serial.print(F("Клавиша "));   Serial.print(key);
Serial.print(F(" (строка "));  Serial.print(key / 16);
Serial.print(F(", столбец ")); Serial.print(key % 16);
Serial.print(F(") → предсказано ")); Serial.print(predicted);
if (predicted == key) { Serial.println(F(" ✓"));
} else { Serial.print(F(" ✗ ["));
for (int k = 0; k < 8; k++) {
Serial.print(output[k], 2);
if (k < 7) Serial.print(F(","));
} Serial.println(F("]")); 
}
}
}
// ============================================================
// ==== ЭКСПОРТ ВЕСОВ ========================================
// ============================================================
void printWeightsForExport() {
Serial.println(F("\n// ==== ВЕСА ДЛЯ ДЕКОДЕРА 256 КЛАВИШ ===="));
Serial.println(F("// Нейросеть: 32 входа → 64 скрытых → 8 выходов\n"));
Serial.println(F("float hiddenWeights[INPUT_NODES][HIDDEN_NODES] = {"));
for (int i = 0; i < INPUT_NODES; i++) { Serial.print(F("  {"));
for (int j = 0; j < HIDDEN_NODES; j++) {
Serial.print(hiddenWeights[i][j], 6);
if (j < HIDDEN_NODES - 1) Serial.print(F(", "));
} Serial.println(F("},"));
} Serial.println(F("};"));
Serial.println(F("float hiddenBias[HIDDEN_NODES] = {"));
Serial.print(F("  "));
for (int j = 0; j < HIDDEN_NODES; j++) {
Serial.print(hiddenBias[j], 6);
if (j < HIDDEN_NODES - 1) Serial.print(F(", "));
} Serial.println(F("\n};"));
Serial.println(F("\nfloat outputWeights[HIDDEN_NODES][OUTPUT_NODES] = {"));
for (int j = 0; j < HIDDEN_NODES; j++) {
Serial.print(F("  {"));
for (int k = 0; k < OUTPUT_NODES; k++) {
Serial.print(outputWeights[j][k], 6);
if (k < OUTPUT_NODES - 1) Serial.print(F(", "));
} Serial.println(F("},"));
} Serial.println(F("};"));
Serial.println(F("\nfloat outputBias[OUTPUT_NODES] = {"));
Serial.print(F("  "));
for (int k = 0; k < OUTPUT_NODES; k++) {
Serial.print(outputBias[k], 6);
if (k < OUTPUT_NODES - 1) Serial.print(F(", "));
}Serial.println(F("\n};"));
}
// ============================================================
// ==== SETUP И LOOP =========================================
// ============================================================

void setup() {
Serial.begin(9600);
randomSeed(analogRead(0));
Serial.println(F("=========================================="));
Serial.println(F("НЕЙРОСЕТЬ-ДЕКОДЕР ДЛЯ 256 КЛАВИШ"));
Serial.println(F("=========================================="));
Serial.println(F("Вход: 16 строк + 16 столбцов (32 бита)"));
Serial.println(F("Выход: 8-битный код клавиши (0-255)"));
Serial.println(F("=========================================="));
Serial.println(F("Команды:"));
Serial.println(F("1 - Начать обучение"));
Serial.println(F("2 - Тест всех 256 клавиш"));
Serial.println(F("3 - Тест 10 случайных клавиш"));
Serial.println(F("4 - Ручной ввод"));
Serial.println(F("5 - Сбросить веса"));
Serial.println(F("7 - Экспортировать веса"));
Serial.println(F("=========================================="));
initializeWeights();
}

void loop() {
if (Serial.available() > 0) {
char command = Serial.read();
while (Serial.available() > 0) Serial.read();
switch (command) {
case '1': isTraining = true;
Serial.println(F("Обучение начато")); break;
case '2': testAllKeys(); break;
case '3': testRandomKeys(10); break;

case '4': {
Serial.println(F("Введите номер строки (0-15) и столбца (0-15):"));
Serial.println(F("Пример: 5,3 для строки 5, столбца 3"));
String input = Serial.readStringUntil('\n');
input.replace(',', ' ');
int row, col;
if (sscanf(input.c_str(), "%d %d", &row, &col) == 2) {
if (row >= 0 && row < 16 && col >= 0 && col < 16) {
// Очищаем вход
for (int i = 0; i < 32; i++) inputs[i] = 0;
// Устанавливаем биты
inputs[row] = 1; inputs[16 + col] = 1;
float hidden[HIDDEN_NODES];
float output[OUTPUT_NODES];
forwardPass(hidden, output);
// Преобразуем выход в число
int key = 0;
for (int k = 0; k < 8; k++) {
if (output[k] > 0.5) { key |= (1 << (7 - k)); }
}
Serial.print(F("Строка "));      Serial.print(row);
Serial.print(F(", столбец "));   Serial.print(col);
Serial.print(F(" → клавиша ")); Serial.println(key);
Serial.print(F("Вероятности битов: "));
for (int k = 0; k < 8; k++) {
Serial.print(output[k], 3); Serial.print(F(" "));
} Serial.println();
}
}
break;
}
        
case '5':
initializeWeights();
Serial.println(F("Веса сброшены"));
break;
        
case '7': printWeightsForExport(); break;
}
}
  
if (isTraining) {
static int epoch = 0; static float totalError = 0;
    
// Обучаем на всех 256 клавишах
for (int e = 0; e < 10; e++) {  // 10 эпох за цикл
for (int key = 0; key < 256; key++) {
trainEpoch(key);
// Считаем ошибку для мониторинга
float hidden[HIDDEN_NODES];
float output[OUTPUT_NODES];
forwardPass(hidden, output);       
float target[OUTPUT_NODES];
generateKeyExample(key, inputs, target);
float error = 0;
for (int k = 0; k < 8; k++) {
error += pow(target[k] - output[k], 2); }
totalError += error; }
}
epoch += 10;
float avgError = totalError / (256 * 10);
Serial.print(F("Эпоха "));      Serial.print(epoch);
Serial.print(F(" | Ошибка: ")); Serial.print(avgError, 6);
// Проверяем точность
int correct = 0;
for (int key = 0; key < 256; key += 16) {  // Проверяем каждую 16-ю для скорости
generateKeyExample(key, inputs, targets);
float hidden[HIDDEN_NODES];
float output[OUTPUT_NODES];
forwardPass(hidden, output);
int predicted = 0;
for (int k = 0; k < 8; k++) {
if (output[k] > 0.5) {
predicted |= (1 << (7 - k));
}
}
if (predicted == key) correct++;
}
float accuracy = (float)correct / 16 * 100;
Serial.print(F(" | Точность: "));
Serial.print(accuracy, 1);
Serial.println(F("%"));
totalError = 0;
// Останавливаемся при 100%
if (accuracy >= 99.9) {
isTraining = false;
Serial.println(F("✅ ОБУЧЕНИЕ ЗАВЕРШЕНО! Точность 100%"));
testAllKeys();
}
}
}

однако тут не показана база для обучения… она много весить будет, так что для наглядности как она работает вот второй код , вначале показаны входные 8 слоев через запятую, а в конце выход, эта база вопрос - ответ, многократно проходит через нейросеть, и она меняет свои веса, если сеть обучится на 100% она сможет правильно угадывать…

#include <EEPROM.h>

// Структура нейросети
#define INPUT_NODES 8
#define HIDDEN_NODES 16
#define OUTPUT_NODES 1

// Параметры обучения
#define LEARNING_RATE 0.3
#define MOMENTUM 0.8

// Адреса EEPROM
#define EEPROM_START_HIDDEN 0
#define EEPROM_MAGIC_ADDR 1020

// Пины
#define LED_PIN 13

// ============================================================
// ==== ВАША ПОЛНАЯ ВЫБОРКА ДЛЯ ОБУЧЕНИЯ (255 примеров) ======
// ============================================================
// Первые 8 чисел - вход, последнее - правильный выход (0 или 1)
const byte trainingData[255][9] PROGMEM = {
  {0,0,0,0,0,0,0,1,1},  // 1 - нечетное
  {0,0,0,0,0,0,1,0,0},  // 2 - четное
  {0,0,0,0,0,0,1,1,1},  // 3 - нечетное
  {0,0,0,0,0,1,0,0,0},  // 4 - четное
  {0,0,0,0,0,1,0,1,1},  // 5 - нечетное
  {0,0,0,0,0,1,1,0,0},  // 6 - четное
  {0,0,0,0,0,1,1,1,1},  // 7 - нечетное
  {0,0,0,0,1,0,0,0,0},  // 8 - четное
  {0,0,0,0,1,0,0,1,1},  // 9 - нечетное
  {0,0,0,0,1,0,1,0,0},  // 10 - четное
  {0,0,0,0,1,0,1,1,1},  // 11 - нечетное
  {0,0,0,0,1,1,0,0,0},  // 12 - четное
  {0,0,0,0,1,1,0,1,1},  // 13 - нечетное
  {0,0,0,0,1,1,1,0,0},  // 14 - четное
  {0,0,0,0,1,1,1,1,1},  // 15 - нечетное
  {0,0,0,1,0,0,0,0,0},  // 16 - четное
  {0,0,0,1,0,0,0,1,1},  // 17 - нечетное
  {0,0,0,1,0,0,1,0,0},  // 18 - четное
  {0,0,0,1,0,0,1,1,1},  // 19 - нечетное
  {0,0,0,1,0,1,0,0,0},  // 20 - четное
  {0,0,0,1,0,1,0,1,1},  // 21 - нечетное
  {0,0,0,1,0,1,1,0,0},  // 22 - четное
  {0,0,0,1,0,1,1,1,1},  // 23 - нечетное
  {0,0,0,1,1,0,0,0,0},  // 24 - четное
  {0,0,0,1,1,0,0,1,1},  // 25 - нечетное
  {0,0,0,1,1,0,1,0,0},  // 26 - четное
  {0,0,0,1,1,0,1,1,1},  // 27 - нечетное
  {0,0,0,1,1,1,0,0,0},  // 28 - четное
  {0,0,0,1,1,1,0,1,1},  // 29 - нечетное
  {0,0,0,1,1,1,1,0,0},  // 30 - четное
  {0,0,0,1,1,1,1,1,1},  // 31 - нечетное
  {0,0,1,0,0,0,0,0,0},  // 32 - четное
  {0,0,1,0,0,0,0,1,1},  // 33 - нечетное
  {0,0,1,0,0,0,1,0,0},  // 34 - четное
  {0,0,1,0,0,0,1,1,1},  // 35 - нечетное
  {0,0,1,0,0,1,0,0,0},  // 36 - четное
  {0,0,1,0,0,1,0,1,1},  // 37 - нечетное
  {0,0,1,0,0,1,1,0,0},  // 38 - четное
  {0,0,1,0,0,1,1,1,1},  // 39 - нечетное
  {0,0,1,0,1,0,0,0,0},  // 40 - четное
  {0,0,1,0,1,0,0,1,1},  // 41 - нечетное
  {0,0,1,0,1,0,1,0,0},  // 42 - четное
  {0,0,1,0,1,0,1,1,1},  // 43 - нечетное
  {0,0,1,0,1,1,0,0,0},  // 44 - четное
  {0,0,1,0,1,1,0,1,1},  // 45 - нечетное
  {0,0,1,0,1,1,1,0,0},  // 46 - четное
  {0,0,1,0,1,1,1,1,1},  // 47 - нечетное
  {0,0,1,1,0,0,0,0,0},  // 48 - четное
  {0,0,1,1,0,0,0,1,1},  // 49 - нечетное
  {0,0,1,1,0,0,1,0,0},  // 50 - четное
  {0,0,1,1,0,0,1,1,1},  // 51 - нечетное
  {0,0,1,1,0,1,0,0,0},  // 52 - четное
  {0,0,1,1,0,1,0,1,1},  // 53 - нечетное
  {0,0,1,1,0,1,1,0,0},  // 54 - четное
  {0,0,1,1,0,1,1,1,1},  // 55 - нечетное
  {0,0,1,1,1,0,0,0,0},  // 56 - четное
  {0,0,1,1,1,0,0,1,1},  // 57 - нечетное
  {0,0,1,1,1,0,1,0,0},  // 58 - четное
  {0,0,1,1,1,0,1,1,1},  // 59 - нечетное
  {0,0,1,1,1,1,0,0,0},  // 60 - четное
  {0,0,1,1,1,1,0,1,1},  // 61 - нечетное
  {0,0,1,1,1,1,1,0,0},  // 62 - четное
  {0,0,1,1,1,1,1,1,1},  // 63 - нечетное
  {0,1,0,0,0,0,0,0,0},  // 64 - четное
  {0,1,0,0,0,0,0,1,1},  // 65 - нечетное
  {0,1,0,0,0,0,1,0,0},  // 66 - четное
  {0,1,0,0,0,0,1,1,1},  // 67 - нечетное
  {0,1,0,0,0,1,0,0,0},  // 68 - четное
  {0,1,0,0,0,1,0,1,1},  // 69 - нечетное
  {0,1,0,0,0,1,1,0,0},  // 70 - четное
  {0,1,0,0,0,1,1,1,1},  // 71 - нечетное
  {0,1,0,0,1,0,0,0,0},  // 72 - четное
  {0,1,0,0,1,0,0,1,1},  // 73 - нечетное
  {0,1,0,0,1,0,1,0,0},  // 74 - четное
  {0,1,0,0,1,0,1,1,1},  // 75 - нечетное
  {0,1,0,0,1,1,0,0,0},  // 76 - четное
  {0,1,0,0,1,1,0,1,1},  // 77 - нечетное
  {0,1,0,0,1,1,1,0,0},  // 78 - четное
  {0,1,0,0,1,1,1,1,1},  // 79 - нечетное
  {0,1,0,1,0,0,0,0,0},  // 80 - четное
  {0,1,0,1,0,0,0,1,1},  // 81 - нечетное
  {0,1,0,1,0,0,1,0,0},  // 82 - четное
  {0,1,0,1,0,0,1,1,1},  // 83 - нечетное
  {0,1,0,1,0,1,0,0,0},  // 84 - четное
  {0,1,0,1,0,1,0,1,1},  // 85 - нечетное
  {0,1,0,1,0,1,1,0,0},  // 86 - четное
  {0,1,0,1,0,1,1,1,1},  // 87 - нечетное
  {0,1,0,1,1,0,0,0,0},  // 88 - четное
  {0,1,0,1,1,0,0,1,1},  // 89 - нечетное
  {0,1,0,1,1,0,1,0,0},  // 90 - четное
  {0,1,0,1,1,0,1,1,1},  // 91 - нечетное
  {0,1,0,1,1,1,0,0,0},  // 92 - четное
  {0,1,0,1,1,1,0,1,1},  // 93 - нечетное
  {0,1,0,1,1,1,1,0,0},  // 94 - четное
  {0,1,0,1,1,1,1,1,1},  // 95 - нечетное
  {0,1,1,0,0,0,0,0,0},  // 96 - четное
  {0,1,1,0,0,0,0,1,1},  // 97 - нечетное
  {0,1,1,0,0,0,1,0,0},  // 98 - четное
  {0,1,1,0,0,0,1,1,1},  // 99 - нечетное
  {0,1,1,0,0,1,0,0,0},  // 100 - четное
  {0,1,1,0,0,1,0,1,1},  // 101 - нечетное
  {0,1,1,0,0,1,1,0,0},  // 102 - четное
  {0,1,1,0,0,1,1,1,1},  // 103 - нечетное
  {0,1,1,0,1,0,0,0,0},  // 104 - четное
  {0,1,1,0,1,0,0,1,1},  // 105 - нечетное
  {0,1,1,0,1,0,1,0,0},  // 106 - четное
  {0,1,1,0,1,0,1,1,1},  // 107 - нечетное
  {0,1,1,0,1,1,0,0,0},  // 108 - четное
  {0,1,1,0,1,1,0,1,1},  // 109 - нечетное
  {0,1,1,0,1,1,1,0,0},  // 110 - четное
  {0,1,1,0,1,1,1,1,1},  // 111 - нечетное
  {0,1,1,1,0,0,0,0,0},  // 112 - четное
  {0,1,1,1,0,0,0,1,1},  // 113 - нечетное
  {0,1,1,1,0,0,1,0,0},  // 114 - четное
  {0,1,1,1,0,0,1,1,1},  // 115 - нечетное
  {0,1,1,1,0,1,0,0,0},  // 116 - четное
  {0,1,1,1,0,1,0,1,1},  // 117 - нечетное
  {0,1,1,1,0,1,1,0,0},  // 118 - четное
  {0,1,1,1,0,1,1,1,1},  // 119 - нечетное
  {0,1,1,1,1,0,0,0,0},  // 120 - четное
  {0,1,1,1,1,0,0,1,1},  // 121 - нечетное
  {0,1,1,1,1,0,1,0,0},  // 122 - четное
  {0,1,1,1,1,0,1,1,1},  // 123 - нечетное
  {0,1,1,1,1,1,0,0,0},  // 124 - четное
  {0,1,1,1,1,1,0,1,1},  // 125 - нечетное
  {0,1,1,1,1,1,1,0,0},  // 126 - четное
  {0,1,1,1,1,1,1,1,1},  // 127 - нечетное
  {1,0,0,0,0,0,0,0,0},  // 128 - четное
  {1,0,0,0,0,0,0,1,1},  // 129 - нечетное
  {1,0,0,0,0,0,1,0,0},  // 130 - четное
  {1,0,0,0,0,0,1,1,1},  // 131 - нечетное
  {1,0,0,0,0,1,0,0,0},  // 132 - четное
  {1,0,0,0,0,1,0,1,1},  // 133 - нечетное
  {1,0,0,0,0,1,1,0,0},  // 134 - четное
  {1,0,0,0,0,1,1,1,1},  // 135 - нечетное
  {1,0,0,0,1,0,0,0,0},  // 136 - четное
  {1,0,0,0,1,0,0,1,1},  // 137 - нечетное
  {1,0,0,0,1,0,1,0,0},  // 138 - четное
  {1,0,0,0,1,0,1,1,1},  // 139 - нечетное
  {1,0,0,0,1,1,0,0,0},  // 140 - четное
  {1,0,0,0,1,1,0,1,1},  // 141 - нечетное
  {1,0,0,0,1,1,1,0,0},  // 142 - четное
  {1,0,0,0,1,1,1,1,1},  // 143 - нечетное
  {1,0,0,1,0,0,0,0,0},  // 144 - четное
  {1,0,0,1,0,0,0,1,1},  // 145 - нечетное
  {1,0,0,1,0,0,1,0,0},  // 146 - четное
  {1,0,0,1,0,0,1,1,1},  // 147 - нечетное
  {1,0,0,1,0,1,0,0,0},  // 148 - четное
  {1,0,0,1,0,1,0,1,1},  // 149 - нечетное
  {1,0,0,1,0,1,1,0,0},  // 150 - четное
  {1,0,0,1,0,1,1,1,1},  // 151 - нечетное
  {1,0,0,1,1,0,0,0,0},  // 152 - четное
  {1,0,0,1,1,0,0,1,1},  // 153 - нечетное
  {1,0,0,1,1,0,1,0,0},  // 154 - четное
  {1,0,0,1,1,0,1,1,1},  // 155 - нечетное
  {1,0,0,1,1,1,0,0,0},  // 156 - четное
  {1,0,0,1,1,1,0,1,1},  // 157 - нечетное
  {1,0,0,1,1,1,1,0,0},  // 158 - четное
  {1,0,0,1,1,1,1,1,1},  // 159 - нечетное
  {1,0,1,0,0,0,0,0,0},  // 160 - четное
  {1,0,1,0,0,0,0,1,1},  // 161 - нечетное
  {1,0,1,0,0,0,1,0,0},  // 162 - четное
  {1,0,1,0,0,0,1,1,1},  // 163 - нечетное
  {1,0,1,0,0,1,0,0,0},  // 164 - четное
  {1,0,1,0,0,1,0,1,1},  // 165 - нечетное
  {1,0,1,0,0,1,1,0,0},  // 166 - четное
  {1,0,1,0,0,1,1,1,1},  // 167 - нечетное
  {1,0,1,0,1,0,0,0,0},  // 168 - четное
  {1,0,1,0,1,0,0,1,1},  // 169 - нечетное
  {1,0,1,0,1,0,1,0,0},  // 170 - четное
  {1,0,1,0,1,0,1,1,1},  // 171 - нечетное
  {1,0,1,0,1,1,0,0,0},  // 172 - четное
  {1,0,1,0,1,1,0,1,1},  // 173 - нечетное
  {1,0,1,0,1,1,1,0,0},  // 174 - четное
  {1,0,1,0,1,1,1,1,1},  // 175 - нечетное
  {1,0,1,1,0,0,0,0,0},  // 176 - четное
  {1,0,1,1,0,0,0,1,1},  // 177 - нечетное
  {1,0,1,1,0,0,1,0,0},  // 178 - четное
  {1,0,1,1,0,0,1,1,1},  // 179 - нечетное
  {1,0,1,1,0,1,0,0,0},  // 180 - четное
  {1,0,1,1,0,1,0,1,1},  // 181 - нечетное
  {1,0,1,1,0,1,1,0,0},  // 182 - четное
  {1,0,1,1,0,1,1,1,1},  // 183 - нечетное
  {1,0,1,1,1,0,0,0,0},  // 184 - четное
  {1,0,1,1,1,0,0,1,1},  // 185 - нечетное
  {1,0,1,1,1,0,1,0,0},  // 186 - четное
  {1,0,1,1,1,0,1,1,1},  // 187 - нечетное
  {1,0,1,1,1,1,0,0,0},  // 188 - четное
  {1,0,1,1,1,1,0,1,1},  // 189 - нечетное
  {1,0,1,1,1,1,1,0,0},  // 190 - четное
  {1,0,1,1,1,1,1,1,1},  // 191 - нечетное
  {1,1,0,0,0,0,0,0,0},  // 192 - четное
  {1,1,0,0,0,0,0,1,1},  // 193 - нечетное
  {1,1,0,0,0,0,1,0,0},  // 194 - четное
  {1,1,0,0,0,0,1,1,1},  // 195 - нечетное
  {1,1,0,0,0,1,0,0,0},  // 196 - четное
  {1,1,0,0,0,1,0,1,1},  // 197 - нечетное
  {1,1,0,0,0,1,1,0,0},  // 198 - четное
  {1,1,0,0,0,1,1,1,1},  // 199 - нечетное
  {1,1,0,0,1,0,0,0,0},  // 200 - четное
  {1,1,0,0,1,0,0,1,1},  // 201 - нечетное
  {1,1,0,0,1,0,1,0,0},  // 202 - четное
  {1,1,0,0,1,0,1,1,1},  // 203 - нечетное
  {1,1,0,0,1,1,0,0,0},  // 204 - четное
  {1,1,0,0,1,1,0,1,1},  // 205 - нечетное
  {1,1,0,0,1,1,1,0,0},  // 206 - четное
  {1,1,0,0,1,1,1,1,1},  // 207 - нечетное
  {1,1,0,1,0,0,0,0,0},  // 208 - четное
  {1,1,0,1,0,0,0,1,1},  // 209 - нечетное
  {1,1,0,1,0,0,1,0,0},  // 210 - четное
  {1,1,0,1,0,0,1,1,1},  // 211 - нечетное
  {1,1,0,1,0,1,0,0,0},  // 212 - четное
  {1,1,0,1,0,1,0,1,1},  // 213 - нечетное
  {1,1,0,1,0,1,1,0,0},  // 214 - четное
  {1,1,0,1,0,1,1,1,1},  // 215 - нечетное
  {1,1,0,1,1,0,0,0,0},  // 216 - четное
  {1,1,0,1,1,0,0,1,1},  // 217 - нечетное
  {1,1,0,1,1,0,1,0,0},  // 218 - четное
  {1,1,0,1,1,0,1,1,1},  // 219 - нечетное
  {1,1,0,1,1,1,0,0,0},  // 220 - четное
  {1,1,0,1,1,1,0,1,1},  // 221 - нечетное
  {1,1,0,1,1,1,1,0,0},  // 222 - четное
  {1,1,0,1,1,1,1,1,1},  // 223 - нечетное
  {1,1,1,0,0,0,0,0,0},  // 224 - четное
  {1,1,1,0,0,0,0,1,1},  // 225 - нечетное
  {1,1,1,0,0,0,1,0,0},  // 226 - четное
  {1,1,1,0,0,0,1,1,1},  // 227 - нечетное
  {1,1,1,0,0,1,0,0,0},  // 228 - четное
  {1,1,1,0,0,1,0,1,1},  // 229 - нечетное
  {1,1,1,0,0,1,1,0,0},  // 230 - четное
  {1,1,1,0,0,1,1,1,1},  // 231 - нечетное
  {1,1,1,0,1,0,0,0,0},  // 232 - четное
  {1,1,1,0,1,0,0,1,1},  // 233 - нечетное
  {1,1,1,0,1,0,1,0,0},  // 234 - четное
  {1,1,1,0,1,0,1,1,1},  // 235 - нечетное
  {1,1,1,0,1,1,0,0,0},  // 236 - четное
  {1,1,1,0,1,1,0,1,1},  // 237 - нечетное
  {1,1,1,0,1,1,1,0,0},  // 238 - четное
  {1,1,1,0,1,1,1,1,1},  // 239 - нечетное
  {1,1,1,1,0,0,0,0,0},  // 240 - четное
  {1,1,1,1,0,0,0,1,1},  // 241 - нечетное
  {1,1,1,1,0,0,1,0,0},  // 242 - четное
  {1,1,1,1,0,0,1,1,1},  // 243 - нечетное
  {1,1,1,1,0,1,0,0,0},  // 244 - четное
  {1,1,1,1,0,1,0,1,1},  // 245 - нечетное
  {1,1,1,1,0,1,1,0,0},  // 246 - четное
  {1,1,1,1,0,1,1,1,1},  // 247 - нечетное
  {1,1,1,1,1,0,0,0,0},  // 248 - четное
  {1,1,1,1,1,0,0,1,1},  // 249 - нечетное
  {1,1,1,1,1,0,1,0,0},  // 250 - четное
  {1,1,1,1,1,0,1,1,1},  // 251 - нечетное
  {1,1,1,1,1,1,0,0,0},  // 252 - четное
  {1,1,1,1,1,1,0,1,1},  // 253 - нечетное
  {1,1,1,1,1,1,1,0,0},  // 254 - четное
  {1,1,1,1,1,1,1,1,1}   // 255 - нечетное
};
// ============================================================

// Веса сети
float hiddenWeights[INPUT_NODES][HIDDEN_NODES];
float outputWeights[HIDDEN_NODES][OUTPUT_NODES];
float hiddenBias[HIDDEN_NODES];
float outputBias[OUTPUT_NODES];

// Для момента
float hiddenDeltaWeights[INPUT_NODES][HIDDEN_NODES];
float outputDeltaWeights[HIDDEN_NODES][OUTPUT_NODES];
float hiddenDeltaBias[HIDDEN_NODES];
float outputDeltaBias[OUTPUT_NODES];

bool isTraining = false;
bool stopTraining = false;
unsigned long lastSaveTime = 0;
const unsigned long saveInterval = 600000;

float inputs[INPUT_NODES];

void getExample(int index, float* input, float* target) {
  byte example[9];
  for (int i = 0; i < 9; i++) {
    example[i] = pgm_read_byte(&trainingData[index][i]);
  }
  for (int i = 0; i < INPUT_NODES; i++) {
    input[i] = example[i];
  }
  *target = example[8];
}

float sigmoid(float x) {
  if (x < -10.0) return 0.0;
  if (x > 10.0) return 1.0;
  return 1.0 / (1.0 + exp(-x));
}

float sigmoidDerivative(float x) {
  return x * (1.0 - x);
}

void forwardPass(float* hiddenOutput, float* finalOutput) {
  for (int j = 0; j < HIDDEN_NODES; j++) {
    float sum = hiddenBias[j];
    for (int i = 0; i < INPUT_NODES; i++) {
      sum += inputs[i] * hiddenWeights[i][j];
    }
    hiddenOutput[j] = sigmoid(sum);
  }
  
  float sum = outputBias[0];
  for (int j = 0; j < HIDDEN_NODES; j++) {
    sum += hiddenOutput[j] * outputWeights[j][0];
  }
  finalOutput[0] = sigmoid(sum);
}

void trainEpoch(int exampleIndex) {
  float target;
  getExample(exampleIndex, inputs, &target);
  
  float hiddenOutput[HIDDEN_NODES];
  float finalOutput[OUTPUT_NODES];
  forwardPass(hiddenOutput, finalOutput);
  
  float outputError = target - finalOutput[0];
  float outputDelta = outputError * sigmoidDerivative(finalOutput[0]);
  
  float hiddenDelta[HIDDEN_NODES];
  for (int j = 0; j < HIDDEN_NODES; j++) {
    float hiddenError = outputDelta * outputWeights[j][0];
    hiddenDelta[j] = hiddenError * sigmoidDerivative(hiddenOutput[j]);
  }
  
  for (int j = 0; j < HIDDEN_NODES; j++) {
    float delta = LEARNING_RATE * outputDelta * hiddenOutput[j];
    outputDeltaWeights[j][0] = MOMENTUM * outputDeltaWeights[j][0] + delta;
    outputWeights[j][0] += outputDeltaWeights[j][0];
  }
  
  outputDeltaBias[0] = MOMENTUM * outputDeltaBias[0] + LEARNING_RATE * outputDelta;
  outputBias[0] += outputDeltaBias[0];
  
  for (int i = 0; i < INPUT_NODES; i++) {
    for (int j = 0; j < HIDDEN_NODES; j++) {
      float delta = LEARNING_RATE * hiddenDelta[j] * inputs[i];
      hiddenDeltaWeights[i][j] = MOMENTUM * hiddenDeltaWeights[i][j] + delta;
      hiddenWeights[i][j] += hiddenDeltaWeights[i][j];
    }
  }
  
  for (int j = 0; j < HIDDEN_NODES; j++) {
    float delta = LEARNING_RATE * hiddenDelta[j];
    hiddenDeltaBias[j] = MOMENTUM * hiddenDeltaBias[j] + delta;
    hiddenBias[j] += hiddenDeltaBias[j];
  }
}

void initializeWeights() {
  for (int i = 0; i < INPUT_NODES; i++) {
    for (int j = 0; j < HIDDEN_NODES; j++) {
      hiddenWeights[i][j] = random(-1000, 1001) / 1000.0;
      hiddenDeltaWeights[i][j] = 0;
    }
  }
  
  for (int j = 0; j < HIDDEN_NODES; j++) {
    hiddenBias[j] = random(-1000, 1001) / 1000.0;
    hiddenDeltaBias[j] = 0;
  }
  
  for (int j = 0; j < HIDDEN_NODES; j++) {
    outputWeights[j][0] = random(-1000, 1001) / 1000.0;
    outputDeltaWeights[j][0] = 0;
  }
  
  outputBias[0] = random(-1000, 1001) / 1000.0;
  outputDeltaBias[0] = 0;
}

void printWeightsForExport() {
  Serial.println(F("\n=== ВЕСА ДЛЯ ВСТАВКИ В КОД ===\n"));
  
  Serial.println(F("float hiddenWeights[INPUT_NODES][HIDDEN_NODES] = {"));
  for (int i = 0; i < INPUT_NODES; i++) {
    Serial.print(F("  {"));
    for (int j = 0; j < HIDDEN_NODES; j++) {
      Serial.print(hiddenWeights[i][j], 6);
      if (j < HIDDEN_NODES - 1) Serial.print(F(", "));
    }
    Serial.println(F("},"));
  }
  Serial.println(F("};"));
  
  Serial.println(F("\nfloat hiddenBias[HIDDEN_NODES] = {"));
  Serial.print(F("  "));
  for (int j = 0; j < HIDDEN_NODES; j++) {
    Serial.print(hiddenBias[j], 6);
    if (j < HIDDEN_NODES - 1) Serial.print(F(", "));
  }
  Serial.println(F("\n};"));
  
  Serial.println(F("\nfloat outputWeights[HIDDEN_NODES][OUTPUT_NODES] = {"));
  for (int j = 0; j < HIDDEN_NODES; j++) {
    Serial.print(F("  {"));
    Serial.print(outputWeights[j][0], 6);
    Serial.println(F("},"));
  }
  Serial.println(F("};"));
  
  Serial.println(F("\nfloat outputBias[OUTPUT_NODES] = {"));
  Serial.print(F("  "));
  Serial.print(outputBias[0], 6);
  Serial.println(F("\n};"));
}

void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
  randomSeed(analogRead(0));
  
  Serial.println(F("=== НЕЙРОСЕТЬ С ВАШЕЙ ВЫБОРКОЙ ==="));
  Serial.println(F("Команды:"));
  Serial.println(F("1 - Начать обучение"));
  Serial.println(F("2 - Проверить число (введите 8 бит)"));
  Serial.println(F("3 - Остановить обучение"));
  Serial.println(F("5 - Сбросить веса случайно"));
  Serial.println(F("7 - Экспортировать веса"));
  
  initializeWeights();
}

void loop() {
  if (Serial.available() > 0) {
    char command = Serial.read();
    while (Serial.available() > 0) Serial.read();
    
    switch (command) {
      case '1':
        isTraining = true;
        stopTraining = false;
        Serial.println(F("Обучение начато"));
        break;
      case '2':
        Serial.println(F("Введите 8 бит (0 или 1) через запятую:"));
        waitForInput();
        break;
      case '3':
        isTraining = false;
        stopTraining = true;
        Serial.println(F("Обучение остановлено"));
        break;
      case '5':
        initializeWeights();
        Serial.println(F("Веса сброшены случайно"));
        break;
      case '7':
        printWeightsForExport();
        break;
    }
  }
  
  if (isTraining && !stopTraining) {
    static int epoch = 0;
    static float totalError = 0;
    static int correct = 0;
    
    for (int e = 0; e < 10; e++) {  // 10 эпох за цикл
      for (int ex = 0; ex < 255; ex++) {
        trainEpoch(ex);
        
        float target;
        getExample(ex, inputs, &target);
        
        float hidden[HIDDEN_NODES];
        float out[1];
        forwardPass(hidden, out);
        
        totalError += pow(target - out[0], 2);
        if ((out[0] > 0.5 && target > 0.5) || (out[0] <= 0.5 && target <= 0.5)) {
          correct++;
        }
      }
    }
    
    epoch += 10;
    float avgError = totalError / (255 * 10);
    float accuracy = (float)correct / (255 * 10) * 100;
    
    Serial.print(F("Эпоха "));
    Serial.print(epoch);
    Serial.print(F(" | Ошибка: "));
    Serial.print(avgError, 6);
    Serial.print(F(" | Точность: "));
    Serial.print(accuracy, 2);
    Serial.println(F("%"));
    
    totalError = 0;
    correct = 0;
  }
}

void waitForInput() {
  String s = Serial.readStringUntil('\n');
  s.replace(',', ' ');
  
  float in[8];
  int idx = 0;
  int pos = 0;
  
  while (pos < s.length() && idx < 8) {
    int next = s.indexOf(' ', pos);
    if (next == -1) next = s.length();
    String val = s.substring(pos, next);
    val.trim();
    if (val.length() > 0) {
      in[idx++] = val.toInt();
    }
    pos = next + 1;
  }
  
  if (idx == 8) {
    for (int i = 0; i < 8; i++) inputs[i] = in[i];
    
    float hidden[HIDDEN_NODES];
    float out[1];
    forwardPass(hidden, out);
    
    Serial.print(F("Результат: "));
    Serial.println(out[0], 6);
    Serial.print(F("Это "));
    Serial.println(out[0] > 0.5 ? F("НЕЧЕТНОЕ (1)") : F("ЧЕТНОЕ (0)"));
  }
}

тестировал на esp32, если у вас возникли вопросы, ответ ¯\_(ツ)_/¯ но может кто другой вникнет, и будет создавать что то свое, заодно и объяснит!
сеть универсальная, есть так же и другие сети, для распознавания речи, или изображений… более сложные, и с обучением на пк или сайте!
https://circuitdigest.com/microcontrollers-projects/esp32-offline-voice-recognition-using-edge-impulse
https://circuitdigest.com/microcontroller-projects/esp32-cam-face-recognition-using-edge-impulse
и куча других, однако у меня просто показывает универсальную, и скорее знакомит с тем что такое нейросеть, однако в сети есть и другие, более сложные, и даже обученные!

Какого эта тема в проектах?!

1 лайк

BOOM дружище, это два реально рабочих кода нейросети, которая обучается прямо на esp32, если вы вникнете в код, вы поймете что там все описано, и вопросы попросту не нужны, надо вникать если что то не понятно, там все выводится в монитор порта, сделанная для робототехников, возможно кому то пригодится, и позже сам опубликует что у него получилось, взяв за основу примеры 2 кодов

если есть какие то сомнения, могу только оставить код обученных перенесенных весов, где можно протестировать их отдельно, что вроде все объясняет…

// ============================================================
// ==== ДЕКОДЕР КЛАВИАТУРЫ 16x16 (256 клавиш) ================
// ==== С ВАШИМИ ОБУЧЕННЫМИ ВЕСАМИ ============================
// ============================================================

#define INPUT_NODES 32     // 16 строк + 16 столбцов
#define HIDDEN_NODES 64    // 64 скрытых нейрона
#define OUTPUT_NODES 8     // 8 бит = 256 комбинаций

// ============================================================
// ==== ВАШИ ВЕСА (из экспорта) ==============================
// ============================================================

float hiddenWeights[INPUT_NODES][HIDDEN_NODES] = {
  {-1.140066, 1.062764, 0.056409, 0.714106, -1.176116, -0.303846, -0.366674, -0.803433, 0.956042, -0.123809, -0.923827, -1.051633, -0.870570, -0.021952, 0.415550, -0.812733, -1.157299, 0.258146, 0.114352, -0.560537, -1.382504, -1.254801, 1.448225, 1.207037, 0.414098, -1.492741, 1.105656, -0.829292, -1.086970, -0.666698, -0.453588, -0.161208, 0.157049, 0.348037, 0.859823, 0.136275, -0.737275, 0.146575, -0.963280, 0.137149, -0.239438, 1.338812, 0.786839, 0.088443, 0.093390, 0.221448, -0.439288, -1.032446, 0.099332, -1.122403, 0.034457, -1.698512, -0.407043, 0.230102, -0.669343, 1.464069, 0.225415, 0.738666, -0.123579, -0.645432, -0.969901, 0.466749, -0.050798, 0.066167},
  {-1.736296, -0.266211, -0.249199, 0.733791, -0.368852, 0.180677, -0.651152, -0.527678, 0.911017, 0.610649, -0.231912, -0.159328, 0.412876, -0.191018, 0.548929, -0.726174, -0.153521, 0.429519, -0.075759, -0.065255, -0.940070, -0.646044, 0.902112, 2.010602, 0.561704, -0.754879, -0.352609, 0.480584, -1.287688, -0.016203, -0.324300, -0.077328, -0.213033, 0.903270, 0.964794, -0.250421, -0.820565, -0.266317, -0.085897, -0.720190, 0.079390, 0.947148, 0.792295, 0.006229, -0.602203, 0.572345, 0.343118, -0.113893, 0.474191, -0.679871, -0.067915, -0.069157, -0.803871, -0.279390, -0.841876, 1.241267, 0.250891, -0.334884, 0.264472, -0.229974, -0.182876, -0.135327, -0.446029, 0.601635},
  {-0.842206, 1.969301, 0.315543, -0.095787, -1.006476, -0.087172, 0.498618, -0.352616, 0.780791, 0.604431, -0.624770, -0.722437, -0.619979, 0.229358, 0.224972, 0.026555, -0.249981, 0.027053, 0.052928, -0.415208, -0.402598, -0.160392, 1.221355, 0.205246, 0.860618, -1.347330, 1.496370, -0.484077, -0.587087, -0.568624, -0.354668, -0.011618, 0.083916, -0.691950, 0.143022, 0.724277, -0.408079, 0.859810, 0.368006, 0.724300, 0.127630, -0.340498, -0.133908, 0.550145, 0.232132, -0.613878, -0.457939, -0.292041, -0.719225, 0.447313, 0.160915, -0.338646, -0.976769, -0.372365, 0.202751, 0.168567, 0.544719, -0.193223, -0.083224, -0.589287, -0.249687, 0.570062, -0.041535, -0.174392},
  {-1.477658, 0.807647, -0.136515, 0.173244, -0.729780, 0.138733, -0.347387, 0.150976, 0.329563, 1.084859, 0.056527, -0.184431, 0.432735, 0.152832, 0.685641, -0.087443, 0.312539, -0.027947, -0.194205, -0.210365, -0.500819, 0.142596, 0.829927, 1.194484, 0.537783, -0.837725, 0.349756, 0.228081, -0.892767, -0.262620, 0.295739, 0.081264, -0.299336, 0.000363, 0.371287, -0.237777, -0.939309, 0.486892, 1.046777, -0.615098, 0.121534, -0.396555, -0.302242, 0.220419, -0.492180, -0.349872, 0.529364, 0.383900, -0.359161, 0.201509, -0.146090, 1.154508, -1.244629, -0.610932, -0.287639, 0.159394, 0.215691, -0.876178, -0.153507, -0.110792, -0.070491, -0.264255, -0.676113, 0.133247},
  {0.308530, -0.677946, -0.285036, 0.953195, -0.542750, -1.035156, 0.463114, -0.275266, -0.291027, -0.471030, -0.937592, -1.154091, 0.019237, -0.664064, -0.967667, -0.526367, -0.571052, 0.977222, 0.447925, 0.175467, 0.401184, -0.021737, 0.473934, -0.305934, 0.042653, 0.794102, -0.240662, -0.386977, 0.787793, -0.886525, -1.293511, 0.810346, 0.534936, 0.923010, 0.088674, 0.032732, -0.477061, -0.329486, -0.815491, -0.075570, -0.639862, 0.340132, -0.645185, 0.210083, 0.291918, 0.458772, -0.222253, -0.354357, -0.654276, -0.256462, 0.057948, -1.388984, 0.997490, 0.942134, -0.119181, 1.323258, -0.417153, 1.116940, 0.019281, 0.090990, 0.052711, 0.310398, 1.149398, -0.196169},
  {-1.003451, -1.474310, -0.381239, 0.667524, 0.161869, -0.698575, -0.207612, -0.173578, -0.184052, 0.250473, -0.344415, -0.372966, 0.881063, -0.480892, -0.513233, -0.701947, 0.178160, 0.761671, 0.010971, 0.338335, 0.176276, 0.237413, -0.070120, 0.860919, -0.068594, 1.394356, -0.830060, 0.247592, 0.193347, -0.313732, -0.786111, 0.794229, 0.311546, 0.983061, 0.465203, -0.443712, -0.551282, -0.445544, -0.363963, -0.887489, 0.037569, 0.244448, -0.231916, 0.146476, -0.568187, 0.495024, 0.639565, 0.592593, 0.021208, -0.059007, 0.266989, -0.011387, 0.288034, 0.281171, -0.596024, 0.795726, -0.205966, 0.058118, 0.337828, 0.097987, 0.732217, -0.042983, 0.300012, 0.424250},
  {0.252337, 1.140182, 0.125849, 0.194773, -0.798519, -0.565310, 0.986312, -0.387152, -0.253459, 0.001024, -0.495647, -0.776644, -0.301386, -0.021621, -0.757192, 0.164940, 0.005149, 0.386647, 0.067735, 0.085525, 0.743675, 0.658733, 0.620555, -0.693718, 0.319230, 0.488969, 0.899840, -0.226456, 0.465638, -0.903134, -0.583332, 0.481339, 0.116422, -0.484084, -0.591630, 0.362153, -0.572795, 0.868475, 0.388874, 0.365344, -0.273005, -0.691120, -1.124733, 0.621728, 0.090349, -0.740664, -0.206046, 0.115772, -1.012097, 1.022261, -0.191935, -0.364337, -0.200540, 0.335132, 0.130933, -0.007970, 0.277090, -0.062914, -0.447282, -0.266341, 0.362273, 0.525141, 0.575145, -0.357946},
  {-0.829060, -0.414706, -0.027294, 0.182035, -0.468775, -0.239163, 0.031343, 0.261342, -0.273685, 0.936449, 0.152667, -0.024417, 0.663070, -0.139362, -0.074502, -0.274533, 0.923916, 0.604495, -0.037802, 0.485945, 0.516058, 1.107082, 0.044803, 0.387590, 0.338319, 0.744342, -0.285786, 0.478710, -0.099177, -0.396839, -0.226481, 0.399359, 0.035333, -0.162080, -0.396538, -0.275437, -0.742196, 0.383539, 0.751396, -0.418450, -0.044672, -0.560642, -0.850889, 0.585516, -0.638346, -0.240890, 0.291614, 0.850777, -0.629473, 0.912106, -0.270684, 0.687372, -0.677745, -0.320902, -0.279596, -0.257841, 0.286826, -0.486320, -0.144248, -0.267123, 0.873966, -0.133383, 0.072477, -0.160335},
  {1.464345, -0.229332, -0.053237, -0.692233, 0.886188, 0.695399, -0.688600, 0.092767, 0.493858, -1.468615, 0.391085, 0.665170, -1.102543, 0.264528, 0.298356, 0.461071, -1.093774, -1.418586, -0.377283, -0.571073, -0.839757, -1.375610, -0.797464, -0.784804, -0.893430, -1.336193, 0.031660, -0.738812, -0.164736, 0.949024, 0.773165, -1.129367, -0.648280, -0.403724, 0.089777, -0.156047, 1.706474, -0.722956, -1.048232, 0.953904, -0.545957, 0.627731, 1.450670, -0.828345, 0.479908, -0.011709, -0.778273, -0.786476, 1.201562, -1.021685, -0.111530, -0.927057, 0.681240, -0.347163, 0.397941, -0.665224, -0.348476, 0.430823, 0.181642, -0.109150, -1.134011, -0.354318, -0.666140, -0.292255},
  {0.273355, -1.160102, 0.005831, -0.446996, 1.535171, 0.622839, -0.773968, 0.343428, 0.207812, -0.411335, 0.660587, 1.077210, -0.085675, 0.369136, 0.949478, 0.387836, -0.054671, -1.058020, -0.093019, -0.323069, -0.285498, -0.617223, -0.818598, 0.540464, -0.547292, -0.438487, -0.665799, 0.203752, -0.280987, 1.449662, 1.181336, -0.483937, -0.418137, 0.397596, 0.291151, -0.399090, 0.754052, -0.759434, -0.155499, -0.266618, 0.061297, 0.642314, 1.511075, -0.652221, -0.308493, 0.610581, 0.317938, 0.027639, 1.329900, -0.753925, -0.105593, 0.686258, 0.220935, -0.281739, -0.252081, -0.707772, -0.183674, -0.230459, 0.084283, 0.465289, -0.243562, -0.458582, -0.852087, -0.059144},
  {1.378151, 1.505566, -0.001012, -0.803442, 0.071646, 0.766919, 0.427790, 0.390133, 0.328084, -0.204745, 0.266488, 0.703195, -0.576242, 0.526610, 0.127268, 0.897147, -0.172026, -0.968003, -0.032828, -0.184958, -0.081576, -0.232177, -0.490817, -0.918211, -0.135286, -1.104365, 0.911218, -0.499942, 0.026354, 0.441006, 1.071709, -0.696649, -0.128471, -1.063274, -0.526612, 0.209637, 0.709063, 0.236353, 0.215812, 1.200049, -0.293004, -0.689915, 0.178956, -0.122926, 0.707260, -0.880838, -0.628173, -0.339191, -0.133056, 0.093037, -0.127852, 0.284624, -0.524523, -0.297998, 0.747751, -1.282221, 0.090225, -0.362094, -0.341443, -0.126603, -0.547333, 0.056544, -0.365478, -0.453515},
  {-0.017759, 0.039836, -0.090791, -0.845947, 0.777889, 0.600766, -0.275674, 0.335222, 0.087248, 0.612255, 0.859568, 0.976652, 0.137961, 0.559192, 0.858526, 0.650022, 0.413699, -0.913921, -0.224284, -0.184183, -0.204493, 0.342685, -0.464966, -0.331347, 0.025773, -0.671629, -0.014664, 0.239921, -0.425277, 0.856435, 1.164568, -0.465100, -0.435101, -0.552355, -0.039577, -0.349821, 0.223197, -0.114001, 0.685745, -0.063395, 0.450773, -0.680776, 0.107560, -0.358236, -0.469642, -0.450514, 0.315720, 0.544345, 0.374253, 0.058356, -0.041843, 1.630438, -0.737177, -0.412133, -0.093867, -1.160224, 0.234374, -0.711768, -0.213978, 0.144350, -0.212256, -0.411763, -0.695910, -0.243200},
  {1.601417, -1.133600, 0.053947, 0.252817, 0.693420, -0.567795, 0.325038, -0.212030, -0.494342, -1.116541, -0.075238, -0.293127, -0.285765, -0.469173, -0.830442, 0.086112, -0.424118, 0.233937, 0.306411, 0.299534, 0.693638, -0.338452, -0.744649, -1.163568, -0.677853, 1.171887, -0.505946, -0.485871, 1.310769, -0.059215, -0.636771, 0.004318, -0.053516, 0.319119, -0.327149, -0.148490, 0.892292, -0.547219, -0.971825, 0.399278, -0.490160, 0.257225, -0.343935, -0.431474, 0.741403, 0.546372, -0.235480, -0.193982, -0.223555, -0.437828, 0.078548, -1.056791, 1.596151, 0.443844, 0.397691, -0.169135, -0.781385, 1.023558, -0.153428, 0.175071, 0.142101, 0.018907, 0.920941, -0.237580},
  {0.380056, -1.717325, -0.098179, -0.111243, 1.252556, -0.285947, -0.202912, 0.237199, -0.398152, -0.422248, 0.371493, 0.407215, 0.873379, -0.162911, -0.464021, -0.021380, 0.151059, 0.141860, -0.099359, 0.288971, 0.420587, 0.251413, -1.023023, -0.101208, -0.456135, 1.347254, -0.999042, 0.716425, 0.528301, 0.400929, 0.043288, 0.137296, 0.136379, 0.903271, 0.086157, -0.412484, 0.188910, -0.527506, -0.089322, -0.448673, 0.086741, 0.316131, -0.134491, -0.157204, -0.365875, 0.738879, 0.473807, 0.518532, 0.496350, -0.087496, -0.032616, 0.601401, 1.086161, 0.125381, -0.334395, -0.157238, -0.263086, 0.357651, 0.388006, 0.421091, 0.311215, -0.314218, -0.041809, 0.180478},
  {1.505522, 0.939387, 0.200572, -0.375062, -0.262074, -0.017583, 0.825667, 0.169996, -0.356652, -0.287297, 0.159123, -0.243512, -0.216497, -0.153570, -0.736054, 0.657667, 0.219780, -0.265427, 0.202187, 0.231491, 0.662041, 0.612386, -0.444597, -1.180933, 0.015003, 0.565426, 0.404317, -0.138364, 1.199221, -0.100396, -0.016051, 0.128363, 0.074552, -0.820528, -0.657609, 0.244738, 0.556756, 0.429215, 0.301076, 0.706275, -0.159010, -1.013889, -0.887251, 0.069129, 0.485349, -0.743078, -0.189689, -0.161833, -0.696204, 0.952146, -0.050991, 0.095566, 0.452998, 0.016605, 0.515569, -0.891483, 0.085359, 0.022034, -0.309851, -0.175064, 0.225962, 0.347231, 0.171521, -0.321892},
  {-0.066570, -0.551949, -0.259456, -0.471761, 0.447986, 0.076402, -0.015205, 0.190969, -0.644815, 0.244950, 0.217410, 0.325328, 0.674379, 0.140786, -0.329219, 0.418969, 0.753590, -0.074128, -0.241878, 0.020395, 0.703907, 0.974913, -0.603758, -0.373502, -0.232924, 0.814244, -0.502656, 0.500861, 0.167447, 0.090635, 0.096417, -0.086420, -0.284853, -0.455761, -0.474929, -0.338393, 0.057531, -0.147729, 0.771932, -0.454507, -0.113900, -0.806018, -0.779330, -0.135641, -0.490970, -0.456373, 0.268913, 0.870038, -0.055266, 0.918042, 0.084082, 1.387986, -0.320103, -0.233037, 0.240723, -0.858999, -0.217893, -0.717052, -0.169794, -0.152859, 0.656484, -0.324798, 0.031791, 0.000825},
  {-0.011453, 0.145593, -0.423306, -1.078671, -0.404786, -1.121830, -0.825318, -0.361088, 0.498003, 1.144498, 0.356510, -0.318404, -0.368277, -0.845635, -1.092287, 0.853477, -0.544763, -0.536954, -0.333219, -1.010694, 0.022278, -0.434248, 0.215054, 0.022993, -0.465835, 0.120147, -0.971533, -0.505265, 0.164683, -0.182136, 0.232122, -0.316327, 0.181602, -0.692372, -0.369970, -0.607817, -0.159510, -0.094864, 0.336379, -1.147969, -0.103166, 0.907537, 0.119026, 0.422335, 1.080425, 0.239032, -0.699035, 0.434437, -0.043360, 0.126629, -0.070510, -0.465353, -0.357683, 0.523789, -0.687063, -0.385345, 0.087466, -0.193066, 0.007126, -0.125166, -0.433896, -1.020043, 0.150275, -0.587728},
  {-0.216721, 0.302716, -0.327243, -0.914370, -0.216926, -1.189358, -0.279660, -0.180054, -0.074701, 0.553961, -0.242138, 0.665075, 0.034398, -1.159426, -0.440081, 0.117758, -0.190581, 0.745847, -1.082639, -0.095239, -0.990153, -0.770021, 0.375288, -0.081151, -0.615857, 0.237489, -0.651050, -1.049790, 0.583268, 0.399630, -0.242633, 0.186349, -0.209312, -1.156986, -0.589948, 0.687025, -0.794014, -0.204220, 0.971836, 0.187922, -0.434936, 0.569984, -0.021323, -0.396975, 0.389887, 0.366520, 0.199966, -0.400357, 0.791802, 0.155290, -0.911816, 0.007750, -0.059597, 0.746696, -0.566480, -0.575139, -0.373708, -0.305948, 0.021705, -0.186968, -0.758519, -0.543720, -0.006915, -0.516308},
  {0.114890, -0.206250, -1.008869, -0.217433, 0.345299, -0.419458, -0.803910, -0.552999, 0.762824, 1.212461, -0.322076, -1.009162, -0.467811, 0.792398, -0.920770, 0.398274, 0.037846, 0.223985, -0.198201, -1.036297, 1.245227, 0.296732, -0.546889, 0.299488, -1.174843, -0.103754, -0.363038, -0.136323, 0.437225, 0.053533, 0.431561, -0.099510, -0.305413, -0.731972, 0.476412, -0.559938, 0.429802, 0.636251, -0.392919, -0.516174, -0.114016, 0.203537, -0.185965, 0.621114, 0.591988, -0.156609, -0.157111, -0.315649, -0.445433, -0.243232, -0.765229, -0.453887, -0.534993, -0.381332, -0.795857, 0.106534, 0.201052, 0.207060, 0.211046, -0.265781, -0.871275, -0.720407, -0.701862, 0.066083},
  {-0.335002, -0.053091, -0.972848, -0.245697, 0.492294, -0.522786, -0.336011, -0.641275, -0.541182, 0.739097, -0.614775, -0.178824, 0.065484, 0.658233, -0.000915, 0.005437, 0.338519, 1.664201, -0.624027, -0.093490, 0.283034, -0.065763, -0.036750, -0.081709, -1.345500, -0.233816, -0.111693, -0.522452, 0.732161, 1.142179, 0.313608, 0.543685, -0.205666, -1.136563, 0.161992, 0.688445, -0.059176, 0.227319, 0.236232, 0.751372, -0.166306, -0.165032, -0.038665, -0.442892, -0.067057, 0.120374, 0.711884, -0.926999, -0.018576, 0.004355, -0.996234, -0.537204, -0.327158, 0.085582, -0.828633, 0.165116, -0.339559, -0.043744, -0.235521, -0.179318, -0.929476, -0.109856, -0.740025, 0.224663},
  {-0.001728, 0.319214, -0.116965, -1.069420, -0.600734, -0.304884, 0.139501, 0.186096, 0.914631, 0.728817, 0.230395, -0.305232, -1.053983, -1.067548, -0.432361, 0.036106, -1.030434, -1.169678, 0.657892, 0.372891, -0.542177, 0.561288, -0.331051, -0.314219, -0.043118, 0.095079, -0.038432, -0.150443, -0.088818, 0.279238, -0.254545, -0.859945, 0.384873, 0.531542, -1.339980, -0.943097, -0.215556, 0.033017, -0.411611, -1.081338, 0.317687, 1.192152, -0.580930, 0.430313, 0.493277, 0.500412, -0.349270, 1.083881, 0.364497, 0.121273, 0.455609, 0.177339, -0.058751, -0.287603, 0.629718, 0.386190, -0.170302, -0.210920, -0.146975, -0.275706, 0.184474, -0.533780, -0.233886, -0.392498},
  {-0.450928, 0.474510, 0.043664, -0.812429, -0.353967, -0.088946, 0.810432, 0.085948, -0.046036, -0.033979, -0.557261, 0.748386, -0.547810, -1.177154, 0.424983, -0.487862, -0.998845, 0.147979, -0.389035, 1.160995, -1.233734, 0.393561, 0.269856, -0.377137, -0.310696, 0.103642, 0.338362, -0.875675, 0.170113, 1.270617, -0.611764, -0.203904, 0.485475, -0.001886, -1.486273, 0.254550, -0.754176, -0.280753, 0.447142, -0.373691, -0.282180, 0.808007, -0.450528, -0.468544, -0.384307, 0.455311, 0.287259, 0.175990, 0.980185, 0.254741, -0.290517, 0.439058, 0.594845, -0.116851, 0.558980, 0.060117, -0.522446, -0.265597, -0.235697, -0.188119, 0.031131, -0.210528, 0.114335, -0.187345},
  {-0.078338, -0.053672, -0.616757, -0.004083, 0.542679, 0.866606, -0.072368, -0.215483, 0.836050, 0.613407, -0.354800, -0.909576, -1.104635, 0.676333, 0.043721, 0.000155, -0.340995, -0.528906, 0.706181, 0.253009, 0.933602, 1.058819, -0.451392, -0.344612, -0.786849, -0.373347, 0.320747, 0.236477, 0.317376, 0.686403, 0.194967, -0.566874, 0.529560, 0.617074, -0.650661, -0.813449, 0.379799, 0.642989, -0.666845, -0.822699, 0.226264, 0.502520, -0.763688, 0.793330, 0.008947, 0.027154, 0.199333, 0.310884, -0.467649, -0.214471, -0.309235, -0.121232, -0.173103, -0.796915, 0.520036, 1.221574, -0.176175, 0.017724, 0.103272, -0.404914, 0.097987, 0.001641, -0.803840, 0.593431},
  {-0.418544, 0.356590, -0.488841, 0.189710, 0.516160, 0.763547, 0.646079, 0.143867, -0.264708, 0.075434, -0.729915, 0.036810, -0.170506, 0.614508, 0.815845, -0.691018, -0.133107, 0.996848, 0.161186, 1.108096, 0.141866, 0.904353, -0.499711, -0.277549, -0.948546, -0.426716, 0.588331, -0.498137, 0.256649, 1.604029, -0.220861, 0.035287, 0.301910, 0.083372, -0.879473, 0.139265, -0.150161, 0.363916, -0.357711, 0.661900, 0.129445, 0.166517, -0.583209, -0.147682, -0.326554, 0.357050, 1.042580, -0.181967, 0.344246, -0.004680, -0.760973, 0.072045, 0.306473, -0.380926, 0.447306, 1.000399, -0.441995, -0.240955, -0.261345, -0.110122, -0.200545, 0.373401, -0.831923, 0.946052},
  {0.649399, -0.268943, 0.811421, -0.218793, -0.360730, -0.717919, -0.672440, -0.130549, 0.187083, 0.081244, 1.043527, 0.113755, 0.495660, -0.535535, -0.772600, 0.704629, 0.051430, -0.826812, -0.037223, -1.069409, -0.111340, -0.612672, 0.596053, 0.488267, 1.049877, 0.195854, -0.738332, 0.323318, -0.506709, -1.381096, 0.274694, -0.162090, -0.418840, 0.049222, 1.039663, -0.154204, 0.181975, -0.227131, 0.200324, -0.411879, 0.096013, -0.238685, 0.950423, 0.499714, 0.519076, -0.329211, -0.680014, 0.172699, -0.450544, 0.341431, 0.985216, 0.031043, 0.111753, 0.697838, -0.095373, -0.845853, 0.717976, 0.397150, -0.103608, 0.230522, 0.132499, -0.196022, 0.740109, -0.686305},
  {0.014181, -0.136219, 0.918603, 0.087595, -0.413918, -0.429850, -0.408146, 0.259744, -0.740623, -0.474719, 0.191962, 1.017546, 1.229575, -0.616906, 0.088353, -0.130883, 0.335051, 0.302952, -0.824764, -0.261490, -0.922027, -1.128913, 0.659951, -0.046852, 0.720401, 0.448832, -0.469024, -0.393463, -0.148365, -0.813368, -0.166774, 0.503924, -0.328024, -0.339318, 0.344624, 0.913108, -0.314662, -0.526428, 0.878381, 0.926634, -0.069435, -0.403541, 1.035269, -0.677578, -0.108317, -0.209952, -0.438612, -0.541762, 0.429606, 0.409205, 0.110082, 0.087085, 0.086466, 0.656130, -0.426898, -1.073108, -0.145566, -0.007199, -0.340266, 0.454751, -0.188527, 0.104576, 0.935453, -0.688881},
  {0.258632, -0.555699, 0.179731, 0.529556, 0.499531, 0.091961, -0.728772, 0.079284, 0.002434, -0.214546, 0.356986, -0.478429, 0.176598, 1.222589, -0.638562, 0.223615, 1.144494, 0.010008, 0.266529, -1.048066, 1.401141, -0.329940, -0.043016, 0.513194, 0.361385, -0.056387, -0.179677, 0.607599, -0.361003, -1.291638, 0.814451, -0.132596, -0.343333, 0.038297, 1.723736, 0.060429, 0.997018, 0.152232, -0.428690, -0.114843, 0.016510, -0.840820, 0.249289, 0.602546, 0.129399, -0.554033, -0.474593, -0.548392, -0.732805, -0.292480, 0.207662, -0.393544, -0.442133, -0.045509, -0.264274, -0.070289, 0.572913, 0.524717, -0.120090, -0.064157, -0.192733, 0.171553, 0.092906, -0.240515},
  {0.129620, -0.466929, 0.074735, 0.983294, 0.415841, 0.134882, -0.255662, -0.096417, -0.948584, -0.538908, -0.010902, 0.196980, 1.057698, 0.899019, 0.656678, -0.129214, 1.145806, 1.340313, -0.657738, -0.379683, 0.040854, -0.463353, 0.186886, -0.065651, -0.131732, -0.323936, 0.129486, 0.351962, -0.188927, -0.520741, 0.168127, 0.978468, -0.616198, -0.387334, 1.160233, 0.845588, 0.546837, 0.046594, 0.163327, 1.354327, -0.306490, -1.078916, 0.496445, -0.377395, -0.317616, -0.478254, 0.280423, -0.693178, -0.145980, 0.036131, -0.415875, -0.215508, -0.109055, -0.008871, -0.631667, -0.314572, -0.237881, 0.507973, -0.035401, 0.416776, -0.128712, 0.654969, -0.190876, -0.056631},
  {0.087915, 0.246838, 0.839759, 0.058931, -0.596550, 0.571694, 0.191033, 0.385747, 0.140195, -0.704231, 0.891019, 0.264390, -0.365198, -0.657953, -0.254829, -0.194933, -0.308963, -1.352211, 0.891776, -0.071914, -0.539288, 0.108880, 0.099812, -0.214231, 1.455718, 0.092701, 0.012037, 0.477027, -0.736788, -1.018527, -0.139291, -0.694843, 0.149345, 1.111771, -0.378240, -0.602697, 0.239674, -0.321301, -0.569888, -0.765636, 0.325709, 0.077131, 0.299812, 0.291078, -0.069843, -0.090887, -0.715788, 0.869775, -0.051397, -0.251507, 1.097905, 0.551141, 0.310070, -0.113127, 0.817890, 0.090455, 0.473486, -0.056072, -0.303570, 0.198966, 0.977619, 0.131419, 0.725514, -0.354879},
  {-0.072015, 0.234183, 0.768043, -0.008459, -0.622848, 0.280063, 0.653820, 0.464948, -0.708437, -1.137018, 0.294247, 1.128089, 0.588431, -0.719342, 1.087864, -0.682234, -0.469228, -0.499406, -0.383078, 0.917667, -1.166821, -0.454549, 0.486423, -0.091551, 0.898738, 0.137605, 0.592816, 0.144014, -0.453456, -0.415968, -0.622878, 0.031604, -0.116810, 0.740869, -0.740399, 0.314942, -0.577533, -0.591997, 0.207533, 0.513567, -0.097099, -0.196076, 0.046676, -0.677583, -0.812178, 0.076821, 0.136591, -0.070565, 0.446284, -0.170542, 0.458812, 0.543225, 1.011022, -0.016332, 0.767405, -0.373289, -0.214026, -0.228185, -0.563802, 0.029107, 0.831991, 0.456574, 0.408414, -0.274813},
  {0.223991, -0.289045, 0.315308, 0.847481, 0.302173, 1.259200, 0.040643, 0.085591, -0.178961, -0.631011, 0.016136, -0.554973, -0.463444, 1.067964, 0.351033, -0.393337, 0.010400, -0.885949, 1.011921, 0.065850, 0.903303, 0.719574, -0.311182, -0.037660, 0.786820, -0.288176, 0.445284, 0.762294, -0.531995, -0.772555, 0.137504, -0.484748, -0.036072, 1.215723, 0.589131, -0.638513, 0.938502, 0.292445, -1.004930, -0.280388, -0.044694, -0.682180, -0.378892, 0.241216, -0.401142, -0.508781, -0.089121, 0.230959, -0.484699, -0.489737, 0.681563, -0.044528, 0.022136, -0.702761, 0.586567, 0.657281, 0.469310, -0.015047, 0.010417, -0.243875, 0.577750, 0.403009, -0.428223, 0.308783},
  {-0.096497, -0.295844, 0.193515, 1.277065, 0.420374, 1.245280, 0.496235, 0.459673, -0.868250, -1.009803, -0.255368, 0.175252, 0.471869, 0.802085, 1.210581, -0.897729, 0.391804, 0.405028, -0.163202, 1.031311, -0.279466, 0.157533, -0.195414, -0.198504, 0.224961, -0.477990, 0.928577, 0.616756, -0.431985, 0.139598, -0.227623, 0.058911, -0.311190, 0.658791, -0.154244, 0.037265, 0.042393, -0.146154, -0.384211, 1.098720, 0.078616, -1.023359, -0.286227, -0.621880, -0.980177, -0.269348, 0.222658, -0.527129, -0.318435, -0.242573, 0.098685, 0.020352, 0.522811, -0.437091, 0.582203, 0.337369, -0.332344, 0.143764, -0.168607, 0.216163, 0.200807, 1.066132, -0.355079, 0.678825},
};

float hiddenBias[HIDDEN_NODES] = {
  -0.063103, -0.002053, -0.612552, -0.050729, -0.231613, -0.105304, -0.362547, -0.779222, -0.336772, -0.255286, -0.325206, -0.122316, -0.227954, -0.232367, -0.083851, -0.412264, -0.266545, -0.064992, -0.640404, -0.390986, -0.139697, -0.226217, -0.154334, -0.192634, -0.055327, -0.012024, -0.184647, -0.362605, -0.359074, -0.239051, -0.291842, -0.359361, -0.831348, -0.166769, -0.188155, -0.454109, -0.138284, -0.534835, -0.302150, -0.245183, -1.027583, -0.139731, -0.116987, -0.508635, -0.403900, -0.417900, -0.617357, -0.426877, -0.296267, -0.431161, -0.593357, -0.204464, -0.173893, -0.562548, -0.363884, -0.037067, -0.739547, -0.507095, -1.026078, -0.939095, -0.247179, -0.569586, -0.233615, -0.732320
};

float outputWeights[HIDDEN_NODES][OUTPUT_NODES] = {
  {3.448864, 1.122630, -0.103350, -2.616985, 0.518778, -0.505069, -0.154592, -0.862399},
  {-1.340320, -2.131108, 2.771363, -2.600418, -0.903520, 0.423391, -0.997053, 0.264968},
  {0.039112, -0.223322, 0.185313, -0.506505, 1.711429, 0.273771, -1.391878, 0.023755},
  {-1.824132, 0.585189, -1.126930, -0.184781, 1.803414, 0.275878, 1.831572, 0.437456},
  {2.745649, 0.116809, -1.149794, 1.088795, -0.365295, -0.308107, 1.824605, 0.093582},
  {1.147876, -1.670802, 0.500350, 0.267624, 0.962771, 2.157414, 1.573657, -0.051809},
  {-0.270305, 1.061414, 0.998251, -1.327724, -0.189165, 1.691736, -0.301635, 0.993430},
  {1.009683, 0.058182, 0.479068, 0.447260, 0.547938, 0.682151, -0.483006, 0.185694},
  {-0.742844, -1.885533, -0.377589, -0.423101, -1.599511, -0.016149, -0.513176, -2.005514},
  {-1.627785, -0.443342, 1.454550, 1.398041, -2.885456, -1.563532, -0.136594, -1.250451},
  {1.617300, -0.415411, 0.399105, 0.885070, 0.970082, -0.479795, -1.207831, -1.145755},
  {2.165702, -0.956087, 0.213291, 1.159613, 0.552912, -0.010595, -1.809651, 1.869488},
  {-0.362150, 1.136255, 0.042675, 1.859665, 1.512143, -1.452653, -0.253106, 1.485829},
  {0.582286, -1.105223, 0.590813, -0.021364, 0.484753, -0.435848, 3.364998, -0.405443},
  {0.088492, -2.338201, 0.062775, 0.863834, 0.675025, 1.590976, 0.654934, 1.975170},
  {1.623064, -0.310837, 0.968734, -0.462002, -0.718203, -1.563225, -0.599910, -1.274730},
  {0.129131, 0.785246, 1.300616, 1.378433, 1.094755, -1.531939, 1.367530, 0.332150},
  {-2.147340, 1.601598, -0.475893, 0.031477, -1.132041, -1.838334, 1.652779, 2.825075},
  {-0.284693, 0.336666, -0.225964, -0.528192, 0.070153, 1.324478, 0.373658, -1.802880},
  {-0.069983, 1.029266, 0.017927, 0.196998, -0.644017, 2.333665, -0.182344, 1.759439},
  {0.691880, 2.236938, 0.745149, -0.104389, -0.425284, -0.978113, 2.654046, -2.106980},
  {-0.156807, 1.769941, 1.736339, 0.841614, -1.236585, 1.740847, 1.131860, -0.811926},
  {-2.848481, -0.984813, 0.300564, -0.763962, 0.487735, -0.733881, -1.299327, 0.532723},
  {-2.473748, -1.612512, -1.138316, 1.919686, 0.224268, -0.943509, 0.002352, -0.474482},
  {-1.581985, -0.426509, 0.823764, -0.042394, 2.614708, 0.590338, -1.669609, -0.771428},
  {0.359073, 3.763654, -0.600869, 0.985414, -0.063002, -0.513196, -1.172817, -0.078863},
  {-0.982815, -1.400561, 1.341743, -2.022112, 0.257984, 1.599758, 0.884152, 0.745153},
  {0.026921, 0.432200, 0.167802, 1.605002, 1.386072, 0.369251, 0.786031, -1.066269},
  {1.240942, 2.257514, -0.118578, -1.199668, -1.789608, -0.762618, 0.234472, 0.464520},
  {2.084476, -1.251643, -0.554417, 0.786584, -3.347621, 0.976728, 0.620941, 1.758308},
  {1.941522, -1.797752, 0.702762, 0.635354, -0.089064, -1.093024, 0.689053, -0.945620},
  {-1.260303, 1.378087, -0.088147, 0.147578, 0.170234, -1.184881, 0.376174, 1.366052},
  {-0.684002, 0.633514, -0.178206, -0.432800, -0.965030, 0.750355, -0.424370, -0.372989},
  {-0.917653, 0.505457, -2.284498, 0.851110, 1.274208, 2.381461, -0.113284, -1.089143},
  {-0.959469, -1.102821, -1.316501, 0.396579, 1.877237, -2.584513, 1.457461, -0.907645},
  {-0.389522, -0.258519, 0.427661, -1.132604, 0.212306, -1.231710, -0.186312, 2.044246},
  {2.748500, -0.386646, -0.587044, -1.048326, 0.680786, -0.341601, 1.399835, -1.351444},
  {-1.035530, -0.125591, 1.486905, -0.690459, -0.844313, -0.146601, 1.014323, -0.626355},
  {-0.196984, -0.079734, 2.152265, 1.148368, -0.544911, -1.441589, -1.482110, 1.298191},
  {0.967683, -0.695882, 0.501203, -2.286633, 0.948793, -0.772620, 1.042824, 2.706481},
  {-0.151563, -0.384414, 0.339447, 0.688322, -0.078751, 0.283262, -0.097588, -0.546851},
  {-0.634633, -1.103192, -2.643226, -0.234449, -2.595234, 0.243328, -1.766998, -0.768881},
  {0.783854, -2.563901, -1.895148, 0.079301, 1.078367, -1.551913, -0.885685, 0.030172},
  {-1.273232, 0.406595, 0.677450, -0.232771, -0.578924, -0.255737, 0.227383, -2.023908},
  {0.561111, -0.106851, -0.183234, -1.873188, -1.306649, -1.452959, -0.842231, -1.372142},
  {-0.141320, 0.129057, -2.073502, 0.532179, -1.307296, 0.206605, -0.812027, 0.290268},
  {-0.279557, 0.348658, -0.104425, 1.427650, -0.979746, 0.329716, 0.897900, 1.362586},
  {0.139594, 0.892109, 0.763999, 1.523337, -0.557410, 1.066351, -1.315223, -1.477683},
  {1.311083, -1.487863, -1.593797, 0.787597, -1.008757, 0.197102, -1.460809, 1.259616},
  {-0.225103, 1.303395, 2.152234, 0.062074, -0.330402, -0.473575, -0.783066, 0.261945},
  {-0.104405, 0.039329, -0.248175, -0.152559, 1.425023, 0.658187, -1.176001, -1.345396},
  {1.186805, -0.209814, 2.129526, 2.806864, 0.229628, 0.858015, -0.983645, 0.294007},
  {1.377652, 1.673621, -2.124993, -1.101398, 0.384339, 1.035474, -0.782012, 0.815716},
  {-0.342399, 0.912567, -0.814946, -0.794608, -0.114622, -1.519524, -1.402203, 0.380115},
  {1.081602, 0.112825, 0.704519, -1.144220, 0.324602, 2.180710, -0.532067, -0.235145},
  {-2.895247, 0.079487, -2.019139, -0.420382, -1.073103, 1.664790, 1.518604, -0.581392},
  {-0.658844, -0.666237, 0.730806, 0.017346, 0.535761, -0.519586, -0.125242, -1.255382},
  {-0.098069, 0.589394, -1.719733, -1.537460, 0.370882, -0.597866, 0.373923, -0.309154},
  {0.000044, -0.130100, -0.734669, 0.291253, -0.492330, -0.399808, 0.142121, -0.426579},
  {0.703401, 0.336236, -0.480788, 0.405013, 0.520547, -0.384868, -0.276710, 0.300376},
  {-0.310506, 1.661688, 0.527086, 0.905359, 1.136149, 1.443218, -0.702976, -0.445167},
  {-0.766588, 0.142022, 0.179805, -1.100823, 1.183481, 0.725027, 0.786319, 0.866353},
  {-0.649638, 1.667606, -0.400983, -1.126980, 1.032457, -0.604545, -1.916835, -0.113954},
  {-0.546425, -0.148580, -0.535348, 0.562720, -0.583787, 0.803755, 1.420499, 0.303892},
};

float outputBias[OUTPUT_NODES] = {
  -0.071575, -0.570380, -0.229510, -0.187630, -0.511148, -0.297186, -0.425346, -0.106539
};

// ============================================================
// ==== ОСНОВНОЙ КОД =========================================
// ============================================================

float inputs[INPUT_NODES];

float sigmoid(float x) {
  if (x < -15.0) return 0.0;
  if (x > 15.0) return 1.0;
  return 1.0 / (1.0 + exp(-x));
}

void forwardPass(float* hiddenOutput, float* finalOutput) {
  // Скрытый слой
  for (int j = 0; j < HIDDEN_NODES; j++) {
    float sum = hiddenBias[j];
    for (int i = 0; i < INPUT_NODES; i++) {
      sum += inputs[i] * hiddenWeights[i][j];
    }
    hiddenOutput[j] = sigmoid(sum);
  }
  
  // Выходной слой
  for (int k = 0; k < OUTPUT_NODES; k++) {
    float sum = outputBias[k];
    for (int j = 0; j < HIDDEN_NODES; j++) {
      sum += hiddenOutput[j] * outputWeights[j][k];
    }
    finalOutput[k] = sigmoid(sum);
  }
}

// Преобразование 8-битного выхода в число
int outputToKey(float* output) {
  int key = 0;
  for (int k = 0; k < 8; k++) {
    if (output[k] > 0.5) {
      key |= (1 << (7 - k));
    }
  }
  return key;
}

// Тестирование всех 256 комбинаций
void testAllKeys() {
  Serial.println(F("\n=== ТЕСТИРОВАНИЕ ВСЕХ 256 КЛАВИШ ==="));
  int correct = 0;
  
  for (int key = 0; key < 256; key++) {
    int row = key / 16;
    int col = key % 16;
    
    // Очищаем вход
    for (int i = 0; i < 32; i++) inputs[i] = 0;
    
    // Устанавливаем биты строки и столбца
    inputs[row] = 1;
    inputs[16 + col] = 1;
    
    float hidden[HIDDEN_NODES];
    float output[OUTPUT_NODES];
    forwardPass(hidden, output);
    
    int predicted = outputToKey(output);
    
    if (predicted == key) {
      correct++;
    } else if (key < 10) {  // Показываем только первые 10 ошибок
      Serial.print(F("Клавиша "));
      Serial.print(key);
      Serial.print(F(" (ряд "));
      Serial.print(row);
      Serial.print(F(", кол "));
      Serial.print(col);
      Serial.print(F(") → предсказано "));
      Serial.print(predicted);
      Serial.print(F(", биты: "));
      for (int k = 0; k < 8; k++) {
        Serial.print(output[k], 2);
        Serial.print(F(" "));
      }
      Serial.println();
    }
  }
  
  float accuracy = (float)correct / 256 * 100;
  Serial.print(F("\n✅ ТОЧНОСТЬ: "));
  Serial.print(accuracy, 2);
  Serial.println(F("%"));
  
  if (accuracy == 100) {
    Serial.println(F("ПОЛНЫЙ УСПЕХ! Нейросеть идеально декодирует все 256 клавиш!"));
  }
}

// Тест конкретной клавиши
void testKey(int row, int col) {
  Serial.print(F("\n=== ТЕСТ: ряд "));
  Serial.print(row);
  Serial.print(F(", столбец "));
  Serial.println(col);
  
  // Очищаем вход
  for (int i = 0; i < 32; i++) inputs[i] = 0;
  
  // Устанавливаем биты
  inputs[row] = 1;
  inputs[16 + col] = 1;
  
  // Показываем входные данные
  Serial.print(F("Вход: строки ["));
  for (int i = 0; i < 16; i++) {
    Serial.print((int)inputs[i]);
  }
  Serial.print(F("], столбцы ["));
  for (int i = 16; i < 32; i++) {
    Serial.print((int)inputs[i]);
  }
  Serial.println(F("]"));
  
  float hidden[HIDDEN_NODES];
  float output[OUTPUT_NODES];
  forwardPass(hidden, output);
  
  int key = outputToKey(output);
  
  Serial.print(F("Выход нейросети (биты): "));
  for (int k = 0; k < 8; k++) {
    Serial.print(output[k], 3);
    Serial.print(F(" "));
  }
  Serial.println();
  
  Serial.print(F("Результат: клавиша "));
  Serial.print(key);
  Serial.print(F(" (ожидалось "));
  Serial.print(row * 16 + col);
  Serial.print(F(") → "));
  
  if (key == row * 16 + col) {
    Serial.println(F("✓ СОВПАДАЕТ"));
  } else {
    Serial.println(F("✗ ОШИБКА"));
  }
}

// Тест всех клавиш в одном ряду
void testRow(int row) {
  Serial.print(F("\n=== ТЕСТ РЯДА "));
  Serial.println(row);
  
  for (int col = 0; col < 16; col++) {
    // Очищаем вход
    for (int i = 0; i < 32; i++) inputs[i] = 0;
    
    inputs[row] = 1;
    inputs[16 + col] = 1;
    
    float hidden[HIDDEN_NODES];
    float output[OUTPUT_NODES];
    forwardPass(hidden, output);
    
    int key = outputToKey(output);
    int expected = row * 16 + col;
    
    if (key == expected) {
      Serial.print(F("."));
    } else {
      Serial.print(F("X"));
    }
  }
  Serial.println(F(" ✓"));
}

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(0));
  
  Serial.println(F("=========================================="));
  Serial.println(F("ДЕКОДЕР КЛАВИАТУРЫ 16x16 (256 клавиш)"));
  Serial.println(F("=========================================="));
  Serial.println(F("Нейросеть обучена на 256 комбинаций"));
  Serial.println(F("=========================================="));
  Serial.println(F("Команды:"));
  Serial.println(F("1 - Тест всех 256 клавиш"));
  Serial.println(F("2 - Тест конкретной клавиши"));
  Serial.println(F("3 - Тест всех рядов"));
  Serial.println(F("4 - Показать веса (диагностика)"));
  Serial.println(F("==========================================\n"));
}

void loop() {
  if (Serial.available() > 0) {
    char command = Serial.read();
    while (Serial.available() > 0) Serial.read();
    
    switch (command) {
      case '1':
        testAllKeys();
        break;
        
      case '2': {
        Serial.println(F("Введите номер ряда (0-15) и столбца (0-15):"));
        Serial.println(F("Пример: 5 3"));
        
        String input = Serial.readStringUntil('\n');
        input.replace(',', ' ');
        
        int row, col;
        if (sscanf(input.c_str(), "%d %d", &row, &col) == 2) {
          if (row >= 0 && row < 16 && col >= 0 && col < 16) {
            testKey(row, col);
          } else {
            Serial.println(F("Ошибка: ряд и столбец должны быть 0-15"));
          }
        } else {
          Serial.println(F("Ошибка ввода! Используйте: ряд столбец"));
        }
        break;
      }
      
      case '3': {
        Serial.println(F("\n=== ТЕСТ ВСЕХ РЯДОВ ==="));
        for (int row = 0; row < 16; row++) {
          testRow(row);
        }
        break;
      }
      
      case '4': {
        Serial.println(F("\n=== ДИАГНОСТИКА ВЕСОВ ==="));
        Serial.print(F("Размер скрытого слоя: "));
        Serial.println(HIDDEN_NODES);
        
        // Проверка диапазона весов
        float minW = 100, maxW = -100;
        for (int i = 0; i < INPUT_NODES; i++) {
          for (int j = 0; j < HIDDEN_NODES; j++) {
            if (hiddenWeights[i][j] < minW) minW = hiddenWeights[i][j];
            if (hiddenWeights[i][j] > maxW) maxW = hiddenWeights[i][j];
          }
        }
        
        Serial.print(F("Диапазон весов скрытого слоя: от "));
        Serial.print(minW, 3);
        Serial.print(F(" до "));
        Serial.println(maxW, 3);
        break;
      }
    }
    Serial.println(F("\n--- Готов к работе ---"));
  }
}

как писал ранее надо вникать, если все таки возникают вопросы ¯\_(ツ)_/¯ вникайте, там все написано

Ты не понял. Это раздел для СВОИХ проектов

2 лайка

да, эти проекты написанные мной, а не скопированы…. я даже не выкладывал их в сеть, а ссылки показывают на другие нейросети, более сложные, для работы с распознаванием фраз, или опознаванием лица, что бы показать что это не предел! а мои коды показывают более простые нейросети, спс за то что внимательно бдите!

Это придется доказывать :wink:

1 лайк

v258 я не проверял что есть в сети, я делал сам! так что не стесняйтесь, если найдете что, скидывайте ссылку на авторитетный ресурс, где указана будет дата публикации, и я внимательно изучу!)))

Не пей , Иванушка, из лужи, нейросетёнком станешь))

1 лайк

Слабо верится. В заголовке написано «для ардуино». А где перечень поддерживаемых досок ардуино?

1 лайк

Кто-то говорил, что ты спионерил чужой код? Нет, Бабосик, но код от ИИ своим тоже не считается :wink:

1 лайк

и вам спасибо за то что бдите!

как указал ранее, тестировал на esp32, так же код написан без использования библиотек, и много на каких платах должен идти, (на ардуино уно естественно компилируется и работает ) так же на всякий случай указываю что версия ядра esp32 V2.0.9, до версии ядра 3 должно запускаться без проблем, если бы вы проявили больше усердия, и нашли платы на которых не сможет скомпилироваться, другие бы узнали где не получится запустить, а если бы еще вникли в код, и поправили бы еще для компиляции на той плате где увидели что не запуститься, тогда вовсе помогли бы многим! если есть время, тогда вы сможете стать частью проекта! протестируйте полный список плат с достаточной памятью, я же просто тестировал на esp32, и ардуино уно

есть там часть кода написанная ии, провереная, и протестирована мной! и так же 3 код для проверки полностью ии писал, и я его конечно проверил тоже! на тот случай если вам самим лень к ии обращаться, что бы проверить веса и код на работоспособность….

не стесняйтесь скидывайте ссылку на сообщение, или на ресурс с кодом, я все изучу!

сдается мне товарищи вы не подошли к вопросу серьезно! и не стали даже вникать…
так что повторюсь, изучайте товарищи, там все написано!

Эта чё, ИИ такого наплодил?

Этого достаточно.

товарищи вы по прежнему ленитесь и не вникаете, иногда даже переворачиваете мои слова!
надо вам сначала вникнуть, а потом уже гадать, без погружения в код что то утверждать не стоит!
если вам лень вникать ,то ответ ¯\_(ツ)_/¯ может быть только такой, вникайте товарищи! не ленитесь!
попробуйте прибегнуть к силе ии! для анализа кода, что бы подтвердить или опровергнуть что то… если уж сами ленитесь вникать…
сразу как вы вникнете в проект, большинство ваших вопросов и утверждений отпадет)))

Это тебе нужно сначала изучить какие темы попадают в раздел «Проекты».

Я не читал Ваших слов, я посмотрел на код и задал вопрос, а слова, которые были ниже, читал уже потом.

1 лайк

ЕвгенийП я подумал что вы тоже троллить меня решили…))))

это реальное воспроизведение нейросети универсальной, на ардуино, ее обучением вопрос - ответ, и использованием весов для угадывания
часть функций писал ии, но я все перепроверил… как минимум скормите этот код ии, и он сможет подчеркнуть самые важные моменты, я думаю стоит обратить внимание на реализацию, это не просто код от ии, типа напиши мне нейросеть, а он выдает не понятно что… а перепроверял его, и даже выложил отдельный код, для переноса весов, и тестирования тому чему она обучилась

Та, не, ну так-то я вижу там ключевые моменты, они понятны.

Меня смутила функция loop размером в 113 строк. Думал, что человек бы такое вряд ли написал. Но, сам, так сам. Я просто удивился.

сам, но не без помощи ии)) там запутаешься с выводом этого всего…