【人工知能】 ニューラルネットワークの接続を作ろう! 綺麗な接続をめざす
完成イメージ
人工知能研究のために作ったプログラムですが、めちゃ綺麗だったので記事として保存しとく!
自由に設定して、簡単に作れるぜ
おすすめはニューロン数1000, キョリ100だよ
GENERATE(作成)したら、CREATURES(生物)に追加されるので、クリック(タップ)してね
例としてID:0のネットワークが追加されているよ!
例としてID:0のネットワークが追加されているよ!
※ 全然わかりやすくない説明です。
// Object.js
コードはこちら
<div style="color: white;min-height: 100%;background: rgb(34, 34, 34);padding: 15% 0;overflow: scroll;"> <center style="padding: 20px;"> <input type="range" value="350" min="200" max="1500" onchange="document.getElementById('canvas').style.width = this.value+'px';document.getElementById('canvas').style.height = this.value+'px';"><br> <canvas id='canvas'></canvas> </center> <style> #canvas { border: 2px solid skyblue; width: 350px;height: 350px; margin-bottom: 50px; } #percentage-title { font-size: 1.2rem; } #percentage-title::after { content: ' : '; } #percentage-number { font-size: 1.2rem; } #percentage-number::after { content: '%'; } </style> <center> <h1>GENERATE</h1> <table> <tr> <th>項目</th><th>数値</th> </tr> <tr> <td>ニューロン数</td><td><input type="number" id="ニューロン数" value="1000"></td> </tr> <tr> <td>接続限界キョリ</td><td><input type="number" id="接続限界キョリ" value="500"></td> </tr> </table> <button onclick="GenerateCreatures(document.getElementById('ニューロン数').value,document.getElementById('接続限界キョリ').value);">GENERATE</button> <br><br> <h1>CREATURES</h1> <table id="CREATURES-table"> <tr><th>ID</th><th>GENERATION</th><th>QUANTITY</th></tr> </table> </center> </div> <style> table { background: rgba(0,0,0,0); } table tr { text-align: center; cursor: pointer; } table tr:hover { background: gray; } table th { color: aqua; background: rgba(0,0,0,0) !important; padding: 7px; } table td { color: white; border-bottom: 1px solid gray; padding: 7px; } </style> <script> const canvas = document.getElementById('canvas'); canvas.width = 3000;canvas.height = 3000; const ctx = canvas.getContext('2d'); </script> // Object.js <script> function error(sentence) { console.log('Error :', sentence); } function distance(p, q) { let d = 0; p.forEach((e, i) => { d += (e - q[i])**2 }); return Math.sqrt(d) } function round(v) { if(typeof v == 'object') { // 配列の場合 for(var i=0;i<v.length;++i) { v[i] = round(v[i]); } return v } else if(typeof v == 'number') { // 数値 return Math.round( v * 100) / 100 } else { error('The value cannot be rounded off.\nvalue is '+v); } } function random(max) { return round(Math.random() * max) } function keys(dict) { return Array.from(Object.keys(dict)) } function percentage(title, number) { console.log(title, ":", number * 100); } // network.js class Neuron { constructor(info, id) { let new_position = []; info.shape.forEach( s => { new_position.push(Math.random() * s); }); this.id = id; this.value = 0; this.threshold = random(limit.threshold); this.connections = []; this.position = round(new_position); } } class Network { // Generate network constructor( // ex info = { shape : [1000, 1000], quantity : 1000, }, limit = { connection : 100, weight : 5, threshold : 10, }, id = '0', generation = 1, ) { this.ID = id; this.DNA = []; this.GENERATION = generation; this.INFO = info; this.LIMIT = limit; this.NETWORK = {}; // Generate neurons for(var _=0;_<info.quantity;++_) { let new_id = '0'; while(keys(this.NETWORK).includes(new_id)) { new_id = String(Math.round(Math.random() * 10**5)); } this.NETWORK[new_id] = new Neuron(info, new_id); } // Generate connections var _ = 0; for(var key in this.NETWORK) { let neuron = this.NETWORK[key]; for(var target_key in this.NETWORK) { if(key != target_key) { let target_neuron = this.NETWORK[target_key]; if(this.connect(neuron.position, target_neuron.position)) { neuron.connections.push({ 'id' : target_key, 'weight' : random(limit.weight), }); } } } ++_; } document.getElementById('CREATURES-table').innerHTML += "<tr onclick='creatures["+this.ID+"].draw();'><td>"+this.ID+"</td><td>"+this.GENERATION+"</td><td>"+this.INFO.quantity+"</td></tr>" } input(data, type) { switch(type) { case 'eye': break; } } // Whether neurons connect true/false connect(p, q) { return Math.random() <= -distance(p, q)/(this.LIMIT.connection) + 1 } // Details of network show(detail=false) { let sum_connections = 0; for(var key in this.NETWORK){ let neuron = this.NETWORK[key]; sum_connections += neuron.connections.length; if(detail) { console.log('id :', neuron.id, '\nvalue :', neuron.value, '\nconnections :', neuron.connections, '\nposition :', neuron.position); } } console.log('【 NETWORK SHOW 】', '\nID :', this.ID, '\nGENERATION :', this.GENERATION, '\nINFO :', this.INFO, '\nsum connections :', sum_connections, '\naverage connections :', sum_connections/keys(this.NETWORK).length); } draw() { // canvasサイズの変更 let PADDING = [this.INFO.canvas.padding[0] * this.INFO.shape[0] * this.INFO.canvas.quality, this.INFO.canvas.padding[1] * this.INFO.shape[1] * this.INFO.canvas.quality,] canvas.width = this.INFO.shape[0] * this.INFO.canvas.quality + PADDING[0] * 2;canvas.height = this.INFO.shape[1] * this.INFO.canvas.quality + PADDING[1] * 2; ctx.clearRect(0, 0, canvas.width, canvas.height); for(var key in this.NETWORK) { let neuron = this.NETWORK[key] // neuronsの表示 ctx.beginPath(); ctx.arc(neuron.position[0] * this.INFO.canvas.quality + PADDING[0], neuron.position[1] * this.INFO.canvas.quality + PADDING[1], canvas.width * this.INFO.canvas.neuron, 0*Math.PI/180, 360*Math.PI/180, false) ; ctx.fillStyle = "gray" ; ctx.fill(); ctx.strokeStyle = "white"; ctx.lineWidth = canvas.width * 0.001; ctx.stroke(); // connectionsの表示 ctx.strokeStyle = "aqua"; ctx.lineWidth = canvas.width * 0.0005 ; neuron.connections.forEach(connection => { var destination = this.NETWORK[connection['id']].position; ctx.beginPath(); ctx.moveTo( neuron.position[0] * this.INFO.canvas.quality + PADDING[0], neuron.position[1] * this.INFO.canvas.quality + PADDING[1]); ctx.lineTo( destination[0] * this.INFO.canvas.quality + PADDING[0], destination[1] * this.INFO.canvas.quality + PADDING[1]); ctx.stroke(); }); } } } // main.js let creatures = {}; function GenerateCreatures(new_quality=1000, new_connection=100) { let new_id = '0'; while(Array.from(Object.keys(creatures)).includes(new_id)) { new_id = String(Math.round(Math.random() * 10**5)); } creatures[new_id] = new Network( info = { shape : [1000, 1000], quantity : new_quality, canvas : { quality : 3, padding : [0.1, 0.1], // 割合指定 neuron: 0, } }, limit = { connection : new_connection, weight : 5, threshold : 10, }, id = new_id, generation = 1, ); creatures[new_id].show(); } for(var _=0;_<1;++_) { GenerateCreatures(); } </script>