powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Архитектура приложения, использующего нейронные сети.
6 сообщений из 6, страница 1 из 1
Архитектура приложения, использующего нейронные сети.
    #38950884
Sergeyyy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И снова здравствуйте!

Решил, давече, написать небольшую программку ее суть такова: Есть небольшая нейронная сеть, построенная на нейронах модели Ижикевича, у нее есть небольшая графическая часть ( связи и сами нейроны присутствуют).Вот ее скриншот:



И вот код самой программы:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class BrainMod extends JPanel implements ActionListener {
	private static final long serialVersionUID = 1L;
	private static JTextArea textin;

	final static int Nexc = 12; // количество возбуждающих нейронов
	final static int Ninh = 3; // Количество тормозных нейронов
	final static int Nneur = Nexc + Ninh;
	final static int Ncon = (int) (Nneur * Nneur * 0.1f); // Количество связей
	// 0.1
	static float[] Vms = new float[Nneur]; // Мембранные потенциалы
	static float[] Ums = new float[Nneur]; // вспомогательные переменные модели

	static float V0 = -60.0f; // начальное значение для мембранного потенциала
	static float U0 = 0.0f; // начальное значение для вспомогательной переменной
	static int[] pre_conns = new int[Ncon]; // Индексы пресинаптических нейронов
	static int[] post_conns = new int[Ncon];// Индексы постсинаптических
											// нейронов
	static float[] weights = new float[Ncon]; // Веса связей
	static float psc_excxpire_time = 4.0f; // характерное вермя спадания
	// постсинаптического тока, мс
	static float minWeight = 50.0f; // веса, размерность пкА
	static float maxWeight = 100.0f;

	// Параметры нейрона
	static float Iex_max = 40.0f; // максимальный приложенный к нейрону ток 50
									// пкА
	static float a = 0.02f;
	static float b = 0.5f;
	static float c = -40.0f; // значение мембранного потенциала до которого он
	// сбрасываеться после спайка
	static float d = 100.0f;
	static float k = 0.5f;
	static float Vr = -60.0f;
	static float Vt = -45.0f;
	static float Vpeak = 35.0f; // максимальное значение мембранного потенциала,
								// при
	// котором происходит сброс до значения с
	static float Cm = 50.0f; // электрическая ёмкость нейрона, размерность пкФ
	static float[] y = new float[Ncon];
	static float[] Iex = new float[Nneur]; // Внешний постоянный ток приложенный
											// к
	// нейрону
	static float[] Isyn = new float[Nneur]; // Синаптический ток на каждый
											// нейрон

	final static float h = .5f; // временной шаг интегрирования
	int j;

	static int[] GrNeur = new int[Nneur];
	static Map<Integer, HashSet<Integer>> Map1Neuron;
	static Map<Integer, Integer> Map1NeuronDr;
	static String[] StrN = new String[Ncon];
	static HashSet<Integer> intcsp = new HashSet<Integer>();

	public void paintComponent(Graphics g) {
		// Инициализируем генератор
		int min = 50;
		int max = 600;
		Random rnd = new Random(System.currentTimeMillis());
		int numberx;
		int numbery;
		// Получаем случайное число в диапазоне от min до max (включительно)
		// Рисуем нейроны в количестве Nneur
		for (int i = 0; i < Nneur; i++) {
			numberx = min + rnd.nextInt(max - min + 1);
			numbery = min + rnd.nextInt(max - min + 1);
			g.setColor(Color.RED);
			HashSet<Integer> intN = new HashSet<Integer>();
			intN.add(numberx);
			intN.add(numbery);
			Map1Neuron.put(i, intN);
			g.fillOval(numberx, numbery, 20, 20);
		}

		// Рисуем связи нейронов - пост и пресинаптического.
		for (int con_idx = 0; con_idx < Ncon; con_idx++) {
			String[] arrayMessage = StrN[con_idx].split(" ");

			int icpre = Integer.parseInt(arrayMessage[0]);
			int ibpost = Integer.parseInt(arrayMessage[1]);

			int drstx = 0;
			int drsty = 0;

			int drctx = 0;
			int drcty = 0;

			for (Map.Entry<Integer, HashSet<Integer>> entry : Map1Neuron
					.entrySet()) {
				int key = entry.getKey();
				HashSet<Integer> value = entry.getValue();

				int[] ints = new int[value.size()];
				int index = 0;
				for (Integer i : value) {
					ints[index++] = i;
				}

				if (icpre == key) {
					drstx = ints[0];
					drsty = ints[1];
					break;
				}

			}
			for (Map.Entry<Integer, HashSet<Integer>> entry : Map1Neuron
					.entrySet()) {
				int key = entry.getKey();
				HashSet<Integer> value = entry.getValue();

				int[] ints = new int[value.size()];
				int index = 0;
				for (Integer i : value) {
					ints[index++] = i;
				}
				if (ibpost == key) {
					drctx = ints[0];
					drcty = ints[1];
					break;
				}
			}
			g.setColor(Color.GREEN);
			g.drawLine(drstx, drsty, drctx, drcty);
		}

		// Модуль рисования возбуждения отдельного нейрона.
		for (Integer i : intcsp) {
			for (Map.Entry<Integer, HashSet<Integer>> entry : Map1Neuron
					.entrySet()) {
				int key = entry.getKey();
				HashSet<Integer> value = entry.getValue();

				int[] ints = new int[value.size()];
				int index = 0;
				for (Integer l : value) {
					ints[index++] = l;
				}
				if (i == key) {
					try {
						g.setColor(Color.ORANGE);
						g.fillOval(ints[0], ints[1], 20, 20);
						Thread.sleep(1000);
						intcsp.remove(i);
						break;
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}

		// this.repaint();
	}

	public static void main(String args[]) {
		Map1Neuron = new HashMap<Integer, HashSet<Integer>>();
		Map1NeuronDr = new HashMap<Integer, Integer>();
		init_connections();
		JFrame frame = new JFrame("BrainNeuro Expert2.0");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		BrainMod panel = new BrainMod();
		textin = new JTextArea(2, 50);
		textin.setLineWrap(true);
		panel.add(textin);
		JButton button = new JButton("Анализ");
		ActionListener actionListener = new BrainMod();
		button.addActionListener(actionListener);
		panel.add(button);
		frame.add(panel);
		frame.setSize(900, 750);
		frame.setLocationRelativeTo(frame);
		frame.setVisible(true);
	}

	private static void init_connections() {
		for (int con_idx = 0; con_idx < Ncon; con_idx++) {
			// случайно выбираем постсипантические и пресинаптические нейроны
			int pre = (int) (Math.random() * Nneur);
			int post = (int) (Math.random() * Nneur);
			pre_conns[con_idx] = pre;
			post_conns[con_idx] = post;
			StrN[con_idx] = pre + " " + post;
			weights[con_idx] = (float) ((Math.random() * ((int) (maxWeight - minWeight) * 10)) / 10.0f + minWeight);
			if (pre >= Nexc) {
				// если пресинаптический нейрон тормозный то вес связи идет со
				// знаком минус
				weights[con_idx] = -weights[con_idx];
			}
			y[con_idx] = 0.0f;
		}
	}

	private static float izhik_Um(int neuron) {
		return a * (b * (Vms[neuron] - Vr) - Ums[neuron]);
	}

	private static float izhik_Vm(int neuron) {
		return (k * (Vms[neuron] - Vr) * (Vms[neuron] - Vt) - Ums[neuron]
				+ Iex[neuron] + Isyn[neuron])
				/ Cm;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		j = 0;
		String s = textin.getText().trim();
		try {
			j = Integer.parseInt(s); // Номер нейрона,который мы активируем.
			intcsp.add(j);
			Iex[j] = (float) ((Math.random() * (int) (Iex_max * 10)) / 10.0f);
			Isyn[j] = 0.0f;
			Vms[j] = V0;
			Ums[j] = U0;
			System.out.println("#neur -  " + j + " - "
					+ (float) ((Math.random() * (int) (Iex_max * 10)) / 10.0f)
					+ " V0 " + V0 + " U0 " + U0);

			float expire_coeff = (float) Math.exp(-h / psc_excxpire_time);

			for (int neur = 0; neur < Nneur; neur++) {
				Vms[neur] = Vms[neur] + h * izhik_Vm(neur);
				Ums[neur] = Ums[neur] + h * izhik_Um(neur);
				Isyn[neur] = 0.0f;
				if (Vms[neur] > Vpeak) {
					intcsp.add(neur); // Добавляем номер нейрона, который
										// "активизировался"
					Vms[neur] = c;
					Ums[neur] = Ums[neur] + d;
				}
			}
			for (int con = 0; con < Ncon; con++) {
				y[con] = y[con] * expire_coeff;

				if (Vms[pre_conns[con]] > Vpeak) {
					y[con] = 1.0f;
				}
				Isyn[post_conns[con]] += y[con] * weights[con];
			}
		} catch (NumberFormatException ex) {
			System.out.println("Ошибка ввода!");
			System.exit(0);
		}
	}
}



Прошу сразу тапочками не кидать, хоть за такой код и очень хочется)
Хотел бы спросить, не подскажите как лучше сделать такой момент: Некий поток, запускаемый отдельно от основного кода, который "смотрит" не появилось ли в коллекции HashSet intcsp элементов, если появились то мы их изучаем и рисуем что либо.

Попытался написать такое сам - В public void actionPerformed(ActionEvent e) { Мы обрабатываем нажатие и переменную (j) заносим в сет intcsp.add(j); . Далее уже в методе public void paintComponent(Graphics g) { мы обрабатываем это начиная отсюда // Модуль рисования возбуждения отдельного нейрона.

Но видимо после нажатия кнопки, возврата к паинткомпоненту нет, так сказать, отрисовал и забыл..
Вот хотелось бы динамический метод-поток какой нибудь создать, чтобы он вытаскивал новые значения из сета и рисовал что-нибудь, а потом это значение удалял.

Кстати, с зелеными черточками, это "связи" между нейронами, получились кривоваты...

Заранее огромное спасибо вам!

Кто дочитал уже герой просто))
Кстати, основная часть кода взята отсюда: http://geektimes.ru/post/201220/
...
Рейтинг: 0 / 0
Архитектура приложения, использующего нейронные сети.
    #38950890
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код не смотрел - слишком много.

Но судя по описанию - вы можете отнаследоваться от существующего Set, добавив туда генерацию событий.

Дальше в зависимости от пожеланий. В простейшем случае эти события через concurrentQueue уходят в другой поток и там обрабатываются.
...
Рейтинг: 0 / 0
Архитектура приложения, использующего нейронные сети.
    #38950893
Sergeyyy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chabapok,

Спасибо! Но вот можно ли сделать отдельный поток и в котором еще можно рисовать?
Как то создав там Graphics..Я то думал, что только в паинткомпоненте можно..

В самом сете все данные есть, их главное дорисовать.
...
Рейтинг: 0 / 0
Архитектура приложения, использующего нейронные сети.
    #38951017
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sergeyyy,

SwingWorker вам поможет
...
Рейтинг: 0 / 0
Архитектура приложения, использующего нейронные сети.
    #38951061
Sergeyyy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл ник,

Так он вроде бы параметризован двумя типами, а нам в принципе то возвращать то ничего не надо, нам дорисовать поверх картины и увсе)
...
Рейтинг: 0 / 0
Архитектура приложения, использующего нейронные сети.
    #38951074
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SergeyyyНекий поток, запускаемый отдельно от основного кода, который "смотрит" не появилось ли в коллекции HashSet intcsp элементов, если появились то мы их изучаем и рисуем что либо.


У вас в целом не верный подход. Нужно понять что вы не управляете процессом отрисовки в Swing.
Методы paint* нужно делать очень быстрыми. Так как они вызываются очень часто. Поэтому нужно все данные держать в памяти в виде некоторой готовой к отрисовке модели. А метод paint* должен очень быстро эту модель выводить в Graphics.
У вас же в paintComponent куча тяжеловесной логики.

Логику и представление нужно отделять.

Второй момент это полная непонятка с потоком. Поток никуда не "смотрит". Поток исполняет код. То что в коллекции что-то появилось это событие. И вам нужно на это событие отреагировать. Можно самому реализовать Listener. Но рас уж речь зашла о потоках, то можно использовать ExecutorService и его очередь. Как только в очереди появляется задача, ExecutorService будит поток и выполняет код этой задачи. Нужно оно тут или нет - решать вам.

Если свяжетесь с потоками, то обязательно к прочтению:
https://docs.oracle.com/javase/tutorial/uiswing/concurrency/
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Архитектура приложения, использующего нейронные сети.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]