Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Вопрос про простой перцептрон. / 8 сообщений из 8, страница 1 из 1
22.03.2017, 09:38
    #39424579
bobo96
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про простой перцептрон.
Приветствую!
Тема нейронных сетей давно интересовала, поэтому почитал, что по этому поводу пишут интернеты и вчера вечером навскидку запилил структуру простого перцептрона и прикрутил к нему обучение, если не путаю, по методу обратного распространения ошибки.

Код:


Код: 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.
259.
260.
261.
262.
263.
264.
265.
266.
267.
import java.util.*;

class Neural {

    /**
     *  Число входов
     */
    private final int SIZE_INPUTS = 6;

    /**
     *  Число узлов в скрытом слое
     */
    private final int SIZE_HIDDEN = 7;

    /**
     *  Количество эпох
     */
    private final int EPOCHS = 25000;

    /**
     *  Коэффициент для обучения
     */
    private final double LEARNING_RATE = .005;

    /**
     *  Выходное значение
     */
    private double output;

    /**
     *  Массивы значений на входном и скрытом слоях и массив весов скрытого слоя
     */
    private double[] valueInput, valueHidden, weightsHidden;

    /**
     *  Двумерный массив весов входного слоя
     */
    private double[][] weightsInput;

    /**
     *  Коллекция для обучения сети
     */
    private List<Map<Double, double[]>> trainingList;


    /**
     *  Конструктор. Инициализируем веса и заполняем лист для обучения
     */
    Neural() {
        weightsInput = generateWeights(SIZE_INPUTS, SIZE_HIDDEN);
        weightsHidden = generateWeights(SIZE_HIDDEN);

        trainingList = generateTraningList();
    }

    /**
     *  Передаем в переменную массив входных значений
     * @param valueInput
     */
    private void setValueInput(double[] valueInput) {
        if(valueInput.length != SIZE_INPUTS) {
            System.out.println(String.format("Input values count error! Right count is %d.", SIZE_INPUTS));
            return;
        }
        this.valueInput = valueInput;
    }

    /**
     *  Функция активации - сигмоид
     * @param value
     * @return
     */
    private double getSigmoid(double value) {
        return  1 / (1 + Math.exp(-value));
    }

    /**
     *  Приводим результат либо к нулю, если он меньше 0.5, либо к еденице в обратном случае
     * @param value
     * @return
     */
    private int getResult(double value) {
        return value >= .5 ? 1 : 0;
    }

    /**
     *  Суммируем произведения входных значений и весов и получаем активационную функцию
     * @param input
     * @param weight
     * @return
     */
    private double getActivationFunction(double[] input, double[] weight) {
        double summ = 0;
        for (int x = 0; x < input.length; x++) {
            summ += input[x] * weight[x];
        }
        return getSigmoid(summ);
    }

    /**
     *  Вычисляем значения нейронов на скрытом и на выходном слоях
     */
    private void calculateValues() {
        valueHidden = calculateHiddenValues(valueInput, SIZE_HIDDEN);
        output = calculateOutputValue(valueHidden);
    }

    /**
     *  В начале работы задаем рандомные веса для каждого узла.
     *  В этой функции делаем это для скрытого слоя
     * @param sizeInputs
     * @param sizeHidden
     * @return
     */
    private double[][] generateWeights(int sizeInputs, int sizeHidden) {
        double[][] result = new double[sizeHidden][sizeInputs];
        for(int x = 0; x < sizeHidden; x++) {
            for (int y = 0; y < sizeInputs; y++) {
                result[x][y] = Math.random() * .3;
            }
        }
        return result;
    }

    /**
     *  В начале работы задаем рандомные веса для каждого входа.
     *  В этой функции задаем их для входного слоя
     * @param sizeHidden
     * @return
     */
    private double[] generateWeights(int sizeHidden) {
        double[] result = new double[sizeHidden];
        for(int x = 0; x < sizeHidden; x++) {
            result[x] = Math.random() * .3;
        }
        return result;
    }

    /**
     *  Вычисляем значения на скрытом слое
     * @param valueInput
     * @param size
     * @return
     */
    private double[] calculateHiddenValues(double[] valueInput, int size) {
        double[] result = new double[size];
        for(int x = 0; x < size; x++) {
            result[x] = getActivationFunction(valueInput, weightsInput[x]);
        }
        return result;
    }

    /**
     *  Вычисляем выходное значение
     * @param valueHidden
     * @return
     */
    private double calculateOutputValue(double[] valueHidden) {
        return getActivationFunction(valueHidden, weightsHidden);
    }

    /**
     *  Создаем список для обучения. В комментариях указано ожидаемое значение на выходе
     * @return
     */
    private ArrayList<Map<Double, double[]>> generateTraningList() {
        ArrayList<Map<Double, double[]>> result = new ArrayList<>();
        Map<Double, double[]> map1, map2, map3, map4, map5, map6, map7, map8, map9, map10;
        double[] valuesInput1, valuesInput2, valuesInput3, valuesInput4, valuesInput5, valuesInput6, valuesInput7,
                     valuesInput8, valuesInput9, valuesInput10;

        valuesInput1 =      new double[]{ 0, 1, 1, 0, 0, 0 }; // 0
        map1 = new HashMap<>();
        map1.put(0.0, valuesInput1);

        valuesInput2 =      new double[]{ 0, 0, 0, 1, 1, 0 }; // 1
        map2 = new HashMap<>();
        map2.put(1.0, valuesInput2);

        valuesInput3 =      new double[]{ 0, 0, 1, 1, 1, 0 }; // 1
        map3 = new HashMap<>();
        map3.put(1.0, valuesInput3);

        valuesInput4 =      new double[]{ 1, 1, 0, 0, 1, 0 }; // 1
        map4 = new HashMap<>();
        map4.put(1.0, valuesInput4);

        valuesInput5 =      new double[]{ 0, 1, 1, 1, 0, 0 }; // 0
        map5 = new HashMap<>();
        map5.put(0.0, valuesInput5);

        valuesInput6 =      new double[]{ 0, 0, 0, 0, 0, 1 }; // 1
        map6 = new HashMap<>();
        map6.put(1.0, valuesInput6);

        valuesInput7 =      new double[]{ 0, 1, 1, 0, 0, 1 }; // 0
        map7 = new HashMap<>();
        map7.put(0.0, valuesInput7);

        valuesInput8 =      new double[]{ 0, 1, 1, 1, 1, 1 }; // 1
        map8 = new HashMap<>();
        map8.put(1.0, valuesInput8);

        valuesInput9 =      new double[]{ 0, 0, 0, 0, 0, 0 }; // 0
        map9 = new HashMap<>();
        map9.put(0.0, valuesInput9);

        valuesInput10 =     new double[]{ 1, 0, 0, 0, 0, 0 }; // 1
        map10 = new HashMap<>();
        map10.put(1.0, valuesInput10);

        result.add(map1);
        result.add(map2);
        result.add(map3);
        result.add(map4);
        result.add(map5);
        result.add(map6);
        result.add(map7);
        result.add(map8);
        result.add(map9);
        result.add(map10);

        return result;
    }


    /**
     *  Функция для обучения сети
     */
    void train() {

        for (int x = 0; x <= EPOCHS; x++) {

            double error, weightDelta;
            Collections.shuffle(trainingList);

            for (Map<Double, double[]> aTrainingList : trainingList) {

                for (Map.Entry<Double, double[]> item : aTrainingList.entrySet()) {

                    setValueInput(item.getValue());
                    calculateValues();

                    error = output - item.getKey();
                    weightDelta = error * (getSigmoid(output) * (1 - getSigmoid(output)));

                    for(int y = 0; y < weightsHidden.length; y++) {
                        weightsHidden[y] -= valueHidden[y] * weightDelta * LEARNING_RATE;

                        error = weightsHidden[y] * weightDelta;
                        weightDelta = error * (getSigmoid(valueHidden[y]) * (1 - getSigmoid(valueHidden[y])));

                        for(int z = 0; z < weightsInput[y].length; z++) {
                            weightsInput[y][z] -= valueInput[z] * weightDelta * LEARNING_RATE;
                        }

                    }

                }

            }

        }

    }

}




В целом все ок, вылазит что-то вроде этого:
value output: 0,001, prediction: 0, expected: 0
value output: 0,980, prediction: 1, expected: 1
value output: 0,023, prediction: 0, expected: 0
value output: 0,962, prediction: 1, expected: 1
value output: 0,026, prediction: 0, expected: 0
value output: 0,979, prediction: 1, expected: 1
value output: 0,976, prediction: 1, expected: 1
value output: 0,976, prediction: 1, expected: 1
value output: 0,210, prediction: 0, expected: 0
value output: 0,947, prediction: 1, expected: 1

То-есть: значение на выходе - преобразование в 1\0 - значение, которое ожидалось увидеть. Вопросов нет.

Но бывает (редко!) вылазит вот такое:
value output: 1,000, prediction: 1, expected: 1
value output: 1,000, prediction: 1, expected: 0
value output: 1,000, prediction: 1, expected: 1
value output: 1,000, prediction: 1, expected: 1
value output: 1,000, prediction: 1, expected: 1
value output: 1,000, prediction: 1, expected: 1
value output: 1,000, prediction: 1, expected: 0
value output: 1,000, prediction: 1, expected: 0
value output: 1,000, prediction: 1, expected: 1
value output: 1,000, prediction: 1, expected: 0

Не могу понять почему!
Подскажите где ошибка, очень прошу!
...
Рейтинг: 0 / 0
22.03.2017, 10:24
    #39424605
Partisan M
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про простой перцептрон.
Ошибка в том, что вы стали программировать то, что не надо программировать. Перцептроны устарели. Сейчас применяются более общие модели обучающихся систем, частным случаем которых являются нейронные сети, неинтересным частным случаем которых является перцептрон. И всё уже запрограммировано до вас. Надо только ознакомиться с теорией (тема Deep Learning), найти подходящую библиотеки и документацию и пользоваться. Запрограммировать своё будет иметь смысл после ознакомления с тем, что есть.
...
Рейтинг: 0 / 0
22.03.2017, 17:28
    #39425122
wst
wst
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про простой перцептрон.
Хотел было отписать про локальный минимум, но вовремя заметил слишком вольное обращение с weightDelta в конце.
...
Рейтинг: 0 / 0
22.03.2017, 17:45
    #39425140
bobo96
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про простой перцептрон.
Partisan MОшибка в том, что вы стали программировать то, что не надо программировать. Перцептроны устарели. Сейчас применяются более общие модели обучающихся систем, частным случаем которых являются нейронные сети, неинтересным частным случаем которых является перцептрон. И всё уже запрограммировано до вас. Надо только ознакомиться с теорией (тема Deep Learning), найти подходящую библиотеки и документацию и пользоваться. Запрограммировать своё будет иметь смысл после ознакомления с тем, что есть.
С простым бы разобраться, прежде чем в дебри лезть :)

wstХотел было отписать про локальный минимум, но вовремя заметил слишком вольное обращение с weightDelta в конце.
Вы, простите, самоутвердиться в тему зашли что ли ?
Вроде по-человечески спросил и ни на что не претендую. Тема новая для меня, да, поэтому ничего удивительного, что ерунду мог наговнокодить.
...
Рейтинг: 0 / 0
22.03.2017, 18:30
    #39425162
wst
wst
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про простой перцептрон.
Где ошибка я написал. Тратить свое время на то чтобы расписывать подробности после такой реакции не собираюсь.
...
Рейтинг: 0 / 0
22.03.2017, 22:25
    #39425274
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про простой перцептрон.
Partisan MОшибка в том, что вы стали программировать то, что не надо программировать. Перцептроны устарели. Сейчас применяются более общие модели обучающихся систем, частным случаем которых являются нейронные сети, неинтересным частным случаем которых является перцептрон. И всё уже запрограммировано до вас. Надо только ознакомиться с теорией (тема Deep Learning), найти подходящую библиотеки и документацию и пользоваться. Запрограммировать своё будет иметь смысл после ознакомления с тем, что есть.
Есть два возможных направления этого топика. Первое. Мы изучаем вместе теорию.
Читаем источники из которых вы написали этот исходних. И пытаемся восстановить
вашу логику которой вы руководствовались при написании кода.

Второе. Мы даем вам ссылку на коробочные библиотеки machine-learning, и говорим
бери чел и не парься.
...
Рейтинг: 0 / 0
23.03.2017, 07:06
    #39425356
bobo96
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про простой перцептрон.
wstГде ошибка я написал. Тратить свое время на то чтобы расписывать подробности после такой реакции не собираюсь.
Ну да, действительно, чойэтоя. Перечитал ваше первое сообщение еще раз и сразу стало понятно, какую ошибку я совершил, спасибо!!!!111
А если серьезно, что б вам так же "подсказывали" ;)

maytonЕсть два возможных направления этого топика. Первое. Мы изучаем вместе теорию.
Читаем источники из которых вы написали этот исходних. И пытаемся восстановить
вашу логику которой вы руководствовались при написании кода.

Второе. Мы даем вам ссылку на коробочные библиотеки machine-learning, и говорим
бери чел и не парься.
Теорию читал, и читал в разных местах, а конкретно код запилил после просмотра вот этого видео. Вообще, у меня есть сомнения, правильно ли я понял, когда чел рассказывал о корректирующем расчете весов входного слоя, возможно в этих расчетах и скрыта ошибка.
[spoiler]
YouTube Video
...
Рейтинг: 0 / 0
23.03.2017, 21:11
    #39426085
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про простой перцептрон.
bobo96, я не знаю где ошибка в твоем сорце. Но сделаю несколько ремарок.

1) Ты используешь random-генераторы и shuffle. Как они инстанциируется? В разных JDK можно
получать разные или повторяющиеся стартовые последовательности.
2) Набор единичек которые ты получил на выходе сети надо продебажить в обратную сторону.
Тоесть взять твой worst-case и понять почему на вход пороговой функции идёт ооочень большая
величина которая после пороговой функции тождественно равна 1.
Опять-же... у тебя есть консоль. Выведи промежуточные значения в фазе обучения для всех выходов.
Лучше - графически в виде полосок или точек в Excel. Так легче искать тренды.
3) Выставлять жесткое требование по равенству для выхода нейро-сети - сложно.
Это не модульный тест бизнес-логики. Это - тонкая наука. Обычно берут критерии
попадания в диапазон точности. Или берут в контролной выборке 95-97% успешных
кейсов и считают что ОК.

По поводу ссылок. Таких не дам ибо не знаю. Я последний раз изучал предмет в 98 году и кажется
пользовался книгой Саймона Хайкина.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Вопрос про простой перцептрон. / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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