Нейронные сети. Лабораторная работа № 2.. Лабораторная работа 2 магистрант гр. 3Мпп1801 Симанова Д. А. подпись дата Проверил
Скачать 77.45 Kb.
|
1 2 Структурная схема нейронной сети Вывод. Проделав работу, можно выявить достоинства и недостатки данного метода обучения однослойного персептрона. Преимущества SG: Метод приспособлен для динамического обучения, когда обучающие объекты поступают потоком, и надо быстро обновлять вектор. Алгоритм способен обучаться на избыточно больших выборках за счет того, что случайной подвыборки может хватить для обучения. Недостатки SG и способы их устранения: Исходный код программы public class Main { public static void main(String[] args) { GUI gui = new GUI(); } } public class NeuralNet { private int inputVectorSize; private Neuron[] layer; private int epochNumber; private boolean complete; private double[] error; private double errorNet; private double eta = 0.00000001; private double epsThreshold = 0.000000001; public double getErrorNet() { return errorNet; } public NeuralNet(int inputVectorSize, int outputNeuronsCount) { this.inputVectorSize = inputVectorSize; layer = new Neuron[outputNeuronsCount]; for (int j = 0; j < outputNeuronsCount; j++) { layer[j] = new Neuron(inputVectorSize); } error = new double[layer.length]; } public double[] getError() { return error; } public int getEpochNumber() { return epochNumber; } public boolean isComplete() { return complete; } public void setComplete(boolean complete) { this.complete = complete; } public void train(Vector[] vectorSet) throws InterruptedException { // эпоха обучения равна нулю epochNumber = 0; double[][] deltaWeight = new double[layer.length][]; for (int j = 0; j < layer.length; j++) { // создаем пустой массив для каждого //синаптического веса wij каждого j-го нейрона в слое deltaWeight[j] = new double[layer[j].getWeight().length]; } // массив для хранения ошибки каждого нейрона error = new double[layer.length]; Random random = new Random(); while (true) { // Шаг 3 и 4. Берем случайным образом обучающий вектор int m = random.nextInt(vectorSet.length); // Шаг 5 for (int j = 0; j < layer.length; j++) //перебор нейронов { layer[j].calcOut(vectorSet[m].getX()); } errorNet = 0.0; // Шаг 6 for (int j = 0; j < layer.length; j++) { // считаем ошибка каждого j-го нейрона error[j] = (vectorSet[m].getDesireOutputs()[j] - layer[j].getOut()) * (vectorSet[m].getDesireOutputs()[j] - layer[j].getOut()); errorNet += 0.5 * error[j]; } // Шаг 7 if (errorNet < epsThreshold) // ошибка < ошибки порог. break; // прерываем внешний цикл // критерий останова обучения // Шаг 8. Цикл коррекции синаптических весов for (int j = 0; j < layer.length; j++) { layer[j].calcSigma(vectorSet[m].getDesireOutputs()[j]); int n = layer[j].getWeight().length; // кол-во синаптических весов j-го нейрона for (int i = 0; i < n; i++) { deltaWeight[j][i] = - eta * layer[j].getSigma() * vectorSet[m].getX()[i]; } layer[j].correctWeights(deltaWeight[j]); } epochNumber++; } complete = true; } public double[] test(double[] vector) { double[] outVector = new double[layer.length]; for (int j = 0; j < layer.length; j++) { layer[j].calcOut(vector); outVector[j] = Math.round(layer[j].getOut() * 100.0) / 100.0; } return outVector; } } import java.util.Random; public class Neuron { private double[] weight; private double out; // y private double sum; // net private double sigma; public static Random random = new Random(); public double rangeMin = -0.0003; public double rangeMax = 0.0003; public double getSigma() { return sigma; } public void calcSigma(double desireResponse) { this.sigma = -(desireResponse - this.out) * derivativeActivationFunc(sum); } public void calcOut(double[] x) { this.sum = 0; for (int i = 0; i < x.length; i++) { sum += x[i]*weight[i]; } this.out = activationFunc(sum); } public Neuron(int weightsCount) { this.weight = new double[weightsCount]; this.out = 0.0; randomizeWeights(); } public void randomizeWeights() { for (int i = 0; i < weight.length; i++) { weight[i] = rangeMin + (rangeMax - rangeMin) * random.nextDouble(); } } private double activationFunc(double val) { return 1.0 / (1.0 + Math.exp(-val)); } private double derivativeActivationFunc(double val) { return activationFunc(val) * (1.0 - activationFunc(val)); } public double getOut() { return out; } public void correctWeights(double[] deltaWeight) { for (int i = 0; i < weight.length; i++) { weight[i] += deltaWeight[i]; } } public double[] getWeight() { return weight; } } public class Vector { private double[] x; private double[] desireOutputs; public Vector(double[] x, double[] desireOutputs) { this.x = new double[x.length +1]; this.x[0] = 1; for (int i = 1; i < x.length; i++) { this.x[i] = x[i - 1]; } this.desireOutputs = desireOutputs; } public double[] getX() { return x; } public double[] getDesireOutputs() { return desireOutputs; } } import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; import static javax.swing.JOptionPane.showMessageDialog; public class GUI extends JFrame { private JPanel rootPanel; private JButton buttonTrain; private JPanel imagePanel; private JLabel imageLabel; private JLabel labelError; private JLabel labelAnswer; private JLabel labelEpoch; private JTextArea textAreaAnswer; private JButton buttonTest; private JLabel labelNetError; private NeuralNet neuralNet; public GUI() { setContentPane(rootPanel); pack(); setTitle("Обучение методом SGD"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); setVisible(true); buttonTest.setEnabled(false); buttonTrain.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { train(); } }); buttonTest.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { test(); } }); } public void train() { try { buttonTest.setEnabled(false); Vector[] trainVectorSet = readTrainVectors("C://Train"); neuralNet = new NeuralNet(trainVectorSet[0].getX().length, trainVectorSet[0].getDesireOutputs().length); neuralNet.setComplete(false); Runnable task1 = () -> { try { neuralNet.train(trainVectorSet); } catch (InterruptedException e) {} }; Thread thread1 = new Thread(task1); Runnable task2 = () -> { while (!neuralNet.isComplete()) { labelEpoch.setText("Номер эпохи: " + neuralNet.getEpochNumber()); double[] err = neuralNet.getError(); StringBuilder s = new StringBuilder(); IntStream.range(0, err.length) .forEach(i -> s.append(String.format("[%.5f] ", err[i]))); labelError.setText("Ошибка нейронов: " + s); labelNetError.setText("Ошибка вектора: " + neuralNet.getErrorNet()); } textAreaAnswer.append("Обучение завершено\n"); buttonTest.setEnabled(true); }; Thread thread2 = new Thread(task2); thread1.start(); thread2.start(); } catch (IOException e) { showMessageDialog(null, "Файл не найден"); } catch (Exception e) { showMessageDialog(null, e.toString()); } int f = 0; } public void test() { try { String path = "c://Test//"; int totalCount = 0; int totalPassed = 0; for (int i = 0; i < 3; i++) { File[] files = new File(path + i).listFiles(); int count = 0; int passed = 0; for (File file : files) { double[] testVector = readVector(file.getPath()); double[] answer = neuralNet.test(testVector); count++; if (i == getMaxNeuronIdx(answer)) { passed++; } } double percent = (double)passed / count * 100.0; textAreaAnswer.append(String .format("Процент распознавания класса образов №%d: %.2f%n", i, percent)); totalCount += count; totalPassed += passed; } double percent = 100.0 - (double)totalPassed / totalCount * 100.0; textAreaAnswer.append(String .format("Процент ошибки распознавания: %.2f%n", percent)); } catch (IOException e) { showMessageDialog(null, "Файл не найден"); } catch (Exception e) { showMessageDialog(null, e.toString()); } } public int getMaxNeuronIdx(double[] answer) { int maxIdx = 0; for (int i = 1; i < answer.length; i++) { if (answer[maxIdx] < answer[i]) maxIdx = i; } return maxIdx; } public double[] readVector(String path) throws IOException { BufferedImage image = ImageIO.read(new File(path)); int[][] grayImage = imageToGrayScale(image); double[] imageVector = imageToVector(grayImage); return imageVector; } public Vector[] readTrainVectors(String rootDir) throws IOException { List for (int i = 0; i < 3; i++) { File[] files = new File(rootDir + "//" + i).listFiles(); for (File file : files) { BufferedImage image = ImageIO.read(file); int[][] grayImage = imageToGrayScale(image); double[] imageVector = imageToVector(grayImage); double[] desireOutputs = new double[3]; for (int k = 0; k < desireOutputs.length; k++) { desireOutputs[k] = i == k ? 1 : 0; } trainVectorSet.add(new Vector(imageVector, desireOutputs)); //imageLabel.setIcon(new ImageIcon(image)); } } return (Vector[])trainVectorSet.toArray(new Vector[trainVectorSet.size()]); } public int[][] imageToGrayScale(BufferedImage image) { int[][] resultImage = new int[image.getWidth()][image.getHeight()]; for(int x = 0; x < image.getWidth(); x++) { for (int y = 0; y < image.getHeight(); y++) { Color c = new Color(image.getRGB(x, y)); resultImage[x][y] = (c.getRed() + c.getGreen() + c.getBlue()) / 3; } } return resultImage; } public BufferedImage grayScaleToImage(int[][] grayImage) { int height = grayImage[0].length; int width = grayImage[1].length; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Color c = new Color(grayImage[x][y], grayImage[x][y], grayImage[x][y], 0); image.setRGB(x, y, c.getRGB()); } } return image; } public double[] imageToVector(int[][] image) { double[] resultVector = new double[image[0].length * image[1].length]; int i = 0; for(int x = 0; x < image.length; x++) { for (int y = 0; y < image.length; y++) { resultVector[i++] = image[x][y]; } } return resultVector; } } 1 2 |