Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package org.example;
- public class Main {
- // Количество нейронов по слоям
- static final int INPUT_NEURONS = 4; // температура, влажность, скорость ветра, давление
- static final int HIDDEN_NEURONS = 3;
- static final int OUTPUT_NEURONS = 4; // 4 класса погоды
- static final double LEARN_RATE = 0.2;
- static final int MAX_SAMPLES = 16;
- // Весовые коэффициенты (с учётом смещений)
- double[][] wih = new double[INPUT_NEURONS + 1][HIDDEN_NEURONS]; // вход -> скрытый слой
- double[][] who = new double[HIDDEN_NEURONS + 1][OUTPUT_NEURONS]; // скрытый -> выходной слой
- // Значения нейронов
- double[] inputs = new double[INPUT_NEURONS];
- double[] hidden = new double[HIDDEN_NEURONS];
- double[] target = new double[OUTPUT_NEURONS];
- double[] actual = new double[OUTPUT_NEURONS];
- // Ошибки нейронов
- double[] erro = new double[OUTPUT_NEURONS];
- double[] errh = new double[HIDDEN_NEURONS];
- // Массив с названиями погодных условий (индексы: 0 – "Солнечно", 1 – "Облачно", 2 – "Дождливо", 3 – "Шторм")
- String[] conditions = {"Солнечно", "Облачно", "Дождливо", "Шторм"};
- // Класс, представляющий обучающий пример
- static class Sample {
- double temperature; // температура (например, °C)
- double humidity; // влажность (в %)
- double windSpeed; // скорость ветра (м/с)
- double pressure; // давление (гПа)
- double[] out; // one-hot представление класса
- Sample(double temperature, double humidity, double windSpeed, double pressure, double[] out) {
- this.temperature = temperature;
- this.humidity = humidity;
- this.windSpeed = windSpeed;
- this.pressure = pressure;
- this.out = out;
- }
- }
- // Обучающий набор (16 примеров: по 4 для каждого класса)
- Sample[] samples = new Sample[] {
- // "Солнечно": высокая температура, низкая влажность, слабый ветер, высокое давление
- new Sample(30, 20, 5, 1020, new double[]{1.0, 0.0, 0.0, 0.0}),
- new Sample(32, 18, 4, 1018, new double[]{1.0, 0.0, 0.0, 0.0}),
- new Sample(29, 22, 6, 1022, new double[]{1.0, 0.0, 0.0, 0.0}),
- new Sample(31, 19, 5, 1021, new double[]{1.0, 0.0, 0.0, 0.0}),
- // "Облачно": умеренная температура, средняя влажность, слабый ветер, среднее давление
- new Sample(22, 50, 3, 1012, new double[]{0.0, 1.0, 0.0, 0.0}),
- new Sample(23, 48, 4, 1013, new double[]{0.0, 1.0, 0.0, 0.0}),
- new Sample(21, 52, 3, 1011, new double[]{0.0, 1.0, 0.0, 0.0}),
- new Sample(22, 50, 2, 1012, new double[]{0.0, 1.0, 0.0, 0.0}),
- // "Дождливо": ниже температура, высокая влажность, умеренный ветер, низкое давление
- new Sample(18, 80, 10, 1005, new double[]{0.0, 0.0, 1.0, 0.0}),
- new Sample(17, 85, 9, 1004, new double[]{0.0, 0.0, 1.0, 0.0}),
- new Sample(19, 78, 11, 1006, new double[]{0.0, 0.0, 1.0, 0.0}),
- new Sample(18, 82, 10, 1005, new double[]{0.0, 0.0, 1.0, 0.0}),
- // "Шторм": умеренная или низкая температура, очень высокая влажность, сильный ветер, очень низкое давление
- new Sample(16, 90, 20, 995, new double[]{0.0, 0.0, 0.0, 1.0}),
- new Sample(15, 92, 22, 993, new double[]{0.0, 0.0, 0.0, 1.0}),
- new Sample(16, 88, 19, 996, new double[]{0.0, 0.0, 0.0, 1.0}),
- new Sample(15, 91, 21, 994, new double[]{0.0, 0.0, 0.0, 1.0})
- };
- // Фиксированные минимальные и максимальные значения для каждого входного параметра
- // (значения подобраны на основе обучающего набора)
- static final double TEMP_MIN = 15; // °C
- static final double TEMP_MAX = 32; // °C
- static final double HUMIDITY_MIN = 18; // %
- static final double HUMIDITY_MAX = 92; // %
- static final double WIND_MIN = 2; // м/с
- static final double WIND_MAX = 22; // м/с
- static final double PRESSURE_MIN = 993; // гПа
- static final double PRESSURE_MAX = 1022; // гПа
- // Нормализация входных данных: перевод значений в диапазон [0,1]
- void normalizeInputs() {
- inputs[0] = (inputs[0] - TEMP_MIN) / (TEMP_MAX - TEMP_MIN); // температура
- inputs[1] = (inputs[1] - HUMIDITY_MIN) / (HUMIDITY_MAX - HUMIDITY_MIN); // влажность
- inputs[2] = (inputs[2] - WIND_MIN) / (WIND_MAX - WIND_MIN); // скорость ветра
- inputs[3] = (inputs[3] - PRESSURE_MIN) / (PRESSURE_MAX - PRESSURE_MIN); // давление
- }
- // Инициализация весов случайными значениями в диапазоне [-0.5, 0.5]
- void assignRandomWeights() {
- for (int inp = 0; inp < INPUT_NEURONS + 1; inp++) {
- for (int hid = 0; hid < HIDDEN_NEURONS; hid++) {
- wih[inp][hid] = Math.random() - 0.5;
- }
- }
- for (int hid = 0; hid < HIDDEN_NEURONS + 1; hid++) {
- for (int out = 0; out < OUTPUT_NEURONS; out++) {
- who[hid][out] = Math.random() - 0.5;
- }
- }
- }
- // Функция активации (сигмоида) и её производная
- double sigmoid(double val) {
- return 1.0 / (1.0 + Math.exp(-val));
- }
- double sigmoidDerivative(double val) {
- return val * (1.0 - val);
- }
- // Прямое распространение сигнала по сети
- void feedForward() {
- // Вычисление выхода скрытого слоя
- for (int hid = 0; hid < HIDDEN_NEURONS; hid++) {
- double sum = 0.0;
- for (int inp = 0; inp < INPUT_NEURONS; inp++) {
- sum += inputs[inp] * wih[inp][hid];
- }
- // Добавление смещения
- sum += wih[INPUT_NEURONS][hid];
- hidden[hid] = sigmoid(sum);
- }
- // Вычисление выхода выходного слоя
- for (int out = 0; out < OUTPUT_NEURONS; out++) {
- double sum = 0.0;
- for (int hid = 0; hid < HIDDEN_NEURONS; hid++) {
- sum += hidden[hid] * who[hid][out];
- }
- // Добавление смещения
- sum += who[HIDDEN_NEURONS][out];
- actual[out] = sigmoid(sum);
- }
- }
- // Алгоритм обратного распространения ошибки
- void backPropagate() {
- // Вычисление ошибки на выходном слое
- for (int out = 0; out < OUTPUT_NEURONS; out++) {
- erro[out] = (target[out] - actual[out]) * sigmoidDerivative(actual[out]);
- }
- // Вычисление ошибки на скрытом слое
- for (int hid = 0; hid < HIDDEN_NEURONS; hid++) {
- errh[hid] = 0.0;
- for (int out = 0; out < OUTPUT_NEURONS; out++) {
- errh[hid] += erro[out] * who[hid][out];
- }
- errh[hid] *= sigmoidDerivative(hidden[hid]);
- }
- // Обновление весов выходного слоя
- for (int out = 0; out < OUTPUT_NEURONS; out++) {
- for (int hid = 0; hid < HIDDEN_NEURONS; hid++) {
- who[hid][out] += LEARN_RATE * erro[out] * hidden[hid];
- }
- // Обновление смещения
- who[HIDDEN_NEURONS][out] += LEARN_RATE * erro[out];
- }
- // Обновление весов скрытого слоя
- for (int hid = 0; hid < HIDDEN_NEURONS; hid++) {
- for (int inp = 0; inp < INPUT_NEURONS; inp++) {
- wih[inp][hid] += LEARN_RATE * errh[hid] * inputs[inp];
- }
- // Обновление смещения
- wih[INPUT_NEURONS][hid] += LEARN_RATE * errh[hid];
- }
- }
- // Функция выбора индекса выходного нейрона с максимальным значением
- int action(double[] vector) {
- int sel = 0;
- double max = vector[0];
- for (int i = 1; i < OUTPUT_NEURONS; i++) {
- if (vector[i] > max) {
- max = vector[i];
- sel = i;
- }
- }
- return sel;
- }
- public static void main(String[] args) {
- Main wc = new Main();
- wc.assignRandomWeights();
- int sampleIndex = 0;
- double err;
- // Обучение сети (например, 10000 итераций)
- for (int step = 0; step < 10000; step++) {
- sampleIndex = (sampleIndex + 1) % MAX_SAMPLES;
- Sample s = wc.samples[sampleIndex];
- // Задание входного вектора: температура, влажность, скорость ветра, давление
- wc.inputs[0] = s.temperature;
- wc.inputs[1] = s.humidity;
- wc.inputs[2] = s.windSpeed;
- wc.inputs[3] = s.pressure;
- // Нормализация входных данных
- wc.normalizeInputs();
- // Копирование целевого вектора
- for (int i = 0; i < OUTPUT_NEURONS; i++) {
- wc.target[i] = s.out[i];
- }
- wc.feedForward();
- err = 0.0;
- for (int i = 0; i < OUTPUT_NEURONS; i++) {
- double diff = s.out[i] - wc.actual[i];
- err += diff * diff;
- }
- err = 0.5 * err;
- if (step % 1000 == 0) {
- System.out.println("step = " + step + " mse = " + err);
- }
- wc.backPropagate();
- }
- System.out.println();
- int correct = 0;
- // Проверка сети на обучающих примерах
- for (int i = 0; i < MAX_SAMPLES; i++) {
- Sample s = wc.samples[i];
- wc.inputs[0] = s.temperature;
- wc.inputs[1] = s.humidity;
- wc.inputs[2] = s.windSpeed;
- wc.inputs[3] = s.pressure;
- wc.normalizeInputs();
- for (int j = 0; j < OUTPUT_NEURONS; j++) {
- wc.target[j] = s.out[j];
- }
- wc.feedForward();
- int predicted = wc.action(wc.actual);
- int expected = wc.action(wc.target);
- if (predicted != expected) {
- System.out.println("Input: " + s.temperature + " " + s.humidity + " "
- + s.windSpeed + " " + s.pressure +
- " predicted: " + wc.conditions[predicted] +
- " expected: " + wc.conditions[expected]);
- } else {
- correct++;
- }
- }
- System.out.println("Network is " + ((float) correct / MAX_SAMPLES * 100.0) + "% correct\n");
- // Дополнительное тестирование с новыми входными данными
- double[][] testInputs = {
- {30, 20, 5, 1020}, // ожидается "Солнечно"
- {22, 50, 3, 1012}, // ожидается "Облачно"
- {18, 80, 10, 1005}, // ожидается "Дождливо"
- {15, 92, 22, 993} // ожидается "Шторм"
- };
- for (double[] test : testInputs) {
- // Задаём тестовый входной вектор
- wc.inputs[0] = test[0];
- wc.inputs[1] = test[1];
- wc.inputs[2] = test[2];
- wc.inputs[3] = test[3];
- wc.normalizeInputs();
- wc.feedForward();
- int index = wc.action(wc.actual);
- System.out.println("Input: [" + test[0] + ", " + test[1] + ", " + test[2] + ", " + test[3]
- + "] -> " + wc.conditions[index]);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement