В предыдущей статье (Синаптические веса в нейронных сетях – просто и доступно https://habr.com/ru/post/589893/) рассказывалось о смысле синаптических весов на примере модели определения цифры для 13-ти сегментного индикатора.
Конечно, для 13-ти сегментов с двумя состояниями (вкл/выкл) можно занести в память все комбинации и определять все простым перебором и совпадением. Но у нас задача учебная, пытаемся осмыслить и переходить к сложному (многослойные нейронные сети) постепенно. Можно сказать, что у нас уже и так нейронная сеть с 13 нейронами на входе и с одним слоем на 10 нейронов. Просто мы пока не используем огромные датасеты и машинное или глубокое обучение. Пока "обучение" прошло простыми расчетами, описанными в предыдущей статье. Итак, продолжим по порядку...
В продолжение составим программу для демонстрации, чтобы сегменты можно было "зажигать" не установкой 1 в ячейке в Excel, а мышкой на сайте.
Немного изменим нумерацию сегментов, чтобы было не по кругу, как в предыдущей статье, а более стандартно – вертикально/горизонтально.
HTML
Рисуем индикатор
<table>
<tr>
<td id="id1" onclick="paint(1)">1</td>
<td id="id2" onclick="paint(2)">2</td>
<td id="id3" onclick="paint(3)">3</td>
</tr>
<tr>
<td id="id4" onclick="paint(4)">4</td>
<td class="td2"> </td>
<td id="id5" onclick="paint(5)">5</td>
</tr>
<tr>
<td id="id6" onclick="paint(6)">6</td>
<td id="id7" onclick="paint(7)">7</td>
<td id="id8" onclick="paint(8)">8</td>
</tr>
<tr>
<td id="id9" onclick="paint(9)">9</td>
<td class="td2"> </td>
<td id="id10" onclick="paint(10)">10</td>
</tr>
<tr>
<td id="id11" onclick="paint(11)">11</td>
<td id="id12" onclick="paint(12)">12</td>
<td id="id13" onclick="paint(13)">13</td>
</tr>
</table>
<div id="resume"> </div>
Задаем стили, чтобы при наведении мышки сегмент «зажигался».
<style type="text/css">
body{ background: green;}
table {color: grey; border-collapse: collapse;margin:auto;}
td {background: #ffffff; border: 1px solid black ;padding:20px;}
td:hover {background: #333333}
td.td2 {background: #ffffff;}
</style>
С рисованием закончили, переходим непосредственно к скрипту на js и расчетам.
JS
Установим начальные значения и зададим веса из таблицы.
var sum1=0;
var figure=0;
var indicator_point = [];
var x_massive = [];
var y_massive = [];
x_massive [0]=[1.1,1.1,1.1,1.1,1.1,1.1,-100,1.1,1.1,1.1,1.1,1.1,1.1,1.1];
x_massive [1]=[0,-100,-100,2.6,-100,2.6,-100,-100,2.6,-100,2.6,-100,-100,2.6];
x_massive [2]=[0,1.2,1.2,1.2,-100,1.2,1.2,1.2,1.2,1.2,-100,1.2,1.2,1.2];
x_massive [3]=[0,1.2,1.2,1.2,-100,1.2,1.2,1.2,1.2,-100,1.2,1.2,1.2,1.2];
x_massive [4]=[0,1.5,-100,1.5,1.5,1.5,1.5,1.5,1.5,-100,1.5,1.5,-100,1.5];
x_massive [5]=[0,1.2,1.2,1.2,1.2,-100,1.2,1.2,1.2,-100,1.2,1.2,1.2,1.2];
x_massive [6]=[0,1.1,1.1,1.1,1.1,-100,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1];
x_massive [7]=[0,1.9,1.9,1.9,-100,1.9,-100,-100,1.9,-100,1.9,-100,-100,1.9];
x_massive [8]=[0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0];
x_massive [9]=[0,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,-100,1.1,1.1,1.1,1.1];
При нажимании на сегменты пересчитываем суммы и выводим результат в виде числа.
function paint(id)
{
sum1=0;
for(var k = 0; k < 10; k++){y_massive[k]=0;}
if(document.getElementById('id'+id).style.backgroundColor) {
document.getElementById('id'+id).style.backgroundColor = "";
indicator_point[id]=0;
}
else {
document.getElementById('id'+id).style.backgroundColor = "black";
indicator_point[id]=1;
}
for(var i = 0; i < 13; i++){ sum1 += indicator_point[i+1]; }
for(var k = 0; k < 10; k++){
for(var i = 0; i < 13; i++){ y_massive[k] += indicator_point[i+1]*x_massive [k][i+1]; }
}
max_sum = Math.max.apply(null, y_massive);
for(var k = 0; k < 10; k++){ if (y_massive[k]== max_sum) figure=k; }
if (max_sum==0) figure="";
document.getElementById("resume").innerHTML=figure;
}
Итог
При нажимании на сегменты происходит закрашивание ("зажигание") сегментов и под индикатором показана выявленная цифра. При корректном выборе сегментов все цифры определяются корректно, логика при подборе весов оказалась правильной.
Примечание:
При тестировании видно, что программа пытается определить цифру в любом случае, даже если сегменты нажаты не все или не точно по цифре. На этом как раз хорошо заметно, как меняется цифра при нажимании на сегменты. Так можно ощутить важность каждого сегмента для каждой цифры. Хотя это и не входило в задачу в данном случае, но очевидно, что можно так подобрать коэффициенты, что качество восприятия цифры по неполному набору сегментов еще более улучшится.
Ссылка на программу: https://global-com.ru/neuronet/v2/
Можно тестировать любые комбинации.